def test_pwr_squelch_003(self): # Test set/gets alpha = 0.0001 thr1 = 10 thr2 = 20 ramp = 1 ramp2 = 2 gate = True gate2 = False op = analog.pwr_squelch_ff(thr1, alpha, ramp, gate) op.set_threshold(thr2) t = op.threshold() self.assertEqual(thr2, t) op.set_ramp(ramp2) r = op.ramp() self.assertEqual(ramp2, r) op.set_gate(gate2) g = op.gate() self.assertEqual(gate2, g)
def __init__(self, samp_rate=16E3, name="unnamed", save_dir=None, postscript=None): gr.hier_block2.__init__(self, "Recorder", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(1, 1, gr.sizeof_float)) self.timeout = 18000 self.save_dir = save_dir self.postscript = postscript self.record_squelch = analog.pwr_squelch_ff(-200, 0.1, 0, True) self.blocks_wavfile_sink = blocks.wavfile_sink("/dev/null", 1, samp_rate, 16) self.blocks_null_source = blocks.null_source(gr.sizeof_float * 1) self.connect(self, (self.record_squelch, 0)) self.connect((self.record_squelch, 0), (self.blocks_wavfile_sink, 0)) self.connect((self.blocks_null_source, 0), self) thread = threading.Thread(target=self.timer_thread, args=(name, self.save_dir, self.blocks_wavfile_sink, \ self.record_squelch, self.postscript, self.timeout)) thread.daemon = True thread.start()
def __init__(self, alpha=0.0001, threshold_db=-10, gate=False): gr.hier_block2.__init__( self, "standard_squelch", gr.io_signature(1, 1, gr.sizeof_float), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature #fixed coeffs, Chebyshev type 2 LPF=[0, 0.4, 0.7], HPF=[0.4, 0.7, 1] self.low_iir = iir_filter_ffd([ 0.12260106307699403, -0.22058023529806434, 0.22058023529806436, -0.12260106307699434 ], [ 1.00000000000000000, 0.7589332900264623, 0.5162740252200005, 0.07097813844342238 ], False) self.low_square = blocks.multiply_ff() self.low_smooth = single_pole_iir_filter_ff(alpha) self.hi_iir = iir_filter_ffd([ 0.1913118666668073, 0.4406071020350289, 0.4406071020350288, 0.19131186666680736 ], [ 1.000000000000000000, -0.11503633296078866, 0.3769676347066441, 0.0019066356578167866 ], False) self.hi_square = blocks.multiply_ff() self.hi_smooth = single_pole_iir_filter_ff(alpha) #inverted thresholds because we reversed the division block inputs #to make the threshold output 1 when open and 0 when closed self.gate = blocks.threshold_ff(0, 0, 0) self.set_threshold(threshold_db) self.squelch_lpf = single_pole_iir_filter_ff(alpha) self.squelch_mult = blocks.multiply_ff() self.div = blocks.divide_ff() #This is horrible, but there's no better way to gate samples. #the block is fast, so realistically there's little overhead #TODO: implement a valve block that gates based on an input value self.valve = analog.pwr_squelch_ff(-100, 1, 0, gate) #sample path self.connect(self, (self.squelch_mult, 0)) #filter path (LPF) self.connect(self, self.low_iir) self.connect(self.low_iir, (self.low_square, 0)) self.connect(self.low_iir, (self.low_square, 1)) self.connect(self.low_square, self.low_smooth, (self.div, 0)) #filter path (HPF) self.connect(self, self.hi_iir) self.connect(self.hi_iir, (self.hi_square, 0)) self.connect(self.hi_iir, (self.hi_square, 1)) self.connect(self.hi_square, self.hi_smooth, (self.div, 1)) #control path self.connect(self.div, self.gate, self.squelch_lpf, (self.squelch_mult, 1)) self.connect(self.squelch_mult, self)
def __init__(self): gr.top_block.__init__(self, "SAME Decoder test") ################################################## # Variables ################################################## self.samp_rate = samp_rate = 8000 ################################################## # Blocks ################################################## self.rational_resampler_44k = filter.rational_resampler_fff( interpolation=80, decimation=441, ) self.rational_resampler_xxx_0 = filter.rational_resampler_ccc( interpolation=100, decimation=96, taps=None, fractional_bw=None, ) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_fcc(1, (firdes.low_pass(1, samp_rate, 600, 100)), 1822.916667, samp_rate) self.digital_gmsk_demod_0 = digital.gmsk_demod( samples_per_symbol=16, gain_mu=0.175, mu=0.5, omega_relative_limit=0.1, freq_error=0.0, verbose=True, log=False, ) #self.src = audio.source(samp_rate, "plughw:CARD=PCH,DEV=2", True) self.blocks_wavfile_source_0 = blocks.wavfile_source("eas-test-11-7-2013.wav", False) self.blocks_bitstream_sink = blocks.file_sink(1, "bitstream.bin") self.xlat_sink = blocks.wavfile_sink("xlat.wav", 1, 8333) self.xlat_complex_to_float = blocks.complex_to_float() self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_ff(-50, 0.0001, 0) self.msg_queue = gr.msg_queue(10) self.same_dec_0 = same.same_dec(self.msg_queue) ################################################## # Connections ################################################## self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.rational_resampler_xxx_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.xlat_complex_to_float, 0), (self.xlat_sink, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.digital_gmsk_demod_0, 0)) self.connect((self.digital_gmsk_demod_0, 0), (self.same_dec_0, 0)) self.connect((self.digital_gmsk_demod_0, 0), (self.blocks_bitstream_sink, 0)) #self.connect((self.src, 0), (self.rational_resampler_44k, 0)) #self.connect((self.rational_resampler_44k, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.blocks_wavfile_source_0, 0), (self.analog_pwr_squelch_xx_0,0)) self.connect((self.analog_pwr_squelch_xx_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self._watcher = _queue_watcher_thread(self.msg_queue)
def __init__(self, alpha=0.0001, threshold_db=-10, gate=False): gr.hier_block2.__init__(self, "standard_squelch", gr.io_signature(1, 1, gr.sizeof_float), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature #fixed coeffs, Chebyshev type 2 LPF=[0, 0.4, 0.7], HPF=[0.4, 0.7, 1] self.low_iir = iir_filter_ffd([0.12260106307699403, -0.22058023529806434, 0.22058023529806436, -0.12260106307699434], [1.00000000000000000, 0.7589332900264623, 0.5162740252200005, 0.07097813844342238], False) self.low_square = blocks.multiply_ff() self.low_smooth = single_pole_iir_filter_ff(alpha) self.hi_iir = iir_filter_ffd([0.1913118666668073, 0.4406071020350289, 0.4406071020350288, 0.19131186666680736], [1.000000000000000000, -0.11503633296078866, 0.3769676347066441, 0.0019066356578167866], False) self.hi_square = blocks.multiply_ff() self.hi_smooth = single_pole_iir_filter_ff(alpha) #inverted thresholds because we reversed the division block inputs #to make the threshold output 1 when open and 0 when closed self.gate = blocks.threshold_ff(0,0,0) self.set_threshold(threshold_db) self.squelch_lpf = single_pole_iir_filter_ff(alpha) self.squelch_mult = blocks.multiply_ff() self.div = blocks.divide_ff() #This is horrible, but there's no better way to gate samples. #the block is fast, so realistically there's little overhead #TODO: implement a valve block that gates based on an input value self.valve = analog.pwr_squelch_ff(-100, 1, 0, gate) #sample path self.connect(self, (self.squelch_mult, 0)) #filter path (LPF) self.connect(self,self.low_iir) self.connect(self.low_iir,(self.low_square,0)) self.connect(self.low_iir,(self.low_square,1)) self.connect(self.low_square,self.low_smooth,(self.div,0)) #filter path (HPF) self.connect(self,self.hi_iir) self.connect(self.hi_iir,(self.hi_square,0)) self.connect(self.hi_iir,(self.hi_square,1)) self.connect(self.hi_square,self.hi_smooth,(self.div,1)) #control path self.connect(self.div, self.gate, self.squelch_lpf, (self.squelch_mult,1)) self.connect(self.squelch_mult, self)
def __init__(self, samp_rate=16E3, name="unnamed"): gr.hier_block2.__init__(self, "Recorder", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(1, 1, gr.sizeof_float)) self.record_squelch = analog.pwr_squelch_ff(-200, 0.1, 0, True) self.blocks_wavfile_sink = blocks.wavfile_sink("/dev/null", 1, samp_rate, 16) self.blocks_null_source = blocks.null_source(gr.sizeof_float*1) self.connect(self, (self.record_squelch, 0)) self.connect((self.record_squelch, 0), (self.blocks_wavfile_sink, 0)) self.connect((self.blocks_null_source, 0), self) thread = threading.Thread(target=self.timer_thread, args=(name, self.blocks_wavfile_sink, self.record_squelch)) thread.daemon = True thread.start()
def __init__(self): gr.top_block.__init__(self, "SAME Decoder test") ################################################## # Variables ################################################## self.samp_rate = samp_rate = 8000 ################################################## # Blocks ################################################## self.rational_resampler_44k = filter.rational_resampler_fff( interpolation=80, decimation=441, ) self.rational_resampler_xxx_0 = filter.rational_resampler_ccc( interpolation=100, decimation=96, taps=None, fractional_bw=None, ) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_fcc(1, (firdes.low_pass(1, samp_rate, 600, 100)), 1822.916667, samp_rate) self.digital_gmsk_demod_0 = digital.gmsk_demod( samples_per_symbol=16, gain_mu=0.175, mu=0.5, omega_relative_limit=0.1, freq_error=0.0, verbose=True, log=False, ) self.src = audio.source(samp_rate, "plughw:CARD=PCH,DEV=2", True) #self.blocks_wavfile_source_0 = blocks.wavfile_source("Monthly_Test_WUAL_DEC-2013.wav", False) self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_ff(-50, 0.0001, 0) self.msg_queue = gr.msg_queue(10) self.same_dec_0 = same.same_dec(self.msg_queue) ################################################## # Connections ################################################## self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.rational_resampler_xxx_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.digital_gmsk_demod_0, 0)) self.connect((self.digital_gmsk_demod_0, 0), (self.same_dec_0, 0)) self.connect((self.src, 0), (self.rational_resampler_44k, 0)) self.connect((self.rational_resampler_44k, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.analog_pwr_squelch_xx_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self._watcher = _queue_watcher_thread(self.msg_queue)
def test_pwr_squelch_004(self): alpha = 0.0001 thr = -25 src_data = map(lambda x: float(x)/10.0, range(1, 40)) src = blocks.vector_source_f(src_data) op = analog.pwr_squelch_ff(thr, alpha) dst = blocks.vector_sink_f() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() expected_result = src_data expected_result[0:20] = 20*[0,] result_data = dst.data() self.assertFloatTuplesAlmostEqual(expected_result, result_data, 4)
def test_pwr_squelch_004(self): alpha = 0.0001 thr = -25 src_data = [float(x) / 10.0 for x in range(1, 40)] src = blocks.vector_source_f(src_data) op = analog.pwr_squelch_ff(thr, alpha) dst = blocks.vector_sink_f() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() expected_result = src_data expected_result[0:20] = 20*[0,] result_data = dst.data() self.assertFloatTuplesAlmostEqual(expected_result, result_data, 4)
def __init__(self, samp_rate=4E6, audio_rate=8000, record=True): gr.hier_block2.__init__(self, "TunerDemodNBFM", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) # Default values self.center_freq = 0 squelch_db = -60 self.quad_demod_gain = 0.050 self.file_name = "/dev/null" self.record = record # Decimation values for four stages of decimation decims = (5, int(samp_rate/1E6)) # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ grfilter.firdes_low_pass(1, 1, 0.090, 0.010, grfilter.firdes.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ grfilter.freq_xlating_fir_filter_ccc(decims[0], low_pass_filter_taps_0, self.center_freq, samp_rate) # FIR filter decimating by 5 fir_filter_ccc_0 = grfilter.fir_filter_ccc(decims[0], low_pass_filter_taps_0) # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth low_pass_filter_taps_1 = grfilter.firdes_low_pass( 1, samp_rate/decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], low_pass_filter_taps_1) # Non blocking power squelch self.analog_pwr_squelch_cc = analog.pwr_squelch_cc(squelch_db, 1e-1, 0, False) # Quadrature demod with gain set for decent audio # The gain will be later multiplied by the 0 dB normalized volume self.analog_quadrature_demod_cf = \ analog.quadrature_demod_cf(self.quad_demod_gain) # 3.5 kHz cutoff for audio bandwidth low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ 3.5E3, 500, grfilter.firdes.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], low_pass_filter_taps_2) # Polyphase resampler allows arbitary RF sample rates # Takes 8-15.98 ksps to a constant 8 ksps for audio pfb_resamp = audio_rate/float(samp_rate/(decims[1] * decims[0]**3)) pfb_arb_resampler_fff = pfb.arb_resampler_fff(pfb_resamp, taps=None, flt_size=32) # Connect the blocks for the demod self.connect(self, self.freq_xlating_fir_filter_ccc) self.connect(self.freq_xlating_fir_filter_ccc, fir_filter_ccc_0) self.connect(fir_filter_ccc_0, fir_filter_ccc_1) self.connect(fir_filter_ccc_1, self.analog_pwr_squelch_cc) self.connect(self.analog_pwr_squelch_cc, self.analog_quadrature_demod_cf) self.connect(self.analog_quadrature_demod_cf, fir_filter_fff_0) self.connect(fir_filter_fff_0, pfb_arb_resampler_fff) self.connect(pfb_arb_resampler_fff, self) # Need to set this to a very low value of -200 since it is after demod # Only want it to gate when the previuos squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and 8 bits/sample self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, audio_rate, 8) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink)
def __init__(self,infile, outfile, input_rate, channel_rate, codec_provoice, codec_p25, sslevel, svlevel): gr.top_block.__init__(self, "Top Block") self.input_rate = input_rate self.channel_rate = channel_rate self.source = blocks.file_source(gr.sizeof_gr_complex*1, infile, False) self.lp1_decim = int(input_rate/(channel_rate*1.6)) print self.lp1_decim self.lp1 = filter.fir_filter_ccc(self.lp1_decim,firdes.low_pass( 1.0, self.input_rate, (self.channel_rate/2), ((self.channel_rate/2)*0.6), firdes.WIN_HAMMING)) #self.audiodemod = gr.quadrature_demod_cf(1) audio_pass = (input_rate/self.lp1_decim)*0.25 audio_stop = audio_pass+2000 self.audiodemod = analog.fm_demod_cf(channel_rate=(input_rate/self.lp1_decim), audio_decim=1, deviation=15000, audio_pass=audio_pass, audio_stop=audio_stop, gain=8, tau=75e-6) self.throttle = blocks.throttle(gr.sizeof_gr_complex*1, self.input_rate) self.signal_squelch = analog.pwr_squelch_cc(sslevel,0.01, 0, True) self.vox_squelch = analog.pwr_squelch_ff(svlevel, 0.0005, 0, True) self.audiosink = blocks.wavfile_sink(outfile, 1, 8000) if codec_provoice: self.dsd = dsd.block_ff(dsd.dsd_FRAME_PROVOICE,dsd.dsd_MOD_AUTO_SELECT,1,0,False) channel_rate = input_rate/self.lp1_decim self.resampler_in = filter.rational_resampler_fff(interpolation=48000, decimation=channel_rate, taps=None, fractional_bw=None, ) output_rate = 8000 resampler = filter.rational_resampler_fff( interpolation=(input_rate/self.lp1_decim), decimation=output_rate, taps=None, fractional_bw=None, ) elif codec_p25: symbol_deviation = 600.0 symbol_rate = 4800 channel_rate = input_rate/self.lp1_decim fm_demod_gain = channel_rate / (2.0 * pi * symbol_deviation) fm_demod = analog.quadrature_demod_cf(fm_demod_gain) symbol_decim = 1 samples_per_symbol = channel_rate // symbol_rate symbol_coeffs = (1.0/samples_per_symbol,) * samples_per_symbol symbol_filter = filter.fir_filter_fff(symbol_decim, symbol_coeffs) autotuneq = gr.msg_queue(2) demod_fsk4 = op25.fsk4_demod_ff(autotuneq, channel_rate, symbol_rate) # symbol slicer levels = [ -2.0, 0.0, 2.0, 4.0 ] slicer = op25.fsk4_slicer_fb(levels) imbe = repeater.vocoder(False, True, 0, "", 0, False) self.decodequeue = decodequeue = gr.msg_queue(10000) decoder = repeater.p25_frame_assembler('', 0, 0, True, True, False, decodequeue) float_conversion = blocks.short_to_float(1, 8192) resampler = filter.rational_resampler_fff( interpolation=8000, decimation=8000, taps=None, fractional_bw=None, ) #Tone squelch, custom GRC block that rips off CTCSS squelch to detect 4800 hz tone and latch squelch after that if not codec_provoice and not codec_p25: #self.tone_squelch = gr.tone_squelch_ff(audiorate, 4800.0, 0.05, 300, 0, True) #tone squelch is EDACS ONLY self.high_pass = filter.fir_filter_fff(1, firdes.high_pass(1, (input_rate/self.lp1_decim), 300, 30, firdes.WIN_HAMMING, 6.76)) #output_rate = channel_rate resampler = filter.rational_resampler_fff( interpolation=8000, decimation=(input_rate/self.lp1_decim), taps=None, fractional_bw=None, ) if(codec_provoice): self.connect(self.source, self.throttle, self.lp1, self.audiodemod, self.resampler_in, self.dsd, self.audiosink) elif(codec_p25): self.connect(self.source, self.throttle, self.lp1, fm_demod, symbol_filter, demod_fsk4, slicer, decoder, imbe, float_conversion, resampler, self.audiosink) else: self.connect(self.source, self.throttle, self.lp1, self.signal_squelch, self.audiodemod, self.high_pass, self.vox_squelch, resampler, self.audiosink) self.time_open = time.time() self.time_tone = 0 self.time_activity = 0
def __init__(self): grc_wxgui.top_block_gui.__init__(self, title="[FG]MRS Receiver") _icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png" self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY)) ################################################## # Variables ################################################## self.samp_rate = samp_rate = 1e6 self.channel_width = channel_width = 25e3 self.rf_freq_mhz = rf_freq_mhz = 462.5625 self.decimation = decimation = int(samp_rate/channel_width) self.squelch = squelch = -20 self.spec_size = spec_size = 480,256 self.rf_freq = rf_freq = rf_freq_mhz*1.0e6 self.decimated_rate = decimated_rate = samp_rate/decimation self.center_freq = center_freq = (int(rf_freq_mhz)+0.5)*1e6 self.cctss_freq = cctss_freq = 0 self.audio_rate = audio_rate = int(11025) ################################################## # Blocks ################################################## _squelch_sizer = wx.BoxSizer(wx.VERTICAL) self._squelch_text_box = forms.text_box( parent=self.GetWin(), sizer=_squelch_sizer, value=self.squelch, callback=self.set_squelch, label="Squelch (dBm)", converter=forms.float_converter(), proportion=0, ) self._squelch_slider = forms.slider( parent=self.GetWin(), sizer=_squelch_sizer, value=self.squelch, callback=self.set_squelch, minimum=-50, maximum=0, num_steps=50, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.GridAdd(_squelch_sizer, 3, 3, 1, 2) self._cctss_freq_chooser = forms.drop_down( parent=self.GetWin(), value=self.cctss_freq, callback=self.set_cctss_freq, label="Privacy Code", choices=[0,67.0,71.9,74.4,77.0,79.7,82.5,85.4,88.5,91.5,94.8,97.4,100.0,103.5,107.2,110.9,114.8,118.8,123.0,127.3,131.8,136.5,141.3,146.2,151.4,156.7,162.2,167.9,173.8,179.9,186.2,192.8,203.5,210.7,218.1,225.7,233.7,241.8,250.3], labels=['0 (Monitor)',1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38], ) self.GridAdd(self._cctss_freq_chooser, 3, 2, 1, 1) self.wxgui_waterfallsink2_1_0 = waterfallsink2.waterfall_sink_f( self.GetWin(), baseband_freq=0, dynamic_range=40, ref_level=-25, ref_scale=2.0, sample_rate=audio_rate, fft_size=512, fft_rate=15, average=False, avg_alpha=None, title="Raw Audio Spectrum", size=(spec_size), ) self.GridAdd(self.wxgui_waterfallsink2_1_0.win, 2, 4, 1, 3) self.wxgui_waterfallsink2_1 = waterfallsink2.waterfall_sink_f( self.GetWin(), baseband_freq=0, dynamic_range=40, ref_level=-25, ref_scale=2.0, sample_rate=audio_rate, fft_size=512, fft_rate=15, average=False, avg_alpha=None, title="Squelched Audio Spectrum", size=(spec_size), ) self.GridAdd(self.wxgui_waterfallsink2_1.win, 2, 1, 1, 3) self.wxgui_waterfallsink2_0_0 = waterfallsink2.waterfall_sink_c( self.GetWin(), baseband_freq=center_freq, dynamic_range=40, ref_level=-25, ref_scale=2.0, sample_rate=samp_rate, fft_size=512, fft_rate=15, average=False, avg_alpha=None, title="RF Spectrum", size=(spec_size), ) self.GridAdd(self.wxgui_waterfallsink2_0_0.win, 1, 1, 1, 3) self.wxgui_waterfallsink2_0 = waterfallsink2.waterfall_sink_c( self.GetWin(), baseband_freq=0, dynamic_range=40, ref_level=-25, ref_scale=2.0, sample_rate=samp_rate, fft_size=512, fft_rate=15, average=False, avg_alpha=None, title="Baseband Spectrum", size=(spec_size), ) self.GridAdd(self.wxgui_waterfallsink2_0.win, 1, 4, 1, 3) self._rf_freq_mhz_chooser = forms.drop_down( parent=self.GetWin(), value=self.rf_freq_mhz, callback=self.set_rf_freq_mhz, label="Channel", choices=[462.5625, 462.5875, 462.6125, 462.6375, 462.6625, 462.6875, 462.7125, 467.5625, 467.5875, 467.6125, 467.6375, 467.6625, 467.6875, 467.7125, 462.550, 462.575, 462.600, 462.625,462.650,462.675,462.700, 462.725], labels=['FRS1 / GMRS 9',2,3,4,5,6,'FRS7 / GMRS15 ','FRS8',9,10,11,12,13,'FRS14','GMRS1',2,3,4,5,6,7,'GMRS8'], ) self.GridAdd(self._rf_freq_mhz_chooser, 3, 1, 1, 1) self.rational_resampler_xxx_0 = filter.rational_resampler_ccc( interpolation=int(audio_rate), decimation=int(decimated_rate), taps=None, fractional_bw=None, ) self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + "" ) self.osmosdr_source_0.set_sample_rate(samp_rate) self.osmosdr_source_0.set_center_freq(center_freq, 0) self.osmosdr_source_0.set_freq_corr(0, 0) self.osmosdr_source_0.set_dc_offset_mode(0, 0) self.osmosdr_source_0.set_iq_balance_mode(0, 0) self.osmosdr_source_0.set_gain_mode(True, 0) self.osmosdr_source_0.set_gain(10, 0) self.osmosdr_source_0.set_if_gain(20, 0) self.osmosdr_source_0.set_bb_gain(20, 0) self.osmosdr_source_0.set_antenna("", 0) self.osmosdr_source_0.set_bandwidth(0, 0) self.low_pass_filter_0 = filter.fir_filter_ccf(decimation, firdes.low_pass( 1, samp_rate, decimated_rate*0.8, decimated_rate*0.2, firdes.WIN_HAMMING, 6.76)) self.dc_blocker_xx_0 = filter.dc_blocker_cc(32, True) self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) self.audio_sink_0 = audio.sink(audio_rate, "", True) self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, rf_freq, 1, 0) self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_ff(squelch, 0.0001, 1, False) self.analog_nbfm_rx_0 = analog.nbfm_rx( audio_rate=audio_rate, quad_rate=audio_rate, tau=75e-6, max_dev=5e3, ) self.analog_ctcss_squelch_ff_0 = analog.ctcss_squelch_ff(audio_rate, cctss_freq, 0.01, 0, 1, False) ################################################## # Connections ################################################## self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.low_pass_filter_0, 0), (self.rational_resampler_xxx_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.analog_nbfm_rx_0, 0)) self.connect((self.analog_nbfm_rx_0, 0), (self.wxgui_waterfallsink2_1_0, 0)) self.connect((self.analog_nbfm_rx_0, 0), (self.analog_ctcss_squelch_ff_0, 0)) self.connect((self.analog_ctcss_squelch_ff_0, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.analog_pwr_squelch_xx_0, 0), (self.audio_sink_0, 0)) self.connect((self.analog_pwr_squelch_xx_0, 0), (self.wxgui_waterfallsink2_1, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.wxgui_waterfallsink2_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.dc_blocker_xx_0, 0)) self.connect((self.dc_blocker_xx_0, 0), (self.wxgui_waterfallsink2_0_0, 0)) self.connect((self.dc_blocker_xx_0, 0), (self.blocks_multiply_xx_0, 1))
def __init__(self, samp_rate=4E6, audio_rate=8000, record=True): gr.hier_block2.__init__(self, "TunerDemodAM", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) # Default values self.center_freq = 0 squelch_db = -60 self.agc_ref = 0.1 self.file_name = "/dev/null" self.record = record # Decimation values for four stages of decimation decims = (5, int(samp_rate/1E6)) # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ grfilter.firdes_low_pass(1, 1, 0.090, 0.010, grfilter.firdes.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ grfilter.freq_xlating_fir_filter_ccc(decims[0], low_pass_filter_taps_0, self.center_freq, samp_rate) # FIR filter decimating by 5 fir_filter_ccc_0 = grfilter.fir_filter_ccc(decims[0], low_pass_filter_taps_0) # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth low_pass_filter_taps_1 = grfilter.firdes_low_pass( 1, samp_rate/decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], low_pass_filter_taps_1) # Non blocking power squelch # Squelch level needs to be lower than NBFM or else choppy AM demod self.analog_pwr_squelch_cc = analog.pwr_squelch_cc(squelch_db, 1e-1, 0, False) # AGC with reference set for nomninal 0 dB volume # Paramaters tweaked to prevent impulse during squelching self.agc3_cc = analog.agc3_cc(1.0, 1E-4, self.agc_ref, 10, 1) self.agc3_cc.set_max_gain(65536) # AM demod with complex_to_mag() # Can't use analog.am_demod_cf() since it won't work with N>2 demods am_demod_cf = blocks.complex_to_mag(1) # 3.5 kHz cutoff for audio bandwidth low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ 3.5E3, 500, grfilter.firdes.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], low_pass_filter_taps_2) # Polyphase resampler allows arbitary RF sample rates # Takes 8-15.98 ksps to a constant 8 ksps for audio pfb_resamp = audio_rate/float(samp_rate/(decims[1] * decims[0]**3)) pfb_arb_resampler_fff = pfb.arb_resampler_fff(pfb_resamp, taps=None, flt_size=32) # Connect the blocks for the demod self.connect(self, self.freq_xlating_fir_filter_ccc) self.connect(self.freq_xlating_fir_filter_ccc, fir_filter_ccc_0) self.connect(fir_filter_ccc_0, fir_filter_ccc_1) self.connect(fir_filter_ccc_1, self.analog_pwr_squelch_cc) self.connect(self.analog_pwr_squelch_cc, self.agc3_cc) self.connect(self.agc3_cc, am_demod_cf) self.connect(am_demod_cf, fir_filter_fff_0) self.connect(fir_filter_fff_0, pfb_arb_resampler_fff) self.connect(pfb_arb_resampler_fff, self) # Need to set this to a very low value of -200 since it is after demod # Only want it to gate when the previuos squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and 8 bits/sample self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, audio_rate, 8) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink)
def __init__(self): gr.top_block.__init__(self, "Ham2Mon NBFM Receiver Flow Example") Qt.QWidget.__init__(self) self.setWindowTitle("Ham2Mon NBFM Receiver Flow Example") try: self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) except: pass self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) self.top_scroll_layout.addWidget(self.top_scroll) self.top_scroll.setWidgetResizable(True) self.top_widget = Qt.QWidget() self.top_scroll.setWidget(self.top_widget) self.top_layout = Qt.QVBoxLayout(self.top_widget) self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) self.settings = Qt.QSettings("GNU Radio", "nbfm_flow_example") self.restoreGeometry(self.settings.value("geometry").toByteArray()) ################################################## # Variables ################################################## self.samp_rate = samp_rate = 1E6 self.initial_decim = initial_decim = 5 self.samp_ratio = samp_ratio = samp_rate/1E6 self.final_rate = final_rate = samp_rate/initial_decim**2/int(samp_rate/1E6) self.variable_low_pass_filter_taps_2 = variable_low_pass_filter_taps_2 = firdes.low_pass(1.0, final_rate, 3500, 500, firdes.WIN_HAMMING, 6.76) self.variable_low_pass_filter_taps_1 = variable_low_pass_filter_taps_1 = firdes.low_pass(1.0, samp_rate/25, 12.5E3, 1E3, firdes.WIN_HAMMING, 6.76) self.variable_low_pass_filter_taps_0 = variable_low_pass_filter_taps_0 = firdes.low_pass(1.0, 1, 0.090, 0.010, firdes.WIN_HAMMING, 6.76) self.squelch_dB = squelch_dB = -70 self.gain_db = gain_db = 30 self.final_decim = final_decim = int(samp_rate/1E6) self.file_name = file_name = "test.wav" self.fft_length = fft_length = 256 * int(pow(2, np.ceil(np.log(samp_ratio)/np.log(2)))) self.demod_bb_freq = demod_bb_freq = 390E3 self.center_freq = center_freq = 144E6 ################################################## # Blocks ################################################## self._squelch_dB_range = Range(-100, 0, 5, -70, 200) self._squelch_dB_win = RangeWidget(self._squelch_dB_range, self.set_squelch_dB, "Squelch (dB)", "counter_slider", float) self.top_grid_layout.addWidget(self._squelch_dB_win, 5,1,1,3) self._gain_db_range = Range(0, 70, 1, 30, 200) self._gain_db_win = RangeWidget(self._gain_db_range, self.set_gain_db, "HW Gain (dB)", "counter_slider", float) self.top_grid_layout.addWidget(self._gain_db_win, 4,1,1,3) self._demod_bb_freq_range = Range(-samp_rate/2, samp_rate/2, 5E3, 390E3, 200) self._demod_bb_freq_win = RangeWidget(self._demod_bb_freq_range, self.set_demod_bb_freq, "Demod BB Freq (Hz)", "counter_slider", float) self.top_grid_layout.addWidget(self._demod_bb_freq_win, 3,1,1,3) self.qtgui_time_sink_x_0 = qtgui.time_sink_f( fft_length, #size samp_rate, #samp_rate "Averaged Spectrum", #name 1 #number of inputs ) self.qtgui_time_sink_x_0.set_update_time(0.10) self.qtgui_time_sink_x_0.set_y_axis(-60, 40) self.qtgui_time_sink_x_0.set_y_label("Power", "") self.qtgui_time_sink_x_0.enable_tags(-1, True) self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "") self.qtgui_time_sink_x_0.enable_autoscale(False) self.qtgui_time_sink_x_0.enable_grid(False) self.qtgui_time_sink_x_0.enable_control_panel(False) if not True: self.qtgui_time_sink_x_0.disable_legend() labels = ["", "", "", "", "", "", "", "", "", ""] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "blue"] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_time_sink_x_0.set_line_label(i, labels[i]) self.qtgui_time_sink_x_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_0.set_line_style(i, styles[i]) self.qtgui_time_sink_x_0.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win, 0,1,3,1) self.qtgui_freq_sink_x_0_0 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 0, #fc final_rate, #bw "Decimated Channel", #name 1 #number of inputs ) self.qtgui_freq_sink_x_0_0.set_update_time(0.10) self.qtgui_freq_sink_x_0_0.set_y_axis(-200, -60) self.qtgui_freq_sink_x_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0_0.enable_autoscale(False) self.qtgui_freq_sink_x_0_0.enable_grid(False) self.qtgui_freq_sink_x_0_0.set_fft_average(1.0) self.qtgui_freq_sink_x_0_0.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_0_0.disable_legend() if complex == type(float()): self.qtgui_freq_sink_x_0_0.set_plot_pos_half(not True) labels = ["", "", "", "", "", "", "", "", "", ""] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue"] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0_0.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_0_win, 3,0,3,1) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( fft_length, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 144E6, #fc samp_rate, #bw "Spectrum", #name 1 #number of inputs ) self.qtgui_freq_sink_x_0.set_update_time(0.10) self.qtgui_freq_sink_x_0.set_y_axis(-120, -20) self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(False) self.qtgui_freq_sink_x_0.enable_grid(False) self.qtgui_freq_sink_x_0.set_fft_average(1.0) self.qtgui_freq_sink_x_0.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_0.disable_legend() if complex == type(float()): self.qtgui_freq_sink_x_0.set_plot_pos_half(not True) labels = ["", "", "", "", "", "", "", "", "", ""] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue"] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win, 0,0,3,1) self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_fff( 16E3/float(final_rate/5), taps=None, flt_size=32) self.pfb_arb_resampler_xxx_0.declare_sample_delay(0) self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + "uhd" ) self.osmosdr_source_0.set_sample_rate(samp_rate) self.osmosdr_source_0.set_center_freq(center_freq, 0) self.osmosdr_source_0.set_freq_corr(0, 0) self.osmosdr_source_0.set_dc_offset_mode(0, 0) self.osmosdr_source_0.set_iq_balance_mode(0, 0) self.osmosdr_source_0.set_gain_mode(False, 0) self.osmosdr_source_0.set_gain(gain_db, 0) self.osmosdr_source_0.set_if_gain(20, 0) self.osmosdr_source_0.set_bb_gain(20, 0) self.osmosdr_source_0.set_antenna("", 0) self.osmosdr_source_0.set_bandwidth(samp_rate*0.8, 0) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(initial_decim, (variable_low_pass_filter_taps_0), demod_bb_freq, samp_rate) self.fir_filter_xxx_0_1 = filter.fir_filter_fff(initial_decim, (variable_low_pass_filter_taps_0)) self.fir_filter_xxx_0_1.declare_sample_delay(0) self.fir_filter_xxx_0_0 = filter.fir_filter_ccc(int(samp_rate/1E6), (variable_low_pass_filter_taps_0)) self.fir_filter_xxx_0_0.declare_sample_delay(0) self.fir_filter_xxx_0 = filter.fir_filter_ccc(initial_decim, (variable_low_pass_filter_taps_0)) self.fir_filter_xxx_0.declare_sample_delay(0) self.fft_vxx_0 = fft.fft_vcc(fft_length, True, (window.blackmanharris(fft_length)), True, 1) self.blocks_wavfile_sink_0 = blocks.wavfile_sink(file_name, 1, 16000, 8) self.blocks_vector_to_stream_0 = blocks.vector_to_stream(gr.sizeof_float*1, fft_length) self.blocks_stream_to_vector_0 = blocks.stream_to_vector(gr.sizeof_gr_complex*1, fft_length) self.blocks_probe_signal_vx_0 = blocks.probe_signal_vf(fft_length) self.blocks_nlog10_ff_0 = blocks.nlog10_ff(10, fft_length, 0) self.blocks_keep_one_in_n_0 = blocks.keep_one_in_n(gr.sizeof_gr_complex*fft_length, int(round(samp_rate/fft_length/1000))) self.blocks_integrate_xx_0 = blocks.integrate_ff(100, fft_length) self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(fft_length) self.audio_sink_0 = audio.sink(16000, "", True) self.analog_quadrature_demod_cf_0 = analog.quadrature_demod_cf(0.050) self.analog_pwr_squelch_xx_0_0 = analog.pwr_squelch_ff(-200, 0.1, 0, True) self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_cc(squelch_dB, 0.1, 0, False) ################################################## # Connections ################################################## self.connect((self.analog_pwr_squelch_xx_0, 0), (self.analog_quadrature_demod_cf_0, 0)) self.connect((self.analog_pwr_squelch_xx_0_0, 0), (self.blocks_wavfile_sink_0, 0)) self.connect((self.analog_quadrature_demod_cf_0, 0), (self.fir_filter_xxx_0_1, 0)) self.connect((self.blocks_complex_to_mag_squared_0, 0), (self.blocks_integrate_xx_0, 0)) self.connect((self.blocks_integrate_xx_0, 0), (self.blocks_nlog10_ff_0, 0)) self.connect((self.blocks_keep_one_in_n_0, 0), (self.fft_vxx_0, 0)) self.connect((self.blocks_nlog10_ff_0, 0), (self.blocks_probe_signal_vx_0, 0)) self.connect((self.blocks_nlog10_ff_0, 0), (self.blocks_vector_to_stream_0, 0)) self.connect((self.blocks_stream_to_vector_0, 0), (self.blocks_keep_one_in_n_0, 0)) self.connect((self.blocks_vector_to_stream_0, 0), (self.qtgui_time_sink_x_0, 0)) self.connect((self.fft_vxx_0, 0), (self.blocks_complex_to_mag_squared_0, 0)) self.connect((self.fir_filter_xxx_0, 0), (self.fir_filter_xxx_0_0, 0)) self.connect((self.fir_filter_xxx_0_0, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.fir_filter_xxx_0_0, 0), (self.qtgui_freq_sink_x_0_0, 0)) self.connect((self.fir_filter_xxx_0_1, 0), (self.pfb_arb_resampler_xxx_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.fir_filter_xxx_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.blocks_stream_to_vector_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.qtgui_freq_sink_x_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.analog_pwr_squelch_xx_0_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.audio_sink_0, 0))
def __init__(self): gr.top_block.__init__(self, "Ham2Mon Receiver Flow Example") Qt.QWidget.__init__(self) self.setWindowTitle("Ham2Mon Receiver Flow Example") try: self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) except: pass self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) self.top_scroll_layout.addWidget(self.top_scroll) self.top_scroll.setWidgetResizable(True) self.top_widget = Qt.QWidget() self.top_scroll.setWidget(self.top_widget) self.top_layout = Qt.QVBoxLayout(self.top_widget) self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) self.settings = Qt.QSettings("GNU Radio", "flow_example") self.restoreGeometry(self.settings.value("geometry").toByteArray()) ################################################## # Variables ################################################## self.samp_rate = samp_rate = 1E6 self.initial_decim = initial_decim = 5 self.samp_ratio = samp_ratio = samp_rate / 1E6 self.final_rate = final_rate = samp_rate / initial_decim**2 / int( samp_rate / 1E6) self.variable_low_pass_filter_taps_2 = variable_low_pass_filter_taps_2 = firdes.low_pass( 1.0, final_rate, 3500, 500, firdes.WIN_HAMMING, 6.76) self.variable_low_pass_filter_taps_1 = variable_low_pass_filter_taps_1 = firdes.low_pass( 1.0, samp_rate / 25, 12.5E3, 1E3, firdes.WIN_HAMMING, 6.76) self.variable_low_pass_filter_taps_0 = variable_low_pass_filter_taps_0 = firdes.low_pass( 1.0, 1, 0.090, 0.010, firdes.WIN_HAMMING, 6.76) self.squelch_dB = squelch_dB = -70 self.gain_db = gain_db = 30 self.final_decim = final_decim = int(samp_rate / 1E6) self.file_name = file_name = "test.wav" self.fft_length = fft_length = 256 * int( pow(2, np.ceil(np.log(samp_ratio) / np.log(2)))) self.demod_bb_freq = demod_bb_freq = 390E3 self.center_freq = center_freq = 144E6 ################################################## # Blocks ################################################## self._squelch_dB_range = Range(-100, 0, 5, -70, 200) self._squelch_dB_win = RangeWidget(self._squelch_dB_range, self.set_squelch_dB, "Squelch (dB)", "counter_slider", float) self.top_grid_layout.addWidget(self._squelch_dB_win, 5, 1, 1, 3) self._gain_db_range = Range(0, 70, 1, 30, 200) self._gain_db_win = RangeWidget(self._gain_db_range, self.set_gain_db, "HW Gain (dB)", "counter_slider", float) self.top_grid_layout.addWidget(self._gain_db_win, 4, 1, 1, 3) self._demod_bb_freq_range = Range(-samp_rate / 2, samp_rate / 2, 5E3, 390E3, 200) self._demod_bb_freq_win = RangeWidget(self._demod_bb_freq_range, self.set_demod_bb_freq, "Demod BB Freq (Hz)", "counter_slider", float) self.top_grid_layout.addWidget(self._demod_bb_freq_win, 3, 1, 1, 3) self.qtgui_time_sink_x_0 = qtgui.time_sink_f( fft_length, #size samp_rate, #samp_rate "Averaged Spectrum", #name 1 #number of inputs ) self.qtgui_time_sink_x_0.set_update_time(0.10) self.qtgui_time_sink_x_0.set_y_axis(-60, 40) self.qtgui_time_sink_x_0.set_y_label("Power", "") self.qtgui_time_sink_x_0.enable_tags(-1, True) self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "") self.qtgui_time_sink_x_0.enable_autoscale(False) self.qtgui_time_sink_x_0.enable_grid(False) self.qtgui_time_sink_x_0.enable_control_panel(False) if not True: self.qtgui_time_sink_x_0.disable_legend() labels = ["", "", "", "", "", "", "", "", "", ""] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "blue" ] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_time_sink_x_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_time_sink_x_0.set_line_label(i, labels[i]) self.qtgui_time_sink_x_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_0.set_line_style(i, styles[i]) self.qtgui_time_sink_x_0.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_0_win = sip.wrapinstance( self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win, 0, 1, 3, 1) self.qtgui_freq_sink_x_0_0 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 0, #fc final_rate, #bw "Decimated Channel", #name 1 #number of inputs ) self.qtgui_freq_sink_x_0_0.set_update_time(0.10) self.qtgui_freq_sink_x_0_0.set_y_axis(-200, -60) self.qtgui_freq_sink_x_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0_0.enable_autoscale(False) self.qtgui_freq_sink_x_0_0.enable_grid(False) self.qtgui_freq_sink_x_0_0.set_fft_average(1.0) self.qtgui_freq_sink_x_0_0.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_0_0.disable_legend() if complex == type(float()): self.qtgui_freq_sink_x_0_0.set_plot_pos_half(not True) labels = ["", "", "", "", "", "", "", "", "", ""] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_0_win = sip.wrapinstance( self.qtgui_freq_sink_x_0_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_0_win, 3, 0, 3, 1) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( fft_length, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 144E6, #fc samp_rate, #bw "Spectrum", #name 1 #number of inputs ) self.qtgui_freq_sink_x_0.set_update_time(0.10) self.qtgui_freq_sink_x_0.set_y_axis(-120, -20) self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(False) self.qtgui_freq_sink_x_0.enable_grid(False) self.qtgui_freq_sink_x_0.set_fft_average(1.0) self.qtgui_freq_sink_x_0.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_0.disable_legend() if complex == type(float()): self.qtgui_freq_sink_x_0.set_plot_pos_half(not True) labels = ["", "", "", "", "", "", "", "", "", ""] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_win = sip.wrapinstance( self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win, 0, 0, 3, 1) self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_fff( 16E3 / float(final_rate / 5), taps=None, flt_size=32) self.pfb_arb_resampler_xxx_0.declare_sample_delay(0) self.osmosdr_source_0 = osmosdr.source(args="numchan=" + str(1) + " " + "uhd") self.osmosdr_source_0.set_sample_rate(samp_rate) self.osmosdr_source_0.set_center_freq(center_freq, 0) self.osmosdr_source_0.set_freq_corr(0, 0) self.osmosdr_source_0.set_dc_offset_mode(0, 0) self.osmosdr_source_0.set_iq_balance_mode(0, 0) self.osmosdr_source_0.set_gain_mode(False, 0) self.osmosdr_source_0.set_gain(gain_db, 0) self.osmosdr_source_0.set_if_gain(20, 0) self.osmosdr_source_0.set_bb_gain(20, 0) self.osmosdr_source_0.set_antenna("", 0) self.osmosdr_source_0.set_bandwidth(samp_rate * 0.8, 0) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc( initial_decim, (variable_low_pass_filter_taps_0), demod_bb_freq, samp_rate) self.fir_filter_xxx_0_1 = filter.fir_filter_fff( initial_decim, (variable_low_pass_filter_taps_0)) self.fir_filter_xxx_0_1.declare_sample_delay(0) self.fir_filter_xxx_0_0 = filter.fir_filter_ccc( int(samp_rate / 1E6), (variable_low_pass_filter_taps_0)) self.fir_filter_xxx_0_0.declare_sample_delay(0) self.fir_filter_xxx_0 = filter.fir_filter_ccc( initial_decim, (variable_low_pass_filter_taps_0)) self.fir_filter_xxx_0.declare_sample_delay(0) self.fft_vxx_0 = fft.fft_vcc(fft_length, True, (window.blackmanharris(fft_length)), True, 1) self.blocks_wavfile_sink_0 = blocks.wavfile_sink( file_name, 1, 16000, 8) self.blocks_vector_to_stream_0 = blocks.vector_to_stream( gr.sizeof_float * 1, fft_length) self.blocks_stream_to_vector_0 = blocks.stream_to_vector( gr.sizeof_gr_complex * 1, fft_length) self.blocks_probe_signal_vx_0 = blocks.probe_signal_vf(fft_length) self.blocks_nlog10_ff_0 = blocks.nlog10_ff(10, fft_length, 0) self.blocks_keep_one_in_n_0 = blocks.keep_one_in_n( gr.sizeof_gr_complex * fft_length, int(round(samp_rate / fft_length / 1000))) self.blocks_integrate_xx_0 = blocks.integrate_ff(100, fft_length) self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared( fft_length) self.audio_sink_0 = audio.sink(16000, "", True) self.analog_quadrature_demod_cf_0 = analog.quadrature_demod_cf(0.050) self.analog_pwr_squelch_xx_0_0 = analog.pwr_squelch_ff( -200, 0.1, 0, True) self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_cc( squelch_dB, 0.1, 0, False) ################################################## # Connections ################################################## self.connect((self.analog_pwr_squelch_xx_0, 0), (self.analog_quadrature_demod_cf_0, 0)) self.connect((self.analog_pwr_squelch_xx_0_0, 0), (self.blocks_wavfile_sink_0, 0)) self.connect((self.analog_quadrature_demod_cf_0, 0), (self.fir_filter_xxx_0_1, 0)) self.connect((self.blocks_complex_to_mag_squared_0, 0), (self.blocks_integrate_xx_0, 0)) self.connect((self.blocks_integrate_xx_0, 0), (self.blocks_nlog10_ff_0, 0)) self.connect((self.blocks_keep_one_in_n_0, 0), (self.fft_vxx_0, 0)) self.connect((self.blocks_nlog10_ff_0, 0), (self.blocks_probe_signal_vx_0, 0)) self.connect((self.blocks_nlog10_ff_0, 0), (self.blocks_vector_to_stream_0, 0)) self.connect((self.blocks_stream_to_vector_0, 0), (self.blocks_keep_one_in_n_0, 0)) self.connect((self.blocks_vector_to_stream_0, 0), (self.qtgui_time_sink_x_0, 0)) self.connect((self.fft_vxx_0, 0), (self.blocks_complex_to_mag_squared_0, 0)) self.connect((self.fir_filter_xxx_0, 0), (self.fir_filter_xxx_0_0, 0)) self.connect((self.fir_filter_xxx_0_0, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.fir_filter_xxx_0_0, 0), (self.qtgui_freq_sink_x_0_0, 0)) self.connect((self.fir_filter_xxx_0_1, 0), (self.pfb_arb_resampler_xxx_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.fir_filter_xxx_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.blocks_stream_to_vector_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self.connect((self.osmosdr_source_0, 0), (self.qtgui_freq_sink_x_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.analog_pwr_squelch_xx_0_0, 0)) self.connect((self.pfb_arb_resampler_xxx_0, 0), (self.audio_sink_0, 0))
def build_blocks(self,config): if not self.device_found: return self.error = False fft_size = self.main.fft_size_control.get_value() frame_rate = self.main.framerate_control.get_value() average = self.main.average_control.get_value() ssb_lo = self.ssb_lo ssb_hi = self.ssb_hi USB = self.mode == self.main.MODE_USB or self.mode == self.main.MODE_CW_USB self.audio_dec_nrw = 1 self.dec_nrw, self.interp_nrw = self.compute_dec_interp(self.sample_rate,self.audio_rate) self.audio_dec_wid = self.if_sample_rate / self.audio_rate self.dec_wid, self.interp_wid = self.compute_dec_interp(self.sample_rate,self.if_sample_rate) volume = .1 self.configure_source_controls() self.create_update_freq_xlating_fir_filter() self.analog_agc_cc = analog.agc2_cc(1e-1, 1e-2, 1.0, 1.0) self.analog_agc_cc.set_max_gain(1) self.analog_agc_ff = analog.agc2_ff(1e-1, 1e-2, 1.0, 1.0) self.analog_agc_ff.set_max_gain(1) self.rational_resampler_wid = filter.rational_resampler_ccc( decimation=int(self.dec_wid), interpolation=int(self.interp_wid), taps=None, fractional_bw=None, ) self.rational_resampler_nrw = filter.rational_resampler_ccc( decimation=int(self.dec_nrw), interpolation=int(self.interp_nrw), taps=None, fractional_bw=None, ) self.analog_pwr_squelch = analog.pwr_squelch_cc(self.squelch_level, 1e-4, 0, True) self.analog_pwr_squelch_ssb = analog.pwr_squelch_ff(self.squelch_level, 1e-4, 0, True) self.blocks_multiply = blocks.multiply_vcc(1) self.blocks_complex_to_real = blocks.complex_to_real(1) #self.rebuild_filters(config) self.blocks_complex_to_mag_am = blocks.complex_to_mag(1) self.analog_nbfm_rcv = analog.nbfm_rx( audio_rate=self.audio_rate, quad_rate=self.audio_rate, tau=75e-6, max_dev=6e3, ) self.analog_wfm_rcv = analog.wfm_rcv( quad_rate=self.if_sample_rate, audio_decimation=self.audio_dec_wid, ) self.hilbert_fc_2 = filter.hilbert_fc(self.hilbert_taps_ssb, firdes.WIN_HAMMING, 6.76) self.hilbert_fc_1 = filter.hilbert_fc(self.hilbert_taps_ssb, firdes.WIN_HAMMING, 6.76) self.blocks_multiply_ssb = blocks.multiply_vcc(1) self.blocks_complex_to_float_ssb = blocks.complex_to_float(1) self.create_usb_lsb_switch() self.blocks_add = blocks.add_vff(1) self.blocks_complex_to_real = blocks.complex_to_real(1) self.blocks_complex_to_imag = blocks.complex_to_imag(1) # this is the source for the FFT display's data self.logpwrfft = logpwrfft.logpwrfft_c( sample_rate=self.sample_rate, fft_size=fft_size, ref_scale=2, frame_rate=frame_rate, avg_alpha=average, average=(average != 1), ) # this is the main FFT display self.fft_vector_sink = MyVectorSink(self.main,fft_size) self.blocks_multiply_const_volume = blocks.multiply_const_vff((volume, )) # only create this once if self.audio_sink == None: try: self.audio_sink = audio.sink(self.audio_rate, config['audio_device'], True) except Exception as e: self.main.message_dialog("Audio Error","A problem has come up while accessing the audio system: %s" % e) self.error = True self.audio_sink = None self.main.af_gain_control.set_value()
def __init__(self): # Call the initialization method from the parent class gr.top_block.__init__(self) # Setup the parser for command line arguments parser = OptionParser(option_class=eng_option) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="print settings to stdout") parser.add_option("-a", "--args", type="string", dest="src_args", default='addr=192.168.1.13', help="USRP device address args") parser.add_option("-g", "--gain", type="eng_float", dest="src_gain", default=0, help="USRP gain in dB") parser.add_option("-q", "--squelch", type="eng_float", dest="squelch_thresh", default=-80, help="Squelch threshold in dB") parser.add_option("-s", "--soundrate", type="eng_float", dest="snd_card_rate", default=48000, help="Sound card rate in Hz (must be n*100 Hz)") parser.add_option("-c", "--channels", type="string", dest="channel_file_name", default='channels.txt', help="Text file of EOL delimited channels in Hz") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit, 1 # Define the user constants src_args = str(options.src_args) src_gain = float(options.src_gain) squelch_thresh = float(options.squelch_thresh) snd_card_rate = int(options.snd_card_rate) channel_file_name = str(options.channel_file_name) # Define other constants (don't mess with these) max_rf_bandwidth = 25E6 # Limited by N210 channel_sample_rate = 20000 nbfm_maxdev = 2.5E3 nbfm_tau = 75E-6 # Open file, split to list, remove empty strings, and convert to float with open(channel_file_name) as chanfile: lines = chanfile.read().splitlines() chanfile.close() lines = __builtin__.filter(None, lines) chanlist = [float(chan) for chan in lines] # Source decimation is first deternmined by the required RF bandwidth rf_bandwidth = max(chanlist) - min(chanlist) + 2*channel_sample_rate src_decimation = int(math.floor(max_rf_bandwidth/rf_bandwidth)) # Check if rf_bandwidth is too wide if rf_bandwidth > max_rf_bandwidth: print 'Error: Channels spaced beyond the \ %f MHz maximum RF bandwidth!' % (max_rf_bandwidth/1E6) sys.exit([1]) else: pass # Don't let the source decimation go above 100 (USRP N210 limit) if src_decimation > 100: src_decimation = 100 # This is a little tricky # Don't want odd values of source decimation greater than 1 # Also want the source sample rate \ # to be an integer multiple of channel sample rate src_sample_rate = max_rf_bandwidth / src_decimation while ((src_decimation%2 != 0) or \ ((max_rf_bandwidth/src_decimation) % channel_sample_rate != 0)) \ and src_decimation > 1: src_decimation = src_decimation - 1 src_sample_rate = max_rf_bandwidth / src_decimation # Calculate the channel decimation for the fxlating filter # (it will be an integer) channel_decimation = int(src_sample_rate / channel_sample_rate) # Calculate center frequency src_center_freq = (max(chanlist) + min(chanlist)) / 2 # Print some info to stdout for verbose option if options.verbose: print 'Source args string "%s" ' % src_args print 'Source center frequency = %f MHz' % (src_center_freq/1E6) print 'Source decimation = %i' % src_decimation print 'Source sample rate = %i Hz' % src_sample_rate print 'Source gain = %i dB' % src_gain print 'Squelch threshold = %i dB' % squelch_thresh print 'Channel decimation = %i' % channel_decimation print 'Channel sample rate = %i Hz' % channel_sample_rate print 'Sound card rate = %i Hz' % snd_card_rate print 'Channel list = %s' % str(chanlist) # Setup the source src = uhd.usrp_source(src_args, uhd.io_type_t.COMPLEX_FLOAT32, 1) src.set_samp_rate(src_sample_rate) src.set_center_freq(src_center_freq, 0) src.set_gain(src_gain, 0) # Get USRP true center frequency # Do nothing with it as it's only a few Hz error #print src.get_center_freq() # Create N channel flows--------------------------------------------- # Design taps for frequency translating FIR filter filter_taps = filter.firdes.low_pass(1.0, src_sample_rate, 8E3, 2E3, filter.firdes.WIN_HAMMING) # N parallel fxlating FIR filter with decimation to channel rate # Note how the tune freq is chan-src_center_freq ; reversed from GR 3.6 fxlate = [filter.freq_xlating_fir_filter_ccc(channel_decimation, filter_taps, chan - src_center_freq, src_sample_rate) for chan in chanlist] # Power squelch (complex, non blocking) prior to NBFM squelch1 = [analog.pwr_squelch_cc(squelch_thresh, 0.1, 1, False) for chan in chanlist] # NBFM receiver nbfm = [analog.nbfm_rx(channel_sample_rate, channel_sample_rate, nbfm_tau, nbfm_maxdev) for chan in chanlist] # Power squelch (float, blocking) prior to wav file resampling squelch2 = [analog.pwr_squelch_ff(squelch_thresh, 0.1, 1, True) for chan in chanlist] # Rational resampler for channel rate to 8 kHz wav file rate resampwav = [filter.rational_resampler_fff(8000, int(channel_sample_rate)) for chan in chanlist] # Wav file sink wavfile = [blocks.wavfile_sink(str(int(chan))+'.wav', 1, 8000, 8) for chan in chanlist] # Connect the blocks for chan in range(len(chanlist)): self.connect(src, fxlate[chan], squelch1[chan], nbfm[chan], squelch2[chan], resampwav[chan], wavfile[chan]) # Adder to sum the nbfm outputs for sound card adder = blocks.add_vff(1) # Rational resampler for channel rate to audio rate resampsc = filter.rational_resampler_fff(int(snd_card_rate), int(channel_sample_rate)) # Sound card sink sndcard = audio.sink(snd_card_rate, "", True) # Connect the blocks for chan in range(len(chanlist)): self.connect(nbfm[chan], (adder, chan)) # Connect the blocks self.connect(adder, resampsc, sndcard)
def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, audio_bps=8): gr.hier_block2.__init__(self, "TunerDemodAM", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) # Default values self.center_freq = 0 squelch_db = -60 self.agc_ref = 0.1 self.file_name = "/dev/null" self.record = record # Decimation values for four stages of decimation decims = (5, int(samp_rate / 1E6)) # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ grfilter.firdes_low_pass(1, 1, 0.090, 0.010, grfilter.firdes.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ grfilter.freq_xlating_fir_filter_ccc(decims[0], low_pass_filter_taps_0, self.center_freq, samp_rate) # FIR filter decimating by 5 fir_filter_ccc_0 = grfilter.fir_filter_ccc(decims[0], low_pass_filter_taps_0) # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth low_pass_filter_taps_1 = grfilter.firdes_low_pass( 1, samp_rate / decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], low_pass_filter_taps_1) # Non blocking power squelch # Squelch level needs to be lower than NBFM or else choppy AM demod self.analog_pwr_squelch_cc = analog.pwr_squelch_cc( squelch_db, 1e-1, 0, False) # AGC with reference set for nomninal 0 dB volume # Paramaters tweaked to prevent impulse during squelching self.agc3_cc = analog.agc3_cc(1.0, 1E-4, self.agc_ref, 10, 1) self.agc3_cc.set_max_gain(65536) # AM demod with complex_to_mag() # Can't use analog.am_demod_cf() since it won't work with N>2 demods am_demod_cf = blocks.complex_to_mag(1) # 3.5 kHz cutoff for audio bandwidth low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ 3.5E3, 500, grfilter.firdes.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], low_pass_filter_taps_2) # Polyphase resampler allows arbitary RF sample rates # Takes 8-15.98 ksps to a constant 8 ksps for audio pfb_resamp = audio_rate / float(samp_rate / (decims[1] * decims[0]**3)) pfb_arb_resampler_fff = pfb.arb_resampler_fff(pfb_resamp, taps=None, flt_size=32) # Connect the blocks for the demod self.connect(self, self.freq_xlating_fir_filter_ccc) self.connect(self.freq_xlating_fir_filter_ccc, fir_filter_ccc_0) self.connect(fir_filter_ccc_0, fir_filter_ccc_1) self.connect(fir_filter_ccc_1, self.analog_pwr_squelch_cc) self.connect(self.analog_pwr_squelch_cc, self.agc3_cc) self.connect(self.agc3_cc, am_demod_cf) self.connect(am_demod_cf, fir_filter_fff_0) self.connect(fir_filter_fff_0, pfb_arb_resampler_fff) self.connect(pfb_arb_resampler_fff, self) # Need to set this to a very low value of -200 since it is after demod # Only want it to gate when the previous squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and 8 bits/sample self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, audio_rate, audio_bps) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink)
def __init__(self): grc_wxgui.top_block_gui.__init__(self, title="Acars") _icon_path = "C:\Program Files\GNURadio-3.7\share\icons\hicolor\scalable/apps\gnuradio-grc.png" self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY)) ################################################## # Variables ################################################## self.samp_rate = samp_rate = 250000 ################################################## # Blocks ################################################## self.wxgui_waterfallsink2_0 = waterfallsink2.waterfall_sink_c( self.GetWin(), baseband_freq=0, dynamic_range=100, ref_level=0, ref_scale=2.0, sample_rate=samp_rate, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title='Waterfall Plot', ) self.Add(self.wxgui_waterfallsink2_0.win) self.wxgui_fftsink2_0_0 = fftsink2.fft_sink_c( self.GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=192000, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title='FFT Plot', peak_hold=False, ) self.Add(self.wxgui_fftsink2_0_0.win) self.rtlsdr_source_0 = osmosdr.source(args="numchan=" + str(1) + " " + '') self.rtlsdr_source_0.set_sample_rate(samp_rate) self.rtlsdr_source_0.set_center_freq(131.550e6, 0) self.rtlsdr_source_0.set_freq_corr(0, 0) self.rtlsdr_source_0.set_dc_offset_mode(0, 0) self.rtlsdr_source_0.set_iq_balance_mode(2, 0) self.rtlsdr_source_0.set_gain_mode(True, 0) self.rtlsdr_source_0.set_gain(40, 0) self.rtlsdr_source_0.set_if_gain(20, 0) self.rtlsdr_source_0.set_bb_gain(20, 0) self.rtlsdr_source_0.set_antenna('', 0) self.rtlsdr_source_0.set_bandwidth(0, 0) self.rational_resampler_xxx_0 = filter.rational_resampler_fff( interpolation=48000, decimation=250000, taps=None, fractional_bw=None, ) self.low_pass_filter_0 = filter.fir_filter_ccf( 1, firdes.low_pass(1, samp_rate, 5000, 100, firdes.WIN_HAMMING, 6.76)) self.blocks_wavfile_sink_0 = blocks.wavfile_sink( 'D:\\Projects\\SDR\\EE-504-Intro-Project\\acars_test2.wav', 1, 48000, 16) self.blocks_complex_to_mag_0 = blocks.complex_to_mag(1) self.audio_sink_0 = audio.sink(48000, '', True) self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_ff( -20, 1e-3, 0, False) ################################################## # Connections ################################################## self.connect((self.analog_pwr_squelch_xx_0, 0), (self.blocks_wavfile_sink_0, 0)) self.connect((self.blocks_complex_to_mag_0, 0), (self.rational_resampler_xxx_0, 0)) self.connect((self.low_pass_filter_0, 0), (self.blocks_complex_to_mag_0, 0)) self.connect((self.low_pass_filter_0, 0), (self.wxgui_fftsink2_0_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.audio_sink_0, 0)) self.connect((self.rtlsdr_source_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.rtlsdr_source_0, 0), (self.wxgui_waterfallsink2_0, 0))
def __init__(self): # Call the initialization method from the parent class gr.top_block.__init__(self) # Setup the parser for command line arguments parser = OptionParser(option_class=eng_option) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="print settings to stdout") parser.add_option("-a", "--args", type="string", dest="src_args", default='addr=192.168.1.13', help="USRP device address args") parser.add_option("-g", "--gain", type="eng_float", dest="src_gain", default=0, help="USRP gain in dB") parser.add_option("-q", "--squelch", type="eng_float", dest="squelch_thresh", default=-80, help="Squelch threshold in dB") parser.add_option("-s", "--soundrate", type="eng_float", dest="snd_card_rate", default=48000, help="Sound card rate in Hz (must be n*100 Hz)") parser.add_option("-c", "--channels", type="string", dest="channel_file_name", default='channels.txt', help="Text file of EOL delimited channels in Hz") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit, 1 # Define the user constants src_args = str(options.src_args) src_gain = float(options.src_gain) squelch_thresh = float(options.squelch_thresh) snd_card_rate = int(options.snd_card_rate) channel_file_name = str(options.channel_file_name) # Define other constants (don't mess with these) max_rf_bandwidth = 25E6 # Limited by N210 channel_sample_rate = 20000 nbfm_maxdev = 2.5E3 nbfm_tau = 75E-6 # Open file, split to list, remove empty strings, and convert to float with open(channel_file_name) as chanfile: lines = chanfile.read().splitlines() chanfile.close() lines = __builtin__.filter(None, lines) chanlist = [float(chan) for chan in lines] # Source decimation is first deternmined by the required RF bandwidth rf_bandwidth = max(chanlist) - min(chanlist) + 2 * channel_sample_rate src_decimation = int(math.floor(max_rf_bandwidth / rf_bandwidth)) # Check if rf_bandwidth is too wide if rf_bandwidth > max_rf_bandwidth: print 'Error: Channels spaced beyond the \ %f MHz maximum RF bandwidth!' % (max_rf_bandwidth / 1E6) sys.exit([1]) else: pass # Don't let the source decimation go above 100 (USRP N210 limit) if src_decimation > 100: src_decimation = 100 # This is a little tricky # Don't want odd values of source decimation greater than 1 # Also want the source sample rate \ # to be an integer multiple of channel sample rate src_sample_rate = max_rf_bandwidth / src_decimation while ((src_decimation%2 != 0) or \ ((max_rf_bandwidth/src_decimation) % channel_sample_rate != 0)) \ and src_decimation > 1: src_decimation = src_decimation - 1 src_sample_rate = max_rf_bandwidth / src_decimation # Calculate the channel decimation for the fxlating filter # (it will be an integer) channel_decimation = int(src_sample_rate / channel_sample_rate) # Calculate center frequency src_center_freq = (max(chanlist) + min(chanlist)) / 2 # Print some info to stdout for verbose option if options.verbose: print 'Source args string "%s" ' % src_args print 'Source center frequency = %f MHz' % (src_center_freq / 1E6) print 'Source decimation = %i' % src_decimation print 'Source sample rate = %i Hz' % src_sample_rate print 'Source gain = %i dB' % src_gain print 'Squelch threshold = %i dB' % squelch_thresh print 'Channel decimation = %i' % channel_decimation print 'Channel sample rate = %i Hz' % channel_sample_rate print 'Sound card rate = %i Hz' % snd_card_rate print 'Channel list = %s' % str(chanlist) # Setup the source src = uhd.usrp_source(src_args, uhd.io_type_t.COMPLEX_FLOAT32, 1) src.set_samp_rate(src_sample_rate) src.set_center_freq(src_center_freq, 0) src.set_gain(src_gain, 0) # Get USRP true center frequency # Do nothing with it as it's only a few Hz error #print src.get_center_freq() # Create N channel flows--------------------------------------------- # Design taps for frequency translating FIR filter filter_taps = filter.firdes.low_pass(1.0, src_sample_rate, 8E3, 2E3, filter.firdes.WIN_HAMMING) # N parallel fxlating FIR filter with decimation to channel rate # Note how the tune freq is chan-src_center_freq ; reversed from GR 3.6 fxlate = [ filter.freq_xlating_fir_filter_ccc(channel_decimation, filter_taps, chan - src_center_freq, src_sample_rate) for chan in chanlist ] # Power squelch (complex, non blocking) prior to NBFM squelch1 = [ analog.pwr_squelch_cc(squelch_thresh, 0.1, 1, False) for chan in chanlist ] # NBFM receiver nbfm = [ analog.nbfm_rx(channel_sample_rate, channel_sample_rate, nbfm_tau, nbfm_maxdev) for chan in chanlist ] # Power squelch (float, blocking) prior to wav file resampling squelch2 = [ analog.pwr_squelch_ff(squelch_thresh, 0.1, 1, True) for chan in chanlist ] # Rational resampler for channel rate to 8 kHz wav file rate resampwav = [ filter.rational_resampler_fff(8000, int(channel_sample_rate)) for chan in chanlist ] # Wav file sink wavfile = [ blocks.wavfile_sink(str(int(chan)) + '.wav', 1, 8000, 8) for chan in chanlist ] # Connect the blocks for chan in range(len(chanlist)): self.connect(src, fxlate[chan], squelch1[chan], nbfm[chan], squelch2[chan], resampwav[chan], wavfile[chan]) # Adder to sum the nbfm outputs for sound card adder = blocks.add_vff(1) # Rational resampler for channel rate to audio rate resampsc = filter.rational_resampler_fff(int(snd_card_rate), int(channel_sample_rate)) # Sound card sink sndcard = audio.sink(snd_card_rate, "", True) # Connect the blocks for chan in range(len(chanlist)): self.connect(nbfm[chan], (adder, chan)) # Connect the blocks self.connect(adder, resampsc, sndcard)
def __init__(self): gr.top_block.__init__(self, "Top Block") ################################################## # Variables ################################################## self.audio_rate = audio_rate = int(48e3) self.rtl_rate = rtl_rate = int(240e3) self.out_intermediary_rate = out_intermediary_rate = audio_rate*4 self.out_gain = out_gain = .25 self.out_frequency_offset = out_frequency_offset = -50e3 self.out_frequency = out_frequency = 145.521e6 self.out_audio_inverted = out_audio_inverted = True self.in_frequency_offset = in_frequency_offset = 0 self.in_frequency = in_frequency = 145.551e6 self.in_final_gain = in_final_gain = 0.5 self.in_decimation_factor = in_decimation_factor = 8 self.in_audio_inverted = in_audio_inverted = True self.hackrf_rate = hackrf_rate = 2e6 self.dstar_bandwidth = dstar_bandwidth = 6.5e3 ################################################## # Blocks ################################################## self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + "" ) self.rtlsdr_source_0.set_sample_rate(rtl_rate) self.rtlsdr_source_0.set_center_freq(in_frequency+in_frequency_offset, 0) self.rtlsdr_source_0.set_freq_corr(69, 0) self.rtlsdr_source_0.set_dc_offset_mode(0, 0) self.rtlsdr_source_0.set_iq_balance_mode(0, 0) self.rtlsdr_source_0.set_gain_mode(False, 0) self.rtlsdr_source_0.set_gain(10, 0) self.rtlsdr_source_0.set_if_gain(20, 0) self.rtlsdr_source_0.set_bb_gain(20, 0) self.rtlsdr_source_0.set_antenna("", 0) self.rtlsdr_source_0.set_bandwidth(0, 0) self.rational_resampler_xxx_3 = filter.rational_resampler_ccc( interpolation=int(hackrf_rate), decimation=out_intermediary_rate, taps=None, fractional_bw=None, ) self.osmosdr_sink_0 = osmosdr.sink( args="numchan=" + str(1) + " " + "" ) self.osmosdr_sink_0.set_sample_rate(hackrf_rate) self.osmosdr_sink_0.set_center_freq(out_frequency-out_frequency_offset, 0) self.osmosdr_sink_0.set_freq_corr(4, 0) self.osmosdr_sink_0.set_gain(14, 0) self.osmosdr_sink_0.set_if_gain(0, 0) self.osmosdr_sink_0.set_bb_gain(0, 0) self.osmosdr_sink_0.set_antenna("0", 0) self.osmosdr_sink_0.set_bandwidth(100e3, 0) self.low_pass_filter_1 = filter.fir_filter_ccf(5, firdes.low_pass( 1, rtl_rate, dstar_bandwidth*2, 500, firdes.WIN_HAMMING, 6.76)) self.low_pass_filter_0 = filter.fir_filter_fff(1, firdes.low_pass( 1, audio_rate, dstar_bandwidth*2, 200, firdes.WIN_KAISER, 6.76)) self.freq_xlating_fft_filter_ccc_0 = filter.freq_xlating_fft_filter_ccc(1, (1, ), 0-out_frequency_offset, out_intermediary_rate) self.freq_xlating_fft_filter_ccc_0.set_nthreads(1) self.freq_xlating_fft_filter_ccc_0.declare_sample_delay(0) self.dc_blocker_xx_0 = filter.dc_blocker_ff(128, True) self.blocks_multiply_const_vxx_2 = blocks.multiply_const_vff(((-1 if out_audio_inverted else 1)*out_gain, )) self.blocks_multiply_const_vxx_1 = blocks.multiply_const_vff((0-in_final_gain if in_audio_inverted else in_final_gain, )) self.audio_source_0 = audio.source(audio_rate, "hw:10,1", True) self.audio_sink_1 = audio.sink(audio_rate, "plughw:11,0", True) self.analog_pwr_squelch_xx_1 = analog.pwr_squelch_cc(-30, 1, 1, False) self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_ff(-60, 1, 1, True) self.analog_nbfm_tx_0 = analog.nbfm_tx( audio_rate=int(audio_rate), quad_rate=int(out_intermediary_rate), tau=0, max_dev=dstar_bandwidth, ) self.analog_nbfm_rx_0 = analog.nbfm_rx( audio_rate=audio_rate, quad_rate=audio_rate, tau=0.000000000000000000001, max_dev=dstar_bandwidth*2, ) ################################################## # Connections ################################################## self.connect((self.analog_nbfm_rx_0, 0), (self.blocks_multiply_const_vxx_1, 0)) self.connect((self.analog_nbfm_tx_0, 0), (self.freq_xlating_fft_filter_ccc_0, 0)) self.connect((self.analog_pwr_squelch_xx_0, 0), (self.blocks_multiply_const_vxx_2, 0)) self.connect((self.analog_pwr_squelch_xx_1, 0), (self.analog_nbfm_rx_0, 0)) self.connect((self.audio_source_0, 0), (self.dc_blocker_xx_0, 0)) self.connect((self.blocks_multiply_const_vxx_1, 0), (self.audio_sink_1, 0)) self.connect((self.blocks_multiply_const_vxx_2, 0), (self.low_pass_filter_0, 0)) self.connect((self.dc_blocker_xx_0, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.freq_xlating_fft_filter_ccc_0, 0), (self.rational_resampler_xxx_3, 0)) self.connect((self.low_pass_filter_0, 0), (self.analog_nbfm_tx_0, 0)) self.connect((self.low_pass_filter_1, 0), (self.analog_pwr_squelch_xx_1, 0)) self.connect((self.rational_resampler_xxx_3, 0), (self.osmosdr_sink_0, 0)) self.connect((self.rtlsdr_source_0, 0), (self.low_pass_filter_1, 0))
def configure_blocks(self, protocol): if protocol == 'provoice' or protocol == 'analog_edacs': protocol = 'analog' self.log.debug('configure_blocks(%s)' % protocol) if not (protocol == 'p25' or protocol == 'p25_tdma' or protocol == 'p25_cqpsk' or protocol == 'p25_cqpsk_tdma' or protocol == 'provoice' or protocol == 'dsd_p25' or protocol == 'analog' or protocol == 'none'): raise Exception('Invalid protocol %s' % protocol) if self.protocol == protocol: return True self.lock() if self.protocol == 'analog': self.disconnect(self.source, self.signal_squelch, self.audiodemod, self.high_pass, self.resampler, self.sink) self.signal_squelch = None self.audiodemod = None self.high_pass = None self.resampler = None elif self.protocol == 'p25' or 'p25_tdma': try: self.disconnect(self.source, self.prefilter, self.fm_demod) #, (self.subtract,0)) self.disconnect(self.fm_demod, self.symbol_filter, self.demod_fsk4, self.slicer, self.decoder, self.float_conversion, self.sink) self.disconnect(self.slicer, self.decoder2, self.qsink) self.demod_watcher.keep_running = False except: pass #self.disconnect(self.fm_demod, self.avg, self.mult, (self.subtract,1)) self.prefilter = None self.fm_demod = None #self.avg = None #self.mult = None #self.subtract = None self.symbol_filter = None self.demod_fsk4 = None self.slicer = None self.decoder = None self.decoder2 = None self.qsink = None self.imbe = None self.float_conversion = None self.resampler = None elif self.protocol == 'p25_cqpsk' or self.protocol == 'p25_cqpsk_tdma': self.disconnect(self.source, self.resampler, self.agc, self.symbol_filter_c, self.clock, self.diffdec, self.to_float, self.rescale, self.slicer, self.decoder2, self.qsink) #, (self.subtract,0)) self.disconnect(self.slicer, self.decoder, self.float_conversion, self.sink) self.prefilter = None self.resampler = None self.agc = None self.symbol_filter_c = None self.clock = None self.diffdec = None self.to_float = None self.rescale = None self.slicer = None self.imbe = None self.decodequeue3 = None self.decodequeue2 = None self.decodequeue = None self.demod_watcher = None self.decoder = None self.decoder2 = None self.qsink = None self.float_conversion = None elif self.protocol == 'provoice': self.disconnect(self.source, self.fm_demod, self.resampler_in, self.dsd, self.out_squelch, self.sink) self.fm_demod = None self.resampler_in = None self.dsd = None self.out_squelch = None elif self.protocol == 'dsd_p25': self.disconnect(self.source, self.fm_demod, self.resampler_in, self.dsd, self.sink) self.fm_demod = None self.resampler_in = None self.dsd = None self.protocol = protocol if protocol == 'analog': self.signal_squelch = analog.pwr_squelch_cc(-100, 0.01, 0, True) #self.tone_squelch = gr.tone_squelch_ff(audiorate, 4800.0, 0.05, 300, 0, True) #tone squelch is EDACS ONLY self.audiodemod = analog.fm_demod_cf( channel_rate=self.input_rate, audio_decim=1, deviation=15000, audio_pass=(self.input_rate * 0.25), audio_stop=((self.input_rate * 0.25) + 2000), gain=8, tau=75e-6) self.high_pass = filter.fir_filter_fff( 1, firdes.high_pass(1, self.input_rate, 300, 30, firdes.WIN_HAMMING, 6.76)) self.resampler = filter.rational_resampler_fff( interpolation=8000, decimation=self.input_rate, taps=None, fractional_bw=None, ) self.connect(self.source, self.signal_squelch, self.audiodemod, self.high_pass, self.resampler, self.sink) elif protocol == 'p25' or protocol == 'p25_tdma': self.symbol_deviation = symbol_deviation = 600.0 if protocol == 'p25_tdma': symbol_rate = 6000 else: symbol_rate = 4800 channel_rate = self.input_rate self.prefilter = filter.freq_xlating_fir_filter_ccc( 1, (1, ), 0, self.input_rate) fm_demod_gain = channel_rate / (2.0 * pi * symbol_deviation) self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain) #self.avg = blocks.moving_average_ff(1000, 1, 4000) #self.mult = blocks.multiply_const_vff((0.001, )) #self.subtract = blocks.sub_ff(1) symbol_decim = 1 samples_per_symbol = channel_rate // symbol_rate symbol_coeffs = (1.0 / samples_per_symbol, ) * samples_per_symbol self.symbol_filter = filter.fir_filter_fff(symbol_decim, symbol_coeffs) autotuneq = gr.msg_queue(2) self.demod_fsk4 = op25.fsk4_demod_ff(autotuneq, channel_rate, symbol_rate) # symbol slicer levels = [-2.0, 0.0, 2.0, 4.0] self.slicer = op25.fsk4_slicer_fb(levels) self.imbe = repeater.vocoder(False, True, 0, "", 0, False) self.decodequeue3 = decodequeue3 = gr.msg_queue(10000) self.decodequeue2 = decodequeue2 = gr.msg_queue(10000) self.decodequeue = decodequeue = gr.msg_queue(10000) self.demod_watcher = None #demod_watcher(decodequeue2, self.adjust_channel_offset) self.decoder = repeater.p25_frame_assembler( '', 0, 0, True, True, False, decodequeue2, True, (True if protocol == 'p25_tdma' else False)) self.decoder2 = repeater.p25_frame_assembler( '', 0, 0, False, True, False, decodequeue3, False, False) self.qsink = blocks.message_sink(gr.sizeof_char, self.decodequeue, False) self.float_conversion = blocks.short_to_float(1, 8192) self.connect(self.source, self.prefilter, self.fm_demod) #, (self.subtract,0)) #self.connect(self.fm_demod, self.symbol_filter, self.demod_fsk4, self.slicer, self.decoder, self.imbe, self.float_conversion, self.sink) self.connect(self.fm_demod, self.symbol_filter, self.demod_fsk4, self.slicer, self.decoder, self.float_conversion, self.sink) self.connect(self.slicer, self.decoder2, self.qsink) #self.connect(self.fm_demod, self.avg, self.mult, (self.subtract,1)) elif protocol == 'p25_cqpsk' or protocol == 'p25_cqpsk_tdma': self.symbol_deviation = symbol_deviation = 600.0 self.resampler = blocks.multiply_const_cc(1.0) self.agc = analog.feedforward_agc_cc(1024, 1.0) self.symbol_filter_c = blocks.multiply_const_cc(1.0) gain_mu = 0.025 if protocol == 'p25_cqpsk_tdma': symbol_rate = 6000 else: symbol_rate = 4800 omega = float(self.input_rate) / float(symbol_rate) gain_omega = 0.1 * gain_mu * gain_mu alpha = 0.04 beta = 0.125 * alpha * alpha fmax = 1200 # Hz fmax = 2 * pi * fmax / float(self.input_rate) self.clock = repeater.gardner_costas_cc(omega, gain_mu, gain_omega, alpha, beta, fmax, -fmax) self.diffdec = digital.diff_phasor_cc() self.to_float = blocks.complex_to_arg() self.rescale = blocks.multiply_const_ff((1 / (pi / 4))) # symbol slicer levels = [-2.0, 0.0, 2.0, 4.0] self.slicer = op25.fsk4_slicer_fb(levels) #self.imbe = repeater.vocoder(False, True, 0, "", 0, False) self.decodequeue3 = decodequeue3 = gr.msg_queue(2) self.decodequeue2 = decodequeue2 = gr.msg_queue(2) self.decodequeue = decodequeue = gr.msg_queue(10000) #self.demod_watcher = demod_watcher(decodequeue2, self.adjust_channel_offset) self.decoder = repeater.p25_frame_assembler( '', 0, 0, True, True, False, decodequeue2, True, (False if protocol == 'p25_cqpsk' else True)) self.decoder2 = repeater.p25_frame_assembler( '', 0, 0, False, True, True, decodequeue3, False, False) #temp for debug #self.debug_sink = blocks.file_sink(1, '/dev/null') #self.connect(self.slicer, self.debug_sink) self.qsink = blocks.message_sink(gr.sizeof_char, self.decodequeue, False) self.float_conversion = blocks.short_to_float(1, 8192) self.connect(self.source, self.resampler, self.agc, self.symbol_filter_c, self.clock, self.diffdec, self.to_float, self.rescale, self.slicer, self.decoder2, self.qsink) #, (self.subtract,0)) self.connect(self.slicer, self.decoder, self.float_conversion, self.sink) elif protocol == 'provoice': fm_demod_gain = 0.6 self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain) self.resampler_in = filter.rational_resampler_fff( interpolation=48000, decimation=self.input_rate, taps=None, fractional_bw=None, ) self.dsd = dsd.block_ff(dsd.dsd_FRAME_PROVOICE, dsd.dsd_MOD_AUTO_SELECT, 3, 0, False) self.out_squelch = analog.pwr_squelch_ff(-100, 0.01, 0, True) self.connect(self.source, self.fm_demod, self.resampler_in, self.dsd, self.out_squelch, self.sink) elif protocol == 'dsd_p25': symbol_deviation = 600.0 fm_demod_gain = 0.4 #self.input_rate / (2.0 * pi * symbol_deviation) self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain) self.resampler_in = filter.rational_resampler_fff( interpolation=48000, decimation=self.input_rate, taps=None, fractional_bw=None, ) self.dsd = dsd.block_ff(dsd.dsd_FRAME_P25_PHASE_1, dsd.dsd_MOD_AUTO_SELECT, 3, 3, False) self.connect(self.source, self.fm_demod, self.resampler_in, self.dsd, self.sink) self.unlock()
def __init__(self, samp_rate=4E6, audio_rate=8000, record=True): gr.hier_block2.__init__(self, "TunerDemod", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) # Default values self.center_freq = 0 squelch_db = -60 self.quad_demod_gain = 0.050 self.file_name = "/dev/null" self.record = record # Decimation values for four stages of decimation decims = (5, int(samp_rate / 1E6)) # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ grfilter.firdes_low_pass(1, 1, 0.090, 0.010, grfilter.firdes.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ grfilter.freq_xlating_fir_filter_ccc(decims[0], low_pass_filter_taps_0, self.center_freq, samp_rate) # FIR filter decimating by 5 fir_filter_ccc_0 = grfilter.fir_filter_ccc(decims[0], low_pass_filter_taps_0) # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth low_pass_filter_taps_1 = grfilter.firdes_low_pass( 1, samp_rate / decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], low_pass_filter_taps_1) # Non blocking power squelch self.analog_pwr_squelch_cc = analog.pwr_squelch_cc( squelch_db, 1e-1, 0, False) # Quadrature demod with gain set for decent audio # This will be later multiplied by the volume self.analog_quadrature_demod_cf = \ analog.quadrature_demod_cf(self.quad_demod_gain) # 3.5 kHz cutoff for audio bandwidth low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ 3.5E3, 500, grfilter.firdes.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], low_pass_filter_taps_2) # Polyphase resampler allows arbitary RF sample rates # Takes 8-15.98 ksps to a constant 8 ksps for audio pfb_resamp = audio_rate / float(samp_rate / (decims[1] * decims[0]**3)) pfb_arb_resampler_fff = pfb.arb_resampler_fff(pfb_resamp, taps=None, flt_size=32) # Connect the blocks for the demod self.connect(self, self.freq_xlating_fir_filter_ccc) self.connect(self.freq_xlating_fir_filter_ccc, fir_filter_ccc_0) self.connect(fir_filter_ccc_0, fir_filter_ccc_1) self.connect(fir_filter_ccc_1, self.analog_pwr_squelch_cc) self.connect(self.analog_pwr_squelch_cc, self.analog_quadrature_demod_cf) self.connect(self.analog_quadrature_demod_cf, fir_filter_fff_0) self.connect(fir_filter_fff_0, pfb_arb_resampler_fff) self.connect(pfb_arb_resampler_fff, self) # Need to set this to a very low value of -200 since it is after demod # Only want it to gate when the previuos squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and 8 bits/sample self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, audio_rate, 8) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink)
def __init__(self): grc_wxgui.top_block_gui.__init__(self, title="Am") ################################################## # Variables ################################################## self.decim = decim = 2 self.adc_rate = adc_rate = 2000000 self.xlate_offset_fine = xlate_offset_fine = 0 self.xlate_offset = xlate_offset = 0 self.xlate_decim = xlate_decim = 4 self.xlate_bandwidth = xlate_bandwidth = 10000 self.volume = volume = 10 self.squelch = squelch = 22 self.samp_rate = samp_rate = adc_rate/decim self.main_freq = main_freq = 118.568e6 self.audio_rate = audio_rate = 48000 self.audio_interp = audio_interp = 4 ################################################## # Blocks ################################################## self.main_notebook = self.main_notebook = wx.Notebook(self.GetWin(), style=wx.NB_TOP) self.main_notebook.AddPage(grc_wxgui.Panel(self.main_notebook), "Baseband") self.main_notebook.AddPage(grc_wxgui.Panel(self.main_notebook), "Scope") self.main_notebook.AddPage(grc_wxgui.Panel(self.main_notebook), "Waterfall") self.main_notebook.AddPage(grc_wxgui.Panel(self.main_notebook), "Quad demod") self.Add(self.main_notebook) _xlate_offset_fine_sizer = wx.BoxSizer(wx.VERTICAL) self._xlate_offset_fine_text_box = forms.text_box( parent=self.main_notebook.GetPage(0).GetWin(), sizer=_xlate_offset_fine_sizer, value=self.xlate_offset_fine, callback=self.set_xlate_offset_fine, label="Fine Offset", converter=forms.float_converter(), proportion=0, ) self._xlate_offset_fine_slider = forms.slider( parent=self.main_notebook.GetPage(0).GetWin(), sizer=_xlate_offset_fine_sizer, value=self.xlate_offset_fine, callback=self.set_xlate_offset_fine, minimum=-10000, maximum=10000, num_steps=100, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.main_notebook.GetPage(0).Add(_xlate_offset_fine_sizer) self._xlate_offset_text_box = forms.text_box( parent=self.main_notebook.GetPage(0).GetWin(), value=self.xlate_offset, callback=self.set_xlate_offset, label="Xlate Offset", converter=forms.float_converter(), ) self.main_notebook.GetPage(0).Add(self._xlate_offset_text_box) _xlate_bandwidth_sizer = wx.BoxSizer(wx.VERTICAL) self._xlate_bandwidth_text_box = forms.text_box( parent=self.main_notebook.GetPage(0).GetWin(), sizer=_xlate_bandwidth_sizer, value=self.xlate_bandwidth, callback=self.set_xlate_bandwidth, label="Xlate Bandwidth", converter=forms.float_converter(), proportion=0, ) self._xlate_bandwidth_slider = forms.slider( parent=self.main_notebook.GetPage(0).GetWin(), sizer=_xlate_bandwidth_sizer, value=self.xlate_bandwidth, callback=self.set_xlate_bandwidth, minimum=2500, maximum=250000, num_steps=100, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.main_notebook.GetPage(0).Add(_xlate_bandwidth_sizer) _squelch_sizer = wx.BoxSizer(wx.VERTICAL) self._squelch_text_box = forms.text_box( parent=self.GetWin(), sizer=_squelch_sizer, value=self.squelch, callback=self.set_squelch, label='squelch', converter=forms.float_converter(), proportion=0, ) self._squelch_slider = forms.slider( parent=self.GetWin(), sizer=_squelch_sizer, value=self.squelch, callback=self.set_squelch, minimum=0, maximum=100, num_steps=100, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_squelch_sizer) self._main_freq_text_box = forms.text_box( parent=self.main_notebook.GetPage(0).GetWin(), value=self.main_freq, callback=self.set_main_freq, label="Main Freq", converter=forms.float_converter(), ) self.main_notebook.GetPage(0).Add(self._main_freq_text_box) self.wxgui_waterfallsink2_0 = waterfallsink2.waterfall_sink_c( self.main_notebook.GetPage(2).GetWin(), baseband_freq=0, dynamic_range=100, ref_level=0, ref_scale=2.0, sample_rate=samp_rate, fft_size=512, fft_rate=15, average=False, avg_alpha=None, title="Waterfall Plot", ) self.main_notebook.GetPage(2).Add(self.wxgui_waterfallsink2_0.win) self.wxgui_fftsink2_0 = fftsink2.fft_sink_c( self.main_notebook.GetPage(0).GetWin(), baseband_freq=0, y_per_div=10, y_divs=10, ref_level=0, ref_scale=2.0, sample_rate=samp_rate/xlate_decim, fft_size=1024, fft_rate=15, average=False, avg_alpha=None, title="FFT Plot", peak_hold=False, ) self.main_notebook.GetPage(0).Add(self.wxgui_fftsink2_0.win) _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=0, maximum=20, num_steps=100, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Add(_volume_sizer) self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + "" ) self.rtlsdr_source_0.set_sample_rate(samp_rate) self.rtlsdr_source_0.set_center_freq(main_freq, 0) self.rtlsdr_source_0.set_freq_corr(0, 0) self.rtlsdr_source_0.set_dc_offset_mode(2, 0) self.rtlsdr_source_0.set_iq_balance_mode(2, 0) self.rtlsdr_source_0.set_gain_mode(True, 0) self.rtlsdr_source_0.set_gain(50, 0) self.rtlsdr_source_0.set_if_gain(20, 0) self.rtlsdr_source_0.set_bb_gain(20, 0) self.rtlsdr_source_0.set_antenna("", 0) self.rtlsdr_source_0.set_bandwidth(0, 0) self.rational_resampler_xxx_1 = filter.rational_resampler_fff( interpolation=16000, decimation=48000, taps=None, fractional_bw=None, ) self.rational_resampler_xxx_0 = filter.rational_resampler_ccc( interpolation=audio_rate*audio_interp, decimation=samp_rate/xlate_decim, taps=None, fractional_bw=None, ) self.low_pass_filter = filter.fir_filter_ccf(1, firdes.low_pass( 1, samp_rate/xlate_decim, 5000, 1500, firdes.WIN_HAMMING, 6.76)) 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)), xlate_offset + xlate_offset_fine, samp_rate) self.blocks_wavfile_sink_0 = blocks.wavfile_sink("/Users/ross/Desktop/GRC/testam.wav", 1, 16000, 16) self.audio_sink_0 = audio.sink(48000, "", True) self.analog_pwr_squelch_xx_0 = analog.pwr_squelch_ff(squelch*-1, 0.001, 0, True) self.analog_am_demod_cf_0 = analog.am_demod_cf( channel_rate=48000, audio_decim=4, audio_pass=5000, audio_stop=5500, ) self.analog_agc2_xx_0 = analog.agc2_cc(1e-1, 1e-5, 0.9, 10) self.analog_agc2_xx_0.set_max_gain(10) ################################################## # Connections ################################################## self.connect((self.analog_agc2_xx_0, 0), (self.rational_resampler_xxx_0, 0)) self.connect((self.analog_am_demod_cf_0, 0), (self.analog_pwr_squelch_xx_0, 0)) self.connect((self.analog_pwr_squelch_xx_0, 0), (self.audio_sink_0, 0)) self.connect((self.analog_pwr_squelch_xx_0, 0), (self.rational_resampler_xxx_1, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.low_pass_filter, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.wxgui_fftsink2_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.wxgui_waterfallsink2_0, 0)) self.connect((self.low_pass_filter, 0), (self.analog_agc2_xx_0, 0)) self.connect((self.rational_resampler_xxx_0, 0), (self.analog_am_demod_cf_0, 0)) self.connect((self.rational_resampler_xxx_1, 0), (self.blocks_wavfile_sink_0, 0)) self.connect((self.rtlsdr_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0))