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("-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("-H", "--hostname", type="string", default="localhost", help="set hostname of generic sdr") parser.add_option("-P", "--portnum", type="int", default=None, help="set portnum of generic sdr") parser.add_option("-r", "--sdr_rate", type="eng_float", default=250e3, help="set sample rate of generic sdr") 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)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.vol = options.volume if self.vol is None: self.vol = 0.1 # connect to generic SDR sdr_rate = options.sdr_rate audio_decim = 8 audio_rate = int(sdr_rate/audio_decim) print "audio_rate = ", audio_rate self.interleaved_short_to_complex = gr.interleaved_short_to_complex() self.char_to_short = gr.char_to_short(1) self.sdr_source = grc_blks2.tcp_source( itemsize=gr.sizeof_char*1, addr=options.hostname, port=options.portnum, server=False ) # self.sdr_source = gr.file_source(1, 'sdrs_baseband.dat') # self.throttle = gr.throttle(1, 500e3) # self.connect(self.sdr_source, self.file_sink) self.logger = gr.file_sink(1, 'log.out') self.connect(self.sdr_source, self.logger) # channel filter chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) # print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / sdr_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / sdr_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( 1.0, # Loop BW fm_max_freq, # in radians/sample -fm_max_freq) self.fm_demod.set_alpha(fm_alpha) self.fm_demod.set_beta(fm_beta) self.connect(self.sdr_source, self.char_to_short) self.connect(self.char_to_short, self.interleaved_short_to_complex) self.connect(self.interleaved_short_to_complex, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) # print "# lpr filter:", len(lpr_filter_coeffs), "taps" # print "# pilot filter:", len(pilot_filter_coeffs), "taps" # print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" # print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # volume control, complex2flot, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) output_audio_rate = 48000 self.resamp_L = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.resamp_R = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.connect(self.left, self.volume_control_l, self.resamp_L) self.connect(self.right, self.volume_control_r, self.resamp_R) # self.audio_sink = audio.sink(int(output_audio_rate), # options.audio_output, False) # self.connect(self.resamp_L, (self.audio_sink, 0)) # self.connect(self.resamp_R, (self.audio_sink, 1)) self.file_sink1 = gr.file_sink(gr.sizeof_float, 'audioL.dat') self.file_sink2 = gr.file_sink(gr.sizeof_float, 'audioR.dat') self.file_sink3 = gr.file_sink(gr.sizeof_float, 'fmDemod.dat') self.connect(self.resamp_L, self.file_sink1) self.connect(self.resamp_R, self.file_sink2) self.connect(self.fm_demod, self.file_sink3) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) # print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) # print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_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.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder)
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=91.2e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB") # FIXME add squelch 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)") # print help when called with wrong arguments (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() usrp_rate = self.u.adc_rate() / usrp_decim # 256 kS/s print "usrp_rate =", usrp_rate audio_decim = 8 audio_rate = usrp_rate / audio_decim # 32 kS/s print "audio_rate =", audio_rate #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: g = self.subdev.gain_range() self.gain = float(g[0]+g[1])/2 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 print "Volume:%r, Gain:%r, Freq:%3.1f MHz" % (self.vol, self.gain, self.freq/1e6) # channel filter chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / usrp_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / usrp_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( #fm_alpha, # phase gain #fm_beta, # freq gain 1.0, # Loop BW fm_max_freq, # in radians/sample -fm_max_freq) self.fm_demod.set_alpha(fm_alpha) self.fm_demod.set_beta(fm_beta) self.connect(self.u, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) print "# lpr filter:", len(lpr_filter_coeffs), "taps" print "# pilot filter:", len(pilot_filter_coeffs), "taps" print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # volume control, complex2flot, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) output_audio_rate = 48000 self.audio_sink = audio.sink(int(output_audio_rate), options.audio_output, False) #self.connect(self.left, self.volume_control_l, (self.audio_sink, 0)) #self.connect(self.right, self.volume_control_r, (self.audio_sink, 1)) self.resamp_L = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.resamp_R = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.connect(self.left, self.volume_control_l, self.resamp_L, (self.audio_sink, 0)) self.connect(self.right, self.volume_control_r, self.resamp_R, (self.audio_sink, 1)) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_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.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) self.frame = frame self.panel = panel self._build_gui(vbox, usrp_rate, audio_rate) self.set_gain(self.gain) self.set_vol(self.vol) if not(self.set_freq(self.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("-H", "--hostname", type="string", default="localhost", help="set hostname of generic sdr") parser.add_option("-P", "--portnum", type="int", default=None, help="set portnum of generic sdr") parser.add_option("-W", "--wsportnum", type="int", default=None, help="set portnum of audio websocket server") parser.add_option("-r", "--sdr_rate", type="eng_float", default=250e3, help="set sample rate of generic sdr") 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)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.vol = options.volume if self.vol is None: self.vol = 0.1 # connect to generic SDR sdr_rate = options.sdr_rate audio_decim = 8 audio_rate = int(sdr_rate/audio_decim) print "audio_rate = ", audio_rate self.interleaved_short_to_complex = gr.interleaved_short_to_complex() self.char_to_short = gr.char_to_short(1) self.sdr_source = grc_blks2.tcp_source( itemsize=gr.sizeof_char*1, addr=options.hostname, port=options.portnum, server=False ) # self.sdr_source = gr.file_source(1, 'sdrs_baseband.dat') # self.throttle = gr.throttle(1, 500e3) # self.connect(self.sdr_source, self.file_sink) self.logger = gr.file_sink(1, 'log.out') self.connect(self.sdr_source, self.logger) # channel filter chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) # print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / sdr_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / sdr_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( 1.0, # Loop BW fm_max_freq, # in radians/sample -fm_max_freq) self.fm_demod.set_alpha(fm_alpha) self.fm_demod.set_beta(fm_beta) self.connect(self.sdr_source, self.char_to_short) self.connect(self.char_to_short, self.interleaved_short_to_complex) self.connect(self.interleaved_short_to_complex, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) # print "# lpr filter:", len(lpr_filter_coeffs), "taps" # print "# pilot filter:", len(pilot_filter_coeffs), "taps" # print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" # print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # volume control, complex2flot, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) output_audio_rate = 48000 self.resamp_L = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.resamp_R = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.connect(self.left, self.volume_control_l, self.resamp_L) self.connect(self.right, self.volume_control_r, self.resamp_R) # self.audio_sink = audio.sink(int(output_audio_rate), # options.audio_output, False) # self.connect(self.resamp_L, (self.audio_sink, 0)) # self.connect(self.resamp_R, (self.audio_sink, 1)) # self.file_sink1 = gr.file_sink(gr.sizeof_float, 'audioL.dat') # self.file_sink2 = gr.file_sink(gr.sizeof_float, 'audioR.dat') # self.file_sink3 = gr.file_sink(gr.sizeof_float, 'fmDemod.dat') # self.connect(self.resamp_L, self.file_sink1) # self.connect(self.resamp_R, self.file_sink2) # self.connect(self.fm_demod, self.file_sink3) # Interleave both channels so that we can push over one websocket connection self.audio_interleaver = gr.float_to_complex(1) self.connect(self.resamp_L, (self.audio_interleaver, 0)) self.connect(self.resamp_R, (self.audio_interleaver, 1)) self.ws_audio_server = sdrportal.ws_sink_c(True, options.wsportnum, "FLOAT") self.connect(self.audio_interleaver, self.ws_audio_server) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) # print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) # print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_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.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder)
def __init__(self): grc_wxgui.top_block_gui.__init__( self, title="Stereo FM receiver and RDS Decoder") ################################################## # Variables ################################################## self.xlate_decim = xlate_decim = 4 self.samp_rate = samp_rate = 1000000 self.freq_offset = freq_offset = 250e3 self.freq = freq = 88.5e6 self.baseband_rate = baseband_rate = samp_rate / xlate_decim self.audio_decim = audio_decim = 4 self.xlate_bandwidth = xlate_bandwidth = 250e3 self.volume = volume = 0 self.loop_bw = loop_bw = 16e3 * 0 + 18e3 * 1 self.gain = gain = 10 self.freq_tune = freq_tune = freq - freq_offset self.audio_rate = audio_rate = 48000 self.audio_decim_rate = audio_decim_rate = baseband_rate / audio_decim self.antenna = antenna = 'TX/RX' ################################################## # Message Queues ################################################## gr_rds_data_decoder_0_msgq_out = gr_rds_panel_0_msgq_in = gr.msg_queue( 2) ################################################## # Blocks ################################################## _volume_sizer = wx.BoxSizer(wx.VERTICAL) self._volume_text_box = forms.text_box( parent=self.GetWin(), sizer=_volume_sizer, value=self.volume, callback=self.set_volume, label="Volume", converter=forms.float_converter(), proportion=0, ) self._volume_slider = forms.slider( parent=self.GetWin(), sizer=_volume_sizer, value=self.volume, callback=self.set_volume, minimum=-20, maximum=10, num_steps=300, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_volume_sizer) self.nb = self.nb = wx.Notebook(self.GetWin(), style=wx.NB_TOP) self.nb.AddPage(grc_wxgui.Panel(self.nb), "BB") self.nb.AddPage(grc_wxgui.Panel(self.nb), "Demod") self.nb.AddPage(grc_wxgui.Panel(self.nb), "L+R") self.nb.AddPage(grc_wxgui.Panel(self.nb), "Pilot") self.nb.AddPage(grc_wxgui.Panel(self.nb), "DSBSC") self.nb.AddPage(grc_wxgui.Panel(self.nb), "RDS Raw") self.nb.AddPage(grc_wxgui.Panel(self.nb), "L-R") self.nb.AddPage(grc_wxgui.Panel(self.nb), "RDS") self.Add(self.nb) _loop_bw_sizer = wx.BoxSizer(wx.VERTICAL) self._loop_bw_text_box = forms.text_box( parent=self.GetWin(), sizer=_loop_bw_sizer, value=self.loop_bw, callback=self.set_loop_bw, label="Loop BW", converter=forms.float_converter(), proportion=0, ) self._loop_bw_slider = forms.slider( parent=self.GetWin(), sizer=_loop_bw_sizer, value=self.loop_bw, callback=self.set_loop_bw, minimum=0, maximum=baseband_rate, num_steps=1000, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_loop_bw_sizer) _gain_sizer = wx.BoxSizer(wx.VERTICAL) self._gain_text_box = forms.text_box( parent=self.GetWin(), sizer=_gain_sizer, value=self.gain, callback=self.set_gain, label="Gain", converter=forms.float_converter(), proportion=0, ) self._gain_slider = forms.slider( parent=self.GetWin(), sizer=_gain_sizer, value=self.gain, callback=self.set_gain, minimum=0, maximum=50, num_steps=50, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_gain_sizer) self._freq_offset_text_box = forms.text_box( parent=self.GetWin(), value=self.freq_offset, callback=self.set_freq_offset, label="Freq Offset", converter=forms.float_converter(), ) self.Add(self._freq_offset_text_box) _freq_sizer = wx.BoxSizer(wx.VERTICAL) self._freq_text_box = forms.text_box( parent=self.GetWin(), sizer=_freq_sizer, value=self.freq, callback=self.set_freq, label="Freq", converter=forms.float_converter(), proportion=0, ) self._freq_slider = forms.slider( parent=self.GetWin(), sizer=_freq_sizer, value=self.freq, callback=self.set_freq, minimum=87.5e6, maximum=108e6, num_steps=205, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_freq_sizer) self._antenna_chooser = forms.drop_down( parent=self.GetWin(), value=self.antenna, callback=self.set_antenna, label="Antenna", choices=['TX/RX', 'RX2'], labels=[], ) self.Add(self._antenna_chooser) self.wxgui_scopesink2_0 = scopesink2.scope_sink_f( self.nb.GetPage(3).GetWin(), title="Pilot", sample_rate=baseband_rate, v_scale=0, v_offset=0, t_scale=0, ac_couple=False, xy_mode=False, num_inputs=1, trig_mode=gr.gr_TRIG_MODE_AUTO, y_axis_label="Counts", ) self.nb.GetPage(3).Add(self.wxgui_scopesink2_0.win) self.wxgui_fftsink2_0_0_0_1_0_1 = fftsink2.fft_sink_f( self.nb.GetPage(7).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=-50, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="RDS", peak_hold=False, ) self.nb.GetPage(7).Add(self.wxgui_fftsink2_0_0_0_1_0_1.win) self.wxgui_fftsink2_0_0_0_1_0_0 = fftsink2.fft_sink_f( self.nb.GetPage(6).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=-50, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="L-R", peak_hold=False, ) self.nb.GetPage(6).Add(self.wxgui_fftsink2_0_0_0_1_0_0.win) self.wxgui_fftsink2_0_0_0_1_0 = fftsink2.fft_sink_f( self.nb.GetPage(5).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="RDS", peak_hold=False, ) self.nb.GetPage(5).Add(self.wxgui_fftsink2_0_0_0_1_0.win) self.wxgui_fftsink2_0_0_0_1 = fftsink2.fft_sink_f( self.nb.GetPage(4).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="DSBSC Sub-carrier", peak_hold=False, ) self.nb.GetPage(4).Add(self.wxgui_fftsink2_0_0_0_1.win) self.wxgui_fftsink2_0_0_0 = fftsink2.fft_sink_f( self.nb.GetPage(2).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=audio_decim_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="L+R", peak_hold=False, ) self.nb.GetPage(2).Add(self.wxgui_fftsink2_0_0_0.win) self.wxgui_fftsink2_0_0 = fftsink2.fft_sink_f( self.nb.GetPage(1).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=True, avg_alpha=0.8, title="FM Demod", peak_hold=False, ) self.nb.GetPage(1).Add(self.wxgui_fftsink2_0_0.win) self.wxgui_fftsink2_0 = fftsink2.fft_sink_c( self.nb.GetPage(0).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=-30, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=True, avg_alpha=0.8, title="Baseband", peak_hold=False, ) self.nb.GetPage(0).Add(self.wxgui_fftsink2_0.win) self.uhd_usrp_source_0 = uhd.usrp_source( device_addr="", stream_args=uhd.stream_args( cpu_format="fc32", channels=range(1), ), ) self.uhd_usrp_source_0.set_samp_rate(samp_rate) self.uhd_usrp_source_0.set_center_freq(freq_tune, 0) self.uhd_usrp_source_0.set_gain(gain, 0) self.uhd_usrp_source_0.set_antenna(antenna, 0) self.gr_rds_panel_0 = rds.rdsPanel(gr_rds_panel_0_msgq_in, freq, self.GetWin()) self.Add(self.gr_rds_panel_0) self.gr_rds_freq_divider_0 = rds.freq_divider(16) self.gr_rds_data_decoder_0 = rds.data_decoder( gr_rds_data_decoder_0_msgq_out) self.gr_rds_bpsk_demod_0 = rds.bpsk_demod(audio_decim_rate) self.gr_pll_freqdet_cf_0 = gr.pll_freqdet_cf( 1.0 * 0 + (loop_bw * 2 * math.pi / baseband_rate), +(2.0 * math.pi * 90e3 / baseband_rate), -(2.0 * math.pi * 90e3 / baseband_rate)) self.gr_multiply_const_vxx_0_0 = gr.multiply_const_vff( (10**(1. * volume / 10), )) self.gr_multiply_const_vxx_0 = gr.multiply_const_vff( (10**(1. * volume / 10), )) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc( xlate_decim, (firdes.low_pass(1, samp_rate, xlate_bandwidth / 2, 1000)), freq_offset, samp_rate) self.fir_filter_xxx_7 = filter.fir_filter_fff( audio_decim, (firdes.low_pass(1, baseband_rate, 1.2e3, 1.5e3, firdes.WIN_HAMMING))) self.fir_filter_xxx_6 = filter.fir_filter_fff( audio_decim, (firdes.low_pass(1, baseband_rate, 1.5e3, 2e3, firdes.WIN_HAMMING))) self.fir_filter_xxx_5 = filter.fir_filter_fff( audio_decim, (firdes.low_pass(1.0, baseband_rate, 15e3, 1e3, firdes.WIN_HAMMING))) self.fir_filter_xxx_4 = filter.fir_filter_fff( 1, (firdes.band_pass(1.0, baseband_rate, 57e3 - 3e3, 57e3 + 3e3, 3e3, firdes.WIN_HAMMING))) self.fir_filter_xxx_3 = filter.fir_filter_fff( 1, (firdes.band_pass(1.0, baseband_rate, 38e3 - 15e3 / 2, 38e3 + 15e3 / 2, 1e3, firdes.WIN_HAMMING))) self.fir_filter_xxx_2 = filter.fir_filter_fff( 1, (firdes.band_pass(1.0, baseband_rate, 19e3 - 500, 19e3 + 500, 1e3, firdes.WIN_HAMMING))) self.fir_filter_xxx_1 = filter.fir_filter_fff( audio_decim, (firdes.low_pass(1.0, baseband_rate, 15e3, 1e3, firdes.WIN_HAMMING))) self.fir_filter_xxx_0 = filter.fir_filter_ccc(1, (firdes.low_pass( 1.0, baseband_rate, 80e3, 35e3, firdes.WIN_HAMMING))) self.digital_diff_decoder_bb_0 = digital.diff_decoder_bb(2) self.blocks_sub_xx_0 = blocks.sub_ff(1) self.blocks_multiply_xx_0_0 = blocks.multiply_vff(1) self.blocks_multiply_xx_0 = blocks.multiply_vff(1) self.blocks_add_xx_0 = blocks.add_vff(1) self.blks2_rational_resampler_xxx_0_0 = blks2.rational_resampler_fff( interpolation=audio_rate, decimation=audio_decim_rate, taps=None, fractional_bw=None, ) self.blks2_rational_resampler_xxx_0 = blks2.rational_resampler_fff( interpolation=audio_rate, decimation=audio_decim_rate, taps=None, fractional_bw=None, ) self.blks2_fm_deemph_0_0_0 = blks2.fm_deemph(fs=baseband_rate, tau=75e-6) self.blks2_fm_deemph_0_0 = blks2.fm_deemph(fs=baseband_rate, tau=75e-6) self.audio_sink_0 = audio.sink(audio_rate, "", True) ################################################## # Connections ################################################## self.connect((self.uhd_usrp_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.fir_filter_xxx_0, 0)) self.connect((self.fir_filter_xxx_0, 0), (self.gr_pll_freqdet_cf_0, 0)) self.connect((self.gr_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_1, 0)) self.connect((self.gr_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_2, 0)) self.connect((self.gr_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_4, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0, 1)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0_0, 1)) self.connect((self.fir_filter_xxx_3, 0), (self.blocks_multiply_xx_0, 2)) self.connect((self.fir_filter_xxx_4, 0), (self.blocks_multiply_xx_0_0, 3)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0_0, 2)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.wxgui_fftsink2_0, 0)) self.connect((self.fir_filter_xxx_1, 0), (self.blocks_sub_xx_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.gr_rds_freq_divider_0, 0)) self.connect((self.fir_filter_xxx_1, 0), (self.blocks_add_xx_0, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.fir_filter_xxx_5, 0)) self.connect((self.gr_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_3, 0)) self.connect((self.gr_multiply_const_vxx_0, 0), (self.blks2_rational_resampler_xxx_0, 0)) self.connect((self.blks2_rational_resampler_xxx_0, 0), (self.audio_sink_0, 0)) self.connect((self.blks2_rational_resampler_xxx_0_0, 0), (self.audio_sink_0, 1)) self.connect((self.gr_multiply_const_vxx_0_0, 0), (self.blks2_rational_resampler_xxx_0_0, 0)) self.connect((self.gr_rds_freq_divider_0, 0), (self.fir_filter_xxx_7, 0)) self.connect((self.fir_filter_xxx_7, 0), (self.gr_rds_bpsk_demod_0, 1)) self.connect((self.digital_diff_decoder_bb_0, 0), (self.gr_rds_data_decoder_0, 0)) self.connect((self.gr_rds_bpsk_demod_0, 0), (self.digital_diff_decoder_bb_0, 0)) self.connect((self.fir_filter_xxx_6, 0), (self.gr_rds_bpsk_demod_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.wxgui_scopesink2_0, 0)) self.connect((self.fir_filter_xxx_1, 0), (self.wxgui_fftsink2_0_0_0, 0)) self.connect((self.fir_filter_xxx_3, 0), (self.wxgui_fftsink2_0_0_0_1, 0)) self.connect((self.fir_filter_xxx_4, 0), (self.wxgui_fftsink2_0_0_0_1_0, 0)) self.connect((self.blocks_multiply_xx_0_0, 0), (self.fir_filter_xxx_6, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.wxgui_fftsink2_0_0_0_1_0_0, 0)) self.connect((self.fir_filter_xxx_5, 0), (self.blocks_add_xx_0, 1)) self.connect((self.fir_filter_xxx_5, 0), (self.blocks_sub_xx_0, 1)) self.connect((self.blocks_multiply_xx_0_0, 0), (self.wxgui_fftsink2_0_0_0_1_0_1, 0)) self.connect((self.blocks_sub_xx_0, 0), (self.blks2_fm_deemph_0_0, 0)) self.connect((self.blks2_fm_deemph_0_0, 0), (self.gr_multiply_const_vxx_0_0, 0)) self.connect((self.blocks_add_xx_0, 0), (self.blks2_fm_deemph_0_0_0, 0)) self.connect((self.blks2_fm_deemph_0_0_0, 0), (self.gr_multiply_const_vxx_0, 0)) self.connect((self.gr_pll_freqdet_cf_0, 0), (self.wxgui_fftsink2_0_0, 0))
def __init__(self): grc_wxgui.top_block_gui.__init__(self, title="Stereo FM receiver and RDS Decoder") _icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png" self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY)) ################################################## # Variables ################################################## self.xlate_decim = xlate_decim = 4 self.samp_rate = samp_rate = 1000000 self.freq_offset = freq_offset = 250e3 self.freq = freq = 88.5e6 self.baseband_rate = baseband_rate = samp_rate/xlate_decim self.audio_decim = audio_decim = 4 self.xlate_bandwidth = xlate_bandwidth = 250e3 self.volume = volume = 0 self.loop_bw = loop_bw = 16e3*0 + 18e3*1 self.gain = gain = 10 self.freq_tune = freq_tune = freq - freq_offset self.audio_rate = audio_rate = 48000 self.audio_decim_rate = audio_decim_rate = baseband_rate/audio_decim self.antenna = antenna = 'TX/RX' ################################################## # Message Queues ################################################## gr_rds_data_decoder_0_msgq_out = gr_rds_panel_0_msgq_in = gr.msg_queue(2) ################################################## # Blocks ################################################## _volume_sizer = wx.BoxSizer(wx.VERTICAL) self._volume_text_box = forms.text_box( parent=self.GetWin(), sizer=_volume_sizer, value=self.volume, callback=self.set_volume, label="Volume", converter=forms.float_converter(), proportion=0, ) self._volume_slider = forms.slider( parent=self.GetWin(), sizer=_volume_sizer, value=self.volume, callback=self.set_volume, minimum=-20, maximum=10, num_steps=300, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_volume_sizer) self.nb = self.nb = wx.Notebook(self.GetWin(), style=wx.NB_TOP) self.nb.AddPage(grc_wxgui.Panel(self.nb), "BB") self.nb.AddPage(grc_wxgui.Panel(self.nb), "Demod") self.nb.AddPage(grc_wxgui.Panel(self.nb), "L+R") self.nb.AddPage(grc_wxgui.Panel(self.nb), "Pilot") self.nb.AddPage(grc_wxgui.Panel(self.nb), "DSBSC") self.nb.AddPage(grc_wxgui.Panel(self.nb), "RDS Raw") self.nb.AddPage(grc_wxgui.Panel(self.nb), "L-R") self.nb.AddPage(grc_wxgui.Panel(self.nb), "RDS") self.Add(self.nb) _loop_bw_sizer = wx.BoxSizer(wx.VERTICAL) self._loop_bw_text_box = forms.text_box( parent=self.GetWin(), sizer=_loop_bw_sizer, value=self.loop_bw, callback=self.set_loop_bw, label="Loop BW", converter=forms.float_converter(), proportion=0, ) self._loop_bw_slider = forms.slider( parent=self.GetWin(), sizer=_loop_bw_sizer, value=self.loop_bw, callback=self.set_loop_bw, minimum=0, maximum=baseband_rate, num_steps=1000, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_loop_bw_sizer) _gain_sizer = wx.BoxSizer(wx.VERTICAL) self._gain_text_box = forms.text_box( parent=self.GetWin(), sizer=_gain_sizer, value=self.gain, callback=self.set_gain, label="Gain", converter=forms.float_converter(), proportion=0, ) self._gain_slider = forms.slider( parent=self.GetWin(), sizer=_gain_sizer, value=self.gain, callback=self.set_gain, minimum=0, maximum=50, num_steps=50, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_gain_sizer) self._freq_offset_text_box = forms.text_box( parent=self.GetWin(), value=self.freq_offset, callback=self.set_freq_offset, label="Freq Offset", converter=forms.float_converter(), ) self.Add(self._freq_offset_text_box) _freq_sizer = wx.BoxSizer(wx.VERTICAL) self._freq_text_box = forms.text_box( parent=self.GetWin(), sizer=_freq_sizer, value=self.freq, callback=self.set_freq, label="Freq", converter=forms.float_converter(), proportion=0, ) self._freq_slider = forms.slider( parent=self.GetWin(), sizer=_freq_sizer, value=self.freq, callback=self.set_freq, minimum=87.5e6, maximum=108e6, num_steps=205, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_freq_sizer) self._antenna_chooser = forms.drop_down( parent=self.GetWin(), value=self.antenna, callback=self.set_antenna, label="Antenna", choices=['TX/RX', 'RX2'], labels=[], ) self.Add(self._antenna_chooser) self.wxgui_scopesink2_0 = scopesink2.scope_sink_f( self.nb.GetPage(3).GetWin(), title="Pilot", sample_rate=baseband_rate, v_scale=0, v_offset=0, t_scale=0, ac_couple=False, xy_mode=False, num_inputs=1, trig_mode=wxgui.TRIG_MODE_AUTO, y_axis_label="Counts", ) self.nb.GetPage(3).Add(self.wxgui_scopesink2_0.win) self.wxgui_fftsink2_0_0_0_1_0_1 = fftsink2.fft_sink_f( self.nb.GetPage(7).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=-50, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="RDS", peak_hold=False, ) self.nb.GetPage(7).Add(self.wxgui_fftsink2_0_0_0_1_0_1.win) self.wxgui_fftsink2_0_0_0_1_0_0 = fftsink2.fft_sink_f( self.nb.GetPage(6).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=-50, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="L-R", peak_hold=False, ) self.nb.GetPage(6).Add(self.wxgui_fftsink2_0_0_0_1_0_0.win) self.wxgui_fftsink2_0_0_0_1_0 = fftsink2.fft_sink_f( self.nb.GetPage(5).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="RDS", peak_hold=False, ) self.nb.GetPage(5).Add(self.wxgui_fftsink2_0_0_0_1_0.win) self.wxgui_fftsink2_0_0_0_1 = fftsink2.fft_sink_f( self.nb.GetPage(4).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="DSBSC Sub-carrier", peak_hold=False, ) self.nb.GetPage(4).Add(self.wxgui_fftsink2_0_0_0_1.win) self.wxgui_fftsink2_0_0_0 = fftsink2.fft_sink_f( self.nb.GetPage(2).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=audio_decim_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="L+R", peak_hold=False, ) self.nb.GetPage(2).Add(self.wxgui_fftsink2_0_0_0.win) self.wxgui_fftsink2_0_0 = fftsink2.fft_sink_f( self.nb.GetPage(1).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=True, avg_alpha=0.8, title="FM Demod", peak_hold=False, ) self.nb.GetPage(1).Add(self.wxgui_fftsink2_0_0.win) self.wxgui_fftsink2_0 = fftsink2.fft_sink_c( self.nb.GetPage(0).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=-30, ref_scale=2.0, sample_rate=baseband_rate, fft_size=1024, fft_rate=15, average=True, avg_alpha=0.8, title="Baseband", peak_hold=False, ) self.nb.GetPage(0).Add(self.wxgui_fftsink2_0.win) self.uhd_usrp_source_0 = uhd.usrp_source( ",".join(("", "")), uhd.stream_args( cpu_format="fc32", channels=range(1), ), ) self.uhd_usrp_source_0.set_samp_rate(samp_rate) self.uhd_usrp_source_0.set_center_freq(freq_tune, 0) self.uhd_usrp_source_0.set_gain(gain, 0) self.uhd_usrp_source_0.set_antenna(antenna, 0) self.rational_resampler_xxx_1 = filter.rational_resampler_fff( interpolation=audio_rate, decimation=audio_decim_rate, taps=None, fractional_bw=None, ) self.rational_resampler_xxx_0 = filter.rational_resampler_fff( interpolation=audio_rate, decimation=audio_decim_rate, taps=None, fractional_bw=None, ) self.gr_rds_panel_0 = rds.rdsPanel(gr_rds_panel_0_msgq_in, freq, self.GetWin()) self.Add(self.gr_rds_panel_0) self.gr_rds_freq_divider_0 = rds.freq_divider(16) self.gr_rds_data_decoder_0 = rds.data_decoder(gr_rds_data_decoder_0_msgq_out) self.gr_rds_bpsk_demod_0 = rds.bpsk_demod(audio_decim_rate) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(xlate_decim, (firdes.low_pass(1, samp_rate, xlate_bandwidth/2, 1000)), freq_offset, samp_rate) self.fir_filter_xxx_7 = filter.fir_filter_fff(audio_decim, (firdes.low_pass(1,baseband_rate,1.2e3,1.5e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_7.declare_sample_delay(0) self.fir_filter_xxx_6 = filter.fir_filter_fff(audio_decim, (firdes.low_pass(1,baseband_rate,1.5e3,2e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_6.declare_sample_delay(0) self.fir_filter_xxx_5 = filter.fir_filter_fff(audio_decim, (firdes.low_pass(1.0,baseband_rate,15e3,1e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_5.declare_sample_delay(0) self.fir_filter_xxx_4 = filter.fir_filter_fff(1, (firdes.band_pass(1.0,baseband_rate,57e3-3e3,57e3+3e3,3e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_4.declare_sample_delay(0) self.fir_filter_xxx_3 = filter.fir_filter_fff(1, (firdes.band_pass(1.0,baseband_rate,38e3-15e3/2,38e3+15e3/2,1e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_3.declare_sample_delay(0) self.fir_filter_xxx_2 = filter.fir_filter_fff(1, (firdes.band_pass(1.0,baseband_rate,19e3-500,19e3+500,1e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_2.declare_sample_delay(0) self.fir_filter_xxx_1 = filter.fir_filter_fff(audio_decim, (firdes.low_pass(1.0,baseband_rate,15e3,1e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_1.declare_sample_delay(0) self.fir_filter_xxx_0 = filter.fir_filter_ccc(1, (firdes.low_pass(1.0, baseband_rate, 80e3,35e3,firdes.WIN_HAMMING))) self.fir_filter_xxx_0.declare_sample_delay(0) self.digital_diff_decoder_bb_0 = digital.diff_decoder_bb(2) self.blocks_sub_xx_0 = blocks.sub_ff(1) self.blocks_multiply_xx_0_0 = blocks.multiply_vff(1) self.blocks_multiply_xx_0 = blocks.multiply_vff(1) self.blocks_multiply_const_vxx_1 = blocks.multiply_const_vff((10**(1.*volume/10), )) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((10**(1.*volume/10), )) self.blocks_add_xx_0 = blocks.add_vff(1) self.audio_sink_0 = audio.sink(audio_rate, "", True) self.analog_pll_freqdet_cf_0 = analog.pll_freqdet_cf(1.0*0 + (loop_bw*2*math.pi/baseband_rate), +(2.0 * math.pi * 90e3 / baseband_rate), -(2.0 * math.pi * 90e3 / baseband_rate)) self.analog_fm_deemph_1 = analog.fm_deemph(fs=baseband_rate, tau=75e-6) self.analog_fm_deemph_0 = analog.fm_deemph(fs=baseband_rate, tau=75e-6) ################################################## # Connections ################################################## self.connect((self.uhd_usrp_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.fir_filter_xxx_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0, 1)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0_0, 1)) self.connect((self.fir_filter_xxx_3, 0), (self.blocks_multiply_xx_0, 2)) self.connect((self.fir_filter_xxx_4, 0), (self.blocks_multiply_xx_0_0, 3)) self.connect((self.fir_filter_xxx_2, 0), (self.blocks_multiply_xx_0_0, 2)) self.connect((self.fir_filter_xxx_1, 0), (self.blocks_sub_xx_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.gr_rds_freq_divider_0, 0)) self.connect((self.fir_filter_xxx_1, 0), (self.blocks_add_xx_0, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.fir_filter_xxx_5, 0)) self.connect((self.gr_rds_freq_divider_0, 0), (self.fir_filter_xxx_7, 0)) self.connect((self.fir_filter_xxx_7, 0), (self.gr_rds_bpsk_demod_0, 1)) self.connect((self.digital_diff_decoder_bb_0, 0), (self.gr_rds_data_decoder_0, 0)) self.connect((self.gr_rds_bpsk_demod_0, 0), (self.digital_diff_decoder_bb_0, 0)) self.connect((self.fir_filter_xxx_6, 0), (self.gr_rds_bpsk_demod_0, 0)) self.connect((self.fir_filter_xxx_2, 0), (self.wxgui_scopesink2_0, 0)) self.connect((self.fir_filter_xxx_1, 0), (self.wxgui_fftsink2_0_0_0, 0)) self.connect((self.fir_filter_xxx_3, 0), (self.wxgui_fftsink2_0_0_0_1, 0)) self.connect((self.fir_filter_xxx_4, 0), (self.wxgui_fftsink2_0_0_0_1_0, 0)) self.connect((self.blocks_multiply_xx_0_0, 0), (self.fir_filter_xxx_6, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.wxgui_fftsink2_0_0_0_1_0_0, 0)) self.connect((self.fir_filter_xxx_5, 0), (self.blocks_add_xx_0, 1)) self.connect((self.fir_filter_xxx_5, 0), (self.blocks_sub_xx_0, 1)) self.connect((self.fir_filter_xxx_0, 0), (self.analog_pll_freqdet_cf_0, 0)) self.connect((self.analog_pll_freqdet_cf_0, 0), (self.wxgui_fftsink2_0_0, 0)) self.connect((self.analog_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_1, 0)) self.connect((self.analog_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_2, 0)) self.connect((self.analog_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_4, 0)) self.connect((self.blocks_add_xx_0, 0), (self.analog_fm_deemph_0, 0)) self.connect((self.blocks_multiply_xx_0_0, 0), (self.wxgui_fftsink2_0_0_0_1_0_1, 0)) self.connect((self.analog_fm_deemph_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.rational_resampler_xxx_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.audio_sink_0, 0)) self.connect((self.rational_resampler_xxx_1, 0), (self.audio_sink_0, 1)) self.connect((self.blocks_multiply_const_vxx_1, 0), (self.rational_resampler_xxx_1, 0)) self.connect((self.blocks_sub_xx_0, 0), (self.analog_fm_deemph_1, 0)) self.connect((self.analog_fm_deemph_1, 0), (self.blocks_multiply_const_vxx_1, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.wxgui_fftsink2_0, 0)) self.connect((self.analog_pll_freqdet_cf_0, 0), (self.fir_filter_xxx_3, 0))
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) parser=OptionParser(option_class=eng_option) parser.add_option("-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)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.file_source = gr.file_source(gr.sizeof_gr_complex*1, offline_samples, True) chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / usrp_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / usrp_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( fm_alpha, # phase gain fm_beta, # freq gain fm_max_freq, # in radians/sample -fm_max_freq) self.connect(self.file_source, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) print "# lpr filter:", len(lpr_filter_coeffs), "taps" print "# pilot filter:", len(pilot_filter_coeffs), "taps" print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # send audio to null sink self.null0 = gr.null_sink(gr.sizeof_float) self.null1 = gr.null_sink(gr.sizeof_float) self.connect(self.left, self.null0) self.connect(self.right, self.null1) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_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.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) self.frame = frame self.panel = panel self._build_gui(vbox, usrp_rate, audio_rate)
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("-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)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.file_source = gr.file_source(gr.sizeof_gr_complex * 1, offline_samples, True) chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / usrp_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / usrp_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( fm_alpha, # phase gain fm_beta, # freq gain fm_max_freq, # in radians/sample -fm_max_freq) self.connect(self.file_source, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 19e3 - 500, # low cutoff 19e3 + 500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 38e3 - 15e3 / 2, # low cutoff 38e3 + 15e3 / 2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 57e3 - 3e3, # low cutoff 57e3 + 3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) print "# lpr filter:", len(lpr_filter_coeffs), "taps" print "# pilot filter:", len(pilot_filter_coeffs), "taps" print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # send audio to null sink self.null0 = gr.null_sink(gr.sizeof_float) self.null1 = gr.null_sink(gr.sizeof_float) self.connect(self.left, self.null0) self.connect(self.right, self.null1) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_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.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) self.frame = frame self.panel = panel self._build_gui(vbox, usrp_rate, audio_rate)