示例#1
0
    def __init__(self,
                 channel_rate,
                 audio_decim,
                 deviation,
                 audio_pass,
                 audio_stop,
                 gain=1.0,
                 tau=75e-6):
        gr.hier_block2.__init__(
            self,
            "fm_demod_cf",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_float))  # Output signature

        k = channel_rate / (2 * pi * deviation)
        QUAD = gr.quadrature_demod_cf(k)

        audio_taps = optfir.low_pass(
            gain,  # Filter gain
            channel_rate,  # Sample rate
            audio_pass,  # Audio passband
            audio_stop,  # Audio stopband
            0.1,  # Passband ripple
            60)  # Stopband attenuation
        LPF = gr.fir_filter_fff(audio_decim, audio_taps)

        if tau is not None:
            DEEMPH = fm_deemph(channel_rate, tau)
            self.connect(self, QUAD, DEEMPH, LPF, self)
        else:
            self.connect(self, QUAD, LPF, self)
示例#2
0
    def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3):
        """
        Narrow Band FM Receiver.

        Takes a single complex baseband input stream and produces a single
        float output stream of audio sample in the range [-1, +1].

        Args:
            audio_rate: sample rate of audio stream, >= 16k (integer)
            quad_rate: sample rate of output stream (integer)
            tau: preemphasis time constant (default 75e-6) (float)
            max_dev: maximum deviation in Hz (default 5e3) (float)

        quad_rate must be an integer multiple of audio_rate.

        Exported sub-blocks (attributes):
          squelch
          quad_demod
          deemph
          audio_filter
        """

	gr.hier_block2.__init__(self, "nbfm_rx",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature(1, 1, gr.sizeof_float))      # Output signature

        # FIXME audio_rate and quad_rate ought to be exact rationals
        audio_rate = int(audio_rate)
        quad_rate = int(quad_rate)

        if quad_rate % audio_rate != 0:
            raise ValueError, "quad_rate is not an integer multiple of audio_rate"

        squelch_threshold = 20		# dB
        #self.squelch = gr.simple_squelch_cc(squelch_threshold, 0.001)

        # FM Demodulator  input: complex; output: float
        k = quad_rate/(2*math.pi*max_dev)
        self.quad_demod = gr.quadrature_demod_cf(k)

        # FM Deemphasis IIR filter
        self.deemph = fm_deemph (quad_rate, tau=tau)

        # compute FIR taps for audio filter
        audio_decim = quad_rate // audio_rate
        audio_taps = gr.firdes.low_pass (1.0,            # gain
                                         quad_rate,      # sampling rate
                                         2.7e3,          # Audio LPF cutoff
                                         0.5e3,          # Transition band
                                         gr.firdes.WIN_HAMMING)  # filter type

        print "len(audio_taps) =", len(audio_taps)

        # Decimating audio filter
        # input: float; output: float; taps: float
        self.audio_filter = gr.fir_filter_fff(audio_decim, audio_taps)

        self.connect(self, self.quad_demod, self.deemph, self.audio_filter, self)
示例#3
0
    def __init__(self, quad_rate, audio_decimation):
        """
        Hierarchical block for demodulating a broadcast FM signal.

        The input is the downconverted complex baseband signal (gr_complex).
        The output is the demodulated audio (float).

        @param quad_rate: input sample rate of complex baseband input.
        @type quad_rate: float
        @param audio_decimation: how much to decimate quad_rate to get to audio.
        @type audio_decimation: integer
        """
        gr.hier_block2.__init__(
            self,
            "wfm_rcv",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_float))  # Output signature

        volume = 20.

        max_dev = 75e3
        fm_demod_gain = quad_rate / (2 * math.pi * max_dev)
        audio_rate = quad_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
        self.fm_demod = gr.quadrature_demod_cf(fm_demod_gain)

        # input: float; output: float
        self.deemph = 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
            quad_rate,  # sampling rate
            audio_rate / 2 - width_of_transition_band,
            width_of_transition_band,
            gr.firdes.WIN_HAMMING)
        # input: float; output: float
        self.audio_filter = gr.fir_filter_fff(audio_decimation, audio_coeffs)

        self.connect(self, self.fm_demod, self.audio_filter, self.deemph, self)
示例#4
0
    def __init__ (self, quad_rate, audio_decimation):
        """
        Hierarchical block for demodulating a broadcast FM signal.

        The input is the downconverted complex baseband signal (gr_complex).
        The output is the demodulated audio (float).

        @param quad_rate: input sample rate of complex baseband input.
        @type quad_rate: float
        @param audio_decimation: how much to decimate quad_rate to get to audio.
        @type audio_decimation: integer
        """
	gr.hier_block2.__init__(self, "wfm_rcv",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature(1, 1, gr.sizeof_float))      # Output signature

        volume = 20.

        max_dev = 75e3
        fm_demod_gain = quad_rate/(2*math.pi*max_dev)
        audio_rate = quad_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
        self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain)

        # input: float; output: float
        self.deemph = 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
                                           quad_rate,      # sampling rate
                                           audio_rate/2 - width_of_transition_band,
                                           width_of_transition_band,
                                           gr.firdes.WIN_HAMMING)
        # input: float; output: float
        self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)

        self.connect (self, self.fm_demod, self.audio_filter, self.deemph, self)
示例#5
0
    def __init__(self, channel_rate, audio_decim, deviation,
                 audio_pass, audio_stop, gain=1.0, tau=75e-6):
	gr.hier_block2.__init__(self, "fm_demod_cf",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature(1, 1, gr.sizeof_float))      # Output signature

	k = channel_rate/(2*pi*deviation)
	QUAD = gr.quadrature_demod_cf(k)

	audio_taps = optfir.low_pass(gain, 	   # Filter gain
	                             channel_rate, # Sample rate
				     audio_pass,   # Audio passband
				     audio_stop,   # Audio stopband
				     0.1, 	   # Passband ripple
				     60)	   # Stopband attenuation
	LPF = gr.fir_filter_fff(audio_decim, audio_taps)

	if tau is not None:
	    DEEMPH = fm_deemph(channel_rate, tau)
	    self.connect(self, QUAD, DEEMPH, LPF, self)
        else:
            self.connect(self, QUAD, LPF, self)
示例#6
0
    def __init__(self, freq, subdev_spec, which_USRP, gain, audio_output, debug):
        gr.hier_block2.__init__(self, "analog_receive_path",
                                gr.io_signature(0, 0, 0), #input signature
                                gr.io_signature(0, 0, 0)) #output signature
        
        self.DEBUG = debug
        self.freq = freq
        self.rx_gain = gain

        #Formerly From XML
        self.fusb_block_size = 2048
        self.fusb_nblocks = 8
        self.rx_usrp_pga_gain_scaling = 0.5
        self.rx_base_band_bw = 5e3
        self.rx_freq_deviation = 2.5e3


              
        # acquire USRP via USB 2.0
        #self.u = usrp.source_c(fusb_block_size=self.fusb_block_size,
        #                       fusb_nblocks=self.fusb_nblocks,
        #                       which=which_USRP)
	self.u = uhd.single_usrp_source(
			device_addr="",
			io_type=uhd.io_type_t.COMPLEX_FLOAT32,
			num_channels=1,
			)
        self.u.get_device
        # get A/D converter sampling rate 
        #adc_rate = self.u.adc_rate()      # 64 MS/s
        adc_rate = 64e6      # 64 MS/s
        if self.DEBUG:
            print "    Rx Path ADC rate:      %d" %(adc_rate)

        # setting USRP and GNU Radio decimation rate
        self.audio_rate = 16e3
        self.max_gr_decim_rate = 40

        self._usrp_decim = 250
        self.gr_rate1 = adc_rate / self._usrp_decim
        gr_interp = 1
        gr_decim  = 16
        self.gr_rate2 = self.gr_rate1 / gr_decim
            

        if self.DEBUG:
            print "    usrp decim: ", self._usrp_decim
            print "    gr rate 1:  ", self.gr_rate1
            print "    gr decim: ", gr_decim
            print "    gr rate 2: ", self.gr_rate2
            print "    gr interp: ", gr_interp 
            print "    audio rate: ", self.audio_rate

      
        # ================  Set up flowgraph  =================================
              
        # set USRP decimation ratio
        #self.u.set_decim_rate(self._usrp_decim)
	self.u.set_samp_rate(self.gr_rate1)
	self.u.set_antenna("RX2")
        

        # set USRP daughterboard subdevice
        if subdev_spec is None:
           subdev_spec = usrp.pick_rx_subdevice(self.u)	
        #self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec))
        #self.subdev = usrp.selected_subdev(self.u, subdev_spec)
        #if self.DEBUG:
        #    print "    RX Path use daughterboard:  %s"    % (self.subdev.side_and_name())


        # set USRP RF frequency
        """
        Set the center frequency in Hz.
        Tuning is a two step process.  First we ask the front-end to
        tune as close to the desired frequency as it can.  Then we use
        the result of that operation and our target_frequency to
        determine the value for the digital up converter.
        """
        assert(self.freq != None)
        #r = self.u.tune(0, self.subdev, self.freq)
        r = self.u.set_center_freq(self.freq, 0)
        if self.DEBUG:
            if r:
                print "----Rx RF frequency set to %f Hz" %(self.freq)
            else:
                print "Failed to set Rx frequency to %f Hz" %(self.freq)
                raise ValueError, eng_notation.num_to_str(self.freq)
        


        # set USRP Rx PGA gain   
        #r = self.subdev.gain_range()
        #_rx_usrp_gain_range = r[1] - r[0]          
        #_rx_usrp_gain = r[0]+_rx_usrp_gain_range * self.rx_usrp_pga_gain_scaling
        #self.subdev.set_gain(_rx_usrp_gain)
	#self.u.set_gain(3.25, 0)
        #if self.DEBUG:
        #    print "    USRP Rx PGA Gain Range: min = %g, max = %g, step size = %g" \
        #            %(r[0], r[1], r[2])
        #    print "    USRP Rx PGA gain set to: %g" %(_rx_usrp_gain)        

        # Do NOT Enable USRP Auto Tx/Rx switching for analog flow graph!
        #self.subdev.set_enable(False)     


        # Baseband Channel Filter using FM Carson's Rule
        chan_bw = 2*(self.rx_base_band_bw+self.rx_freq_deviation)     #Carson's Rule
        chan_filt_coeffs_float = optfir.low_pass (1,                        #gain
                                            self.gr_rate1,             #sampling rate
                                            chan_bw,              #passband cutoff
                                            chan_bw*1.35,              #stopband cutoff
                                            0.1,                      #passband ripple
                                            60)                       #stopband attenuation
        chan_filt_coeffs_fixed = (
            0.000457763671875,
            0.000946044921875,                     
            0.00067138671875,                    
            0.001068115234375,
            0.00091552734375,                    
            0.0008544921875,                       
            0.000518798828125,                     
            0.0001220703125,                      
            -0.000396728515625,                     
            -0.0008544921875,                       
            -0.00128173828125,                      
            -0.00146484375,                         
            -0.001434326171875,                     
            -0.0010986328125,                       
            -0.000518798828125,                     
            0.000274658203125,                     
            0.001129150390625,                     
            0.00189208984375,                      
            0.00238037109375,                      
            0.00250244140625,                      
            0.002166748046875,                     
            0.0013427734375,                       
            0.000152587890625,                     
            -0.001220703125,                        
            -0.002532958984375,                     
            -0.0035400390625,                       
            -0.003997802734375,                     
            -0.003753662109375,                     
            -0.002777099609375,                     
            -0.0010986328125,                       
            0.000946044921875,                     
            0.00311279296875,                      
            0.00494384765625,                      
            0.00604248046875,                      
            0.006103515625,                        
            0.005035400390625,                     
            0.00286865234375,                      
            -0.0001220703125,                       
            -0.00347900390625,                      
            -0.006561279296875,                     
            -0.008758544921875,                     
            -0.00958251953125,                     
            -0.008636474609375,                     
            -0.005950927734375,                     
            -0.001739501953125,                     
            0.00335693359375,                      
            0.00848388671875,                      
            0.0126953125,                          
            0.01507568359375,                      
            0.014862060546875,                     
            0.01171875,                            
            0.00579833984375,
            -0.002227783203125,                    
            -0.01123046875,                        
            -0.0196533203125,                       
            -0.02587890625,                         
            -0.028228759765625,                     
            -0.025421142578125,                     
            -0.016754150390625,                     
            -0.002166748046875,                     
            0.017608642578125,                     
            0.041015625,                           
            0.0660400390625,
            0.090240478515625,
            0.111083984375,                        
            0.12640380859375,                      
            0.134490966796875,                     
            0.134490966796875,                     
            0.12640380859375,                     
            0.111083984375,                     
            0.090240478515625,                     
            0.0660400390625,                       
            0.041015625,                           
            0.017608642578125,
            -0.002166748046875,                     
            -0.016754150390625,                     
            -0.025421142578125,                     
            -0.028228759765625,                     
            -0.02587890625,                     
            -0.0196533203125,
            -0.01123046875,                         
            -0.002227783203125,
            0.00579833984375,                      
            0.01171875,                            
            0.014862060546875,
            0.01507568359375,                      
            0.0126953125,                          
            0.00848388671875,                      
            0.00335693359375,                     
            -0.001739501953125,                     
            -0.005950927734375,                    
            -0.008636474609375,                     
            -0.00958251953125,                      
            -0.008758544921875,                     
            -0.006561279296875,                     
            -0.00347900390625,                      
            -0.0001220703125,                       
            0.00286865234375,                      
            0.005035400390625,                     
            0.006103515625,                        
            0.00604248046875,                      
            0.00494384765625,                      
            0.00311279296875,                      
            0.000946044921875,                     
            -0.0010986328125,                       
            -0.002777099609375,                     
            -0.003753662109375,                     
            -0.003997802734375,                     
            -0.0035400390625,                       
            -0.002532958984375,                     
            -0.001220703125,                        
            0.000152587890625,                     
            0.0013427734375,                       
            0.002166748046875,                    
            0.00250244140625,                     
            0.00238037109375,                      
            0.00189208984375,                      
            0.001129150390625,                     
            0.000274658203125,                     
            -0.000518798828125,                     
            -0.0010986328125,                       
            -0.001434326171875,                     
            -0.00146484375,                         
            -0.00128173828125,                      
            -0.0008544921875,                       
            -0.000396728515625,                     
            0.0001220703125,                       
            0.000518798828125,                    
            0.0008544921875,                       
            0.00091552734375,                      
            0.001068115234375,                     
            0.00067138671875,                      
            0.000946044921875,                     
            0.000457763671875)

        #r = gr.enable_realtime_scheduling ()
        self.chan_filt = dsp.fir_ccf_fm_demod_decim (chan_filt_coeffs_fixed, 14, gr_decim, 0, 0, 0, 0)
        print "Tap length of chan FIR: ", len(chan_filt_coeffs_fixed)


        # Set the software LNA gain on the output of the USRP       
        gain= self.rx_gain
        self.rx_gain = max(0.0, min(gain, 1e7))        

        if self.DEBUG:
            print "    Rx Path initial software signal gain: %f (max 1e7)" %(gain)
            print "    Rx Path actual software signal gain : %f (max 1e7)" %(self.rx_gain)        

        #FM Demodulator
        fm_demod_gain = self.audio_rate / (2*math.pi*self.rx_freq_deviation)
        self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain)        


        #Compute FIR filter taps for audio filter
        width_of_transition_band = self.rx_base_band_bw * 0.35
        audio_coeffs = gr.firdes.low_pass (1.0,                  #gain
                                           self.gr_rate2,      #sampling rate
                                           self.rx_base_band_bw,
                                           width_of_transition_band,
                                           gr.firdes.WIN_HAMMING)
        

        self.audio_filter = gr.fir_filter_fff(1, audio_coeffs)
        passband_cutoff = self.rx_base_band_bw        
        stopband_cutoff = passband_cutoff * 1.35
 
        self.deemph = fm_deemph(self.audio_rate)

        if self.DEBUG:
            print "Length Audio FIR ", len(audio_coeffs)
        # Audio sink

        audio_sink = audio.sink(int(self.audio_rate),"default")
        #                         "",     #Audio output pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp
        #                         False)  # ok_to_block
        
        if self.DEBUG:
            print "Before Connecting Blocks"
        # Wiring Up
        #WITH CHANNEL FILTER
        #self.connect (self.u, self.chan_filt, self.lna, self.fm_demod, self.audio_filter, interpolator, self.deemph, self.volume_control, audio_sink)     

        #self.connect (self.u, self.fm_demod, self.audio_filter, self.deemph, self.volume_control, howto_rx, audio_sink)     
        self.connect (self.u, self.chan_filt, self.audio_filter, self.deemph, audio_sink)     
示例#7
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_fmdet",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(2, 2, gr.sizeof_float))  # Output signature
        lowfreq = -125e3 / demod_rate
        highfreq = 125e3 / demod_rate
        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

        self.fm_demod = gr.fmdet_cf(demod_rate, lowfreq, highfreq, 0.05)

        # 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
            # the resulting signal from this multiplier is the carrier
            # with correct phase but at -38000 Hz.
            self.connect(self.stereo_carrier_pll_recovery,
                         (self.stereo_carrier_generator, 1))

            # 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
            # the result is BASEBANDED DSBSC with phase zero!
            self.connect(self.fm_demod, self.stereo_dsbsc_filter,
                         (self.stereo_basebander, 1))

            # 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))
示例#8
0
    def __init__(self, freq, subdev_spec, which_USRP, gain, audio_output,
                 debug):
        gr.hier_block2.__init__(
            self,
            "analog_receive_path",
            gr.io_signature(0, 0, 0),  #input signature
            gr.io_signature(0, 0, 0))  #output signature

        self.DEBUG = debug
        self.freq = freq
        self.rx_gain = gain

        #Formerly From XML
        self.fusb_block_size = 2048
        self.fusb_nblocks = 8
        self.rx_usrp_pga_gain_scaling = 0.5
        self.rx_base_band_bw = 5e3
        self.rx_freq_deviation = 2.5e3

        # acquire USRP via USB 2.0
        #self.u = usrp.source_c(fusb_block_size=self.fusb_block_size,
        #                       fusb_nblocks=self.fusb_nblocks,
        #                       which=which_USRP)
        self.u = uhd.single_usrp_source(
            device_addr="",
            io_type=uhd.io_type_t.COMPLEX_FLOAT32,
            num_channels=1,
        )
        self.u.get_device
        # get A/D converter sampling rate
        #adc_rate = self.u.adc_rate()      # 64 MS/s
        adc_rate = 64e6  # 64 MS/s
        if self.DEBUG:
            print "    Rx Path ADC rate:      %d" % (adc_rate)

        # setting USRP and GNU Radio decimation rate
        self.audio_rate = 16e3
        self.max_gr_decim_rate = 40

        self._usrp_decim = 250
        self.gr_rate1 = adc_rate / self._usrp_decim
        gr_interp = 1
        gr_decim = 16
        self.gr_rate2 = self.gr_rate1 / gr_decim

        if self.DEBUG:
            print "    usrp decim: ", self._usrp_decim
            print "    gr rate 1:  ", self.gr_rate1
            print "    gr decim: ", gr_decim
            print "    gr rate 2: ", self.gr_rate2
            print "    gr interp: ", gr_interp
            print "    audio rate: ", self.audio_rate

        # ================  Set up flowgraph  =================================

        # set USRP decimation ratio
        #self.u.set_decim_rate(self._usrp_decim)
        self.u.set_samp_rate(self.gr_rate1)
        self.u.set_antenna("RX2")

        # set USRP daughterboard subdevice
        if subdev_spec is None:
            subdev_spec = usrp.pick_rx_subdevice(self.u)
        #self.u.set_mux(usrp.determine_rx_mux_value(self.u, subdev_spec))
        #self.subdev = usrp.selected_subdev(self.u, subdev_spec)
        #if self.DEBUG:
        #    print "    RX Path use daughterboard:  %s"    % (self.subdev.side_and_name())

        # set USRP RF frequency
        """
        Set the center frequency in Hz.
        Tuning is a two step process.  First we ask the front-end to
        tune as close to the desired frequency as it can.  Then we use
        the result of that operation and our target_frequency to
        determine the value for the digital up converter.
        """
        assert (self.freq != None)
        #r = self.u.tune(0, self.subdev, self.freq)
        r = self.u.set_center_freq(self.freq, 0)
        if self.DEBUG:
            if r:
                print "----Rx RF frequency set to %f Hz" % (self.freq)
            else:
                print "Failed to set Rx frequency to %f Hz" % (self.freq)
                raise ValueError, eng_notation.num_to_str(self.freq)

        # set USRP Rx PGA gain
        #r = self.subdev.gain_range()
        #_rx_usrp_gain_range = r[1] - r[0]
        #_rx_usrp_gain = r[0]+_rx_usrp_gain_range * self.rx_usrp_pga_gain_scaling
        #self.subdev.set_gain(_rx_usrp_gain)
#self.u.set_gain(3.25, 0)
#if self.DEBUG:
#    print "    USRP Rx PGA Gain Range: min = %g, max = %g, step size = %g" \
#            %(r[0], r[1], r[2])
#    print "    USRP Rx PGA gain set to: %g" %(_rx_usrp_gain)

# Do NOT Enable USRP Auto Tx/Rx switching for analog flow graph!
#self.subdev.set_enable(False)

# Baseband Channel Filter using FM Carson's Rule
        chan_bw = 2 * (self.rx_base_band_bw + self.rx_freq_deviation
                       )  #Carson's Rule
        chan_filt_coeffs_float = optfir.low_pass(
            1,  #gain
            self.gr_rate1,  #sampling rate
            chan_bw,  #passband cutoff
            chan_bw * 1.35,  #stopband cutoff
            0.1,  #passband ripple
            60)  #stopband attenuation
        chan_filt_coeffs_fixed = (
            0.000457763671875, 0.000946044921875, 0.00067138671875,
            0.001068115234375, 0.00091552734375, 0.0008544921875,
            0.000518798828125, 0.0001220703125, -0.000396728515625,
            -0.0008544921875, -0.00128173828125, -0.00146484375,
            -0.001434326171875, -0.0010986328125, -0.000518798828125,
            0.000274658203125, 0.001129150390625, 0.00189208984375,
            0.00238037109375, 0.00250244140625, 0.002166748046875,
            0.0013427734375, 0.000152587890625, -0.001220703125,
            -0.002532958984375, -0.0035400390625, -0.003997802734375,
            -0.003753662109375, -0.002777099609375, -0.0010986328125,
            0.000946044921875, 0.00311279296875, 0.00494384765625,
            0.00604248046875, 0.006103515625, 0.005035400390625,
            0.00286865234375, -0.0001220703125, -0.00347900390625,
            -0.006561279296875, -0.008758544921875, -0.00958251953125,
            -0.008636474609375, -0.005950927734375, -0.001739501953125,
            0.00335693359375, 0.00848388671875, 0.0126953125, 0.01507568359375,
            0.014862060546875, 0.01171875, 0.00579833984375,
            -0.002227783203125, -0.01123046875, -0.0196533203125,
            -0.02587890625, -0.028228759765625, -0.025421142578125,
            -0.016754150390625, -0.002166748046875, 0.017608642578125,
            0.041015625, 0.0660400390625, 0.090240478515625, 0.111083984375,
            0.12640380859375, 0.134490966796875, 0.134490966796875,
            0.12640380859375, 0.111083984375, 0.090240478515625,
            0.0660400390625, 0.041015625, 0.017608642578125,
            -0.002166748046875, -0.016754150390625, -0.025421142578125,
            -0.028228759765625, -0.02587890625, -0.0196533203125,
            -0.01123046875, -0.002227783203125, 0.00579833984375, 0.01171875,
            0.014862060546875, 0.01507568359375, 0.0126953125,
            0.00848388671875, 0.00335693359375, -0.001739501953125,
            -0.005950927734375, -0.008636474609375, -0.00958251953125,
            -0.008758544921875, -0.006561279296875, -0.00347900390625,
            -0.0001220703125, 0.00286865234375, 0.005035400390625,
            0.006103515625, 0.00604248046875, 0.00494384765625,
            0.00311279296875, 0.000946044921875, -0.0010986328125,
            -0.002777099609375, -0.003753662109375, -0.003997802734375,
            -0.0035400390625, -0.002532958984375, -0.001220703125,
            0.000152587890625, 0.0013427734375, 0.002166748046875,
            0.00250244140625, 0.00238037109375, 0.00189208984375,
            0.001129150390625, 0.000274658203125, -0.000518798828125,
            -0.0010986328125, -0.001434326171875, -0.00146484375,
            -0.00128173828125, -0.0008544921875, -0.000396728515625,
            0.0001220703125, 0.000518798828125, 0.0008544921875,
            0.00091552734375, 0.001068115234375, 0.00067138671875,
            0.000946044921875, 0.000457763671875)

        #r = gr.enable_realtime_scheduling ()
        self.chan_filt = dsp.fir_ccf_fm_demod_decim(chan_filt_coeffs_fixed, 14,
                                                    gr_decim, 0, 0, 0, 0)
        print "Tap length of chan FIR: ", len(chan_filt_coeffs_fixed)

        # Set the software LNA gain on the output of the USRP
        gain = self.rx_gain
        self.rx_gain = max(0.0, min(gain, 1e7))

        if self.DEBUG:
            print "    Rx Path initial software signal gain: %f (max 1e7)" % (
                gain)
            print "    Rx Path actual software signal gain : %f (max 1e7)" % (
                self.rx_gain)

        #FM Demodulator
        fm_demod_gain = self.audio_rate / (2 * math.pi *
                                           self.rx_freq_deviation)
        self.fm_demod = gr.quadrature_demod_cf(fm_demod_gain)

        #Compute FIR filter taps for audio filter
        width_of_transition_band = self.rx_base_band_bw * 0.35
        audio_coeffs = gr.firdes.low_pass(
            1.0,  #gain
            self.gr_rate2,  #sampling rate
            self.rx_base_band_bw,
            width_of_transition_band,
            gr.firdes.WIN_HAMMING)

        self.audio_filter = gr.fir_filter_fff(1, audio_coeffs)
        passband_cutoff = self.rx_base_band_bw
        stopband_cutoff = passband_cutoff * 1.35

        self.deemph = fm_deemph(self.audio_rate)

        if self.DEBUG:
            print "Length Audio FIR ", len(audio_coeffs)
        # Audio sink

        audio_sink = audio.sink(int(self.audio_rate), "default")
        #                         "",     #Audio output pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp
        #                         False)  # ok_to_block

        if self.DEBUG:
            print "Before Connecting Blocks"
        # Wiring Up
        #WITH CHANNEL FILTER
        #self.connect (self.u, self.chan_filt, self.lna, self.fm_demod, self.audio_filter, interpolator, self.deemph, self.volume_control, audio_sink)

        #self.connect (self.u, self.fm_demod, self.audio_filter, self.deemph, self.volume_control, howto_rx, audio_sink)
        self.connect(self.u, self.chan_filt, self.audio_filter, self.deemph,
                     audio_sink)
示例#9
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.

        Args:
            demod_rate: input sample rate of complex baseband input. (float)
            audio_decimation: how much to decimate demod_rate to get to audio. (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, demod_rate, 15000, width_of_transition_band, gr.firdes.WIN_HAMMING  # gain  # sampling rate
        )
        # 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))
示例#10
0
    def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3):
        """
        Narrow Band FM Receiver.

        Takes a single complex baseband input stream and produces a single
        float output stream of audio sample in the range [-1, +1].

        @param audio_rate: sample rate of audio stream, >= 16k
        @type audio_rate: integer
        @param quad_rate: sample rate of output stream
        @type quad_rate: integer
        @param tau: preemphasis time constant (default 75e-6)
        @type tau: float
        @param max_dev: maximum deviation in Hz (default 5e3)
        @type max_dev: float

        quad_rate must be an integer multiple of audio_rate.

        Exported sub-blocks (attributes):
          squelch
          quad_demod
          deemph
          audio_filter
        """

        gr.hier_block2.__init__(
            self,
            "nbfm_rx",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_float))  # Output signature

        # FIXME audio_rate and quad_rate ought to be exact rationals
        audio_rate = int(audio_rate)
        quad_rate = int(quad_rate)

        if quad_rate % audio_rate != 0:
            raise ValueError, "quad_rate is not an integer multiple of audio_rate"

        squelch_threshold = 20  # dB
        #self.squelch = gr.simple_squelch_cc(squelch_threshold, 0.001)

        # FM Demodulator  input: complex; output: float
        k = quad_rate / (2 * math.pi * max_dev)
        self.quad_demod = gr.quadrature_demod_cf(k)

        # FM Deemphasis IIR filter
        self.deemph = fm_deemph(quad_rate, tau=tau)

        # compute FIR taps for audio filter
        audio_decim = quad_rate // audio_rate
        audio_taps = gr.firdes.low_pass(
            1.0,  # gain
            quad_rate,  # sampling rate
            2.7e3,  # Audio LPF cutoff
            0.5e3,  # Transition band
            gr.firdes.WIN_HAMMING)  # filter type

        print "len(audio_taps) =", len(audio_taps)

        # Decimating audio filter
        # input: float; output: float; taps: float
        self.audio_filter = gr.fir_filter_fff(audio_decim, audio_taps)

        self.connect(self, self.quad_demod, self.deemph, self.audio_filter,
                     self)
示例#11
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=100.1e6,
                          help="set frequency to FREQ", metavar="FREQ")
        parser.add_option("-g", "--gain", type="eng_float", default=40,
                          help="set gain in dB (default is midpoint)")
        parser.add_option("-V", "--volume", type="eng_float", default=None,
                          help="set volume (default is midpoint)")
        parser.add_option("-O", "--audio-output", type="string", default="",
                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")

        (options, args) = parser.parse_args()
        if len(args) != 0:
            parser.print_help()
            sys.exit(1)

        self.frame = frame
        self.panel = panel

        self.vol = 0
        self.state = "FREQ"
        self.freq = 0

        # build graph

        self.u = usrp.source_c()                    # usrp is data source

        adc_rate = self.u.adc_rate()                # 64 MS/s
        usrp_decim = 200
        self.u.set_decim_rate(usrp_decim)
        usrp_rate = adc_rate / usrp_decim           # 320 kS/s
        chanfilt_decim = 1
        demod_rate = usrp_rate / chanfilt_decim
        sca_chanfilt_decim = 5
        sca_demod_rate = demod_rate / sca_chanfilt_decim  #64 kHz
        audio_decimation = 2
        audio_rate = sca_demod_rate / audio_decimation  # 32 kHz

        if options.rx_subdev_spec is None:
            options.rx_subdev_spec = pick_subdevice(self.u)

        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))
        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
        print "Using RX d'board %s" % (self.subdev.side_and_name(),)

        #Create filter to get main FM Channel we want
        chan_filt_coeffs = optfir.low_pass (1,           # gain
                                            usrp_rate,   # sampling rate
                                            100e3,        # passband cutoff
                                            140e3,       # stopband cutoff
                                            0.1,         # passband ripple
                                            60)          # stopband attenuation
        #print len(chan_filt_coeffs)
        chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)

        #Create demodulator block for Main FM Channel
	max_dev = 75e3
        fm_demod_gain = demod_rate/(2*math.pi*max_dev)
        self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain)

        # Note - deemphasis is not applied to the Main FM Channel as main audio is not decoded

        # SCA Devation is 10% of carrier but some references say 20% if mono with one SCA (6 KHz seems typical)
        max_sca_dev = 6e3

	# Create filter to get SCA channel we want
        sca_chan_coeffs = gr.firdes.low_pass (1.0,                # gain
                                          demod_rate,       # sampling rate
                                          max_sca_dev,      # low pass cutoff freq
                                          max_sca_dev/3,    # width of trans. band
                                          gr.firdes.WIN_HANN) # filter type

        self.ddc = gr.freq_xlating_fir_filter_fcf(sca_chanfilt_decim,       # decimation rate
                                                  sca_chan_coeffs,    # taps
                                                  0,              # frequency translation amount (Gets set by the UI)
                                                  demod_rate)   # input sample rate

        #Create demodulator block for SCA Channel
        sca_demod_gain = sca_demod_rate/(2*math.pi*max_sca_dev)
        self.fm_demod_sca = gr.quadrature_demod_cf (sca_demod_gain)


        # SCA analog audio is bandwidth limited to 5 KHz
        max_sca_audio_freq = 5.0e3
        # SCA analog deephasis is 150 uS (75 uS may be used)
        sca_tau = 150e-6

        # compute FIR filter taps for SCA audio filter
        audio_coeffs = gr.firdes.low_pass (1.0,         # gain
                                           sca_demod_rate,      # sampling rate
                                           max_sca_audio_freq, # low pass cutoff freq
                                           max_sca_audio_freq/2.5,             # width of trans. band
                                           gr.firdes.WIN_HAMMING)

        # input: float; output: float
        self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)

	# Create deemphasis block that is applied after SCA demodulation
        self.deemph = fm_deemph (audio_rate, sca_tau)

        self.volume_control = gr.multiply_const_ff(self.vol)

        # sound card as final sink
        audio_sink = audio.sink (int (audio_rate),
                                 options.audio_output,
                                 False)  # ok_to_block

        # now wire it all together
        self.connect (self.u, chan_filt, self.fm_demod, self.ddc, self.fm_demod_sca)
        self.connect (self.fm_demod_sca, self.audio_filter, self.deemph, self.volume_control, audio_sink)

        self._build_gui(vbox, usrp_rate, demod_rate, sca_demod_rate, audio_rate)

        if options.gain is None:
            # if no gain was specified, use the mid-point in dB
            g = self.subdev.gain_range()
            options.gain = float(g[0]+g[1])/2

        if options.volume is None:
            g = self.volume_range()
            options.volume = float(g[0]+g[1])/2

        if abs(options.freq) < 1e6:
            options.freq *= 1e6

        # set initial values

        self.set_gain(options.gain)
        self.set_vol(options.volume)
        if not(self.set_freq(options.freq)):
            self._set_status_msg("Failed to set initial frequency")
        self.set_sca_freq(67000)  # A common SCA Frequency