def __init__(self, fg, channel_rate, audio_decim, deviation, audio_pass, audio_stop, gain=1.0, tau=75e-6): """ # Equalizer for ~100 us delay delay = 100e-6 num_taps = int(channel_rate*delay) mu = 1e-4/num_taps print "CMA: delay =", delay, "n =", num_taps, "mu =", mu CMA = gr.cma_equalizer_cc(num_taps, 1.0, mu) """ k = channel_rate / (2 * pi * deviation) QUAD = gr.quadrature_demod_cf(k) audio_taps = optfir.low_pass( gain, # Filter gain channel_rate, # Sample rate audio_pass, # Audio passband audio_stop, # Audio stopband 0.1, # Passband ripple 60, ) # Stopband attenuation LPF = gr.fir_filter_fff(audio_decim, audio_taps) if tau is not None: DEEMPH = fm_deemph(fg, channel_rate, tau) fg.connect(QUAD, DEEMPH, LPF) else: fg.connect(QUAD, LPF) gr.hier_block.__init__(self, fg, QUAD, LPF)
def __init__(self, interp, taps=None, atten=100): gr.hier_block2.__init__(self, "pfb_interpolator_ccf", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._interp = interp self._taps = taps if taps is not None: self._taps = taps else: # Create a filter that covers the full bandwidth of the input signal bw = 0.4 tb = 0.2 ripple = 0.99 made = False while not made: try: self._taps = optfir.low_pass(self._interp, self._interp, bw, bw+tb, ripple, atten) made = True except RuntimeError: ripple += 0.01 made = False print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) # Build in an exit strategy; if we've come this far, it ain't working. if(ripple >= 1.0): raise RuntimeError("optfir could not generate an appropriate filter.") self.pfb = gr.pfb_interpolator_ccf(self._interp, self._taps) self.connect(self, self.pfb) self.connect(self.pfb, self)
def __init__(self, rate, taps=None, flt_size=32, atten=100): gr.hier_block2.__init__(self, "pfb_arb_resampler_fff", gr.io_signature(1, 1, gr.sizeof_float), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature self._rate = rate self._size = flt_size if taps is not None: self._taps = taps else: # Create a filter that covers the full bandwidth of the input signal bw = 0.4 tb = 0.2 ripple = 0.1 #self._taps = gr.firdes.low_pass_2(self._size, self._size, bw, tb, atten) made = False while not made: try: self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten) made = True except RuntimeError: ripple += 0.01 made = False print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) # Build in an exit strategy; if we've come this far, it ain't working. if(ripple >= 1.0): raise RuntimeError("optfir could not generate an appropriate filter.") self.pfb = gr.pfb_arb_resampler_fff(self._rate, self._taps, self._size) #print "PFB has %d taps\n" % (len(self._taps),) self.connect(self, self.pfb) self.connect(self.pfb, self)
def __init__(self, channel_rate, audio_decim, deviation, audio_pass, audio_stop, gain=1.0, tau=75e-6): gr.hier_block2.__init__( self, "fm_demod_cf", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature k = channel_rate / (2 * pi * deviation) QUAD = gr.quadrature_demod_cf(k) audio_taps = optfir.low_pass( gain, # Filter gain channel_rate, # Sample rate audio_pass, # Audio passband audio_stop, # Audio stopband 0.1, # Passband ripple 60) # Stopband attenuation LPF = gr.fir_filter_fff(audio_decim, audio_taps) if tau is not None: DEEMPH = fm_deemph(channel_rate, tau) self.connect(self, QUAD, DEEMPH, LPF, self) else: self.connect(self, QUAD, LPF, self)
def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): """ Narrow Band FM Transmitter. Takes a single float input stream of audio samples in the range [-1,+1] and produces a single FM modulated complex baseband output. @param audio_rate: sample rate of audio stream, >= 16k @type audio_rate: integer @param quad_rate: sample rate of output stream @type quad_rate: integer @param tau: preemphasis time constant (default 75e-6) @type tau: float @param max_dev: maximum deviation in Hz (default 5e3) @type max_dev: float quad_rate must be an integer multiple of audio_rate. """ gr.hier_block2.__init__( self, "nbfm_tx", gr.io_signature(1, 1, gr.sizeof_float), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature # FIXME audio_rate and quad_rate ought to be exact rationals audio_rate = int(audio_rate) quad_rate = int(quad_rate) if quad_rate % audio_rate != 0: raise ValueError, "quad_rate is not an integer multiple of audio_rate" do_interp = audio_rate != quad_rate if do_interp: interp_factor = quad_rate / audio_rate interp_taps = optfir.low_pass( interp_factor, # gain quad_rate, # Fs 4500, # passband cutoff 7000, # stopband cutoff 0.1, # passband ripple dB 40) # stopband atten dB #print "len(interp_taps) =", len(interp_taps) self.interpolator = gr.interp_fir_filter_fff( interp_factor, interp_taps) self.preemph = fm_preemph(quad_rate, tau=tau) k = 2 * math.pi * max_dev / quad_rate self.modulator = gr.frequency_modulator_fc(k) if do_interp: self.connect(self, self.interpolator, self.preemph, self.modulator, self) else: self.connect(self, self.preemph, self.modulator, self)
def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3): """ Wide Band FM Transmitter. Takes a single float input stream of audio samples in the range [-1,+1] and produces a single FM modulated complex baseband output. @param audio_rate: sample rate of audio stream, >= 16k @type audio_rate: integer @param quad_rate: sample rate of output stream @type quad_rate: integer @param tau: preemphasis time constant (default 75e-6) @type tau: float @param max_dev: maximum deviation in Hz (default 75e3) @type max_dev: float quad_rate must be an integer multiple of audio_rate. """ gr.hier_block2.__init__( self, "wfm_tx", gr.io_signature(1, 1, gr.sizeof_float), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature # FIXME audio_rate and quad_rate ought to be exact rationals audio_rate = int(audio_rate) quad_rate = int(quad_rate) if quad_rate % audio_rate != 0: raise ValueError, "quad_rate is not an integer multiple of audio_rate" do_interp = audio_rate != quad_rate if do_interp: interp_factor = quad_rate / audio_rate interp_taps = optfir.low_pass( interp_factor, # gain quad_rate, # Fs 16000, # passband cutoff 18000, # stopband cutoff 0.1, # passband ripple dB 40) # stopband atten dB print "len(interp_taps) =", len(interp_taps) self.interpolator = gr.interp_fir_filter_fff( interp_factor, interp_taps) self.preemph = fm_preemph(quad_rate, tau=tau) k = 2 * math.pi * max_dev / quad_rate self.modulator = gr.frequency_modulator_fc(k) if do_interp: self.connect(self, self.interpolator, self.preemph, self.modulator, self) else: self.connect(self, self.preemph, self.modulator, self)
def __init__(self, numchans, taps=None, oversample_rate=1, atten=100): gr.hier_block2.__init__( self, "pfb_channelizer_ccf", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(numchans, numchans, gr.sizeof_gr_complex)) # Output signature self._numchans = numchans self._oversample_rate = oversample_rate if taps is not None: self._taps = taps else: # Create a filter that covers the full bandwidth of the input signal bw = 0.4 tb = 0.2 ripple = 0.1 made = False while not made: try: self._taps = optfir.low_pass(1, self._numchans, bw, bw + tb, ripple, atten) made = True except RuntimeError: ripple += 0.01 made = False print( "Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) # Build in an exit strategy; if we've come this far, it ain't working. if (ripple >= 1.0): raise RuntimeError( "optfir could not generate an appropriate filter.") self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._numchans) self.pfb = gr.pfb_channelizer_ccf(self._numchans, self._taps, self._oversample_rate) self.v2s = gr.vector_to_streams(gr.sizeof_gr_complex, self._numchans) self.connect(self, self.s2ss) for i in xrange(self._numchans): self.connect((self.s2ss, i), (self.pfb, i)) # Get independent streams from the filterbank and send them out self.connect(self.pfb, self.v2s) for i in xrange(self._numchans): self.connect((self.v2s, i), (self, i))
def __init__(self, fg, channel_rate, audio_decim, audio_pass, audio_stop): MAG = gr.complex_to_mag() DCR = gr.add_const_ff(-1.0) audio_taps = optfir.low_pass(0.5, # Filter gain channel_rate, # Sample rate audio_pass, # Audio passband audio_stop, # Audio stopband 0.1, # Passband ripple 60) # Stopband attenuation LPF = gr.fir_filter_fff(audio_decim, audio_taps) fg.connect(MAG, DCR, LPF) gr.hier_block.__init__(self, fg, MAG, LPF)
def __init__(self, channel_rate, audio_decim, audio_pass, audio_stop): gr.hier_block2.__init__(self, "am_demod_cf", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Input signature MAG = gr.complex_to_mag() DCR = gr.add_const_ff(-1.0) audio_taps = optfir.low_pass(0.5, # Filter gain channel_rate, # Sample rate audio_pass, # Audio passband audio_stop, # Audio stopband 0.1, # Passband ripple 60) # Stopband attenuation LPF = gr.fir_filter_fff(audio_decim, audio_taps) self.connect(self, MAG, DCR, LPF, self)
def __init__(self, channel_rate, audio_decim, deviation, audio_pass, audio_stop, gain=1.0, tau=75e-6): gr.hier_block2.__init__(self, "fm_demod_cf", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature k = channel_rate/(2*pi*deviation) QUAD = gr.quadrature_demod_cf(k) audio_taps = optfir.low_pass(gain, # Filter gain channel_rate, # Sample rate audio_pass, # Audio passband audio_stop, # Audio stopband 0.1, # Passband ripple 60) # Stopband attenuation LPF = gr.fir_filter_fff(audio_decim, audio_taps) if tau is not None: DEEMPH = fm_deemph(channel_rate, tau) self.connect(self, QUAD, DEEMPH, LPF, self) else: self.connect(self, QUAD, LPF, self)
def __init__(self, interp, taps=None, atten=100): gr.hier_block2.__init__( self, "pfb_interpolator_ccf", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._interp = interp self._taps = taps if taps is not None: self._taps = taps else: # Create a filter that covers the full bandwidth of the input signal bw = 0.4 tb = 0.2 ripple = 0.99 made = False while not made: try: self._taps = optfir.low_pass(self._interp, self._interp, bw, bw + tb, ripple, atten) made = True except RuntimeError: ripple += 0.01 made = False print( "Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) # Build in an exit strategy; if we've come this far, it ain't working. if (ripple >= 1.0): raise RuntimeError( "optfir could not generate an appropriate filter.") self.pfb = gr.pfb_interpolator_ccf(self._interp, self._taps) self.connect(self, self.pfb) self.connect(self.pfb, self)
def __init__(self, numchans, taps=None, oversample_rate=1, atten=100): gr.hier_block2.__init__(self, "pfb_channelizer_ccf", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(numchans, numchans, gr.sizeof_gr_complex)) # Output signature self._nchans = numchans self._oversample_rate = oversample_rate if taps is not None: self._taps = taps else: # Create a filter that covers the full bandwidth of the input signal bw = 0.4 tb = 0.2 ripple = 0.1 made = False while not made: try: self._taps = optfir.low_pass(1, self._nchans, bw, bw+tb, ripple, atten) made = True except RuntimeError: ripple += 0.01 made = False print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) # Build in an exit strategy; if we've come this far, it ain't working. if(ripple >= 1.0): raise RuntimeError("optfir could not generate an appropriate filter.") self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._nchans) self.pfb = pfb_channelizer_ccf(self._nchans, self._taps, self._oversample_rate) self.connect(self, self.s2ss) for i in xrange(self._nchans): self.connect((self.s2ss,i), (self.pfb,i)) self.connect((self.pfb,i), (self,i))
def __init__(self, options, queue): gr.top_block.__init__(self, "usrp_flex") self.options = options self.offset = 0.0 self.adj_time = time.time() self.verbose = options.verbose if options.from_file is None: # Set up USRP source self.u = uhd.usrp_source(device_addr=options.address, stream_args=uhd.stream_args('fc32')) # Grab 250 KHz of spectrum # (A UHD facility to get sample rate range and granularity would be useful) self.u.set_samp_rate(250e3) rate = self.u.get_samp_rate() if rate != 250e3: print "Unable to set required sample rate of 250 Ksps (got %f)" % rate sys.exit(1) # Tune daughterboard r = self.u.set_center_freq(options.freq + options.calibration, 0) if not r: frange = self.u.get_freq_range() sys.stderr.write(("\nRequested frequency (%f) out or range [%f, %f]\n") % \ (freq, frange.start(), frange.stop())) sys.exit(1) # if no gain was specified, use the mid-point in dB if options.rx_gain is None: grange = self.u.get_gain_range() options.rx_gain = float(grange.start() + grange.stop()) / 2.0 print "\nNo gain specified." print "Setting gain to %f (from [%f, %f])" % \ (options.rx_gain, grange.start(), grange.stop()) self.u.set_gain(options.rx_gain, 0) else: # Use supplied file as source of samples self.u = gr.file_source(gr.sizeof_gr_complex, options.from_file) if options.verbose: print "Reading samples from", options.from_file if options.log and not options.from_file: usrp_sink = gr.file_sink(gr.sizeof_gr_complex, 'usrp.dat') self.connect(self.u, usrp_sink) # Set up 22KHz-wide bandpass about center frequency. Decimate by 10 # to get channel rate of 25Ksps taps = optfir.low_pass( 1.0, # Filter gain 250e3, # Sample rate 11000, # One-sided modulation bandwidth 12500, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation if options.verbose: print "Channel filter has", len(taps), "taps." self.chan = gr.freq_xlating_fir_filter_ccf( 10, # Decimation rate taps, # Filter taps 0.0, # Offset frequency 250e3) # Sample rate if options.log: chan_sink = gr.file_sink(gr.sizeof_gr_complex, 'chan.dat') self.connect(self.chan, chan_sink) # FLEX protocol demodulator self.flex = pager.flex_demod(queue, options.freq, options.verbose, options.log) self.connect(self.u, self.chan, self.flex)
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) parser=OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-f", "--freq", type="eng_float", default=137.5e6, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 200 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 4 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(),) chan_filt_coeffs = optfir.low_pass (1, # gain usrp_rate, # sampling rate 40e3, # passband cutoff 60e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) self.volume_control = gr.multiply_const_ff(self.vol) # sound card as final sink audio_sink = audio.sink (int (audio_rate), options.audio_output) # now wire it all together self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0]+g[1])/2 if options.volume is None: g = self.volume_range() options.volume = float(g[0]+g[1])/2 if abs(options.freq) < 1e6: options.freq *= 1e6 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self, options, queue): gr.top_block.__init__(self, "usrp_flex") self.options = options self.offset = 0.0 self.file_offset = 0.0 self.adj_time = time.time() self.verbose = options.verbose if options.from_file is None: # Set up USRP source with specified RX daughterboard self.src = usrp.source_c() if options.rx_subdev_spec == None: options.rx_subdev_spec = usrp.pick_rx_subdevice(self.src) self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec) self.src.set_mux( usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec)) # set FPGA decimation rate self.src.set_decim_rate(options.decim) # If no gain specified, set to midrange if options.gain is None: g = self.subdev.gain_range() options.gain = (g[0] + g[1]) / 2.0 self.subdev.set_gain(options.gain) # Tune daughterboard actual_frequency = options.frequency + options.calibration tune_result = usrp.tune(self.src, 0, self.subdev, actual_frequency) if not tune_result: sys.stderr.write("Failed to set center frequency to " + ` actual_frequency ` + "\n") sys.exit(1) if options.verbose: print "Using RX daughterboard", self.subdev.side_and_name() print "USRP gain is", options.gain print "USRP tuned to", actual_frequency else: # Use supplied file as source of samples self.file_offset = options.calibration print "File input offset", self.offset self.src = gr.file_source(gr.sizeof_gr_complex, options.from_file) if options.verbose: print "Reading samples from", options.from_file if options.log and not options.from_file: usrp_sink = gr.file_sink(gr.sizeof_gr_complex, 'usrp.dat') self.connect(self.src, usrp_sink) # following is rig to allow fast and easy swapping of signal configuration # blocks between this example and the oscope example which uses self.msgq self.msgq = queue #------------------------------------------------------------------------------- if options.protocol == 0: # ---------- RD-LAP 19.2 kbps (9600 ksps), 25kHz channel, self.symbol_rate = 9600 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps self.channel_decimation = 10 # decimation (final rate should be at least several symbol rate) self.max_frequency_offset = 12000.0 # coarse carrier tracker leash, ~ half a channel either way self.symbol_deviation = 1200.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = 64e6 / options.decim # for USRP: 64MHz / FPGA decimation rate self.protocol_processing = fsk4.rdlap_f( self.msgq, 0) # desired protocol processing block selected here self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter characteristics channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 10000, # One-sided modulation bandwidth 12000, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter characteristics symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type if options.protocol == 1: # ---------- APCO-25 C4FM Test Data self.symbol_rate = 4800 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps self.channel_decimation = 20 # decimation self.max_frequency_offset = 6000.0 # coarse carrier tracker leash self.symbol_deviation = 600.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = 64e6 / options.decim # for USRP: 64MHz / FPGA decimation rate self.protocol_processing = fsk4.apco25_f(self.msgq, 0) self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 5000, # One-sided modulation bandwidth 6500, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type # ---------- End of configuration if options.verbose: print "Channel filter has", len(channel_taps), "taps." self.chan = gr.freq_xlating_fir_filter_ccf( self.channel_decimation, # Decimation rate channel_taps, # Filter taps 0.0, # Offset frequency self.input_sample_rate) # Sample rate # also note: # this specifies the nominal frequency deviation for the 4-level fsk signal self.fm_demod_gain = self.channel_rate / (2.0 * pi * self.symbol_deviation) self.fm_demod = gr.quadrature_demod_cf(self.fm_demod_gain) symbol_decim = 1 self.symbol_filter = gr.fir_filter_fff(symbol_decim, symbol_coeffs) # eventually specify: sample rate, symbol rate self.demod_fsk4 = fsk4.demod_ff(self.msgq, self.channel_rate, self.symbol_rate) if options.log: chan_sink = gr.file_sink(gr.sizeof_gr_complex, 'chan.dat') self.connect(self.chan, chan_sink) if options.log: chan_sink2 = gr.file_sink(gr.sizeof_float, 'demod.dat') self.connect(self.demod_fsk4, chan_sink2) self.connect(self.src, self.chan, self.fm_demod, self.symbol_filter, self.demod_fsk4, self.protocol_processing)
def __init__(self): 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("", "--spec", type="string", default="A:0 A:0", 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("", "--f1", type="eng_float", default=100.7e6, help="set 1st station frequency to FREQ", metavar="FREQ") parser.add_option("", "--f2", type="eng_float", default=102.5e6, help="set 2nd station freq 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("-O", "--audio-output", type="string", default="default", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") parser.add_option("", "--freq-min", type="eng_float", default=87.9e6, help="Set a minimum frequency [default=%default]") parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) if abs(options.f1 - options.f2) > 5.5e6: print "Sorry, two stations must be within 5.5MHz of each other" raise SystemExit f = (options.f1, options.f2) self.vol = .1 self.state = "FREQ" self.fm_freq_min = options.freq_min self.fm_freq_max = options.freq_max # build graph stream_args = uhd.stream_args('fc32', channels=range(2)) self.u = uhd.usrp_source(device_addr=options.args, stream_args=stream_args) # Set front end channel mapping self.u.set_subdev_spec(options.spec) usrp_rate = 320e3 demod_rate = 320e3 audio_rate = 32e3 audio_decim = int(demod_rate / audio_rate) self.u.set_samp_rate(usrp_rate) dev_rate = self.u.get_samp_rate() # Make sure dboard can suppor the required frequencies frange = self.u.get_freq_range() if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): sys.stderr.write("Radio does not support required frequency range.\n") sys.exit(1) # sound card as final sink self.audio_sink = audio.sink(int(audio_rate), options.audio_output) # taps for channel filter nfilts = 32 chan_coeffs = optfir.low_pass (nfilts, # gain nfilts*usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation rrate = usrp_rate / dev_rate # set front end PLL to middle frequency mid_freq = (f[0] + f[1]) / 2.0 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.0 for n in range(2): chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) guts = blks2.wfm_rcv (demod_rate, audio_decim) volume_control = gr.multiply_const_ff(self.vol) #self.connect((self.di, n), chan_filt) self.connect((self.u, n), chan_filt) self.connect(chan_filt, guts, volume_control) self.connect(volume_control, (self.audio_sink, n)) # Test the the requested frequencies are in range if(f[n] < self.fm_freq_min or f[n] > self.fm_freq_max): sys.stderr.write("Requested frequency is outside of required frequency range.\n") sys.exit(1) # Tune each channel by setting the RF freq to mid_freq and the # DDC freq to f[n]. tr = uhd.tune_request(f[n], rf_freq=mid_freq, rf_freq_policy=uhd.tune_request.POLICY_MANUAL) self.u.set_center_freq(tr, n) # Set gain for each channel self.set_gain(options.gain, n) # Set the antenna if(options.antenna): self.u.set_antenna(options.antenna, n)
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) parser = OptionParser(option_class=eng_option) parser.add_option("-e", "--interface", type="string", default="eth0", help="select Ethernet interface, default is eth0") parser.add_option("-m", "--mac-addr", type="string", default="", help="select USRP by MAC address, default is auto-select") #parser.add_option("-A", "--antenna", default=None, # help="select Rx Antenna (only on RFX-series boards)") parser.add_option("-f", "--freq", type="eng_float", default=100.1, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph self.u = usrp2.source_32fc(options.interface, options.mac_addr) adc_rate = self.u.adc_rate() # 100 MS/s usrp_decim = 312 self.u.set_decim(usrp_decim) usrp_rate = adc_rate / usrp_decim # ~320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # ~32 kHz #FIXME: need named constants and text descriptions available to (gr-)usrp2 even #when usrp(1) module is not built. A usrp_common module, perhaps? dbid = self.u.daughterboard_id() print "Using RX d'board 0x%04X" % (dbid,) if not (dbid == 0x0001 or #usrp_dbid.BASIC_RX dbid == 0x0003 or #usrp_dbid.TV_RX dbid == 0x000c or #usrp_dbid.TV_RX_REV_2 dbid == 0x0040 or #usrp_dbid.TV_RX_REV_3 dbid == 0x0043 or #usrp_dbid.TV_RX_MIMO dbid == 0x0044 or #usrp_dbid.TV_RX_REV_2_MIMO dbid == 0x0045 ): #usrp_dbid.TV_RX_REV_3_MIMO print "This daughterboard does not cover the required frequency range" print "for this application. Please use a BasicRX or TVRX daughterboard." raw_input("Press ENTER to continue anyway, or Ctrl-C to exit.") chan_filt_coeffs = optfir.low_pass (1, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) self.volume_control = gr.multiply_const_ff(self.vol) # sound card as final sink audio_sink = audio.sink (int (audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.u.gain_range() options.gain = float(g[0]+g[1])/2 if options.volume is None: g = self.volume_range() options.volume = float(g[0]+g[1])/2 if abs(options.freq) < 1e6: options.freq *= 1e6 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self): gr.top_block.__init__ (self) parser=OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-f", "--freq", type="eng_float", default=91.2e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB") parser.add_option("-s", "--squelch", type="eng_float", default=0, help="set squelch level (default is 0)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) # connect to USRP usrp_decim = 250 self.u = usrp.source_c(0, usrp_decim) print "USRP Serial: ", self.u.serial_number() demod_rate = self.u.adc_rate() / usrp_decim # 256 kS/s audio_decim = 8 audio_rate = demod_rate / audio_decim # 32 kS/s if options.rx_subdev_spec is None: options.rx_subdev_spec = usrp.pick_subdev(self.u, dblist) self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using d'board", self.subdev.side_and_name() # gain, volume, frequency self.gain = options.gain if options.gain is None: self.gain = self.subdev.gain_range()[1] self.vol = options.volume if self.vol is None: g = self.volume_range() self.vol = float(g[0]+g[1])/2 self.freq = options.freq if abs(self.freq) < 1e6: self.freq *= 1e6 print "Volume:%r, Gain:%r, Freq:%3.1f MHz" % (self.vol, self.gain, self.freq/1e6) # channel filter, wfm_rcv_pll chan_filt_coeffs = optfir.low_pass( 1, # gain demod_rate, # rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation self.chan_filt = gr.fir_filter_ccf (1, chan_filt_coeffs) self.guts = blks2.wfm_rcv_pll (demod_rate, audio_decim) self.connect(self.u, self.chan_filt, self.guts) # volume control, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) self.audio_sink = audio.sink(int(audio_rate), options.audio_output, False) self.connect ((self.guts, 0), self.volume_control_l, (self.audio_sink, 0)) self.connect ((self.guts, 1), self.volume_control_r, (self.audio_sink, 1)) # pilot channel filter (band-pass, 18.5-19.5kHz) pilot_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 18.5e3, # low cutoff 19.5e3, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) self.connect(self.guts.fm_demod, self.pilot_filter) # RDS channel filter (band-pass, 54-60kHz) rds_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 54e3, # low cutoff 60e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) self.connect(self.guts.fm_demod, self.rds_filter) # create 57kHz subcarrier from 19kHz pilot, downconvert RDS channel self.mixer = gr.multiply_ff() self.connect(self.pilot_filter, (self.mixer, 0)) self.connect(self.pilot_filter, (self.mixer, 1)) self.connect(self.pilot_filter, (self.mixer, 2)) self.connect(self.rds_filter, (self.mixer, 3)) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(1, rds_bb_filter_coeffs) self.connect(self.mixer, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.rds_clock = rds.freq_divider(16) clock_taps = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HANN) self.clock_filter = gr.fir_filter_fff(1, clock_taps) self.connect(self.pilot_filter, self.rds_clock, self.clock_filter) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(demod_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.clock_filter, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) # set initial values self.subdev.set_gain(self.gain) self.set_vol(self.vol) self.set_freq(self.freq)
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel parser = OptionParser (option_class=eng_option) #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), # help="select USRP Rx side A or B (default=A)") parser.add_option("-d", "--decim", type="int", default=128, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, help="set frequency to FREQ [default=%default])", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=20, help="set gain in dB [default=%default]") parser.add_option("-F", "--filter", action="store_true", default=True, help="Enable channel filter") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit nchan = 4 if options.filter: sw_decim = 4 else: sw_decim = 1 self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") if self.u.nddcs() < nchan: sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( nchan, self.u.nddcs())) raise SystemExit if not self.u.set_nchannels(nchan): sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) raise SystemExit input_rate = self.u.adc_freq() / self.u.decim_rate() print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),) self.subdev = self.u.db(0) + self.u.db(1) if (len(self.subdev) < 4 or self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX): sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') sys.exit(1) self.u.set_mux(gru.hexint(0xf3f2f1f0)) # deinterleave four channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) self.connect(self.u, di) # our destination (8 float inputs) self.scope = scopesink2.scope_sink_f(panel, sample_rate=input_rate/sw_decim, num_inputs=2*nchan) # taps for channel filter chan_filt_coeffs = optfir.low_pass (1, # gain input_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) # bust the deinterleaved complex channels into floats for i in range(nchan): if options.filter: chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) c2f = gr.complex_to_float() self.connect((di, i), chan_filt, c2f) else: c2f = gr.complex_to_float() self.connect((di, i), c2f) self.connect((c2f, 0), (self.scope, 2*i + 0)) self.connect((c2f, 1), (self.scope, 2*i + 1)) self._build_gui(vbox) self.set_gain(options.gain) self.set_freq(options.freq)
def __init__( self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__( self, frame, panel, vbox, argv) self.frame = frame self.panel = panel self.offset = 0.0 # Channel frequency offset parser = OptionParser(option_class=eng_option) parser.add_option("-p", "--protocol", type="int", default=1, help="set protocol: 0 = RDLAP 19.2kbps; 1 = APCO25 (default)") parser.add_option("-g", "--gain", type="eng_float", default=1.0, help="set linear input gain (default: %default)") parser.add_option("-x", "--freq-translation", type="eng_float", default=0.0, help="initial channel frequency translation") parser.add_option("-n", "--frame-decim", type="int", default=1, help="set oscope frame decimation factor to n [default=1]") parser.add_option("-v", "--v-scale", type="eng_float", default=5000, help="set oscope initial V/div to SCALE [default=%default]") parser.add_option("-t", "--t-scale", type="eng_float", default=49e-6, help="set oscope initial s/div to SCALE [default=50us]") parser.add_option("-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp") parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, help="set sample rate to RATE (default: %default)") parser.add_option("-d", "--channel-decim", type="int", default=None, help="set channel decimation factor to n [default depends on protocol]") parser.add_option("-w", "--wav-file", type="string", default=None, help="WAV input path") parser.add_option("-f", "--data-file", type="string", default=None, help="Data input path") parser.add_option("-B", "--base-band", action="store_true", default=False) parser.add_option("-R", "--repeat", action="store_true", default=False) parser.add_option("-o", "--wav-out", type="string", default=None, help="WAV output path") parser.add_option("-G", "--wav-out-gain", type="eng_float", default=0.05, help="set WAV output gain (default: %default)") parser.add_option("-F", "--data-out", type="string", default=None, help="Data output path") parser.add_option("-C", "--carrier-freq", type="eng_float", default=None, help="set data output carrier frequency to FREQ", metavar="FREQ") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.options = options if options.wav_file is not None: #try: self.input_file = gr.wavfile_source(options.wav_file, options.repeat) #except: # print "WAV file not found or not a WAV file" # sys.exit(1) print "WAV input: %i Hz, %i bits, %i channels" % (self.input_file.sample_rate(), self.input_file.bits_per_sample(), self.input_file.channels()) self.sample_rate = self.input_file.sample_rate() self.input_stream = gr.throttle(gr.sizeof_float, self.sample_rate) self.connect(self.input_file, self.input_stream) self.src = gr.multiply_const_ff(options.gain) elif options.data_file is not None: if options.base_band: sample_size = gr.sizeof_float print "Data file is baseband (float)" self.src = gr.multiply_const_ff(options.gain) else: sample_size = gr.sizeof_gr_complex print "Data file is IF (complex)" self.src = gr.multiply_const_cc(options.gain) self.input_file = gr.file_source(sample_size, options.data_file, options.repeat) self.sample_rate = options.sample_rate # E.g. 250000 print "Data file sampling rate = " + str(self.sample_rate) self.input_stream = gr.throttle(sample_size, self.sample_rate) self.connect(self.input_file, self.input_stream) else: self.sample_rate = options.sample_rate print "Soundcard sampling rate = " + str(self.sample_rate) self.input_stream = audio.source(self.sample_rate, options.audio_input) # float samples self.src = gr.multiply_const_ff(options.gain) print "Fixed input gain = " + str(options.gain) self.connect(self.input_stream, self.src) if options.wav_out is not None: output_rate = int(self.sample_rate) if options.channel_decim is not None: output_rate /= options.channel_decim self.wav_out = gr.wavfile_sink(options.wav_out, 1, output_rate, 16) print "Opened WAV output file: " + options.wav_out + " at rate: " + str(output_rate) else: self.wav_out = None if options.data_out is not None: if options.carrier_freq is None: self.data_out = gr.file_sink(gr.sizeof_float, options.data_out) print "Opened float data output file: " + options.data_out else: self.data_out = gr.file_sink(gr.sizeof_gr_complex, options.data_out) print "Opened complex data output file: " + options.data_out else: self.data_out = None self.num_inputs = 1 input_rate = self.sample_rate #title='IF', #size=(1024,800), if (options.data_file is not None) and (options.base_band == False): self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate, frame_decim=options.frame_decim, v_scale=options.v_scale, t_scale=options.t_scale, num_inputs=self.num_inputs) else: self.scope = scopesink2.scope_sink_f(panel, sample_rate=input_rate, frame_decim=options.frame_decim, v_scale=options.v_scale, t_scale=options.t_scale, num_inputs=self.num_inputs) #self.di = gr.deinterleave(gr.sizeof_float) #self.di = gr.complex_to_float(1) #self.di = gr.complex_to_imag() #self.dr = gr.complex_to_real() #self.connect(self.src,self.dr) #self.connect(self.src,self.di) #self.null = gr.null_sink(gr.sizeof_double) #self.connect(self.src,self.di) #self.connect((self.di,0),(self.scope,0)) #self.connect((self.di,1),(self.scope,1)) #self.connect(self.dr,(self.scope,0)) #self.connect(self.di,(self.scope,1)) self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages self.queue_watcher = queue_watcher(self.msgq, self.adjust_freq_norm) #------------------------------------------------------------------------------- if options.protocol == 0: # ---------- RD-LAP 19.2 kbps (9600 ksps), 25kHz channel, print "RD-LAP selected" self.symbol_rate = 9600 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps if options.channel_decim is None: self.channel_decimation = 10 # decimation (final rate should be at least several symbol rate) else: self.channel_decimation = options.channel_decim self.max_frequency_offset = 12000.0 # coarse carrier tracker leash, ~ half a channel either way self.symbol_deviation = 1200.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = self.sample_rate self.protocol_processing = fsk4.rdlap_f(self.msgq, 0) # desired protocol processing block selected here self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter characteristics channel_taps = optfir.low_pass(1.0, # Filter gain self.input_sample_rate, # Sample rate 10000, # One-sided modulation bandwidth 12000, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter characteristics symbol_coeffs = gr.firdes.root_raised_cosine (1.0, # gain self.channel_rate , # sampling rate self.symbol_rate, # symbol rate 0.2, # alpha 500) # taps if options.protocol == 1: # ---------- APCO-25 C4FM Test Data print "APCO selected" self.symbol_rate = 4800 # symbol rate if options.channel_decim is None: self.channel_decimation = 20 # decimation else: self.channel_decimation = options.channel_decim self.max_frequency_offset = 6000.0 # coarse carrier tracker leash self.symbol_deviation = 600.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = self.sample_rate self.protocol_processing = fsk4.apco25_f(self.msgq, 0) self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter if (options.data_file is not None) and (options.base_band == False): channel_taps = optfir.low_pass(1.0, # Filter gain self.input_sample_rate, # Sample rate 5000, # One-sided modulation bandwidth 6500, # One-sided channel bandwidth 0.2, # Passband ripple (was 0.1) 60) # Stopband attenuation else: channel_taps = None # symbol shaping filter symbol_coeffs = gr.firdes.root_raised_cosine (1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # alpha 500) # taps # ----------------- End of setup block print "Input rate = " + str(self.input_sample_rate) print "Channel decimation = " + str(self.channel_decimation) print "Channel rate = " + str(self.channel_rate) if channel_taps is not None: self.chan = gr.freq_xlating_fir_filter_ccf(self.channel_decimation, # Decimation rate channel_taps, # Filter taps 0.0, # Offset frequency self.input_sample_rate) # Sample rate if (options.freq_translation != 0): print "Channel center frequency = " + str(options.freq_translation) self.chan.set_center_freq(options.freq_translation) else: self.chan = None if options.carrier_freq is not None: print "Carrier frequency = " + str(options.carrier_freq) self.sig_carrier = gr.sig_source_c(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, 0) self.carrier_mul = gr.multiply_vcc(1) # cc(gr.sizeof_gr_complex) self.connect(self.sig_carrier, (self.carrier_mul, 0)) self.connect(self.chan, (self.carrier_mul, 1)) self.sig_i_carrier = gr.sig_source_f(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, 0) self.sig_q_carrier = gr.sig_source_f(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, (pi / 2.0)) self.carrier_i_mul = gr.multiply_ff(1) self.carrier_q_mul = gr.multiply_ff(1) self.iq_to_float = gr.complex_to_float(1) self.carrier_iq_add = gr.add_ff(1) self.connect(self.carrier_mul, self.iq_to_float) self.connect((self.iq_to_float, 0), (self.carrier_i_mul, 0)) self.connect((self.iq_to_float, 1), (self.carrier_q_mul, 0)) self.connect(self.sig_i_carrier, (self.carrier_i_mul, 1)) self.connect(self.sig_q_carrier, (self.carrier_q_mul, 1)) self.connect(self.carrier_i_mul, (self.carrier_iq_add, 0)) self.connect(self.carrier_q_mul, (self.carrier_iq_add, 1)) else: self.sig_carrier = None self.carrier_mul = None #lf_channel_taps = optfir.low_pass(1.0, # Filter gain # self.input_sample_rate, # Sample rate # 2500, # One-sided modulation bandwidth # 3250, # One-sided channel bandwidth # 0.1, # Passband ripple (0.1) # 60, # Stopband attenuation # 9) # Extra taps (default 2, which doesn't work at 48kHz) #self.lf = gr.fir_filter_fff(self.channel_decimation, lf_channel_taps) self.scope2 = scopesink2.scope_sink_f(panel, sample_rate=self.symbol_rate, frame_decim=1, v_scale=2, t_scale=0.025, num_inputs=self.num_inputs) # also note: this specifies the nominal frequency deviation for the 4-level fsk signal self.fm_demod_gain = self.channel_rate / (2.0 * pi * self.symbol_deviation) self.fm_demod = gr.quadrature_demod_cf(self.fm_demod_gain) symbol_decim = 1 self.symbol_filter = gr.fir_filter_fff(symbol_decim, symbol_coeffs) # eventually specify: sample rate, symbol rate self.demod_fsk4 = fsk4.demod_ff(self.msgq, self.channel_rate, self.symbol_rate) if (self.chan is not None): self.connect(self.src, self.chan, self.fm_demod, self.symbol_filter, self.demod_fsk4, self.protocol_processing) if options.wav_out is not None: print "WAV output gain = " + str(options.wav_out_gain) self.scaled_wav_data = gr.multiply_const_ff(float(options.wav_out_gain)) self.connect(self.scaled_wav_data, self.wav_out) if self.carrier_mul is None: self.connect(self.fm_demod, self.scaled_wav_data) else: self.connect(self.carrier_iq_add, self.scaled_wav_data) if self.data_out is not None: if self.carrier_mul is None: self.connect(self.fm_demod, self.data_out) else: self.connect(self.carrier_mul, self.data_out) # During signal, -4..4 #self.connect(self.fm_demod, self.scope2) else: self.connect(self.src, self.symbol_filter, self.demod_fsk4, self.protocol_processing) self.connect(self.src, self.scope) #self.connect(self.lf, self.scope) self.connect(self.demod_fsk4, self.scope2) #self.connect(self.symbol_filter, self.scope2) # --------------- End of most of the 4L-FSK hack & slash self._build_gui(vbox) # set initial values if options.gain is None: options.gain = 0 self.set_gain(options.gain)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), # help="select USRP Rx side A or B (default=A)") parser.add_option( "-d", "--decim", type="int", default=128, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, help="set frequency to FREQ [default=%default])", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=20, help="set gain in dB [default=%default]") parser.add_option("-F", "--filter", action="store_true", default=True, help="Enable channel filter") parser.add_option("-o", "--output", type="string", default=None, help="set output basename") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit if options.output is None: parser.print_help() sys.stderr.write( "You must provide an output filename base with -o OUTPUT\n") raise SystemExit else: basename = options.output nchan = 4 nsecs = 4.0 if options.filter: sw_decim = 4 else: sw_decim = 1 self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") if self.u.nddcs() < nchan: sys.stderr.write( 'This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % (nchan, self.u.nddcs())) raise SystemExit if not self.u.set_nchannels(nchan): sys.stderr.write('set_nchannels(%d) failed\n' % (nchan, )) raise SystemExit input_rate = self.u.adc_freq() / self.u.decim_rate() print "USB data rate = %s" % (eng_notation.num_to_str(input_rate), ) sink_data_rate = input_rate / sw_decim print "Scope data rate = %s" % ( eng_notation.num_to_str(sink_data_rate), ) self.subdev = self.u.db(0) + self.u.db(1) if (len(self.subdev) < 4 or self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or self.u.db(1, 0).dbid() != usrp_dbid.BASIC_RX): sys.stderr.write( 'This code requires a Basic Rx board on Sides A & B\n') sys.exit(1) self.u.set_mux(gru.hexint(0xf3f2f1f0)) # collect 1 second worth of data limit = int(nsecs * input_rate * nchan) print "limit = ", limit head = gr.head(gr.sizeof_gr_complex, limit) # deinterleave four channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) self.connect(self.u, head, di) # taps for channel filter chan_filt_coeffs = optfir.low_pass( 1, # gain input_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) for i in range(nchan): sink = gr.file_sink( gr.sizeof_gr_complex, basename + ("-%s-%d.dat" % (eng_notation.num_to_str(sink_data_rate), i))) if options.filter: chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) self.connect((di, i), chan_filt, sink) else: self.connect((di, i), sink) self.set_gain(options.gain) self.set_freq(options.freq)
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) parser = OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-f", "--freq", type="eng_float", default=137.5e6, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 200 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 4 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux( usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(), ) chan_filt_coeffs = optfir.low_pass( 1, # gain usrp_rate, # sampling rate 40e3, # passband cutoff 60e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) self.guts = blks2.wfm_rcv(demod_rate, audio_decimation) self.volume_control = gr.multiply_const_ff(self.vol) # sound card as final sink audio_sink = audio.sink(int(audio_rate), options.audio_output) # now wire it all together self.connect(self.u, chan_filt, self.guts, self.volume_control, audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0] + g[1]) / 2 if options.volume is None: g = self.volume_range() options.volume = float(g[0] + g[1]) / 2 if abs(options.freq) < 1e6: options.freq *= 1e6 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel parser = OptionParser(option_class=eng_option) parser.add_option("-c", "--calibration", type="eng_float", default=0, help="frequency offset", metavar="Hz") parser.add_option("-i", "--input", default="baseband.dat", help="specify input file") parser.add_option("-r", "--repeat", action="store_true", default=False, help="repeat in a loop") parser.add_option("-s", "--sample-rate", type="eng_float", default=0, help="sample rate") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) sample_rate = options.sample_rate symbol_rate = 4800 resample_rate = symbol_rate * 4 FILE = gr.file_source(gr.sizeof_gr_complex, options.input, options.repeat) THROTTLE = gr.throttle(gr.sizeof_gr_complex, sample_rate) # resample to new rate = resample_rate nphases = 64 frac_bw = 0.25 rs_taps = gr.firdes.low_pass(nphases, nphases, frac_bw, 0.5 - frac_bw) #rs_rate = sample_rate / float(resample_rate) rs_rate = resample_rate / float(sample_rate) RESAMP = blks2.pfb_arb_resampler_ccf( rs_rate, (rs_taps), nphases, ) channel_taps = optfir.low_pass(1.0, resample_rate, 6500, 8000, 0.1, 60) TUNE = gr.freq_xlating_fir_filter_ccf(1, channel_taps, options.calibration, resample_rate) # get magnitude squared P = gr.complex_to_mag_squared() # plot FFT SCOPE = fftsink2.fft_sink_f(panel, fft_size=2048, sample_rate=resample_rate) self.connect(FILE, THROTTLE, RESAMP, TUNE, P, SCOPE) vbox.Add(SCOPE.win, 10, wx.EXPAND)
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) parser=OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-f", "--freq", type="eng_float", default=100.1e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=40, help="set gain in dB (default is midpoint)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 200 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim sca_chanfilt_decim = 5 sca_demod_rate = demod_rate / sca_chanfilt_decim #64 kHz audio_decimation = 2 audio_rate = sca_demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(),) #Create filter to get main FM Channel we want chan_filt_coeffs = optfir.low_pass (1, # gain usrp_rate, # sampling rate 100e3, # passband cutoff 140e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) #Create demodulator block for Main FM Channel max_dev = 75e3 fm_demod_gain = demod_rate/(2*math.pi*max_dev) self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain) # Note - deemphasis is not applied to the Main FM Channel as main audio is not decoded # SCA Devation is 10% of carrier but some references say 20% if mono with one SCA (6 KHz seems typical) max_sca_dev = 6e3 # Create filter to get SCA channel we want sca_chan_coeffs = gr.firdes.low_pass (1.0, # gain demod_rate, # sampling rate max_sca_dev, # low pass cutoff freq max_sca_dev/3, # width of trans. band gr.firdes.WIN_HANN) # filter type self.ddc = gr.freq_xlating_fir_filter_fcf(sca_chanfilt_decim, # decimation rate sca_chan_coeffs, # taps 0, # frequency translation amount (Gets set by the UI) demod_rate) # input sample rate #Create demodulator block for SCA Channel sca_demod_gain = sca_demod_rate/(2*math.pi*max_sca_dev) self.fm_demod_sca = gr.quadrature_demod_cf (sca_demod_gain) # SCA analog audio is bandwidth limited to 5 KHz max_sca_audio_freq = 5.0e3 # SCA analog deephasis is 150 uS (75 uS may be used) sca_tau = 150e-6 # compute FIR filter taps for SCA audio filter audio_coeffs = gr.firdes.low_pass (1.0, # gain sca_demod_rate, # sampling rate max_sca_audio_freq, # low pass cutoff freq max_sca_audio_freq/2.5, # width of trans. band gr.firdes.WIN_HAMMING) # input: float; output: float self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) # Create deemphasis block that is applied after SCA demodulation self.deemph = fm_deemph (audio_rate, sca_tau) self.volume_control = gr.multiply_const_ff(self.vol) # sound card as final sink audio_sink = audio.sink (int (audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect (self.u, chan_filt, self.fm_demod, self.ddc, self.fm_demod_sca) self.connect (self.fm_demod_sca, self.audio_filter, self.deemph, self.volume_control, audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, sca_demod_rate, audio_rate) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0]+g[1])/2 if options.volume is None: g = self.volume_range() options.volume = float(g[0]+g[1])/2 if abs(options.freq) < 1e6: options.freq *= 1e6 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") self.set_sca_freq(67000) # A common SCA Frequency
def __init__(self): gr.top_block.__init__(self) parser=OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("", "--f1", type="eng_float", default=100.7e6, help="set 1st station frequency to FREQ", metavar="FREQ") parser.add_option("", "--f2", type="eng_float", default=102.5e6, help="set 2nd station freq to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=40, help="set gain in dB (default is midpoint)") 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 abs(options.f1) < 1e6: options.f1 *= 1e6 if abs(options.f2) < 1e6: options.f2 *= 1e6 if abs(options.f1 - options.f2) > 5.5e6: print "Sorry, two stations must be within 5.5MHz of each other" raise SystemExit f = (options.f1, options.f2) self.vol = .1 self.state = "FREQ" # build graph self.u = usrp.source_c(0, nchan=2) # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 200 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) mv = usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec) mv |= (mv << 8) & 0xff00 # both DDC inputs setup same way self.u.set_mux(mv) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(),) # deinterleave two channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) # wire up the head of the chain self.connect(self.u, di) # sound card as final sink audio_sink = audio.sink(int(audio_rate), options.audio_output) # taps for channel filter chan_filt_coeffs = optfir.low_pass (1, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) mid_freq = (f[0] + f[1]) / 2 # set front end PLL to middle frequency ok, baseband_freq = self.subdev.set_freq(mid_freq) for n in range(2): chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) guts = blks2.wfm_rcv (demod_rate, audio_decimation) volume_control = gr.multiply_const_ff(self.vol) self.connect((di, n), chan_filt) self.connect(chan_filt, guts, volume_control) self.connect(volume_control, (audio_sink, n)) dxc_freq, inverted = usrp.calc_dxc_freq(f[n], baseband_freq, self.u.converter_rate()) self.u.set_rx_freq(n, dxc_freq) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0]+g[1])/2 # set initial values self.set_gain(options.gain)
def __init__(self): gr.flow_graph.__init__(self) parser = OptionParser (option_class=eng_option) #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), # help="select USRP Rx side A or B (default=A)") parser.add_option("-d", "--decim", type="int", default=128, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, help="set frequency to FREQ [default=%default])", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=20, help="set gain in dB [default=%default]") parser.add_option("-F", "--filter", action="store_true", default=True, help="Enable channel filter") parser.add_option("-o", "--output", type="string", default=None, help="set output basename") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit if options.output is None: parser.print_help() sys.stderr.write("You must provide an output filename base with -o OUTPUT\n") raise SystemExit else: basename = options.output nchan = 4 nsecs = 4.0 if options.filter: sw_decim = 4 else: sw_decim = 1 self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") if self.u.nddc() < nchan: sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( nchan, self.u.nddc())) raise SystemExit if not self.u.set_nchannels(nchan): sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) raise SystemExit input_rate = self.u.adc_freq() / self.u.decim_rate() print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) sink_data_rate = input_rate/sw_decim print "Scope data rate = %s" % (eng_notation.num_to_str(sink_data_rate),) self.subdev = self.u.db[0] + self.u.db[1] if (len(self.subdev) != 4 or self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') sys.exit(1) self.u.set_mux(gru.hexint(0xf3f2f1f0)) # collect 1 second worth of data limit = int(nsecs * input_rate * nchan) print "limit = ", limit head = gr.head(gr.sizeof_gr_complex, limit) # deinterleave four channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) self.connect(self.u, head, di) # taps for channel filter chan_filt_coeffs = optfir.low_pass (1, # gain input_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) for i in range(nchan): sink = gr.file_sink(gr.sizeof_gr_complex, basename + ("-%s-%d.dat" % (eng_notation.num_to_str(sink_data_rate), i))) if options.filter: chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) self.connect((di, i), chan_filt, sink) else: self.connect((di, i), sink) self.set_gain(options.gain) self.set_freq(options.freq)
def __init__(self, options): gr.top_block.__init__(self) self.options = options (dev_rate, channel_rate, audio_rate, channel_pass, channel_stop, demod) = demod_params[options.modulation] DEV = uhd_src( options.args, # UHD device address options.spec, # device subdev spec options.antenna, # device antenna dev_rate, # device sample rate options.gain, # Receiver gain options.calibration) # Frequency offset DEV.tune(options.frequency) if_rate = DEV.rate() channel_decim = int(if_rate // channel_rate) audio_decim = int(channel_rate // audio_rate) CHAN_taps = optfir.low_pass( 1.0, # Filter gain if_rate, # Sample rate channel_pass, # One sided modulation bandwidth channel_stop, # One sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation CHAN = gr.freq_xlating_fir_filter_ccf( channel_decim, # Decimation rate CHAN_taps, # Filter taps 0.0, # Offset frequency if_rate) # Sample rate RFSQL = gr.pwr_squelch_cc( options.rf_squelch, # Power threshold 125.0 / channel_rate, # Time constant int(channel_rate / 20), # 50ms rise/fall False) # Zero, not gate output AGC = gr.agc_cc( 1.0 / channel_rate, # Time constant 1.0, # Reference power 1.0, # Initial gain 1.0) # Maximum gain DEMOD = demod(channel_rate, audio_decim) # From RF to audio #self.connect(DEV, CHAN, RFSQL, AGC, DEMOD) self.connect(DEV, CHAN, DEMOD) # Optionally add CTCSS and RSAMP if needed tail = DEMOD if options.ctcss != None and options.ctcss > 60.0: CTCSS = gr.ctcss_squelch_ff( audio_rate, # Sample rate options.ctcss) # Squelch tone self.connect(DEMOD, CTCSS) tail = CTCSS if options.output_rate != audio_rate: out_lcm = gru.lcm(audio_rate, options.output_rate) out_interp = int(out_lcm // audio_rate) out_decim = int(out_lcm // options.output_rate) RSAMP = blks2.rational_resampler_fff(out_interp, out_decim) self.connect(tail, RSAMP) tail = RSAMP # Send to audio output device AUDIO = audio.sink(int(options.output_rate), options.audio_output) self.connect(tail, AUDIO)
def __init__(self): gr.top_block.__init__(self) usage = "usage: %prog [options] input-samples-320kS.dat output.wav" parser = OptionParser(option_class=eng_option, usage=usage) parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") (options, args) = parser.parse_args() if len(args) != 2: parser.print_help() sys.exit(1) input_filename = args[0] output_filename = args[1] self.vol = 0 # build graph self.src = blocks.file_source(gr.sizeof_gr_complex, input_filename, False) adc_rate = 64e6 # 64 MS/s usrp_decim = 200 usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz chan_filt_coeffs = optfir.low_pass( 1, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60, ) # stopband attenuation # print len(chan_filt_coeffs) chan_filt = filter.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) # self.guts = analog.wfm_rcv (demod_rate, audio_decimation) self.guts = analog.wfm_rcv_pll(demod_rate, audio_decimation) # FIXME rework {add,multiply}_const_* to handle multiple streams self.volume_control_l = blocks.multiply_const_ff(self.vol) self.volume_control_r = blocks.multiply_const_ff(self.vol) # wave file as final sink if 1: sink = blocks.wavfile_sink(output_filename, 2, int(audio_rate), 16) else: sink = audio.sink(int(audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect(self.src, chan_filt, self.guts) self.connect((self.guts, 0), self.volume_control_l, (sink, 0)) self.connect((self.guts, 1), self.volume_control_r, (sink, 1)) try: self.guts.stereo_carrier_pll_recovery.squelch_enable(True) except: pass # print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet" if options.volume is None: g = self.volume_range() options.volume = float(g[0] + g[1]) / 2 # set initial values self.set_vol(options.volume) try: self.guts.stereo_carrier_pll_recovery.set_lock_threshold(options.squelch) except: pass
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel parser = OptionParser(option_class=eng_option) #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), # help="select USRP Rx side A or B (default=A)") parser.add_option( "-d", "--decim", type="int", default=128, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, help="set frequency to FREQ [default=%default])", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=20, help="set gain in dB [default=%default]") parser.add_option("-F", "--filter", action="store_true", default=True, help="Enable channel filter") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit nchan = 4 if options.filter: sw_decim = 4 else: sw_decim = 1 self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") if self.u.nddcs() < nchan: sys.stderr.write( 'This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % (nchan, self.u.nddcs())) raise SystemExit if not self.u.set_nchannels(nchan): sys.stderr.write('set_nchannels(%d) failed\n' % (nchan, )) raise SystemExit input_rate = self.u.adc_freq() / self.u.decim_rate() print "USB data rate = %s" % (eng_notation.num_to_str(input_rate), ) print "Scope data rate = %s" % (eng_notation.num_to_str( input_rate / sw_decim), ) self.subdev = self.u.db(0) + self.u.db(1) if (len(self.subdev) < 4 or self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX): sys.stderr.write( 'This code requires a Basic Rx board on Sides A & B\n') sys.exit(1) self.u.set_mux(gru.hexint(0xf3f2f1f0)) # deinterleave four channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) self.connect(self.u, di) # our destination (8 float inputs) self.scope = scopesink2.scope_sink_f(panel, sample_rate=input_rate / sw_decim, num_inputs=2 * nchan) # taps for channel filter chan_filt_coeffs = optfir.low_pass( 1, # gain input_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) # bust the deinterleaved complex channels into floats for i in range(nchan): if options.filter: chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) c2f = gr.complex_to_float() self.connect((di, i), chan_filt, c2f) else: c2f = gr.complex_to_float() self.connect((di, i), c2f) self.connect((c2f, 0), (self.scope, 2 * i + 0)) self.connect((c2f, 1), (self.scope, 2 * i + 1)) self._build_gui(vbox) self.set_gain(options.gain) self.set_freq(options.freq)
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) parser = OptionParser(option_class=eng_option) parser.add_option( "-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)" ) parser.add_option( "-f", "--freq", type="eng_float", default=100.1e6, help="set frequency to FREQ", metavar="FREQ" ) parser.add_option("-g", "--gain", type="eng_float", default=65, help="set gain in dB (default is midpoint)") parser.add_option("-s", "--squelch", type="eng_float", default=0, help="set squelch level (default is 0)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 200 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) chan_filt_coeffs = optfir.low_pass( 1, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60, ) # stopband attenuation # print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) # self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) self.guts = blks2.wfm_rcv_pll(demod_rate, audio_decimation) # FIXME rework {add,multiply}_const_* to handle multiple streams self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) # sound card as final sink audio_sink = audio.sink(int(audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect(self.u, chan_filt, self.guts) self.connect((self.guts, 0), self.volume_control_l, (audio_sink, 0)) self.connect((self.guts, 1), self.volume_control_r, (audio_sink, 1)) try: self.guts.stereo_carrier_pll_recovery.squelch_enable(True) except: print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet" self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0] + g[1]) / 2 if options.volume is None: g = self.volume_range() options.volume = float(g[0] + g[1]) / 2 if abs(options.freq) < 1e6: options.freq *= 1e6 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) try: self.guts.stereo_carrier_pll_recovery.set_lock_threshold(options.squelch) except: print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet" if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) parser = OptionParser(option_class=eng_option) parser.add_option("-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("-f", "--freq", type="eng_float", default=100.1e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=40, help="set gain in dB (default is midpoint)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option( "-O", "--audio-output", type="string", default="", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") parser.add_option("", "--freq-min", type="eng_float", default=87.9e6, help="Set a minimum frequency [default=%default]") parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 self.fm_freq_min = options.freq_min self.fm_freq_max = options.freq_max # build graph self.u = uhd.usrp_source(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) usrp_rate = 320e3 demod_rate = 320e3 audio_rate = 32e3 sca_demod_rate = 64e3 audio_decim = int(demod_rate / audio_rate) sca_chanfilt_decim = int(demod_rate / sca_demod_rate) self.u.set_samp_rate(usrp_rate) dev_rate = self.u.get_samp_rate() nfilts = 32 chan_coeffs = optfir.low_pass( nfilts, # gain nfilts * usrp_rate, # sampling rate 100e3, # passband cutoff 140e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation rrate = usrp_rate / dev_rate self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) #Create demodulator block for Main FM Channel max_dev = 75e3 fm_demod_gain = demod_rate / (2 * math.pi * max_dev) self.fm_demod = gr.quadrature_demod_cf(fm_demod_gain) # Note - deemphasis is not applied to the Main FM Channel as # main audio is not decoded # SCA Devation is 10% of carrier but some references say 20% # if mono with one SCA (6 KHz seems typical) max_sca_dev = 6e3 # Create filter to get SCA channel we want sca_chan_coeffs = gr.firdes.low_pass( 1.0, # gain demod_rate, # sampling rate max_sca_dev, # cutoff freq max_sca_dev / 3, # trans. band gr.firdes.WIN_HANN) # filter type self.ddc = gr.freq_xlating_fir_filter_fcf( sca_chanfilt_decim, # decim rate sca_chan_coeffs, # taps 0, # freq translation amount (Gets set by the UI) demod_rate) # input sample rate #Create demodulator block for SCA Channel sca_demod_gain = sca_demod_rate / (2 * math.pi * max_sca_dev) self.fm_demod_sca = gr.quadrature_demod_cf(sca_demod_gain) # SCA analog audio is bandwidth limited to 5 KHz max_sca_audio_freq = 5.0e3 # SCA analog deephasis is 150 uS (75 uS may be used) sca_tau = 150e-6 # compute FIR filter taps for SCA audio filter audio_coeffs = gr.firdes.low_pass( 1.0, # gain sca_demod_rate, # sampling rate max_sca_audio_freq, # cutoff freq max_sca_audio_freq / 2.5, # trans. band gr.firdes.WIN_HAMMING) # input: float; output: float self.audio_filter = gr.fir_filter_fff(audio_decim, audio_coeffs) # Create deemphasis block that is applied after SCA demodulation self.deemph = blks2.fm_deemph(audio_rate, sca_tau) self.volume_control = gr.multiply_const_ff(self.vol) # 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 self.connect(self.u, self.chan_filt, self.fm_demod, self.ddc, self.fm_demod_sca) self.connect(self.fm_demod_sca, self.audio_filter, self.deemph, self.volume_control, self.audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, sca_demod_rate, audio_rate) 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 if options.volume is None: g = self.volume_range() options.volume = float(g[0] + g[1]) / 2 frange = self.u.get_freq_range() if (frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): sys.stderr.write( "Radio does not support required frequency range.\n") sys.exit(1) if (options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): sys.stderr.write( "Requested frequency is outside of required frequency range.\n" ) sys.exit(1) # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") self.set_sca_freq(67000) # A common SCA Frequency
def __init__(self, frame, panel, vbox, argv): stdgui.gui_flow_graph.__init__(self) self.frame = frame self.panel = panel parser = OptionParser (option_class=eng_option) #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), # help="select USRP Rx side A or B (default=A)") parser.add_option("-d", "--decim", type="int", default=128, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, help="set frequency to FREQ [default=%default])", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=20, help="set gain in dB [default=%default]") parser.add_option("-F", "--filter", action="store_true", default=True, help="Enable channel filter") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit nchan = 4 if options.filter: sw_decim = 4 else: sw_decim = 1 self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") if self.u.nddc() < nchan: sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( nchan, self.u.nddc())) raise SystemExit if not self.u.set_nchannels(nchan): sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) raise SystemExit input_rate = self.u.adc_freq() / self.u.decim_rate() print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),) self.subdev = self.u.db[0] + self.u.db[1] if (len (self.subdev) != 4 or self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') sys.exit(1) self.u.set_mux(gru.hexint(0xf3f2f1f0)) # deinterleave four channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) self.connect(self.u, di) # taps for channel filter chan_filt_coeffs = optfir.low_pass (1, # gain input_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) for i in range(nchan): scope = fftsink.fft_sink_c(self, panel, sample_rate=input_rate/sw_decim, title="Input %d" % (i,), ref_level=80, y_per_div=20) vbox.Add(scope.win, 10, wx.EXPAND) if options.filter: chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) self.connect((di, i), chan_filt, scope) else: self.connect((di, i), scope) self.set_gain(options.gain) self.set_freq(options.freq)
def __init__(self, options): gr.top_block.__init__(self) self.options = options (usrp_decim, channel_decim, audio_decim, channel_pass, channel_stop, demod) = demod_params[options.modulation] USRP = usrp_src(options.rx_subdev_spec, # Daugherboard spec usrp_decim, # IF decimation ratio options.gain, # Receiver gain options.calibration) # Frequency offset USRP.tune(options.frequency) if_rate = USRP.rate() channel_rate = if_rate // channel_decim audio_rate = channel_rate // audio_decim CHAN_taps = optfir.low_pass(1.0, # Filter gain if_rate, # Sample rate channel_pass, # One sided modulation bandwidth channel_stop, # One sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation CHAN = gr.freq_xlating_fir_filter_ccf(channel_decim, # Decimation rate CHAN_taps, # Filter taps 0.0, # Offset frequency if_rate) # Sample rate RFSQL = gr.pwr_squelch_cc(options.rf_squelch, # Power threshold 125.0/channel_rate, # Time constant channel_rate/20, # 50ms rise/fall False) # Zero, not gate output AGC = gr.agc_cc(1.0/channel_rate, # Time constant 1.0, # Reference power 1.0, # Initial gain 1.0) # Maximum gain DEMOD = demod(channel_rate, audio_decim) # From RF to audio self.connect(USRP, CHAN, RFSQL, AGC, DEMOD) # Optionally add CTCSS and RSAMP if needed tail = DEMOD if options.ctcss != None and options.ctcss > 60.0: CTCSS = gr.ctcss_squelch_ff(audio_rate, # Sample rate options.ctcss) # Squelch tone self.connect(DEMOD, CTCSS) tail = CTCSS if options.output_rate != audio_rate: out_lcm = gru.lcm(audio_rate, options.output_rate) out_interp = int(out_lcm // audio_rate) out_decim = int(out_lcm // options.output_rate) RSAMP = blks2.rational_resampler_fff(out_interp, out_decim) self.connect(tail, RSAMP) tail = RSAMP # Send to default audio output AUDIO = audio.sink(options.output_rate, "") self.connect(tail, AUDIO)
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) parser=OptionParser(option_class=eng_option) parser.add_option("-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("-f", "--freq", type="eng_float", default=100.1e6, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="default", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") parser.add_option("", "--freq-min", type="eng_float", default=87.9e6, help="Set a minimum frequency [default=%default]") parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 self.fm_freq_min = options.freq_min self.fm_freq_max = options.freq_max # build graph self.u = uhd.usrp_source(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) usrp_rate = 320e3 demod_rate = 320e3 audio_rate = 32e3 sca_demod_rate = 64e3 audio_decim = int(demod_rate / audio_rate) sca_chanfilt_decim = int(demod_rate / sca_demod_rate) self.u.set_samp_rate(usrp_rate) dev_rate = self.u.get_samp_rate() nfilts = 32 chan_coeffs = optfir.low_pass (nfilts, # gain nfilts*usrp_rate, # sampling rate 100e3, # passband cutoff 140e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation rrate = usrp_rate / dev_rate self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) #Create demodulator block for Main FM Channel max_dev = 75e3 fm_demod_gain = demod_rate/(2*math.pi*max_dev) self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain) # Note - deemphasis is not applied to the Main FM Channel as # main audio is not decoded # SCA Devation is 10% of carrier but some references say 20% # if mono with one SCA (6 KHz seems typical) max_sca_dev = 6e3 # Create filter to get SCA channel we want sca_chan_coeffs = gr.firdes.low_pass (1.0, # gain demod_rate, # sampling rate max_sca_dev, # cutoff freq max_sca_dev/3, # trans. band gr.firdes.WIN_HANN) # filter type self.ddc = gr.freq_xlating_fir_filter_fcf(sca_chanfilt_decim, # decim rate sca_chan_coeffs, # taps 0, # freq translation amount (Gets set by the UI) demod_rate) # input sample rate #Create demodulator block for SCA Channel sca_demod_gain = sca_demod_rate/(2*math.pi*max_sca_dev) self.fm_demod_sca = gr.quadrature_demod_cf (sca_demod_gain) # SCA analog audio is bandwidth limited to 5 KHz max_sca_audio_freq = 5.0e3 # SCA analog deephasis is 150 uS (75 uS may be used) sca_tau = 150e-6 # compute FIR filter taps for SCA audio filter audio_coeffs = gr.firdes.low_pass (1.0, # gain sca_demod_rate, # sampling rate max_sca_audio_freq, # cutoff freq max_sca_audio_freq/2.5, # trans. band gr.firdes.WIN_HAMMING) # input: float; output: float self.audio_filter = gr.fir_filter_fff (audio_decim, audio_coeffs) # Create deemphasis block that is applied after SCA demodulation self.deemph = blks2.fm_deemph (audio_rate, sca_tau) self.volume_control = gr.multiply_const_ff(self.vol) # 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 self.connect (self.u, self.chan_filt, self.fm_demod, self.ddc, self.fm_demod_sca) self.connect (self.fm_demod_sca, self.audio_filter, self.deemph, self.volume_control, self.audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, sca_demod_rate, audio_rate) 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 if options.volume is None: g = self.volume_range() options.volume = float(g[0]+g[1])/2 frange = self.u.get_freq_range() if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): sys.stderr.write("Radio does not support required frequency range.\n") sys.exit(1) if(options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): sys.stderr.write("Requested frequency is outside of required frequency range.\n") sys.exit(1) # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") self.set_sca_freq(67000) # A common SCA Frequency
def __init__(self, options, queue): gr.top_block.__init__(self, "usrp_flex") self.options = options self.offset = 0.0 self.adj_time = time.time() self.verbose = options.verbose if options.from_file is None: # Set up USRP source self.u = uhd.usrp_source(device_addr=options.address, stream_args=uhd.stream_args('fc32')) # Grab 250 KHz of spectrum # (A UHD facility to get sample rate range and granularity would be useful) self.u.set_samp_rate(250e3) rate = self.u.get_samp_rate() if rate != 250e3: print "Unable to set required sample rate of 250 Ksps (got %f)" % rate sys.exit(1) # Tune daughterboard r = self.u.set_center_freq(options.freq+options.calibration, 0) if not r: frange = self.u.get_freq_range() sys.stderr.write(("\nRequested frequency (%f) out or range [%f, %f]\n") % \ (freq, frange.start(), frange.stop())) sys.exit(1) # if no gain was specified, use the mid-point in dB if options.rx_gain is None: grange = self.u.get_gain_range() options.rx_gain = float(grange.start()+grange.stop())/2.0 print "\nNo gain specified." print "Setting gain to %f (from [%f, %f])" % \ (options.rx_gain, grange.start(), grange.stop()) self.u.set_gain(options.rx_gain, 0) else: # Use supplied file as source of samples self.u = gr.file_source(gr.sizeof_gr_complex, options.from_file) if options.verbose: print "Reading samples from", options.from_file if options.log and not options.from_file: usrp_sink = gr.file_sink(gr.sizeof_gr_complex, 'usrp.dat') self.connect(self.u, usrp_sink) # Set up 22KHz-wide bandpass about center frequency. Decimate by 10 # to get channel rate of 25Ksps taps = optfir.low_pass(1.0, # Filter gain 250e3, # Sample rate 11000, # One-sided modulation bandwidth 12500, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation if options.verbose: print "Channel filter has", len(taps), "taps." self.chan = gr.freq_xlating_fir_filter_ccf(10, # Decimation rate taps, # Filter taps 0.0, # Offset frequency 250e3) # Sample rate if options.log: chan_sink = gr.file_sink(gr.sizeof_gr_complex, 'chan.dat') self.connect(self.chan, chan_sink) # FLEX protocol demodulator self.flex = pager.flex_demod(queue, options.freq, options.verbose, options.log) self.connect(self.u, self.chan, self.flex)
def __init__(self, options): gr.top_block.__init__(self) self.options = options (dev_rate, channel_rate, audio_rate, channel_pass, channel_stop, demod) = demod_params[options.modulation] DEV = uhd_src(options.args, # UHD device address options.spec, # device subdev spec options.antenna, # device antenna dev_rate, # device sample rate options.gain, # Receiver gain options.calibration) # Frequency offset DEV.tune(options.frequency) if_rate = DEV.rate() channel_decim = int(if_rate // channel_rate) audio_decim = int(channel_rate // audio_rate) CHAN_taps = optfir.low_pass(1.0, # Filter gain if_rate, # Sample rate channel_pass, # One sided modulation bandwidth channel_stop, # One sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation CHAN = gr.freq_xlating_fir_filter_ccf(channel_decim, # Decimation rate CHAN_taps, # Filter taps 0.0, # Offset frequency if_rate) # Sample rate RFSQL = gr.pwr_squelch_cc(options.rf_squelch, # Power threshold 125.0/channel_rate, # Time constant int(channel_rate/20), # 50ms rise/fall False) # Zero, not gate output AGC = gr.agc_cc(1.0/channel_rate, # Time constant 1.0, # Reference power 1.0, # Initial gain 1.0) # Maximum gain DEMOD = demod(channel_rate, audio_decim) # From RF to audio #self.connect(DEV, CHAN, RFSQL, AGC, DEMOD) self.connect(DEV, CHAN, DEMOD) # Optionally add CTCSS and RSAMP if needed tail = DEMOD if options.ctcss != None and options.ctcss > 60.0: CTCSS = gr.ctcss_squelch_ff(audio_rate, # Sample rate options.ctcss) # Squelch tone self.connect(DEMOD, CTCSS) tail = CTCSS if options.output_rate != audio_rate: out_lcm = gru.lcm(audio_rate, options.output_rate) out_interp = int(out_lcm // audio_rate) out_decim = int(out_lcm // options.output_rate) RSAMP = blks2.rational_resampler_fff(out_interp, out_decim) self.connect(tail, RSAMP) tail = RSAMP # Send to audio output device AUDIO = audio.sink(int(options.output_rate), options.audio_output) self.connect(tail, AUDIO) # Direct asynchronous notifications to callback function if self.options.show_async_msg: self.async_msgq = gr.msg_queue(0) self.async_src = uhd.amsg_source("", self.async_msgq) self.async_rcv = gru.msgq_runner(self.async_msgq, self.async_callback)
def __init__(self, freq, subdev_spec, which_USRP, gain, audio_output, debug): gr.hier_block2.__init__( self, "analog_receive_path", gr.io_signature(0, 0, 0), #input signature gr.io_signature(0, 0, 0)) #output signature self.DEBUG = debug self.freq = freq self.rx_gain = gain #Formerly From XML self.fusb_block_size = 2048 self.fusb_nblocks = 8 self.rx_usrp_pga_gain_scaling = 0.5 self.rx_base_band_bw = 5e3 self.rx_freq_deviation = 2.5e3 # acquire USRP via USB 2.0 #self.u = usrp.source_c(fusb_block_size=self.fusb_block_size, # fusb_nblocks=self.fusb_nblocks, # which=which_USRP) self.u = uhd.single_usrp_source( device_addr="", io_type=uhd.io_type_t.COMPLEX_FLOAT32, num_channels=1, ) self.u.get_device # get A/D converter sampling rate #adc_rate = self.u.adc_rate() # 64 MS/s adc_rate = 64e6 # 64 MS/s if self.DEBUG: print " Rx Path ADC rate: %d" % (adc_rate) # setting USRP and GNU Radio decimation rate self.audio_rate = 16e3 self.max_gr_decim_rate = 40 self._usrp_decim = 250 self.gr_rate1 = adc_rate / self._usrp_decim gr_interp = 1 gr_decim = 16 self.gr_rate2 = self.gr_rate1 / gr_decim if self.DEBUG: print " usrp decim: ", self._usrp_decim print " gr rate 1: ", self.gr_rate1 print " gr decim: ", gr_decim print " gr rate 2: ", self.gr_rate2 print " gr interp: ", gr_interp print " audio rate: ", self.audio_rate # ================ Set up flowgraph ================================= # set USRP decimation ratio #self.u.set_decim_rate(self._usrp_decim) self.u.set_samp_rate(self.gr_rate1) self.u.set_antenna("RX2") # set USRP daughterboard subdevice if subdev_spec is None: subdev_spec = usrp.pick_rx_subdevice(self.u) #self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec)) #self.subdev = usrp.selected_subdev(self.u, subdev_spec) #if self.DEBUG: # print " RX Path use daughterboard: %s" % (self.subdev.side_and_name()) # set USRP RF frequency """ Set the center frequency in Hz. Tuning is a two step process. First we ask the front-end to tune as close to the desired frequency as it can. Then we use the result of that operation and our target_frequency to determine the value for the digital up converter. """ assert (self.freq != None) #r = self.u.tune(0, self.subdev, self.freq) r = self.u.set_center_freq(self.freq, 0) if self.DEBUG: if r: print "----Rx RF frequency set to %f Hz" % (self.freq) else: print "Failed to set Rx frequency to %f Hz" % (self.freq) raise ValueError, eng_notation.num_to_str(self.freq) # set USRP Rx PGA gain #r = self.subdev.gain_range() #_rx_usrp_gain_range = r[1] - r[0] #_rx_usrp_gain = r[0]+_rx_usrp_gain_range * self.rx_usrp_pga_gain_scaling #self.subdev.set_gain(_rx_usrp_gain) #self.u.set_gain(3.25, 0) #if self.DEBUG: # print " USRP Rx PGA Gain Range: min = %g, max = %g, step size = %g" \ # %(r[0], r[1], r[2]) # print " USRP Rx PGA gain set to: %g" %(_rx_usrp_gain) # Do NOT Enable USRP Auto Tx/Rx switching for analog flow graph! #self.subdev.set_enable(False) # Baseband Channel Filter using FM Carson's Rule chan_bw = 2 * (self.rx_base_band_bw + self.rx_freq_deviation ) #Carson's Rule chan_filt_coeffs_float = optfir.low_pass( 1, #gain self.gr_rate1, #sampling rate chan_bw, #passband cutoff chan_bw * 1.35, #stopband cutoff 0.1, #passband ripple 60) #stopband attenuation chan_filt_coeffs_fixed = ( 0.000457763671875, 0.000946044921875, 0.00067138671875, 0.001068115234375, 0.00091552734375, 0.0008544921875, 0.000518798828125, 0.0001220703125, -0.000396728515625, -0.0008544921875, -0.00128173828125, -0.00146484375, -0.001434326171875, -0.0010986328125, -0.000518798828125, 0.000274658203125, 0.001129150390625, 0.00189208984375, 0.00238037109375, 0.00250244140625, 0.002166748046875, 0.0013427734375, 0.000152587890625, -0.001220703125, -0.002532958984375, -0.0035400390625, -0.003997802734375, -0.003753662109375, -0.002777099609375, -0.0010986328125, 0.000946044921875, 0.00311279296875, 0.00494384765625, 0.00604248046875, 0.006103515625, 0.005035400390625, 0.00286865234375, -0.0001220703125, -0.00347900390625, -0.006561279296875, -0.008758544921875, -0.00958251953125, -0.008636474609375, -0.005950927734375, -0.001739501953125, 0.00335693359375, 0.00848388671875, 0.0126953125, 0.01507568359375, 0.014862060546875, 0.01171875, 0.00579833984375, -0.002227783203125, -0.01123046875, -0.0196533203125, -0.02587890625, -0.028228759765625, -0.025421142578125, -0.016754150390625, -0.002166748046875, 0.017608642578125, 0.041015625, 0.0660400390625, 0.090240478515625, 0.111083984375, 0.12640380859375, 0.134490966796875, 0.134490966796875, 0.12640380859375, 0.111083984375, 0.090240478515625, 0.0660400390625, 0.041015625, 0.017608642578125, -0.002166748046875, -0.016754150390625, -0.025421142578125, -0.028228759765625, -0.02587890625, -0.0196533203125, -0.01123046875, -0.002227783203125, 0.00579833984375, 0.01171875, 0.014862060546875, 0.01507568359375, 0.0126953125, 0.00848388671875, 0.00335693359375, -0.001739501953125, -0.005950927734375, -0.008636474609375, -0.00958251953125, -0.008758544921875, -0.006561279296875, -0.00347900390625, -0.0001220703125, 0.00286865234375, 0.005035400390625, 0.006103515625, 0.00604248046875, 0.00494384765625, 0.00311279296875, 0.000946044921875, -0.0010986328125, -0.002777099609375, -0.003753662109375, -0.003997802734375, -0.0035400390625, -0.002532958984375, -0.001220703125, 0.000152587890625, 0.0013427734375, 0.002166748046875, 0.00250244140625, 0.00238037109375, 0.00189208984375, 0.001129150390625, 0.000274658203125, -0.000518798828125, -0.0010986328125, -0.001434326171875, -0.00146484375, -0.00128173828125, -0.0008544921875, -0.000396728515625, 0.0001220703125, 0.000518798828125, 0.0008544921875, 0.00091552734375, 0.001068115234375, 0.00067138671875, 0.000946044921875, 0.000457763671875) #r = gr.enable_realtime_scheduling () self.chan_filt = dsp.fir_ccf_fm_demod_decim(chan_filt_coeffs_fixed, 14, gr_decim, 0, 0, 0, 0) print "Tap length of chan FIR: ", len(chan_filt_coeffs_fixed) # Set the software LNA gain on the output of the USRP gain = self.rx_gain self.rx_gain = max(0.0, min(gain, 1e7)) if self.DEBUG: print " Rx Path initial software signal gain: %f (max 1e7)" % ( gain) print " Rx Path actual software signal gain : %f (max 1e7)" % ( self.rx_gain) #FM Demodulator fm_demod_gain = self.audio_rate / (2 * math.pi * self.rx_freq_deviation) self.fm_demod = gr.quadrature_demod_cf(fm_demod_gain) #Compute FIR filter taps for audio filter width_of_transition_band = self.rx_base_band_bw * 0.35 audio_coeffs = gr.firdes.low_pass( 1.0, #gain self.gr_rate2, #sampling rate self.rx_base_band_bw, width_of_transition_band, gr.firdes.WIN_HAMMING) self.audio_filter = gr.fir_filter_fff(1, audio_coeffs) passband_cutoff = self.rx_base_band_bw stopband_cutoff = passband_cutoff * 1.35 self.deemph = fm_deemph(self.audio_rate) if self.DEBUG: print "Length Audio FIR ", len(audio_coeffs) # Audio sink audio_sink = audio.sink(int(self.audio_rate), "default") # "", #Audio output pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp # False) # ok_to_block if self.DEBUG: print "Before Connecting Blocks" # Wiring Up #WITH CHANNEL FILTER #self.connect (self.u, self.chan_filt, self.lna, self.fm_demod, self.audio_filter, interpolator, self.deemph, self.volume_control, audio_sink) #self.connect (self.u, self.fm_demod, self.audio_filter, self.deemph, self.volume_control, howto_rx, audio_sink) self.connect(self.u, self.chan_filt, self.audio_filter, self.deemph, audio_sink)
def __init__(self, options, queue): gr.top_block.__init__(self, "usrp_flex") self.options = options self.offset = 0.0 self.file_offset = 0.0 self.adj_time = time.time() self.verbose = options.verbose if options.from_file is None: self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + '' ) self.rtlsdr_source_0.set_sample_rate(samp_rate) self.rtlsdr_source_0.set_center_freq(options.frequency, 0) self.rtlsdr_source_0.set_freq_corr(0, 0) self.rtlsdr_source_0.set_dc_offset_mode(0, 0) self.rtlsdr_source_0.set_iq_balance_mode(0, 0) self.rtlsdr_source_0.set_gain_mode(True, 0) self.rtlsdr_source_0.set_gain(50, 0) self.rtlsdr_source_0.set_if_gain(20, 0) self.rtlsdr_source_0.set_bb_gain(20, 0) self.rtlsdr_source_0.set_antenna('', 0) self.rtlsdr_source_0.set_bandwidth(0, 0) else: # Use supplied file as source of samples self.file_offset = options.calibration print "File input offset", self.offset self.src = gr.file_source(gr.sizeof_gr_complex, options.from_file) if options.verbose: print "Reading samples from", options.from_file if options.log and not options.from_file: usrp_sink = gr.file_sink(gr.sizeof_gr_complex, 'usrp.dat') self.connect(self.src, usrp_sink) # following is rig to allow fast and easy swapping of signal configuration # blocks between this example and the oscope example which uses self.msgq self.msgq = queue #------------------------------------------------------------------------------- if options.protocol == 0: # ---------- RD-LAP 19.2 kbps (9600 ksps), 25kHz channel, self.symbol_rate = 9600 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps self.channel_decimation = 10 # decimation (final rate should be at least several symbol rate) self.max_frequency_offset = 12000.0 # coarse carrier tracker leash, ~ half a channel either way self.symbol_deviation = 1200.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = 64e6 / options.decim # for USRP: 64MHz / FPGA decimation rate self.protocol_processing = fsk4.rdlap_f(self.msgq, 0) # desired protocol processing block selected here self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter characteristics channel_taps = optfir.low_pass(1.0, # Filter gain self.input_sample_rate, # Sample rate 10000, # One-sided modulation bandwidth 12000, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter characteristics symbol_coeffs = gr.firdes.root_raised_cosine (1.0, # gain self.channel_rate , # sampling rate self.symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type if options.protocol == 1: # ---------- APCO-25 C4FM Test Data self.symbol_rate = 4800 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps self.channel_decimation = 20 # decimation self.max_frequency_offset = 6000.0 # coarse carrier tracker leash self.symbol_deviation = 600.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = 64e6 / options.decim # for USRP: 64MHz / FPGA decimation rate self.protocol_processing = fsk4.apco25_f(self.msgq, 0) self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter channel_taps = optfir.low_pass(1.0, # Filter gain self.input_sample_rate, # Sample rate 5000, # One-sided modulation bandwidth 6500, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter symbol_coeffs = gr.firdes.root_raised_cosine (1.0, # gain self.channel_rate , # sampling rate self.symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type # ---------- End of configuration if options.verbose: print "Channel filter has", len(channel_taps), "taps." self.chan = gr.freq_xlating_fir_filter_ccf(self.channel_decimation , # Decimation rate channel_taps, # Filter taps 0.0, # Offset frequency self.input_sample_rate) # Sample rate # also note: # this specifies the nominal frequency deviation for the 4-level fsk signal self.fm_demod_gain = self.channel_rate / (2.0 * pi * self.symbol_deviation) self.fm_demod = gr.quadrature_demod_cf (self.fm_demod_gain) symbol_decim = 1 self.symbol_filter = gr.fir_filter_fff (symbol_decim, symbol_coeffs) # eventually specify: sample rate, symbol rate self.demod_fsk4 = fsk4.demod_ff(self.msgq, self.channel_rate , self.symbol_rate) if options.log: chan_sink = gr.file_sink(gr.sizeof_gr_complex, 'chan.dat') self.connect(self.chan, chan_sink) if options.log: chan_sink2 = gr.file_sink(gr.sizeof_float, 'demod.dat') self.connect(self.demod_fsk4, chan_sink2) self.connect(self.src, self.chan, self.fm_demod, self.symbol_filter, self.demod_fsk4, self.protocol_processing)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("", "--f1", type="eng_float", default=100.7e6, help="set 1st station frequency to FREQ", metavar="FREQ") parser.add_option("", "--f2", type="eng_float", default=102.5e6, help="set 2nd station freq to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=40, help="set gain in dB (default is midpoint)") 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 abs(options.f1) < 1e6: options.f1 *= 1e6 if abs(options.f2) < 1e6: options.f2 *= 1e6 if abs(options.f1 - options.f2) > 5.5e6: print "Sorry, two stations must be within 5.5MHz of each other" raise SystemExit f = (options.f1, options.f2) self.vol = .1 self.state = "FREQ" # build graph self.u = usrp.source_c(0, nchan=2) # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 200 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) mv = usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec) mv |= (mv << 8) & 0xff00 # both DDC inputs setup same way self.u.set_mux(mv) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(), ) # deinterleave two channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) # wire up the head of the chain self.connect(self.u, di) # sound card as final sink audio_sink = audio.sink(int(audio_rate), options.audio_output) # taps for channel filter chan_filt_coeffs = optfir.low_pass( 1, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) mid_freq = (f[0] + f[1]) / 2 # set front end PLL to middle frequency tune_result = self.subdev.set_freq(mid_freq) for n in range(2): chan_filt = gr.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) guts = blks2.wfm_rcv(demod_rate, audio_decimation) volume_control = gr.multiply_const_ff(self.vol) self.connect((di, n), chan_filt) self.connect(chan_filt, guts, volume_control) self.connect(volume_control, (audio_sink, n)) dxc_freq, inverted = calc_dxc_freq(f[n], tune_result.baseband_freq, self.u.converter_rate()) self.u.set_rx_freq(n, dxc_freq) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0] + g[1]) / 2 # set initial values self.set_gain(options.gain)
def __init__(self, freq, subdev_spec, which_USRP, gain, audio_output, debug): gr.hier_block2.__init__(self, "analog_receive_path", gr.io_signature(0, 0, 0), #input signature gr.io_signature(0, 0, 0)) #output signature self.DEBUG = debug self.freq = freq self.rx_gain = gain #Formerly From XML self.fusb_block_size = 2048 self.fusb_nblocks = 8 self.rx_usrp_pga_gain_scaling = 0.5 self.rx_base_band_bw = 5e3 self.rx_freq_deviation = 2.5e3 # acquire USRP via USB 2.0 #self.u = usrp.source_c(fusb_block_size=self.fusb_block_size, # fusb_nblocks=self.fusb_nblocks, # which=which_USRP) self.u = uhd.single_usrp_source( device_addr="", io_type=uhd.io_type_t.COMPLEX_FLOAT32, num_channels=1, ) self.u.get_device # get A/D converter sampling rate #adc_rate = self.u.adc_rate() # 64 MS/s adc_rate = 64e6 # 64 MS/s if self.DEBUG: print " Rx Path ADC rate: %d" %(adc_rate) # setting USRP and GNU Radio decimation rate self.audio_rate = 16e3 self.max_gr_decim_rate = 40 self._usrp_decim = 250 self.gr_rate1 = adc_rate / self._usrp_decim gr_interp = 1 gr_decim = 16 self.gr_rate2 = self.gr_rate1 / gr_decim if self.DEBUG: print " usrp decim: ", self._usrp_decim print " gr rate 1: ", self.gr_rate1 print " gr decim: ", gr_decim print " gr rate 2: ", self.gr_rate2 print " gr interp: ", gr_interp print " audio rate: ", self.audio_rate # ================ Set up flowgraph ================================= # set USRP decimation ratio #self.u.set_decim_rate(self._usrp_decim) self.u.set_samp_rate(self.gr_rate1) self.u.set_antenna("RX2") # set USRP daughterboard subdevice if subdev_spec is None: subdev_spec = usrp.pick_rx_subdevice(self.u) #self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec)) #self.subdev = usrp.selected_subdev(self.u, subdev_spec) #if self.DEBUG: # print " RX Path use daughterboard: %s" % (self.subdev.side_and_name()) # set USRP RF frequency """ Set the center frequency in Hz. Tuning is a two step process. First we ask the front-end to tune as close to the desired frequency as it can. Then we use the result of that operation and our target_frequency to determine the value for the digital up converter. """ assert(self.freq != None) #r = self.u.tune(0, self.subdev, self.freq) r = self.u.set_center_freq(self.freq, 0) if self.DEBUG: if r: print "----Rx RF frequency set to %f Hz" %(self.freq) else: print "Failed to set Rx frequency to %f Hz" %(self.freq) raise ValueError, eng_notation.num_to_str(self.freq) # set USRP Rx PGA gain #r = self.subdev.gain_range() #_rx_usrp_gain_range = r[1] - r[0] #_rx_usrp_gain = r[0]+_rx_usrp_gain_range * self.rx_usrp_pga_gain_scaling #self.subdev.set_gain(_rx_usrp_gain) #self.u.set_gain(3.25, 0) #if self.DEBUG: # print " USRP Rx PGA Gain Range: min = %g, max = %g, step size = %g" \ # %(r[0], r[1], r[2]) # print " USRP Rx PGA gain set to: %g" %(_rx_usrp_gain) # Do NOT Enable USRP Auto Tx/Rx switching for analog flow graph! #self.subdev.set_enable(False) # Baseband Channel Filter using FM Carson's Rule chan_bw = 2*(self.rx_base_band_bw+self.rx_freq_deviation) #Carson's Rule chan_filt_coeffs_float = optfir.low_pass (1, #gain self.gr_rate1, #sampling rate chan_bw, #passband cutoff chan_bw*1.35, #stopband cutoff 0.1, #passband ripple 60) #stopband attenuation chan_filt_coeffs_fixed = ( 0.000457763671875, 0.000946044921875, 0.00067138671875, 0.001068115234375, 0.00091552734375, 0.0008544921875, 0.000518798828125, 0.0001220703125, -0.000396728515625, -0.0008544921875, -0.00128173828125, -0.00146484375, -0.001434326171875, -0.0010986328125, -0.000518798828125, 0.000274658203125, 0.001129150390625, 0.00189208984375, 0.00238037109375, 0.00250244140625, 0.002166748046875, 0.0013427734375, 0.000152587890625, -0.001220703125, -0.002532958984375, -0.0035400390625, -0.003997802734375, -0.003753662109375, -0.002777099609375, -0.0010986328125, 0.000946044921875, 0.00311279296875, 0.00494384765625, 0.00604248046875, 0.006103515625, 0.005035400390625, 0.00286865234375, -0.0001220703125, -0.00347900390625, -0.006561279296875, -0.008758544921875, -0.00958251953125, -0.008636474609375, -0.005950927734375, -0.001739501953125, 0.00335693359375, 0.00848388671875, 0.0126953125, 0.01507568359375, 0.014862060546875, 0.01171875, 0.00579833984375, -0.002227783203125, -0.01123046875, -0.0196533203125, -0.02587890625, -0.028228759765625, -0.025421142578125, -0.016754150390625, -0.002166748046875, 0.017608642578125, 0.041015625, 0.0660400390625, 0.090240478515625, 0.111083984375, 0.12640380859375, 0.134490966796875, 0.134490966796875, 0.12640380859375, 0.111083984375, 0.090240478515625, 0.0660400390625, 0.041015625, 0.017608642578125, -0.002166748046875, -0.016754150390625, -0.025421142578125, -0.028228759765625, -0.02587890625, -0.0196533203125, -0.01123046875, -0.002227783203125, 0.00579833984375, 0.01171875, 0.014862060546875, 0.01507568359375, 0.0126953125, 0.00848388671875, 0.00335693359375, -0.001739501953125, -0.005950927734375, -0.008636474609375, -0.00958251953125, -0.008758544921875, -0.006561279296875, -0.00347900390625, -0.0001220703125, 0.00286865234375, 0.005035400390625, 0.006103515625, 0.00604248046875, 0.00494384765625, 0.00311279296875, 0.000946044921875, -0.0010986328125, -0.002777099609375, -0.003753662109375, -0.003997802734375, -0.0035400390625, -0.002532958984375, -0.001220703125, 0.000152587890625, 0.0013427734375, 0.002166748046875, 0.00250244140625, 0.00238037109375, 0.00189208984375, 0.001129150390625, 0.000274658203125, -0.000518798828125, -0.0010986328125, -0.001434326171875, -0.00146484375, -0.00128173828125, -0.0008544921875, -0.000396728515625, 0.0001220703125, 0.000518798828125, 0.0008544921875, 0.00091552734375, 0.001068115234375, 0.00067138671875, 0.000946044921875, 0.000457763671875) #r = gr.enable_realtime_scheduling () self.chan_filt = dsp.fir_ccf_fm_demod_decim (chan_filt_coeffs_fixed, 14, gr_decim, 0, 0, 0, 0) print "Tap length of chan FIR: ", len(chan_filt_coeffs_fixed) # Set the software LNA gain on the output of the USRP gain= self.rx_gain self.rx_gain = max(0.0, min(gain, 1e7)) if self.DEBUG: print " Rx Path initial software signal gain: %f (max 1e7)" %(gain) print " Rx Path actual software signal gain : %f (max 1e7)" %(self.rx_gain) #FM Demodulator fm_demod_gain = self.audio_rate / (2*math.pi*self.rx_freq_deviation) self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain) #Compute FIR filter taps for audio filter width_of_transition_band = self.rx_base_band_bw * 0.35 audio_coeffs = gr.firdes.low_pass (1.0, #gain self.gr_rate2, #sampling rate self.rx_base_band_bw, width_of_transition_band, gr.firdes.WIN_HAMMING) self.audio_filter = gr.fir_filter_fff(1, audio_coeffs) passband_cutoff = self.rx_base_band_bw stopband_cutoff = passband_cutoff * 1.35 self.deemph = fm_deemph(self.audio_rate) if self.DEBUG: print "Length Audio FIR ", len(audio_coeffs) # Audio sink audio_sink = audio.sink(int(self.audio_rate),"default") # "", #Audio output pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp # False) # ok_to_block if self.DEBUG: print "Before Connecting Blocks" # Wiring Up #WITH CHANNEL FILTER #self.connect (self.u, self.chan_filt, self.lna, self.fm_demod, self.audio_filter, interpolator, self.deemph, self.volume_control, audio_sink) #self.connect (self.u, self.fm_demod, self.audio_filter, self.deemph, self.volume_control, howto_rx, audio_sink) self.connect (self.u, self.chan_filt, self.audio_filter, self.deemph, audio_sink)
def __init__(self): gr.top_block.__init__(self) usage = "usage: %prog [options] input-samples-320kS.dat output.wav" parser = OptionParser(option_class=eng_option, usage=usage) parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") (options, args) = parser.parse_args() if len(args) != 2: parser.print_help() sys.exit(1) input_filename = args[0] output_filename = args[1] self.vol = 0 # build graph self.src = gr.file_source(gr.sizeof_gr_complex, input_filename, False) adc_rate = 64e6 # 64 MS/s usrp_decim = 200 usrp_rate = adc_rate / usrp_decim # 320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz chan_filt_coeffs = optfir.low_pass( 1, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) #self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) self.guts = blks2.wfm_rcv_pll(demod_rate, audio_decimation) # FIXME rework {add,multiply}_const_* to handle multiple streams self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) # wave file as final sink if 1: sink = gr.wavfile_sink(output_filename, 2, int(audio_rate), 16) else: sink = audio.sink(int(audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect(self.src, chan_filt, self.guts) self.connect((self.guts, 0), self.volume_control_l, (sink, 0)) self.connect((self.guts, 1), self.volume_control_r, (sink, 1)) try: self.guts.stereo_carrier_pll_recovery.squelch_enable(True) except: pass #print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet" if options.volume is None: g = self.volume_range() options.volume = float(g[0] + g[1]) / 2 # set initial values self.set_vol(options.volume) try: self.guts.stereo_carrier_pll_recovery.set_lock_threshold( options.squelch) except: pass
def __init__(self): 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("", "--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("-f", "--freq", type="eng_float", default=100.1e6, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") parser.add_option("", "--freq-min", type="eng_float", default=87.9e6, help="Set a minimum frequency [default=%default]") parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.state = "FREQ" self.freq = 0 self.fm_freq_min = options.freq_min self.fm_freq_max = options.freq_max # build graph self.u = uhd.usrp_source(device_addr=options.args, stream_args=uhd.stream_args('fc32')) usrp_rate = 320e3 demod_rate = 320e3 audio_rate = 32e3 audio_decim = int(demod_rate / audio_rate) self.u.set_samp_rate(usrp_rate) dev_rate = self.u.get_samp_rate() nfilts = 32 chan_coeffs = optfir.low_pass (nfilts, # gain nfilts*usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation rrate = usrp_rate / dev_rate self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) self.guts = blks2.wfm_rcv (demod_rate, audio_decim) self.volume_control = gr.multiply_const_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 self.connect (self.u, self.chan_filt, self.guts, self.volume_control, self.audio_sink) 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.0 if options.volume is None: g = self.volume_range() options.volume = float(g[0]+g[1])/2 frange = self.u.get_freq_range() if(frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): sys.stderr.write("Radio does not support required frequency range.\n") sys.exit(1) if(options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): sys.stderr.write("Requested frequency is outside of required frequency range.\n") sys.exit(1) # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") # 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)
def __init__(self, options, queue): gr.top_block.__init__(self, "usrp_flex") self.options = options self.offset = 0.0 self.adj_time = time.time() self.verbose = options.verbose if options.from_file is None: # Set up USRP source with specified RX daughterboard self.src = usrp.source_c() if options.rx_subdev_spec == None: options.rx_subdev_spec = usrp.pick_rx_subdevice(self.src) self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec) self.src.set_mux(usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec)) # Grab 250 KHz of spectrum (sample rate becomes 250 ksps complex) self.src.set_decim_rate(256) # If no gain specified, set to midrange if options.gain is None: g = self.subdev.gain_range() options.gain = (g[0]+g[1])/2.0 self.subdev.set_gain(options.gain) # Tune daughterboard actual_frequency = options.frequency+options.calibration tune_result = usrp.tune(self.src, 0, self.subdev, actual_frequency) if not tune_result: sys.stderr.write("Failed to set center frequency to "+`actual_frequency`+"\n") sys.exit(1) if options.verbose: print "Using RX daughterboard", self.subdev.side_and_name() print "USRP gain is", options.gain print "USRP tuned to", actual_frequency else: # Use supplied file as source of samples self.src = gr.file_source(gr.sizeof_gr_complex, options.from_file) if options.verbose: print "Reading samples from", options.from_file if options.log and not options.from_file: usrp_sink = gr.file_sink(gr.sizeof_gr_complex, 'usrp.dat') self.connect(self.src, usrp_sink) # Set up 22KHz-wide bandpass about center frequency. Decimate by 10 # to get channel rate of 25Ksps taps = optfir.low_pass(1.0, # Filter gain 250e3, # Sample rate 11000, # One-sided modulation bandwidth 12500, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation if options.verbose: print "Channel filter has", len(taps), "taps." self.chan = gr.freq_xlating_fir_filter_ccf(10, # Decimation rate taps, # Filter taps 0.0, # Offset frequency 250e3) # Sample rate if options.log: chan_sink = gr.file_sink(gr.sizeof_gr_complex, 'chan.dat') self.connect(self.chan, chan_sink) # FLEX protocol demodulator self.flex = pager.flex_demod(queue, options.frequency, options.verbose, options.log) self.connect(self.src, self.chan, self.flex)
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) parser = OptionParser(option_class=eng_option) parser.add_option("-e", "--interface", type="string", default="eth0", help="select Ethernet interface, default is eth0") parser.add_option( "-m", "--mac-addr", type="string", default="", help="select USRP by MAC address, default is auto-select") #parser.add_option("-A", "--antenna", default=None, # help="select Rx Antenna (only on RFX-series boards)") parser.add_option("-f", "--freq", type="eng_float", default=100.1, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph self.u = usrp2.source_32fc(options.interface, options.mac_addr) adc_rate = self.u.adc_rate() # 100 MS/s usrp_decim = 312 self.u.set_decim(usrp_decim) usrp_rate = adc_rate / usrp_decim # ~320 kS/s chanfilt_decim = 1 demod_rate = usrp_rate / chanfilt_decim audio_decimation = 10 audio_rate = demod_rate / audio_decimation # ~32 kHz #FIXME: need named constants and text descriptions available to (gr-)usrp2 even #when usrp(1) module is not built. A usrp_common module, perhaps? dbid = self.u.daughterboard_id() print "Using RX d'board 0x%04X" % (dbid, ) if not (dbid == 0x0001 or #usrp_dbid.BASIC_RX dbid == 0x0003 or #usrp_dbid.TV_RX dbid == 0x000c or #usrp_dbid.TV_RX_REV_2 dbid == 0x0040 or #usrp_dbid.TV_RX_REV_3 dbid == 0x0043 or #usrp_dbid.TV_RX_MIMO dbid == 0x0044 or #usrp_dbid.TV_RX_REV_2_MIMO dbid == 0x0045): #usrp_dbid.TV_RX_REV_3_MIMO print "This daughterboard does not cover the required frequency range" print "for this application. Please use a BasicRX or TVRX daughterboard." raw_input("Press ENTER to continue anyway, or Ctrl-C to exit.") chan_filt_coeffs = optfir.low_pass( 1, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) self.guts = blks2.wfm_rcv(demod_rate, audio_decimation) self.volume_control = gr.multiply_const_ff(self.vol) # sound card as final sink audio_sink = audio.sink(int(audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect(self.u, chan_filt, self.guts, self.volume_control, audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.u.gain_range() options.gain = float(g[0] + g[1]) / 2 if options.volume is None: g = self.volume_range() options.volume = float(g[0] + g[1]) / 2 if abs(options.freq) < 1e6: options.freq *= 1e6 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) parser=OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-f", "--freq", type="eng_float", default=1008.0e3, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-I", "--use-if-freq", action="store_true", default=False, help="use intermediate freq (compensates DC problems in quadrature boards)" ) parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is maximum)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.use_IF=options.use_if_freq if self.use_IF: self.IF_freq=64000.0 else: self.IF_freq=0.0 self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph #TODO: add an AGC after the channel filter and before the AM_demod self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 250 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 256 kS/s chanfilt_decim = 4 demod_rate = usrp_rate / chanfilt_decim # 64 kHz audio_decimation = 2 audio_rate = demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(),) chan_filt_coeffs = optfir.low_pass (1, # gain usrp_rate, # sampling rate 8e3, # passband cutoff 12e3, # stopband cutoff 1.0, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) self.chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) if self.use_IF: # Turn If to baseband and filter. self.chan_filt = gr.freq_xlating_fir_filter_ccf (chanfilt_decim, chan_filt_coeffs, self.IF_freq, usrp_rate) else: self.chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) self.am_demod = gr.complex_to_mag() self.volume_control = gr.multiply_const_ff(self.vol) audio_filt_coeffs = optfir.low_pass (1, # gain demod_rate, # sampling rate 8e3, # passband cutoff 10e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation self.audio_filt=gr.fir_filter_fff(audio_decimation,audio_filt_coeffs) # sound card as final sink audio_sink = audio.sink (int (audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect (self.u, self.chan_filt, self.am_demod, self.audio_filt, self.volume_control, audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: g = self.subdev.gain_range() if True: # if no gain was specified, use the maximum gain available # (usefull for Basic_RX which is relatively deaf and the most probable board to be used for AM) # TODO: check db type to decide on default gain. options.gain = float(g[1]) else: # if no gain was specified, use the mid-point in dB options.gain = float(g[0]+g[1])/2 if options.volume is None: g = self.volume_range() options.volume = float(g[0]*3+g[1])/4 if abs(options.freq) < 1e3: options.freq *= 1e3 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel self.offset = 0.0 # Channel frequency offset parser = OptionParser(option_class=eng_option) parser.add_option( "-p", "--protocol", type="int", default=1, help="set protocol: 0 = RDLAP 19.2kbps; 1 = APCO25 (default)") parser.add_option("-g", "--gain", type="eng_float", default=1.0, help="set linear input gain (default: %default)") parser.add_option("-x", "--freq-translation", type="eng_float", default=0.0, help="initial channel frequency translation") parser.add_option( "-n", "--frame-decim", type="int", default=1, help="set oscope frame decimation factor to n [default=1]") parser.add_option( "-v", "--v-scale", type="eng_float", default=5000, help="set oscope initial V/div to SCALE [default=%default]") parser.add_option( "-t", "--t-scale", type="eng_float", default=49e-6, help="set oscope initial s/div to SCALE [default=50us]") parser.add_option( "-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp") parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, help="set sample rate to RATE (default: %default)") parser.add_option( "-d", "--channel-decim", type="int", default=None, help= "set channel decimation factor to n [default depends on protocol]") parser.add_option("-w", "--wav-file", type="string", default=None, help="WAV input path") parser.add_option("-f", "--data-file", type="string", default=None, help="Data input path") parser.add_option("-B", "--base-band", action="store_true", default=False) parser.add_option("-R", "--repeat", action="store_true", default=False) parser.add_option("-o", "--wav-out", type="string", default=None, help="WAV output path") parser.add_option("-G", "--wav-out-gain", type="eng_float", default=0.05, help="set WAV output gain (default: %default)") parser.add_option("-F", "--data-out", type="string", default=None, help="Data output path") parser.add_option("-C", "--carrier-freq", type="eng_float", default=None, help="set data output carrier frequency to FREQ", metavar="FREQ") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.options = options if options.wav_file is not None: #try: self.input_file = gr.wavfile_source(options.wav_file, options.repeat) #except: # print "WAV file not found or not a WAV file" # sys.exit(1) print "WAV input: %i Hz, %i bits, %i channels" % ( self.input_file.sample_rate(), self.input_file.bits_per_sample(), self.input_file.channels()) self.sample_rate = self.input_file.sample_rate() self.input_stream = gr.throttle(gr.sizeof_float, self.sample_rate) self.connect(self.input_file, self.input_stream) self.src = gr.multiply_const_ff(options.gain) elif options.data_file is not None: if options.base_band: sample_size = gr.sizeof_float print "Data file is baseband (float)" self.src = gr.multiply_const_ff(options.gain) else: sample_size = gr.sizeof_gr_complex print "Data file is IF (complex)" self.src = gr.multiply_const_cc(options.gain) self.input_file = gr.file_source(sample_size, options.data_file, options.repeat) self.sample_rate = options.sample_rate # E.g. 250000 print "Data file sampling rate = " + str(self.sample_rate) self.input_stream = gr.throttle(sample_size, self.sample_rate) self.connect(self.input_file, self.input_stream) else: self.sample_rate = options.sample_rate print "Soundcard sampling rate = " + str(self.sample_rate) self.input_stream = audio.source( self.sample_rate, options.audio_input) # float samples self.src = gr.multiply_const_ff(options.gain) print "Fixed input gain = " + str(options.gain) self.connect(self.input_stream, self.src) if options.wav_out is not None: output_rate = int(self.sample_rate) if options.channel_decim is not None: output_rate /= options.channel_decim self.wav_out = gr.wavfile_sink(options.wav_out, 1, output_rate, 16) print "Opened WAV output file: " + options.wav_out + " at rate: " + str( output_rate) else: self.wav_out = None if options.data_out is not None: if options.carrier_freq is None: self.data_out = gr.file_sink(gr.sizeof_float, options.data_out) print "Opened float data output file: " + options.data_out else: self.data_out = gr.file_sink(gr.sizeof_gr_complex, options.data_out) print "Opened complex data output file: " + options.data_out else: self.data_out = None self.num_inputs = 1 input_rate = self.sample_rate #title='IF', #size=(1024,800), if (options.data_file is not None) and (options.base_band == False): self.scope = scopesink2.scope_sink_c( panel, sample_rate=input_rate, frame_decim=options.frame_decim, v_scale=options.v_scale, t_scale=options.t_scale, num_inputs=self.num_inputs) else: self.scope = scopesink2.scope_sink_f( panel, sample_rate=input_rate, frame_decim=options.frame_decim, v_scale=options.v_scale, t_scale=options.t_scale, num_inputs=self.num_inputs) #self.di = gr.deinterleave(gr.sizeof_float) #self.di = gr.complex_to_float(1) #self.di = gr.complex_to_imag() #self.dr = gr.complex_to_real() #self.connect(self.src,self.dr) #self.connect(self.src,self.di) #self.null = gr.null_sink(gr.sizeof_double) #self.connect(self.src,self.di) #self.connect((self.di,0),(self.scope,0)) #self.connect((self.di,1),(self.scope,1)) #self.connect(self.dr,(self.scope,0)) #self.connect(self.di,(self.scope,1)) self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages self.queue_watcher = queue_watcher(self.msgq, self.adjust_freq_norm) #------------------------------------------------------------------------------- if options.protocol == 0: # ---------- RD-LAP 19.2 kbps (9600 ksps), 25kHz channel, print "RD-LAP selected" self.symbol_rate = 9600 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps if options.channel_decim is None: self.channel_decimation = 10 # decimation (final rate should be at least several symbol rate) else: self.channel_decimation = options.channel_decim self.max_frequency_offset = 12000.0 # coarse carrier tracker leash, ~ half a channel either way self.symbol_deviation = 1200.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = self.sample_rate self.protocol_processing = fsk4.rdlap_f( self.msgq, 0) # desired protocol processing block selected here self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter characteristics channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 10000, # One-sided modulation bandwidth 12000, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter characteristics symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # alpha 500) # taps if options.protocol == 1: # ---------- APCO-25 C4FM Test Data print "APCO selected" self.symbol_rate = 4800 # symbol rate if options.channel_decim is None: self.channel_decimation = 20 # decimation else: self.channel_decimation = options.channel_decim self.max_frequency_offset = 6000.0 # coarse carrier tracker leash self.symbol_deviation = 600.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = self.sample_rate self.protocol_processing = fsk4.apco25_f(self.msgq, 0) self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter if (options.data_file is not None) and (options.base_band == False): channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 5000, # One-sided modulation bandwidth 6500, # One-sided channel bandwidth 0.2, # Passband ripple (was 0.1) 60) # Stopband attenuation else: channel_taps = None # symbol shaping filter symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # alpha 500) # taps # ----------------- End of setup block print "Input rate = " + str(self.input_sample_rate) print "Channel decimation = " + str(self.channel_decimation) print "Channel rate = " + str(self.channel_rate) if channel_taps is not None: self.chan = gr.freq_xlating_fir_filter_ccf( self.channel_decimation, # Decimation rate channel_taps, # Filter taps 0.0, # Offset frequency self.input_sample_rate) # Sample rate if (options.freq_translation != 0): print "Channel center frequency = " + str( options.freq_translation) self.chan.set_center_freq(options.freq_translation) else: self.chan = None if options.carrier_freq is not None: print "Carrier frequency = " + str(options.carrier_freq) self.sig_carrier = gr.sig_source_c(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, 0) self.carrier_mul = gr.multiply_vcc(1) # cc(gr.sizeof_gr_complex) self.connect(self.sig_carrier, (self.carrier_mul, 0)) self.connect(self.chan, (self.carrier_mul, 1)) self.sig_i_carrier = gr.sig_source_f(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, 0) self.sig_q_carrier = gr.sig_source_f(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, (pi / 2.0)) self.carrier_i_mul = gr.multiply_ff(1) self.carrier_q_mul = gr.multiply_ff(1) self.iq_to_float = gr.complex_to_float(1) self.carrier_iq_add = gr.add_ff(1) self.connect(self.carrier_mul, self.iq_to_float) self.connect((self.iq_to_float, 0), (self.carrier_i_mul, 0)) self.connect((self.iq_to_float, 1), (self.carrier_q_mul, 0)) self.connect(self.sig_i_carrier, (self.carrier_i_mul, 1)) self.connect(self.sig_q_carrier, (self.carrier_q_mul, 1)) self.connect(self.carrier_i_mul, (self.carrier_iq_add, 0)) self.connect(self.carrier_q_mul, (self.carrier_iq_add, 1)) else: self.sig_carrier = None self.carrier_mul = None #lf_channel_taps = optfir.low_pass(1.0, # Filter gain # self.input_sample_rate, # Sample rate # 2500, # One-sided modulation bandwidth # 3250, # One-sided channel bandwidth # 0.1, # Passband ripple (0.1) # 60, # Stopband attenuation # 9) # Extra taps (default 2, which doesn't work at 48kHz) #self.lf = gr.fir_filter_fff(self.channel_decimation, lf_channel_taps) self.scope2 = scopesink2.scope_sink_f(panel, sample_rate=self.symbol_rate, frame_decim=1, v_scale=2, t_scale=0.025, num_inputs=self.num_inputs) # also note: this specifies the nominal frequency deviation for the 4-level fsk signal self.fm_demod_gain = self.channel_rate / (2.0 * pi * self.symbol_deviation) self.fm_demod = gr.quadrature_demod_cf(self.fm_demod_gain) symbol_decim = 1 self.symbol_filter = gr.fir_filter_fff(symbol_decim, symbol_coeffs) # eventually specify: sample rate, symbol rate self.demod_fsk4 = fsk4.demod_ff(self.msgq, self.channel_rate, self.symbol_rate) if (self.chan is not None): self.connect(self.src, self.chan, self.fm_demod, self.symbol_filter, self.demod_fsk4, self.protocol_processing) if options.wav_out is not None: print "WAV output gain = " + str(options.wav_out_gain) self.scaled_wav_data = gr.multiply_const_ff( float(options.wav_out_gain)) self.connect(self.scaled_wav_data, self.wav_out) if self.carrier_mul is None: self.connect(self.fm_demod, self.scaled_wav_data) else: self.connect(self.carrier_iq_add, self.scaled_wav_data) if self.data_out is not None: if self.carrier_mul is None: self.connect(self.fm_demod, self.data_out) else: self.connect(self.carrier_mul, self.data_out) # During signal, -4..4 #self.connect(self.fm_demod, self.scope2) else: self.connect(self.src, self.symbol_filter, self.demod_fsk4, self.protocol_processing) self.connect(self.src, self.scope) #self.connect(self.lf, self.scope) self.connect(self.demod_fsk4, self.scope2) #self.connect(self.symbol_filter, self.scope2) # --------------- End of most of the 4L-FSK hack & slash self._build_gui(vbox) # set initial values if options.gain is None: options.gain = 0 self.set_gain(options.gain)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-e", "--interface", type="string", default="eth0", help="select Ethernet interface, default is eth0") parser.add_option("-m", "--mac-addr", type="string", default="", help="select USRP by MAC address, default is auto-select") #parser.add_option("-A", "--antenna", default=None, # help="select Rx Antenna (only on RFX-series boards)") parser.add_option("-f", "--freq", type="eng_float", default=100.1, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self._volume = options.volume self._usrp_freq = options.freq self._usrp_gain = options.gain self._audio_rate = int(32e3) # build graph self.u = usrp2.source_32fc(options.interface, options.mac_addr) # calculate decimation values to get USRP BW at 320 kHz self.calculate_usrp_bw(320e3) self.set_decim(self._usrp_decim) #FIXME: need named constants and text descriptions available to (gr-)usrp2 even #when usrp(1) module is not built. A usrp_common module, perhaps? dbid = self.u.daughterboard_id() print "Using RX d'board 0x%04X" % (dbid,) #if not (dbid == 0x0001 or #usrp_dbid.BASIC_RX # dbid == 0x0003 or #usrp_dbid.TV_RX # dbid == 0x000c or #usrp_dbid.TV_RX_REV_2 # dbid == 0x0040 or #usrp_dbid.TV_RX_REV_3 # dbid == 0x0043 or #usrp_dbid.TV_RX_MIMO # dbid == 0x0044 or #usrp_dbid.TV_RX_REV_2_MIMO # dbid == 0x0045 ): #usrp_dbid.TV_RX_REV_3_MIMO # print "This daughterboard does not cover the required frequency range" # print "for this application. Please use a BasicRX or TVRX daughterboard." # raw_input("Press ENTER to continue anyway, or Ctrl-C to exit.") chan_filt_coeffs = optfir.low_pass (1, # gain self._usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) chan_filt = gr.fir_filter_ccf (self._chanfilt_decim, chan_filt_coeffs) self.guts = blks2.wfm_rcv (self._demod_rate, self._audio_decim) self.volume_control = gr.multiply_const_ff(1) # sound card as final sink #audio_sink = audio.sink (int (audio_rate), # options.audio_output, # False) # ok_to_block audio_sink = audio.sink (self._audio_rate, options.audio_output) if self._usrp_gain is None: # if no gain was specified, use the mid-point in dB g = self.u.gain_range() print "Gain range: ", g self._usrp_gain = float(g[0]+g[1])/2 if self._volume is None: g = self.volume_range() self._volume = float(g[0]+g[1])/2 if abs(self._usrp_freq) < 1e6: self._usrp_freq *= 1e6 # set initial values self.set_gain(self._usrp_gain) self.set_volume(self._volume) if not(self.set_freq(self._usrp_freq)): print ("Failed to set initial frequency") # Define a GUI sink to display the received signal self.qapp = QtGui.QApplication(sys.argv) fftsize = 2048 self.usrp_rx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, -self._usrp_rate/2.0, self._usrp_rate/2.0, "Received Signal", True, True, False, True, False, use_openGL=False) self.usrp_rx2 = qtgui.sink_f(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, -self._usrp_rate/2.0, self._usrp_rate/2.0, "Received Signal", True, True, False, True, False) # now wire it all together self.connect (self.u, chan_filt, self.guts, self.volume_control, audio_sink) self.connect (self.u, self.usrp_rx) self.connect (self.volume_control, self.usrp_rx2) usrp_rx_widget = sip.wrapinstance(self.usrp_rx.pyqwidget(), QtGui.QWidget) usrp_rx2_widget = sip.wrapinstance(self.usrp_rx2.pyqwidget(), QtGui.QWidget) self.main_box = dialog_box(usrp_rx_widget, usrp_rx2_widget, self) self.main_box.show()
def __init__(self, options, queue): gr.top_block.__init__(self, "usrp_flex") self.options = options self.offset = 0.0 self.adj_time = time.time() self.verbose = options.verbose if options.from_file is None: # Set up USRP source with specified RX daughterboard self.src = usrp.source_c() if options.rx_subdev_spec == None: options.rx_subdev_spec = usrp.pick_rx_subdevice(self.src) self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec) self.src.set_mux( usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec)) # Grab 250 KHz of spectrum (sample rate becomes 250 ksps complex) self.src.set_decim_rate(256) # If no gain specified, set to midrange if options.gain is None: g = self.subdev.gain_range() options.gain = (g[0] + g[1]) / 2.0 self.subdev.set_gain(options.gain) # Tune daughterboard actual_frequency = options.frequency + options.calibration tune_result = usrp.tune(self.src, 0, self.subdev, actual_frequency) if not tune_result: sys.stderr.write("Failed to set center frequency to " + ` actual_frequency ` + "\n") sys.exit(1) if options.verbose: print "Using RX daughterboard", self.subdev.side_and_name() print "USRP gain is", options.gain print "USRP tuned to", actual_frequency else: # Use supplied file as source of samples self.src = gr.file_source(gr.sizeof_gr_complex, options.from_file) if options.verbose: print "Reading samples from", options.from_file if options.log and not options.from_file: usrp_sink = gr.file_sink(gr.sizeof_gr_complex, 'usrp.dat') self.connect(self.src, usrp_sink) # Set up 22KHz-wide bandpass about center frequency. Decimate by 10 # to get channel rate of 25Ksps taps = optfir.low_pass( 1.0, # Filter gain 250e3, # Sample rate 11000, # One-sided modulation bandwidth 12500, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation if options.verbose: print "Channel filter has", len(taps), "taps." self.chan = gr.freq_xlating_fir_filter_ccf( 10, # Decimation rate taps, # Filter taps 0.0, # Offset frequency 250e3) # Sample rate if options.log: chan_sink = gr.file_sink(gr.sizeof_gr_complex, 'chan.dat') self.connect(self.chan, chan_sink) # FLEX protocol demodulator self.flex = pager.flex_demod(queue, options.frequency, options.verbose, options.log) self.connect(self.src, self.chan, self.flex)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-f", "--freq", type="eng_float", default=91.2e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB") parser.add_option("-s", "--squelch", type="eng_float", default=0, help="set squelch level (default is 0)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) # connect to USRP usrp_decim = 250 self.u = usrp.source_c(0, usrp_decim) print "USRP Serial: ", self.u.serial_number() demod_rate = self.u.adc_rate() / usrp_decim # 256 kS/s audio_decim = 8 audio_rate = demod_rate / audio_decim # 32 kS/s if options.rx_subdev_spec is None: options.rx_subdev_spec = usrp.pick_subdev(self.u, dblist) self.u.set_mux( usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using d'board", self.subdev.side_and_name() # gain, volume, frequency self.gain = options.gain if options.gain is None: self.gain = self.subdev.gain_range()[1] self.vol = options.volume if self.vol is None: g = self.volume_range() self.vol = float(g[0] + g[1]) / 2 self.freq = options.freq if abs(self.freq) < 1e6: self.freq *= 1e6 print "Volume:%r, Gain:%r, Freq:%3.1f MHz" % (self.vol, self.gain, self.freq / 1e6) # channel filter, wfm_rcv_pll chan_filt_coeffs = optfir.low_pass( 1, # gain demod_rate, # rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation self.chan_filt = gr.fir_filter_ccf(1, chan_filt_coeffs) self.guts = blks2.wfm_rcv_pll(demod_rate, audio_decim) self.connect(self.u, self.chan_filt, self.guts) # volume control, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) self.audio_sink = audio.sink(int(audio_rate), options.audio_output, False) self.connect((self.guts, 0), self.volume_control_l, (self.audio_sink, 0)) self.connect((self.guts, 1), self.volume_control_r, (self.audio_sink, 1)) # pilot channel filter (band-pass, 18.5-19.5kHz) pilot_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 18.5e3, # low cutoff 19.5e3, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) self.connect(self.guts.fm_demod, self.pilot_filter) # RDS channel filter (band-pass, 54-60kHz) rds_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 54e3, # low cutoff 60e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) self.connect(self.guts.fm_demod, self.rds_filter) # create 57kHz subcarrier from 19kHz pilot, downconvert RDS channel self.mixer = gr.multiply_ff() self.connect(self.pilot_filter, (self.mixer, 0)) self.connect(self.pilot_filter, (self.mixer, 1)) self.connect(self.pilot_filter, (self.mixer, 2)) self.connect(self.rds_filter, (self.mixer, 3)) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(1, rds_bb_filter_coeffs) self.connect(self.mixer, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.rds_clock = rds.freq_divider(16) clock_taps = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HANN) self.clock_filter = gr.fir_filter_fff(1, clock_taps) self.connect(self.pilot_filter, self.rds_clock, self.clock_filter) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(demod_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.clock_filter, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) # set initial values self.subdev.set_gain(self.gain) self.set_vol(self.vol) self.set_freq(self.freq)
def __init__(self): 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("", "--spec", type="string", default="A:0 A:0", 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("", "--f1", type="eng_float", default=100.7e6, help="set 1st station frequency to FREQ", metavar="FREQ") parser.add_option("", "--f2", type="eng_float", default=102.5e6, help="set 2nd station freq to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=40, help="set gain in dB (default is midpoint)") parser.add_option( "-O", "--audio-output", type="string", default="", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") parser.add_option("", "--freq-min", type="eng_float", default=87.9e6, help="Set a minimum frequency [default=%default]") parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) if abs(options.f1 - options.f2) > 5.5e6: print "Sorry, two stations must be within 5.5MHz of each other" raise SystemExit f = (options.f1, options.f2) self.vol = .1 self.state = "FREQ" self.fm_freq_min = options.freq_min self.fm_freq_max = options.freq_max # build graph stream_args = uhd.stream_args('fc32', channels=range(2)) self.u = uhd.usrp_source(device_addr=options.args, stream_args=stream_args) # Set front end channel mapping self.u.set_subdev_spec(options.spec) usrp_rate = 320e3 demod_rate = 320e3 audio_rate = 32e3 audio_decim = int(demod_rate / audio_rate) self.u.set_samp_rate(usrp_rate) dev_rate = self.u.get_samp_rate() # Make sure dboard can suppor the required frequencies frange = self.u.get_freq_range() if (frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): sys.stderr.write( "Radio does not support required frequency range.\n") sys.exit(1) # sound card as final sink self.audio_sink = audio.sink(int(audio_rate), options.audio_output) # taps for channel filter nfilts = 32 chan_coeffs = optfir.low_pass( nfilts, # gain nfilts * usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation rrate = usrp_rate / dev_rate # set front end PLL to middle frequency mid_freq = (f[0] + f[1]) / 2.0 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.0 for n in range(2): chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) guts = blks2.wfm_rcv(demod_rate, audio_decim) volume_control = gr.multiply_const_ff(self.vol) #self.connect((self.di, n), chan_filt) self.connect((self.u, n), chan_filt) self.connect(chan_filt, guts, volume_control) self.connect(volume_control, (self.audio_sink, n)) # Test the the requested frequencies are in range if (f[n] < self.fm_freq_min or f[n] > self.fm_freq_max): sys.stderr.write( "Requested frequency is outside of required frequency range.\n" ) sys.exit(1) # Tune each channel by setting the RF freq to mid_freq and the # DDC freq to f[n]. tr = uhd.tune_request( f[n], rf_freq=mid_freq, rf_freq_policy=uhd.tune_request.POLICY_MANUAL) self.u.set_center_freq(tr, n) # Set gain for each channel self.set_gain(options.gain, n) # Set the antenna if (options.antenna): self.u.set_antenna(options.antenna, n)
def __init__(self): 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("", "--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("-f", "--freq", type="eng_float", default=100.1e6, 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("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option( "-O", "--audio-output", type="string", default="default", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") parser.add_option("", "--freq-min", type="eng_float", default=87.9e6, help="Set a minimum frequency [default=%default]") parser.add_option("", "--freq-max", type="eng_float", default=108.1e6, help="Set a maximum frequency [default=%default]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.state = "FREQ" self.freq = 0 self.fm_freq_min = options.freq_min self.fm_freq_max = options.freq_max # build graph self.u = uhd.usrp_source(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) usrp_rate = 320e3 demod_rate = 320e3 audio_rate = 32e3 audio_decim = int(demod_rate / audio_rate) self.u.set_samp_rate(usrp_rate) dev_rate = self.u.get_samp_rate() nfilts = 32 chan_coeffs = optfir.low_pass( nfilts, # gain nfilts * usrp_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation rrate = usrp_rate / dev_rate self.chan_filt = blks2.pfb_arb_resampler_ccf(rrate, chan_coeffs, nfilts) self.guts = blks2.wfm_rcv(demod_rate, audio_decim) self.volume_control = gr.multiply_const_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 self.connect(self.u, self.chan_filt, self.guts, self.volume_control, self.audio_sink) 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.0 if options.volume is None: g = self.volume_range() options.volume = float(g[0] + g[1]) / 2 frange = self.u.get_freq_range() if (frange.start() > self.fm_freq_max or frange.stop() < self.fm_freq_min): sys.stderr.write( "Radio does not support required frequency range.\n") sys.exit(1) if (options.freq < self.fm_freq_min or options.freq > self.fm_freq_max): sys.stderr.write( "Requested frequency is outside of required frequency range.\n" ) sys.exit(1) # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) parser = OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-f", "--freq", type="eng_float", default=1008.0e3, help="set frequency to FREQ", metavar="FREQ") parser.add_option( "-I", "--use-if-freq", action="store_true", default=False, help= "use intermediate freq (compensates DC problems in quadrature boards)" ) parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is maximum)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") 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) self.frame = frame self.panel = panel self.use_IF = options.use_if_freq if self.use_IF: self.IF_freq = 64000.0 else: self.IF_freq = 0.0 self.vol = 0 self.state = "FREQ" self.freq = 0 # build graph #TODO: add an AGC after the channel filter and before the AM_demod self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 250 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 256 kS/s chanfilt_decim = 4 demod_rate = usrp_rate / chanfilt_decim # 64 kHz audio_decimation = 2 audio_rate = demod_rate / audio_decimation # 32 kHz if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux( usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(), ) chan_filt_coeffs = optfir.low_pass( 1, # gain usrp_rate, # sampling rate 8e3, # passband cutoff 12e3, # stopband cutoff 1.0, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) self.chan_filt = gr.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) if self.use_IF: # Turn If to baseband and filter. self.chan_filt = gr.freq_xlating_fir_filter_ccf( chanfilt_decim, chan_filt_coeffs, self.IF_freq, usrp_rate) else: self.chan_filt = gr.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) self.am_demod = gr.complex_to_mag() self.volume_control = gr.multiply_const_ff(self.vol) audio_filt_coeffs = optfir.low_pass( 1, # gain demod_rate, # sampling rate 8e3, # passband cutoff 10e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation self.audio_filt = gr.fir_filter_fff(audio_decimation, audio_filt_coeffs) # sound card as final sink audio_sink = audio.sink(int(audio_rate), options.audio_output, False) # ok_to_block # now wire it all together self.connect(self.u, self.chan_filt, self.am_demod, self.audio_filt, self.volume_control, audio_sink) self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) if options.gain is None: g = self.subdev.gain_range() if True: # if no gain was specified, use the maximum gain available # (usefull for Basic_RX which is relatively deaf and the most probable board to be used for AM) # TODO: check db type to decide on default gain. options.gain = float(g[1]) else: # if no gain was specified, use the mid-point in dB options.gain = float(g[0] + g[1]) / 2 if options.volume is None: g = self.volume_range() options.volume = float(g[0] * 3 + g[1]) / 4 if abs(options.freq) < 1e3: options.freq *= 1e3 # set initial values self.set_gain(options.gain) self.set_vol(options.volume) if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel self.offset = 0.0 parser = OptionParser(option_class=eng_option) parser.add_option( "-R", "--rx-subdev-spec", type="subdev", default=None, help= "select USRP Rx side A or B (default=first one with a daughterboard)" ) parser.add_option( "-d", "--decim", type="int", default=256, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=None, help="set frequency to FREQ", metavar="FREQ") parser.add_option( "-p", "--protocol", type="int", default=0, help="set protocol: 0 = RDLAP 19.2kbps (default); 1 = APCO25") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is midpoint)") parser.add_option("-8", "--width-8", action="store_true", default=False, help="Enable 8-bit samples across USB") parser.add_option("--no-hb", action="store_true", default=False, help="don't use halfband filter in usrp") parser.add_option( "-C", "--basic-complex", action="store_true", default=False, help= "Use both inputs of a basicRX or LFRX as a single Complex input channel" ) parser.add_option( "-D", "--basic-dualchan", action="store_true", default=False, help= "Use both inputs of a basicRX or LFRX as seperate Real input channels" ) parser.add_option( "-n", "--frame-decim", type="int", default=1, help="set oscope frame decimation factor to n [default=1]") parser.add_option( "-v", "--v-scale", type="eng_float", default=1000, help="set oscope initial V/div to SCALE [default=%default]") parser.add_option( "-t", "--t-scale", type="eng_float", default=49e-6, help="set oscope initial s/div to SCALE [default=50us]") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.show_debug_info = True # build the graph if options.basic_dualchan: self.num_inputs = 2 else: self.num_inputs = 1 if options.no_hb or (options.decim < 8): #Min decimation of this firmware is 4. #contains 4 Rx paths without halfbands and 0 tx paths. self.fpga_filename = "std_4rx_0tx.rbf" self.u = usrp.source_c(nchan=self.num_inputs, decim_rate=options.decim, fpga_filename=self.fpga_filename) else: #Min decimation of standard firmware is 8. #standard fpga firmware "std_2rxhb_2tx.rbf" #contains 2 Rx paths with halfband filters and 2 tx paths (the default) self.u = usrp.source_c(nchan=self.num_inputs, decim_rate=options.decim) if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) if options.width_8: width = 8 shift = 8 format = self.u.make_format(width, shift) #print "format =", hex(format) r = self.u.set_format(format) #print "set_format =", r # determine the daughterboard subdevice we're using self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) if (options.basic_complex or options.basic_dualchan): if ((self.subdev.dbid() == usrp_dbid.BASIC_RX) or (self.subdev.dbid() == usrp_dbid.LF_RX)): side = options.rx_subdev_spec[0] # side A = 0, side B = 1 if options.basic_complex: #force Basic_RX and LF_RX in complex mode (use both I and Q channel) print "Receiver daughterboard forced in complex mode. Both inputs will combined to form a single complex channel." self.dualchan = False if side == 0: self.u.set_mux( 0x00000010 ) #enable adc 0 and 1 to form a single complex input on side A else: #side ==1 self.u.set_mux( 0x00000032 ) #enable adc 3 and 2 to form a single complex input on side B elif options.basic_dualchan: #force Basic_RX and LF_RX in dualchan mode (use input A for channel 0 and input B for channel 1) print "Receiver daughterboard forced in dualchannel mode. Each input will be used to form a seperate channel." self.dualchan = True if side == 0: self.u.set_mux( gru.hexint(0xf0f0f1f0) ) #enable adc 0, side A to form a real input on channel 0 and adc1,side A to form a real input on channel 1 else: #side ==1 self.u.set_mux( 0xf0f0f3f2 ) #enable adc 2, side B to form a real input on channel 0 and adc3,side B to form a real input on channel 1 else: sys.stderr.write( 'options basic_dualchan or basic_complex is only supported for Basic Rx or LFRX at the moment\n' ) sys.exit(1) else: self.dualchan = False self.u.set_mux( usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) input_rate = self.u.adc_freq() / self.u.decim_rate() self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate, frame_decim=options.frame_decim, v_scale=options.v_scale, t_scale=options.t_scale, num_inputs=self.num_inputs) if self.dualchan: # deinterleave two channels from FPGA self.di = gr.deinterleave(gr.sizeof_gr_complex) self.connect(self.u, self.di) self.connect((self.di, 0), (self.scope, 0)) self.connect((self.di, 1), (self.scope, 1)) else: self.connect(self.u, self.scope) self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages self.queue_watcher = queue_watcher(self.msgq, self.adjust_freq_norm) #------------------------------------------------------------------------------- if options.protocol == 0: # ---------- RD-LAP 19.2 kbps (9600 ksps), 25kHz channel, self.symbol_rate = 9600 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps self.channel_decimation = 10 # decimation (final rate should be at least several symbol rate) self.max_frequency_offset = 12000.0 # coarse carrier tracker leash, ~ half a channel either way self.symbol_deviation = 1200.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = 64e6 / options.decim # for USRP: 64MHz / FPGA decimation rate self.protocol_processing = fsk4.rdlap_f( self.msgq, 0) # desired protocol processing block selected here self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter characteristics channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 10000, # One-sided modulation bandwidth 12000, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter characteristics symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type if options.protocol == 1: # ---------- APCO-25 C4FM Test Data self.symbol_rate = 4800 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps self.channel_decimation = 20 # decimation self.max_frequency_offset = 6000.0 # coarse carrier tracker leash self.symbol_deviation = 600.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = 64e6 / options.decim # for USRP: 64MHz / FPGA decimation rate self.protocol_processing = fsk4.apco25_f(self.msgq, 0) self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 5000, # One-sided modulation bandwidth 6500, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type # ----------------- End of setup block self.chan = gr.freq_xlating_fir_filter_ccf( self.channel_decimation, # Decimation rate channel_taps, # Filter taps 0.0, # Offset frequency self.input_sample_rate) # Sample rate self.scope2 = scopesink2.scope_sink_f(panel, sample_rate=self.symbol_rate, frame_decim=1, v_scale=2, t_scale=0.025, num_inputs=self.num_inputs) # also note: # this specifies the nominal frequency deviation for the 4-level fsk signal self.fm_demod_gain = self.channel_rate / (2.0 * pi * self.symbol_deviation) self.fm_demod = gr.quadrature_demod_cf(self.fm_demod_gain) symbol_decim = 1 self.symbol_filter = gr.fir_filter_fff(symbol_decim, symbol_coeffs) # eventually specify: sample rate, symbol rate self.demod_fsk4 = fsk4.demod_ff(self.msgq, self.channel_rate, self.symbol_rate) #self.rdlap_processing = fsk4.rdlap_f(self.msgq, 0) self.connect(self.u, self.chan, self.fm_demod, self.symbol_filter, self.demod_fsk4, self.protocol_processing) self.connect(self.demod_fsk4, self.scope2) # --------------- End of most of the 4L-FSK hack & slash self._build_gui(vbox) # set initial values if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0] + g[1]) / 2 if options.freq is None: if ((self.subdev.dbid() == usrp_dbid.BASIC_RX) or (self.subdev.dbid() == usrp_dbid.LF_RX)): #for Basic RX and LFRX if no freq is specified you probably want 0.0 Hz and not 45 GHz options.freq = 0.0 else: # if no freq was specified, use the mid-point r = self.subdev.freq_range() options.freq = float(r[0] + r[1]) / 2 self.set_gain(options.gain) if self.show_debug_info: # self.myform['decim'].set_value(self.u.decim_rate()) self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) self.myform['dbname'].set_value(self.subdev.name()) self.myform['baseband'].set_value(0) self.myform['ddc'].set_value(0) if self.num_inputs == 2: self.myform['baseband2'].set_value(0) self.myform['ddc2'].set_value(0) if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") if self.num_inputs == 2: if not (self.set_freq2(options.freq)): self._set_status_msg( "Failed to set initial frequency for channel 2")