3 from gnuradio import gr, gru, eng_notation, optfir
4 from gnuradio import audio
5 from gnuradio import usrp
6 from gnuradio import blks
7 from gnuradio.eng_option import eng_option
8 from optparse import OptionParser
13 def pick_subdevice(u):
15 The user didn't specify a subdevice on the command line.
16 Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.
20 return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
21 usrp_dbid.TV_RX_REV_2,
25 class wfm_rx_graph (gr.flow_graph):
28 gr.flow_graph.__init__(self)
30 parser=OptionParser(option_class=eng_option)
31 parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
32 help="select USRP Rx side A or B (default=A)")
33 parser.add_option("", "--f1", type="eng_float", default=100.7e6,
34 help="set 1st station frequency to FREQ", metavar="FREQ")
35 parser.add_option("", "--f2", type="eng_float", default=102.5e6,
36 help="set 2nd station freq to FREQ", metavar="FREQ")
37 parser.add_option("-g", "--gain", type="eng_float", default=40,
38 help="set gain in dB (default is midpoint)")
39 parser.add_option("-O", "--audio-output", type="string", default="",
40 help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp")
42 (options, args) = parser.parse_args()
47 if abs(options.f1) < 1e6:
50 if abs(options.f2) < 1e6:
53 if abs(options.f1 - options.f2) > 5.5e6:
54 print "Sorry, two stations must be within 5.5MHz of each other"
57 f = (options.f1, options.f2)
64 self.u = usrp.source_c(0, nchan=2) # usrp is data source
66 adc_rate = self.u.adc_rate() # 64 MS/s
68 self.u.set_decim_rate(usrp_decim)
69 usrp_rate = adc_rate / usrp_decim # 320 kS/s
71 demod_rate = usrp_rate / chanfilt_decim
73 audio_rate = demod_rate / audio_decimation # 32 kHz
76 if options.rx_subdev_spec is None:
77 options.rx_subdev_spec = pick_subdevice(self.u)
79 mv = usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)
80 mv |= (mv << 8) & 0xff00 # both DDC inputs setup same way
82 self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
83 print "Using RX d'board %s" % (self.subdev.side_and_name(),)
86 # deinterleave two channels from FPGA
87 di = gr.deinterleave(gr.sizeof_gr_complex)
89 # wire up the head of the chain
90 self.connect(self.u, di)
92 # sound card as final sink
93 audio_sink = audio.sink(int(audio_rate), options.audio_output)
95 # taps for channel filter
96 chan_filt_coeffs = optfir.low_pass (1, # gain
97 usrp_rate, # sampling rate
98 80e3, # passband cutoff
99 115e3, # stopband cutoff
100 0.1, # passband ripple
101 60) # stopband attenuation
102 #print len(chan_filt_coeffs)
104 mid_freq = (f[0] + f[1]) / 2
105 # set front end PLL to middle frequency
106 ok, baseband_freq = self.subdev.set_freq(mid_freq)
109 chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
110 guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
111 volume_control = gr.multiply_const_ff(self.vol)
112 self.connect((di, n), chan_filt)
113 self.connect(chan_filt, guts, volume_control)
114 self.connect(volume_control, (audio_sink, n))
115 dxc_freq, inverted = usrp.calc_dxc_freq(f[n], baseband_freq,
116 self.u.converter_rate())
117 self.u.set_rx_freq(n, dxc_freq)
120 if options.gain is None:
121 # if no gain was specified, use the mid-point in dB
122 g = self.subdev.gain_range()
123 options.gain = float(g[0]+g[1])/2
127 self.set_gain(options.gain)
130 def set_vol (self, vol):
132 self.volume_control.set_k(self.vol)
135 def set_gain(self, gain):
136 self.subdev.set_gain(gain)
139 if __name__ == '__main__':
143 except KeyboardInterrupt: