def __init__(self, access_code='', threshold=-1, callback=None, verbose=0):
        """
		packet_demod constructor.
		@param access_code AKA sync vector
		@param threshold detect access_code with up to threshold bits wrong (0 -> use default)
		@param callback a function of args: ok, payload
		"""
        #access code
        if not access_code:  #get access code
            access_code = packet_utils.default_access_code
        if not packet_utils.is_1_0_string(access_code):
            raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (
                access_code, )
        self._access_code = access_code
        #threshold
        if threshold < 0: threshold = DEFAULT_THRESHOLD
        self._threshold = threshold
        #blocks
        msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT)  #holds packets from the PHY
        correlator = gr.correlate_access_code_bb(self._access_code,
                                                 self._threshold)
        framer_sink = logitech_27mhz_transceiver.framer_sink(msgq)

        #initialize hier2
        gr.hier_block2.__init__(
            self,
            "packet_decoder",
            gr.io_signature(1, 1, gr.sizeof_char),  # Input signature
            gr.io_signature(0, 0, 0)  # Output signature
        )
        #connect
        self.connect(self, correlator, framer_sink)
        #start thread
        _packet_decoder_thread(msgq, callback, verbose)
	def __init__(self, access_code='', threshold=-1, callback=None, verbose=0):
		"""
		packet_demod constructor.
		@param access_code AKA sync vector
		@param threshold detect access_code with up to threshold bits wrong (0 -> use default)
		@param callback a function of args: ok, payload
		"""
		#access code
		if not access_code: #get access code
			access_code = packet_utils.default_access_code
		if not packet_utils.is_1_0_string(access_code):
			raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
		self._access_code = access_code
		#threshold
		if threshold < 0: threshold = DEFAULT_THRESHOLD
		self._threshold = threshold
		#blocks
		msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY
		correlator = gr.correlate_access_code_bb(self._access_code, self._threshold)
		framer_sink = logitech_27mhz_transceiver.framer_sink(msgq)

		#initialize hier2
		gr.hier_block2.__init__(
			self,
			"packet_decoder",
			gr.io_signature(1, 1, gr.sizeof_char), # Input signature
			gr.io_signature(0, 0, 0) # Output signature
		)
		#connect
		self.connect(self, correlator, framer_sink)
		#start thread
		_packet_decoder_thread(msgq, callback,verbose)
	def __init__(self, options, queue):
		gr.top_block.__init__(self)

		self.u = usrp.source_c()
		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()
		self.u.set_decim_rate(options.decim)
		self.centerfreq = options.centerfreq
		print "Tuning to: %fMHz" % (self.centerfreq - options.error)
		if not(self.tune(options.centerfreq - options.error)):
			print "Failed to set initial frequency"
	
		if options.gain is None: #set to halfway
			g = self.subdev.gain_range()
			options.gain = (g[0]+g[1]) / 2.0

		print "Setting gain to %i" % options.gain
		self.subdev.set_gain(options.gain)

		if self.subdev.name() == "DBS Rx":
			self.subdev.set_bw(options.bandwidth) #only for DBSRX
			print "Setting DBS RX bandwidth to %fMHz" % float(options.bandwidth / 1e6)

		self.rate = self.u.adc_rate() / options.decim
		
		print "Samples per second is %i" % self.rate

		self._syms_per_sec = 3600;

		options.audiorate = 11025
		options.rate = self.rate

		options.samples_per_second = self.rate #yeah i know it's on the list
		options.syms_per_sec = self._syms_per_sec
		options.gain_mu = 0.01
		options.mu=0.5
		options.omega_relative_limit = 0.3
		options.syms_per_sec = self._syms_per_sec
		options.offset = options.centerfreq - options.freq
		print "Control channel offset: %f" % options.offset

		self.demod = fsk_demod(options)
		self.start_correlator = gr.correlate_access_code_bb("10101100",0) #should mark start of packet
		self.smartnet_sync = smartnet.sync()
		self.smartnet_deinterleave = smartnet.deinterleave()
		self.smartnet_parity = smartnet.parity()
		self.smartnet_crc = smartnet.crc()
		self.smartnet_packetize = smartnet.packetize()
		self.parse = smartnet.parse(queue) #packet-based. this simply posts lightly-formatted messages to the queue.

		self.connect(self.u, self.demod)

		self.connect(self.demod, self.start_correlator, self.smartnet_sync, self.smartnet_deinterleave, self.smartnet_parity, self.smartnet_crc, self.smartnet_packetize, self.parse)
Beispiel #4
0
 def test_001(self):
     pad = (0,) * 64
     #           0  0  0  1  0  0  0  1
     src_data = (1, 0, 1, 1, 1, 1, 0, 1, 1) + pad + (0,) * 7
     expected_result = pad + (1, 0, 1, 1, 3, 1, 0, 1, 1, 2) + (0,) * 6
     src = gr.vector_source_b (src_data)
     op = gr.correlate_access_code_bb("1011", 0)
     dst = gr.vector_sink_b ()
     self.tb.connect (src, op, dst)
     self.tb.run ()
     result_data = dst.data ()
     self.assertEqual (expected_result, result_data)
Beispiel #5
0
 def test_002(self):
     code = tuple(string_to_1_0_list(default_access_code))
     access_code = to_1_0_string(code)
     pad = (0,) * 64
     #print code
     #print access_code
     src_data = code + (1, 0, 1, 1) + pad
     expected_result = pad + code + (3, 0, 1, 1)
     src = gr.vector_source_b (src_data)
     op = gr.correlate_access_code_bb(access_code, 0)
     dst = gr.vector_sink_b ()
     self.tb.connect (src, op, dst)
     self.tb.run ()
     result_data = dst.data ()
     self.assertEqual (expected_result, result_data)
Beispiel #6
0
    def __init__(self,
                 demodulator,
                 access_code=None,
                 callback=None,
                 threshold=-1):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        @param demodulator: instance of demodulator class (gr_block or hier_block2)
        @type demodulator: complex baseband in
        @param access_code: AKA sync vector
        @type access_code: string of 1's and 0's
        @param callback:  function of two args: ok, payload
        @type callback: ok: bool; payload: string
        @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
        @type threshold: int
	"""

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

        self._demodulator = demodulator
        if access_code is None:
            access_code = packet_utils.default_access_code
        if not packet_utils.is_1_0_string(access_code):
            raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (
                access_code, )
        self._access_code = access_code

        if threshold == -1:
            threshold = 12  # FIXME raise exception

        self._rcvd_pktq = gr.msg_queue()  # holds packets from the PHY
        self.correlator = gr.correlate_access_code_bb(access_code, threshold)

        self.framer_sink = gr.framer_sink_1(self._rcvd_pktq)
        self.connect(self, self._demodulator, self.correlator,
                     self.framer_sink)

        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
Beispiel #7
0
    def __init__(self, demodulator, access_code=None, callback=None, threshold=-1):
        """
    Hierarchical block for demodulating and deframing packets.

    The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        @param demodulator: instance of demodulator class (gr_block or hier_block2)
        @type demodulator: complex baseband in
        @param access_code: AKA sync vector
        @type access_code: string of 1's and 0's
        @param callback:  function of two args: ok, payload
        @type callback: ok: bool; payload: string
        @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default)
        @type threshold: int
    """

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

        self._demodulator = demodulator
        if access_code is None:
            access_code = packet_utils.default_access_code
        if not packet_utils.is_1_0_string(access_code):
            raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
        self._access_code = access_code

        if threshold == -1:
            threshold = 12              # FIXME raise exception

        self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY
        self.correlator = gr.correlate_access_code_bb(access_code, threshold)

        self.framer_sink = framer.sink_rs(self._rcvd_pktq)
        self.connect(self, self._demodulator, self.correlator, self.framer_sink)
        print "Using channel coding!"
        
        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
Beispiel #8
0
    def __init__(self):
         gr.hier_block2.__init__(self, "HierBlock_data",
                        gr.io_signature(1, 1, gr.sizeof_float),
                        gr.io_signature(1, 1, 1))
 
         fsk = gr.hilbert_fc((AUDIO_RATE/300)+1)
         bp_coeff = gr.firdes.band_pass(1,AUDIO_RATE,BP_START,BP_STOP,100)
         bpf = gr.fir_filter_fff(1,bp_coeff)
       
         quad_demod = gr.quadrature_demod_cf(1.0)
        
         hpf_coeff = gr.firdes.high_pass(10, AUDIO_RATE, 10, 5)
         dc_block = gr.fir_filter_fff (1, hpf_coeff)
       	
         mm = gr.clock_recovery_mm_ff(REPEAT_TIME,0.000625,0.5,0.01,0.05)
       
         slicer = gr.binary_slicer_fb()
       
         sync_corr = gr.correlate_access_code_bb("0100011101111000",0)
         
       
         self.connect(self,bpf,fsk,quad_demod,dc_block,mm,slicer,sync_corr,self)
Beispiel #9
0
    def __init__(self):
        gr.top_block.__init__(self)
        
        self.rcvd_pktq = gr.msg_queue()
        audio_rate = 48000
         
        
        src = audio.source (audio_rate,"plughw:0,0")
	mult = gr.multiply_const_ff(10)   # multiply
	raw_wave = gr.wavfile_sink(filename, 1, audio_rate,16)
	raw_wave1 = gr.wavfile_sink(filename2, 1, audio_rate,16)
        
        fsk_c = gr.hilbert_fc((audio_rate/300)+1)
	

	


        bp_coeff = gr.firdes.band_pass(1,audio_rate,BandPass,BandStop,100)
        bpf = gr.fir_filter_fff(1,bp_coeff)
        
        quad_demod = gr.quadrature_demod_cf(1)#originally 1
        
       
        hpf_coeff = gr.firdes.high_pass(10, audio_rate, 10, 5)
       
        dc_block = gr.add_const_ff(-2.225)
        mm = gr.clock_recovery_mm_ff(RepeatTime,0.000625,0.5,0.01,0.1)
        
        slicer = gr.binary_slicer_fb()
        
        sync_corr = gr.correlate_access_code_bb("0100011101111000",0)
        
        file_sink = gr.file_sink(1, "decoded-bits.dat")
        sink = goodney.sink2(self.rcvd_pktq)
        self.connect(bpf,raw_wave1)
	self.connect(src,raw_wave)
        self.connect(src,bpf,fsk_c,quad_demod,dc_block,mm,slicer,sync_corr,sink)
        self.watcher = _queue_watcher_thread(self.rcvd_pktq, message_callback)
    def __init__(self, options, queue):
        gr.top_block.__init__(self)

        self.u = usrp.source_c()
        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()
        self.u.set_decim_rate(options.decim)
        self.centerfreq = options.centerfreq
        print "Tuning to: %fMHz" % (self.centerfreq - options.error)
        if not (self.tune(options.centerfreq - options.error)):
            print "Failed to set initial frequency"

        if options.gain is None:  #set to halfway
            g = self.subdev.gain_range()
            options.gain = (g[0] + g[1]) / 2.0

        print "Setting gain to %i" % options.gain
        self.subdev.set_gain(options.gain)

        if self.subdev.name() == "DBS Rx":
            self.subdev.set_bw(options.bandwidth)  #only for DBSRX
            print "Setting DBS RX bandwidth to %fMHz" % float(
                options.bandwidth / 1e6)

        self.rate = self.u.adc_rate() / options.decim

        print "Samples per second is %i" % self.rate

        self._syms_per_sec = 3600

        options.audiorate = 11025
        options.rate = self.rate

        options.samples_per_second = self.rate  #yeah i know it's on the list
        options.syms_per_sec = self._syms_per_sec
        options.gain_mu = 0.01
        options.mu = 0.5
        options.omega_relative_limit = 0.3
        options.syms_per_sec = self._syms_per_sec
        options.offset = options.centerfreq - options.freq
        print "Control channel offset: %f" % options.offset

        self.demod = fsk_demod(options)
        self.start_correlator = gr.correlate_access_code_bb(
            "10101100", 0)  #should mark start of packet
        self.smartnet_sync = smartnet.sync()
        self.smartnet_deinterleave = smartnet.deinterleave()
        self.smartnet_parity = smartnet.parity()
        self.smartnet_crc = smartnet.crc()
        self.smartnet_packetize = smartnet.packetize()
        self.parse = smartnet.parse(
            queue
        )  #packet-based. this simply posts lightly-formatted messages to the queue.

        self.connect(self.u, self.demod)

        self.connect(self.demod, self.start_correlator, self.smartnet_sync,
                     self.smartnet_deinterleave, self.smartnet_parity,
                     self.smartnet_crc, self.smartnet_packetize, self.parse)
Beispiel #11
0
    def __init__(self):
        gr.top_block.__init__(self)

        usage = "%prog: [options] [input file]"
        parser = OptionParser(option_class=eng_option, usage=usage)
        parser.add_option("-c",
                          "--channel",
                          type="string",
                          default='AA',
                          help="two-letter channel code (default: AA)")
        parser.add_option("-a",
                          "--automatic",
                          action="store_true",
                          default=False,
                          help="automatically determine and transmit reponse")
        parser.add_option("-R",
                          "--rx-subdev-spec",
                          type="subdev",
                          default=(0, 0),
                          help="select USRP Rx side A or B (default=A)")
        parser.add_option("-g",
                          "--gain",
                          type="eng_float",
                          default=None,
                          help="set USRP gain in dB (default is midpoint)")

        parser.add_option("-s",
                          "--squelch",
                          type="eng_float",
                          default=20,
                          help="set squelch in dB")

        (options, args) = parser.parse_args()

        inf_str = None
        decim = 64  #1M Samp/sec
        symbol_rate = 152.34e3
        sample_rate = 64e6 / decim

        if len(args) != 0:
            inf_str = args[0]

        squelch = gr.pwr_squelch_cc(float(options.squelch), 0.1, 0, True)
        demod = gr.quadrature_demod_cf(1.0)
        #cr = gr.clock_recovery_mm_ff(6.5643, 0.00765625, 0, 0.175, 0.005)
        cr = gr.clock_recovery_mm_ff(sample_rate / symbol_rate, 0.00765625, 0,
                                     0.175, 0.005)
        slicer = gr.binary_slicer_fb()
        corr = gr.correlate_access_code_bb(AC, 0)
        sink = clicker.sniffer()

        if inf_str is not None:
            print "Reading from: " + inf_str
            src = gr.file_source(gr.sizeof_gr_complex, inf_str, False)

        else:
            freqs = {
                'AA': 917.0e6,
                'AB': 913.0e6,
                'AC': 914.0e6,
                'AD': 915.0e6,
                'BA': 916.0e6,
                'BB': 919.0e6,
                'BC': 920.0e6,
                'BD': 921.0e6,
                'CA': 922.0e6,
                'CB': 923.0e6,
                'CC': 907.0e6,
                'CD': 908.0e6,
                'DA': 905.5e6,
                'DB': 909.0e6,
                'DC': 911.0e6,
                'DD': 910.0e6
            }

            frequency = freqs[options.channel]
            print "Channel: " + options.channel + " (" + str(
                frequency / 1e6) + "MHz)"

            src = usrp.source_c(decim_rate=decim)
            subdev = usrp.selected_subdev(src, options.rx_subdev_spec)
            print "Using RX board %s" % (subdev.side_and_name())
            r = src.tune(0, subdev, frequency)
            if not r:
                raise SystemExit, "Failed to tune USRP. Are you using a 900MHz board?"
            if options.gain is None:
                # if no gain was specified, use the mid-point in dB
                g = subdev.gain_range()
                options.gain = float(g[0] + g[1]) / 2
            subdev.set_gain(options.gain)
            print "Gain: " + str(options.gain) + "dB"

        self.connect(src, squelch, demod, cr, slicer, corr, sink)
	def __init__(self, options, queue):
		gr.top_block.__init__(self)

		if options.filename is not None:
			self.fs = gr.file_source(gr.sizeof_gr_complex, options.filename)
			self.rate = 64000000 / options.decim # allow setting of recorded decimation in options

		else:
			self.u = usrp.source_c()
			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()
			self.u.set_decim_rate(options.decim)
			self.centerfreq = options.centerfreq
			print "Tuning to: %fMHz" % (self.centerfreq - options.error)
			if not(self.tune(options.centerfreq - options.error)):
				print "Failed to set initial frequency"
	
			if options.gain is None: #set to halfway
				g = self.subdev.gain_range()
				options.gain = (g[0]+g[1]) / 2.0

			print "Setting gain to %i" % options.gain
			self.subdev.set_gain(options.gain)

			if self.subdev.name() == "DBS Rx":
				self.subdev.set_bw(options.bandwidth) #only for DBSRX
				print "Setting DBS RX bandwidth to %fMHz" % float(options.bandwidth / 1e6)

			self.rate = self.u.adc_rate() / options.decim
		
		print "Samples per second is %i" % self.rate

		self._syms_per_sec = 3600;


		options.samples_per_second = self.rate
		options.syms_per_sec = self._syms_per_sec
		options.gain_mu = 0.01
		options.mu=0.5
		options.omega_relative_limit = 0.3
		options.syms_per_sec = self._syms_per_sec
		options.offset = options.centerfreq - options.freq
		print "Control channel offset: %f" % options.offset

		self.demod = fsk_demod(options)
		self.start_correlator = gr.correlate_access_code_bb("10101100",0) #should mark start of packet
		self.smartnet_sync = smartnet.sync()
		self.smartnet_deinterleave = smartnet.deinterleave()
		self.smartnet_parity = smartnet.parity()
		self.smartnet_crc = smartnet.crc()
		self.smartnet_packetize = smartnet.packetize()
		self.parse = smartnet.parse(queue) #packet-based. this simply posts lightly-formatted messages to the queue.

#		self.filesink = gr.file_sink(gr.sizeof_char*16, "smartnet_decoded.dat") #set a friggin filename in the options
#		self.paritysink = gr.file_sink(gr.sizeof_char, "smartnet_parity.dat")
		if options.filename is None:		
			self.connect(self.u, self.demod)
		else:
			self.connect(self.fs, self.demod)

		self.connect(self.demod, self.start_correlator, self.smartnet_sync, self.smartnet_deinterleave, self.smartnet_parity, self.smartnet_crc, self.smartnet_packetize, self.parse)

		#hook up the audio patch
		if options.audio:
			self.audiorate = 48000
#			self.audiodemoddecim = 4
			self.audiotaps = gr.firdes.low_pass(1, self.rate, 8000, 2000, firdes.WIN_HANN)
			self.prefilter_decim = (self.rate / self.audiorate) #might have to use a rational resampler for audio
			print "Prefilter decimation: %i" % self.prefilter_decim
			self.audio_prefilter = gr.freq_xlating_fir_filter_ccc(self.prefilter_decim, #decimation
									      self.audiotaps, #taps
									      0, #freq offset
									      self.rate) #sampling rate

			#on a trunked network where you know you will have good signal, a carrier power squelch works well. real FM receviers use a noise squelch, where
			#the received audio is high-passed above the cutoff and then fed to a reverse squelch. If the power is then BELOW a threshold, open the squelch.
			self.squelch = gr.pwr_squelch_cc(options.squelch, #squelch point
											   alpha = 0.1, #wat
											   ramp = 10, #wat
											   gate = False)

			self.audiodemod = blks2.fm_demod_cf(self.rate/self.prefilter_decim, #rate
							    1, #audio decimation
							    4000, #deviation
							    3000, #audio passband
							    4000, #audio stopband
							    1, #gain
							    75e-6) #deemphasis constant

			#the point of the resampler is to bring data to the soundcard at a rate it supports, but it seems to sound fine without it, and it saves some CPU cycles not to have it
			#the audio rate is 48kHz because seemingly it's all my *&$# integrated sound card will support, otherwise it'd be like 8k or something reasonable
			#running a 48kHz audio rate isn't the end of the world -- with decim 18 and prefilter decim 74, the native rate is 48.048kHz. that's close enough to avoid the resampler.
#			self.gcd = self.euclid(self.audiorate, self.rate/self.prefilter_decim)
#			print "Resampling: decim %i, interp %i" % (self.rate/self.prefilter_decim/self.gcd, self.audiorate/self.gcd)
#			self.audioresamp = blks2.rational_resampler_fff(self.audiorate/self.gcd, self.rate/self.prefilter_decim/self.gcd)#, self.audiofilttaps)

			#the filtering removes FSK data woobling from the subaudible channel
			self.audiofilttaps = gr.firdes.high_pass(1, self.audiorate, 300, 50, firdes.WIN_HANN)

			self.audiofilt = gr.fir_filter_fff(1, self.audiofilttaps)

			self.audiogain = gr.multiply_const_ff(options.volume)

#			self.audiosink = audio.sink (self.audiorate, "")
			self.audiosink = gr.wavfile_sink("test.wav", 1, self.audiorate, 8)

			self.mute()

			if options.filename is None:
				self.connect(self.u, self.audio_prefilter)
			else:
				self.connect(self.fs, self.audio_prefilter)

#			self.connect(self.audio_prefilter, self.squelch, self.audiodemod, self.audiofilt, self.audiogain, self.audioresamp, self.audiosink)
			self.connect(self.audio_prefilter, self.squelch, self.audiodemod, self.audiofilt, self.audiogain, self.audiosink)
Beispiel #13
0
    def __init__(self, options, queue):
        gr.top_block.__init__(self)

        if options.filename is not None:
            self.fs = gr.file_source(gr.sizeof_gr_complex, options.filename)
            self.rate = 64000000 / options.decim  # allow setting of recorded decimation in options

        else:
            self.u = usrp.source_c()
            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()
            self.u.set_decim_rate(options.decim)
            self.centerfreq = options.centerfreq
            print "Tuning to: %fMHz" % (self.centerfreq - options.error)
            if not (self.tune(options.centerfreq - options.error)):
                print "Failed to set initial frequency"

            if options.gain is None:  #set to halfway
                g = self.subdev.gain_range()
                options.gain = (g[0] + g[1]) / 2.0

            print "Setting gain to %i" % options.gain
            self.subdev.set_gain(options.gain)

            if self.subdev.name() == "DBS Rx":
                self.subdev.set_bw(options.bandwidth)  #only for DBSRX
                print "Setting DBS RX bandwidth to %fMHz" % float(
                    options.bandwidth / 1e6)

            self.rate = self.u.adc_rate() / options.decim

        print "Samples per second is %i" % self.rate

        self._syms_per_sec = 3600

        options.samples_per_second = self.rate
        options.syms_per_sec = self._syms_per_sec
        options.gain_mu = 0.01
        options.mu = 0.5
        options.omega_relative_limit = 0.3
        options.syms_per_sec = self._syms_per_sec
        options.offset = options.centerfreq - options.freq
        print "Control channel offset: %f" % options.offset

        self.demod = fsk_demod(options)
        self.start_correlator = gr.correlate_access_code_bb(
            "10101100", 0)  #should mark start of packet
        self.smartnet_sync = smartnet.sync()
        self.smartnet_deinterleave = smartnet.deinterleave()
        self.smartnet_parity = smartnet.parity()
        self.smartnet_crc = smartnet.crc()
        self.smartnet_packetize = smartnet.packetize()
        self.parse = smartnet.parse(
            queue
        )  #packet-based. this simply posts lightly-formatted messages to the queue.

        #		self.filesink = gr.file_sink(gr.sizeof_char*16, "smartnet_decoded.dat") #set a friggin filename in the options
        #		self.paritysink = gr.file_sink(gr.sizeof_char, "smartnet_parity.dat")
        if options.filename is None:
            self.connect(self.u, self.demod)
        else:
            self.connect(self.fs, self.demod)

        self.connect(self.demod, self.start_correlator, self.smartnet_sync,
                     self.smartnet_deinterleave, self.smartnet_parity,
                     self.smartnet_crc, self.smartnet_packetize, self.parse)

        #hook up the audio patch
        if options.audio:
            self.audiorate = 48000
            #			self.audiodemoddecim = 4
            self.audiotaps = gr.firdes.low_pass(1, self.rate, 8000, 2000,
                                                firdes.WIN_HANN)
            self.prefilter_decim = (
                self.rate / self.audiorate
            )  #might have to use a rational resampler for audio
            print "Prefilter decimation: %i" % self.prefilter_decim
            self.audio_prefilter = gr.freq_xlating_fir_filter_ccc(
                self.prefilter_decim,  #decimation
                self.audiotaps,  #taps
                0,  #freq offset
                self.rate)  #sampling rate

            #on a trunked network where you know you will have good signal, a carrier power squelch works well. real FM receviers use a noise squelch, where
            #the received audio is high-passed above the cutoff and then fed to a reverse squelch. If the power is then BELOW a threshold, open the squelch.
            self.squelch = gr.pwr_squelch_cc(
                options.squelch,  #squelch point
                alpha=0.1,  #wat
                ramp=10,  #wat
                gate=False)

            self.audiodemod = blks2.fm_demod_cf(
                self.rate / self.prefilter_decim,  #rate
                1,  #audio decimation
                4000,  #deviation
                3000,  #audio passband
                4000,  #audio stopband
                1,  #gain
                75e-6)  #deemphasis constant

            #the point of the resampler is to bring data to the soundcard at a rate it supports, but it seems to sound fine without it, and it saves some CPU cycles not to have it
            #the audio rate is 48kHz because seemingly it's all my *&$# integrated sound card will support, otherwise it'd be like 8k or something reasonable
            #running a 48kHz audio rate isn't the end of the world -- with decim 18 and prefilter decim 74, the native rate is 48.048kHz. that's close enough to avoid the resampler.
            #			self.gcd = self.euclid(self.audiorate, self.rate/self.prefilter_decim)
            #			print "Resampling: decim %i, interp %i" % (self.rate/self.prefilter_decim/self.gcd, self.audiorate/self.gcd)
            #			self.audioresamp = blks2.rational_resampler_fff(self.audiorate/self.gcd, self.rate/self.prefilter_decim/self.gcd)#, self.audiofilttaps)

            #the filtering removes FSK data woobling from the subaudible channel
            self.audiofilttaps = gr.firdes.high_pass(1, self.audiorate, 300,
                                                     50, firdes.WIN_HANN)

            self.audiofilt = gr.fir_filter_fff(1, self.audiofilttaps)

            self.audiogain = gr.multiply_const_ff(options.volume)

            #			self.audiosink = audio.sink (self.audiorate, "")
            self.audiosink = gr.wavfile_sink("test.wav", 1, self.audiorate, 8)

            self.mute()

            if options.filename is None:
                self.connect(self.u, self.audio_prefilter)
            else:
                self.connect(self.fs, self.audio_prefilter)

#			self.connect(self.audio_prefilter, self.squelch, self.audiodemod, self.audiofilt, self.audiogain, self.audioresamp, self.audiosink)
            self.connect(self.audio_prefilter, self.squelch, self.audiodemod,
                         self.audiofilt, self.audiogain, self.audiosink)