Example #1
0
	def __init__(self, options):
		gr.hier_block2.__init__(self, "fsk_demod",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature(1, 1, gr.sizeof_char)) # Output signature

		self._syms_per_sec = options.syms_per_sec # ditto
		self._samples_per_second = options.samples_per_second
		self._gain_mu = options.gain_mu # for the clock recovery block
		self._mu = options.mu
		self._omega_relative_limit = options.omega_relative_limit

		self._freqoffset = options.offset

		#first bring that input stream down to a manageable level, let's say 3 samples per bit.
		self._clockrec_oversample = 3

		self._downsampletaps = gr.firdes.low_pass(1, self._samples_per_second, 10000, 1000, firdes.WIN_HANN)

		self._decim = int(self._samples_per_second / (self._syms_per_sec * self._clockrec_oversample))

		print "Demodulator decimation: %i" % (self._decim,)
		self._downsample = gr.freq_xlating_fir_filter_ccf(self._decim, #decimation
														  self._downsampletaps, #taps
														  self._freqoffset, #freq offset
														  self._samples_per_second) #sampling rate

		#using a pll to demod gets you a nice IIR LPF response for free
		self._demod = gr.pll_freqdet_cf(2.0 / self._clockrec_oversample, #gain alpha, rad/samp
										 2*pi/self._clockrec_oversample,  #max freq, rad/samp
										-2*pi/self._clockrec_oversample)  #min freq, rad/samp

		self._sps = float(self._samples_per_second)/self._decim/self._syms_per_sec

		#band edge filter FLL with a low bandwidth is very good
		#at synchronizing to continuous FSK signals
		self._carriertrack = digital.fll_band_edge_cc(self._sps,
													  0.6, #rolloff factor
													  64,  #taps
													  1.0) #loop bandwidth

		print "Samples per symbol: %f" % (self._sps,)
		self._softbits = digital.clock_recovery_mm_ff(self._sps,
												 0.25*self._gain_mu*self._gain_mu, #gain omega, = mu/2 * mu_gain^2
												 self._mu, #mu (decision threshold)
												 self._gain_mu, #mu gain
												 self._omega_relative_limit) #omega relative limit

		self._subtract = gr.sub_ff()

		self._slicer = digital.binary_slicer_fb()

		self.connect(self, self._downsample, self._carriertrack, self._demod, self._softbits, self._slicer, self)
Example #2
0
    def test_pll_refout(self):
        expected_result = (
            1.1489677586e-07, 0.972821060568, 2.74556447638, 5.14063078448,
            8.00965819311, 11.2291393027, 14.6967068752, 18.3279143967,
            22.0534772463, 25.8170093072, 29.5729107661, 33.284774699,
            36.923857393, 40.4367950308, 43.8452195091, 47.1363835133,
            50.3011949468, 53.3336447847, 56.2301489564, 58.9891659262,
            61.6107668417, 64.0962975824, 66.4481356707, 68.6694531128,
            70.7640326003, 72.7048735417, 74.5033180826, 76.2012544926,
            77.8019199967, 79.3088126954, 80.7255907715, 82.0560369166,
            83.3039516093, 84.47312347, 85.5673411194, 86.5902864563,
            87.5456117346, 88.4368565575, 89.2363918613, 89.9860999864,
            90.688880206, 91.3474598523, 91.9644654653, 92.5423042123,
            93.0832706099, 93.5894872344, 94.0629225081, 94.5054203452,
            94.9186882929, 95.3043331057, 95.6326268597, 95.9117515522,
            96.1801447842, 96.437391527, 96.6831953314, 96.9173605408,
            97.1397982206, 97.3504727968, 97.5493842694, 97.7366275022,
            97.9123092169, 98.0766013539, 98.2297054988, 98.3408087235,
            98.448722155, 98.5534457933, 98.6549322065, 98.7531932527,
            98.8481459259, 98.9397487233, 99.0279067813, 99.1125074491,
            99.193438076, 99.2705800823, 99.3438030304, 99.3817663128,
            99.3911400359, 99.4089388448, 99.4334136894, 99.4630408207,
            99.4964684305, 99.5325166512, 99.5701538394, 99.6084432158,
            99.6466021546, 99.6839073198, 99.7197895289, 99.7537270313,
            99.7542606398, 99.7595848672, 99.7691186729, 99.7822928746,
            99.7986331535, 99.8175940432, 99.838713083, 99.8614922382,
            99.8854571901, 99.9101454781, 99.9351302152, 99.9599845147)

        sampling_freq = 10e3
        freq = sampling_freq / 100

        alpha = 0.2
        beta = alpha * alpha / 4.0
        maxf = 1
        minf = -1

        src = gr.sig_source_c(sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
        pll = gr.pll_freqdet_cf(alpha, beta, maxf, minf)
        head = gr.head(gr.sizeof_float, int(freq))
        dst = gr.vector_sink_f()

        self.tb.connect(src, pll, head)
        self.tb.connect(head, dst)

        self.tb.run()
        dst_data = dst.data()

        # convert it from normalized frequency to absolute frequency (Hz)
        dst_data = [i * (sampling_freq / (2 * math.pi)) for i in dst_data]

        self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 3)
Example #3
0
    def test_pll_freqdet(self):
        expected_result = (
            0.0, 4.33888922882e-08, 0.367369994515, 1.08135249597,
            2.10983253908, 3.42221529438, 4.98940390402, 6.78379190842,
            8.77923286024, 10.9510106794, 13.2758363182, 15.7317829127,
            18.2982902299, 20.9561068599, 23.6755271122, 26.452952094,
            29.2731265301, 32.1219053479, 34.9862418188, 37.8540971414,
            40.7144315483, 43.5571390869, 46.3730179743, 49.1537231663,
            51.8917218889, 54.58026103, 57.2015358514, 59.7513664199,
            62.2380533124, 64.657612252, 67.006640002, 69.2822432184,
            71.4820384499, 73.6041047056, 75.6469478817, 77.6094829742,
            79.4909866472, 81.2911031615, 83.0097850853, 84.6355598352,
            86.1820937186, 87.6504420946, 89.0418441206, 90.3577286819,
            91.5996432431, 92.7692775646, 93.8684162704, 94.8989269904,
            95.8627662892, 96.7619381633, 97.598505899, 98.362769679,
            99.0579904444, 99.6992633875, 100.288805948, 100.828805921,
            101.321421457, 101.76878699, 102.17300138, 102.536116055,
            102.860158727, 103.147085962, 103.398830608, 103.617254366,
            103.792467691, 103.939387906, 104.060030865, 104.15631756,
            104.230085975, 104.283067372, 104.316933727, 104.333238432,
            104.333440018, 104.318914008, 104.290941063, 104.250742554,
            104.187634452, 104.103822339, 104.013227468, 103.916810336,
            103.815448432, 103.709936239, 103.600997093, 103.489283183,
            103.375351833, 103.259712936, 103.142828952, 103.025091195,
            102.90686726, 102.776726069, 102.648078982, 102.521459607,
            102.397294831, 102.275999684, 102.157882471, 102.043215927,
            101.93218978, 101.824958181, 101.72159228, 101.622151366)

        sampling_freq = 10e3
        freq = sampling_freq / 100

        loop_bw = math.pi / 100.0
        maxf = 1
        minf = -1

        src = gr.sig_source_c(sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
        pll = gr.pll_freqdet_cf(loop_bw, maxf, minf)
        head = gr.head(gr.sizeof_float, int(freq))
        dst = gr.vector_sink_f()

        self.tb.connect(src, pll, head)
        self.tb.connect(head, dst)

        self.tb.run()
        dst_data = dst.data()

        # convert it from normalized frequency to absolute frequency (Hz)
        dst_data = [i * (sampling_freq / (2 * math.pi)) for i in dst_data]

        self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 3)
    def test_pll_refout (self):
        expected_result = (1.1489677586e-07,
                           0.972821060568,
                           2.74556447638,
                           5.14063078448,
                           8.00965819311,
                           11.2291393027,
                           14.6967068752,
                           18.3279143967,
                           22.0534772463,
                           25.8170093072,
                           29.5729107661,
                           33.284774699,
                           36.923857393,
                           40.4367950308,
                           43.8452195091,
                           47.1363835133,
                           50.3011949468,
                           53.3336447847,
                           56.2301489564,
                           58.9891659262,
                           61.6107668417,
                           64.0962975824,
                           66.4481356707,
                           68.6694531128,
                           70.7640326003,
                           72.7048735417,
                           74.5033180826,
                           76.2012544926,
                           77.8019199967,
                           79.3088126954,
                           80.7255907715,
                           82.0560369166,
                           83.3039516093,
                           84.47312347,
                           85.5673411194,
                           86.5902864563,
                           87.5456117346,
                           88.4368565575,
                           89.2363918613,
                           89.9860999864,
                           90.688880206,
                           91.3474598523,
                           91.9644654653,
                           92.5423042123,
                           93.0832706099,
                           93.5894872344,
                           94.0629225081,
                           94.5054203452,
                           94.9186882929,
                           95.3043331057,
                           95.6326268597,
                           95.9117515522,
                           96.1801447842,
                           96.437391527,
                           96.6831953314,
                           96.9173605408,
                           97.1397982206,
                           97.3504727968,
                           97.5493842694,
                           97.7366275022,
                           97.9123092169,
                           98.0766013539,
                           98.2297054988,
                           98.3408087235,
                           98.448722155,
                           98.5534457933,
                           98.6549322065,
                           98.7531932527,
                           98.8481459259,
                           98.9397487233,
                           99.0279067813,
                           99.1125074491,
                           99.193438076,
                           99.2705800823,
                           99.3438030304,
                           99.3817663128,
                           99.3911400359,
                           99.4089388448,
                           99.4334136894,
                           99.4630408207,
                           99.4964684305,
                           99.5325166512,
                           99.5701538394,
                           99.6084432158,
                           99.6466021546,
                           99.6839073198,
                           99.7197895289,
                           99.7537270313,
                           99.7542606398,
                           99.7595848672,
                           99.7691186729,
                           99.7822928746,
                           99.7986331535,
                           99.8175940432,
                           99.838713083,
                           99.8614922382,
                           99.8854571901,
                           99.9101454781,
                           99.9351302152,
                           99.9599845147)

        sampling_freq = 10e3
        freq = sampling_freq / 100

        alpha = 0.2
        beta = alpha * alpha / 4.0
        maxf = 1
        minf = -1

        src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
        pll = gr.pll_freqdet_cf(alpha, beta, maxf, minf)
        head = gr.head (gr.sizeof_float, int (freq))
        dst = gr.vector_sink_f ()

        self.fg.connect (src, pll, head)
        self.fg.connect (head, dst)

        self.fg.run ()
        dst_data = dst.data ()

        # convert it from normalized frequency to absolute frequency (Hz)
        dst_data = [i*(sampling_freq/(2*math.pi)) for i in dst_data]

        self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 3)
    def __init__ (self, fg, demod_rate, audio_decimation):
        """
        Hierarchical block for demodulating a broadcast FM signal.
        
        The input is the downconverted complex baseband signal (gr_complex).
        The output is two streams of the demodulated audio (float) 0=Left, 1=Right.
        
        @param fg: flow graph.
        @type fg: flow graph
        @param demod_rate: input sample rate of complex baseband input.
        @type demod_rate: float
        @param audio_decimation: how much to decimate demod_rate to get to audio.
        @type audio_decimation: integer
        """

        bandwidth = 200e3
        audio_rate = demod_rate / audio_decimation


        # We assign to self so that outsiders can grab the demodulator 
        # if they need to.  E.g., to plot its output.
        #
        # input: complex; output: float
        alpha = 0.25*bandwidth * math.pi / demod_rate
        beta = alpha * alpha / 4.0
        max_freq = 2.0*math.pi*100e3/demod_rate
            
        self.fm_demod = gr.pll_freqdet_cf (alpha,beta,max_freq,-max_freq)

        # input: float; output: float
        self.deemph_Left  = fm_deemph (fg, audio_rate)
        self.deemph_Right = fm_deemph (fg, audio_rate)
        
        # compute FIR filter taps for audio filter
        width_of_transition_band = audio_rate / 32
        audio_coeffs = gr.firdes.low_pass (1.0 ,         # gain
                                           demod_rate,      # sampling rate
                                           15000 ,
                                           width_of_transition_band,
                                           gr.firdes.WIN_HAMMING)
        # input: float; output: float
        self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
        if 1:
            # Pick off the stereo carrier/2 with this filter. It attenuated 10 dB so apply 10 dB gain
            # We pick off the negative frequency half because we want to base band by it!
            ##  NOTE  THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO DEEMPHASIS

            stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0,
                                                                   demod_rate,
                                                                   -19020,
                                                                   -18980,
                                                                   width_of_transition_band,
                                                                   gr.firdes.WIN_HAMMING)
            
            #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs)
            #print "stereo carrier filter ", stereo_carrier_filter_coeffs
            #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate

            # Pick off the double side band suppressed carrier Left-Right audio. It is attenuated 10 dB so apply 10 dB gain

            stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0,
                                                                     demod_rate,
                                                                     38000-15000/2,
                                                                     38000+15000/2,
                                                                     width_of_transition_band,
                                                                     gr.firdes.WIN_HAMMING)
            #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
            #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs
            # construct overlap add filter system from coefficients for stereo carrier

            self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs)

            # carrier is twice the picked off carrier so arrange to do a commplex multiply

            self.stereo_carrier_generator = gr.multiply_cc();

            # Pick off the rds signal

            stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0,
                                                                     demod_rate,
                                                                     57000 - 1500,
                                                                     57000 + 1500,
                                                                     width_of_transition_band,
                                                                     gr.firdes.WIN_HAMMING)
            #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
            #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs
            # construct overlap add filter system from coefficients for stereo carrier

            self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs)
	    self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs)






	    self.rds_carrier_generator = gr.multiply_cc();
	    self.rds_signal_generator = gr.multiply_cc();
	    self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex);



            alpha = 5 * 0.25 * math.pi / (audio_rate)
            beta = alpha * alpha / 4.0
            max_freq = -2.0*math.pi*18990/audio_rate;
            min_freq = -2.0*math.pi*19010/audio_rate;
            
            self.stereo_carrier_pll_recovery = gr.pll_refout_cc(alpha,beta,max_freq,min_freq);
            #self.stereo_carrier_pll_recovery.squelch_enable(False) #pll_refout does not have squelch yet, so disabled for now 
            

            # set up mixer (multiplier) to get the L-R signal at baseband

            self.stereo_basebander = gr.multiply_cc();

            # pick off the real component of the basebanded L-R signal.  The imaginary SHOULD be zero

            self.LmR_real = gr.complex_to_real();
            self.Make_Left = gr.add_ff();
            self.Make_Right = gr.sub_ff();
            
            self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs)


        if 1:

            # send the real signal to complex filter to pick off the carrier and then to one side of a multiplier
            fg.connect (self.fm_demod,self.stereo_carrier_filter,self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,0))
            # send the already filtered carrier to the otherside of the carrier
            fg.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1))
            # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz.

            # send the new carrier to one side of the mixer (multiplier)
            fg.connect (self.stereo_carrier_generator, (self.stereo_basebander,0))
            # send the demphasized audio to the DSBSC pick off filter,  the complex
            # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier
            fg.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1))
            # the result is BASEBANDED DSBSC with phase zero!

            # Pick off the real part since the imaginary is theoretically zero and then to one side of a summer
            fg.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0))
            #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter
            fg.connect (self.LmR_real,(self.Make_Right,1))

	    # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone
	    fg.connect (self.stereo_basebander,(self.rds_carrier_generator,0))
            fg.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) 
	    # take signal, filter off rds,  send into mixer 0 channel
	    fg.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0))
            # take rds_carrier_generator output and send into mixer 1 channel
	    fg.connect (self.rds_carrier_generator,(self.rds_signal_generator,1))
	    # send basebanded rds signal and send into "processor" which for now is a null sink
	    fg.connect (self.rds_signal_generator,self_rds_signal_processor)
	    

        if 1:
            # pick off the audio, L+R that is what we used to have and send it to the summer
            fg.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1))
            # take the picked off L+R audio and send it to the PLUS side of the subtractor
            fg.connect(self.audio_filter,(self.Make_Right, 0))
            # The result of  Make_Left  gets    (L+R) +  (L-R) and results in 2*L
            # The result of Make_Right gets  (L+R) - (L-R) and results in 2*R


            # kludge the signals into a stereo channel
            kludge = gr.kludge_copy(gr.sizeof_float)
            fg.connect(self.Make_Left , self.deemph_Left, (kludge, 0))
            fg.connect(self.Make_Right, self.deemph_Right, (kludge, 1))

           #send it to the audio system
            gr.hier_block.__init__(self,
                                   fg,
                                   self.fm_demod,       # head of the pipeline
                                   kludge)              # tail of the pipeline
        else:
            fg.connect (self.fm_demod, self.audio_filter)
            gr.hier_block.__init__(self,
                                   fg,
                                   self.fm_demod,       # head of the pipeline
                                   self.audio_filter)   # tail of the pipeline
Example #6
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("-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")	
Example #7
0
	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 test_pll_freqdet (self):
        expected_result = (0.0,
                           4.33888922882e-08,
                           0.367369994515,
                           1.08135249597,
                           2.10983253908,
                           3.42221529438,
                           4.98940390402,
                           6.78379190842,
                           8.77923286024,
                           10.9510106794,
                           13.2758363182,
                           15.7317829127,
                           18.2982902299,
                           20.9561068599,
                           23.6755271122,
                           26.452952094,
                           29.2731265301,
                           32.1219053479,
                           34.9862418188,
                           37.8540971414,
                           40.7144315483,
                           43.5571390869,
                           46.3730179743,
                           49.1537231663,
                           51.8917218889,
                           54.58026103,
                           57.2015358514,
                           59.7513664199,
                           62.2380533124,
                           64.657612252,
                           67.006640002,
                           69.2822432184,
                           71.4820384499,
                           73.6041047056,
                           75.6469478817,
                           77.6094829742,
                           79.4909866472,
                           81.2911031615,
                           83.0097850853,
                           84.6355598352,
                           86.1820937186,
                           87.6504420946,
                           89.0418441206,
                           90.3577286819,
                           91.5996432431,
                           92.7692775646,
                           93.8684162704,
                           94.8989269904,
                           95.8627662892,
                           96.7619381633,
                           97.598505899,
                           98.362769679,
                           99.0579904444,
                           99.6992633875,
                           100.288805948,
                           100.828805921,
                           101.321421457,
                           101.76878699,
                           102.17300138,
                           102.536116055,
                           102.860158727,
                           103.147085962,
                           103.398830608,
                           103.617254366,
                           103.792467691,
                           103.939387906,
                           104.060030865,
                           104.15631756,
                           104.230085975,
                           104.283067372,
                           104.316933727,
                           104.333238432,
                           104.333440018,
                           104.318914008,
                           104.290941063,
                           104.250742554,
                           104.187634452,
                           104.103822339,
                           104.013227468,
                           103.916810336,
                           103.815448432,
                           103.709936239,
                           103.600997093,
                           103.489283183,
                           103.375351833,
                           103.259712936,
                           103.142828952,
                           103.025091195,
                           102.90686726,
                           102.776726069,
                           102.648078982,
                           102.521459607,
                           102.397294831,
                           102.275999684,
                           102.157882471,
                           102.043215927,
                           101.93218978,
                           101.824958181,
                           101.72159228,
                           101.622151366)

        sampling_freq = 10e3
        freq = sampling_freq / 100

        loop_bw = math.pi/100.0
        maxf = 1
        minf = -1

        src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
        pll = gr.pll_freqdet_cf(loop_bw, maxf, minf)
        head = gr.head (gr.sizeof_float, int (freq))
        dst = gr.vector_sink_f ()

        self.tb.connect (src, pll, head)
        self.tb.connect (head, dst)

        self.tb.run ()
        dst_data = dst.data ()

        # convert it from normalized frequency to absolute frequency (Hz)
        dst_data = [i*(sampling_freq/(2*math.pi)) for i in dst_data]
            
        self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 3)
Example #9
0
	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)
Example #10
0
    def __init__ (self, demod_rate, audio_decimation):
        """
        Hierarchical block for demodulating a broadcast FM signal.

        The input is the downconverted complex baseband signal (gr_complex).
        The output is two streams of the demodulated audio (float) 0=Left, 1=Right.

        @param demod_rate: input sample rate of complex baseband input.
        @type demod_rate: float
        @param audio_decimation: how much to decimate demod_rate to get to audio.
        @type audio_decimation: integer
        """
	gr.hier_block2.__init__(self, "wfm_rcv_pll",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature(2, 2, gr.sizeof_float))      # Output signature
        bandwidth = 250e3
        audio_rate = demod_rate / audio_decimation


        # We assign to self so that outsiders can grab the demodulator
        # if they need to.  E.g., to plot its output.
        #
        # input: complex; output: float
        loop_bw = 2*math.pi/100.0
        max_freq = 2.0*math.pi*90e3/demod_rate
        self.fm_demod = gr.pll_freqdet_cf (loop_bw, max_freq,-max_freq)

        # input: float; output: float
        self.deemph_Left  = fm_deemph (audio_rate)
        self.deemph_Right = fm_deemph (audio_rate)

        # compute FIR filter taps for audio filter
        width_of_transition_band = audio_rate / 32
        audio_coeffs = gr.firdes.low_pass (1.0 ,         # gain
                                           demod_rate,      # sampling rate
                                           15000 ,
                                           width_of_transition_band,
                                           gr.firdes.WIN_HAMMING)
        # input: float; output: float
        self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)
        if 1:
            # Pick off the stereo carrier/2 with this filter. It attenuated 10 dB so apply 10 dB gain
            # We pick off the negative frequency half because we want to base band by it!
            ##  NOTE  THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO DEEMPHASIS

            stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0,
                                                                   demod_rate,
                                                                   -19020,
                                                                   -18980,
                                                                   width_of_transition_band,
                                                                   gr.firdes.WIN_HAMMING)

            #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs)
            #print "stereo carrier filter ", stereo_carrier_filter_coeffs
            #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate

            # Pick off the double side band suppressed carrier Left-Right audio. It is attenuated 10 dB so apply 10 dB gain

            stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0,
                                                                     demod_rate,
                                                                     38000-15000/2,
                                                                     38000+15000/2,
                                                                     width_of_transition_band,
                                                                     gr.firdes.WIN_HAMMING)
            #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
            #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs
            # construct overlap add filter system from coefficients for stereo carrier

            self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs)

            # carrier is twice the picked off carrier so arrange to do a commplex multiply

            self.stereo_carrier_generator = gr.multiply_cc();

            # Pick off the rds signal

            stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0,
                                                                     demod_rate,
                                                                     57000 - 1500,
                                                                     57000 + 1500,
                                                                     width_of_transition_band,
                                                                     gr.firdes.WIN_HAMMING)
            #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
            #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs
            # construct overlap add filter system from coefficients for stereo carrier

	    self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs)






	    self.rds_carrier_generator = gr.multiply_cc();
	    self.rds_signal_generator = gr.multiply_cc();
	    self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex);



            loop_bw = 2*math.pi/100.0
            max_freq = -2.0*math.pi*18990/audio_rate;
            min_freq = -2.0*math.pi*19010/audio_rate;

            self.stereo_carrier_pll_recovery = gr.pll_refout_cc(loop_bw, max_freq, min_freq);
            #self.stereo_carrier_pll_recovery.squelch_enable(False) #pll_refout does not have squelch yet, so disabled for now


            # set up mixer (multiplier) to get the L-R signal at baseband

            self.stereo_basebander = gr.multiply_cc();

            # pick off the real component of the basebanded L-R signal.  The imaginary SHOULD be zero

            self.LmR_real = gr.complex_to_real();
            self.Make_Left = gr.add_ff();
            self.Make_Right = gr.sub_ff();

            self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs)


        if 1:

            # send the real signal to complex filter to pick off the carrier and then to one side of a multiplier
            self.connect (self, self.fm_demod,self.stereo_carrier_filter,self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,0))
            # send the already filtered carrier to the otherside of the carrier
            self.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1))
            # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz.

            # send the new carrier to one side of the mixer (multiplier)
            self.connect (self.stereo_carrier_generator, (self.stereo_basebander,0))
            # send the demphasized audio to the DSBSC pick off filter,  the complex
            # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier
            self.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1))
            # the result is BASEBANDED DSBSC with phase zero!

            # Pick off the real part since the imaginary is theoretically zero and then to one side of a summer
            self.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0))
            #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter
            self.connect (self.LmR_real,(self.Make_Right,1))

	    # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone
	    self.connect (self.stereo_basebander,(self.rds_carrier_generator,0))
            self.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1))
	    # take signal, filter off rds,  send into mixer 0 channel
	    self.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0))
            # take rds_carrier_generator output and send into mixer 1 channel
	    self.connect (self.rds_carrier_generator,(self.rds_signal_generator,1))
	    # send basebanded rds signal and send into "processor" which for now is a null sink
	    self.connect (self.rds_signal_generator,self_rds_signal_processor)


        if 1:
            # pick off the audio, L+R that is what we used to have and send it to the summer
            self.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1))
            # take the picked off L+R audio and send it to the PLUS side of the subtractor
            self.connect(self.audio_filter,(self.Make_Right, 0))
            # The result of  Make_Left  gets    (L+R) +  (L-R) and results in 2*L
            # The result of Make_Right gets  (L+R) - (L-R) and results in 2*R
            self.connect(self.Make_Left , self.deemph_Left, (self, 0))
            self.connect(self.Make_Right, self.deemph_Right, (self, 1))
Example #11
0
    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))
Example #12
0
    def test_pll_refout (self):
        expected_result = (0.0,
                           1.1489677586e-07,
                           0.972820967928,
                           2.74556447638,
                           5.14063115504,
                           8.00965893424,
                           11.2291407849,
                           14.6967083575,
                           18.3279143967,
                           22.0534772463,
                           25.8170063427,
                           29.5729048372,
                           33.28476877,
                           36.923851464,
                           40.4367920663,
                           43.8452165447,
                           47.1363805488,
                           50.3011890178,
                           53.3336388558,
                           56.2301430274,
                           58.9891659262,
                           61.6107668417,
                           64.0962975824,
                           66.4481415997,
                           68.6694590418,
                           70.7640385293,
                           72.7048794706,
                           74.5033240115,
                           76.2012544926,
                           77.8019140677,
                           79.3088126954,
                           80.7255967005,
                           82.0560428456,
                           83.3039575383,
                           84.473129399,
                           85.5673470484,
                           86.5902864563,
                           87.5456176636,
                           88.4368624865,
                           89.2363977903,
                           89.9861118444,
                           90.6888920639,
                           91.3474657813,
                           91.9644713943,
                           92.5423101413,
                           93.0832765389,
                           93.5894931633,
                           94.0629225081,
                           94.5054203452,
                           94.9186882929,
                           95.3043331057,
                           95.6326268597,
                           95.9117515522,
                           96.1801447842,
                           96.437391527,
                           96.6831953314,
                           96.9173605408,
                           97.1397982206,
                           97.3504727968,
                           97.5493842694,
                           97.7366275022,
                           97.9123032879,
                           98.0766013539,
                           98.2297054988,
                           98.3408027946,
                           98.4487102971,
                           98.5534280064,
                           98.6549025616,
                           98.7531576788,
                           98.848110352,
                           98.9397131494,
                           99.0278712074,
                           99.1124718752,
                           99.193408431,
                           99.2705445084,
                           99.3437733855,
                           99.3817366678,
                           99.391110391,
                           99.4089151289,
                           99.4333959024,
                           99.4630289627,
                           99.4964565726,
                           99.5325047932,
                           99.5701419814,
                           99.6084313579,
                           99.6465902967,
                           99.6838954618,
                           99.7197776709,
                           99.7537270313,
                           99.7542606398,
                           99.7595848672,
                           99.7691305308,
                           99.7823047325,
                           99.7986450115,
                           99.8176059012,
                           99.838724941,
                           99.8615040962,
                           99.8854690481,
                           99.910157336,
                           99.9351302152)

        sampling_freq = 10e3
        freq = sampling_freq / 100

        alpha = 0.2
        beta = alpha * alpha / 4.0
        maxf = 1
        minf = -1

        src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0)
        pll = gr.pll_freqdet_cf(alpha, beta, maxf, minf)
        head = gr.head (gr.sizeof_float, int (freq))
        dst = gr.vector_sink_f ()

        self.tb.connect (src, pll, head)
        self.tb.connect (head, dst)

        self.tb.run ()
        dst_data = dst.data ()

        # convert it from normalized frequency to absolute frequency (Hz)
        dst_data = [i*(sampling_freq/(2*math.pi)) for i in dst_data]

        self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 3)
Example #13
0
	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))
Example #14
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)
Example #15
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)