def __init__(self, parent, title='', sample_rate=1, size=default_scopesink_size, frame_decim=default_frame_decim, v_scale=default_v_scale, t_scale=None, num_inputs=1, xy_mode=False, **kwargs): gr.hier_block2.__init__( self, "scope_sink_c", gr.io_signature(num_inputs, num_inputs, gr.sizeof_gr_complex), gr.io_signature(0, 0, 0)) msgq = gr.msg_queue(2) # message queue that holds at most 2 messages self.guts = gr.oscope_sink_f(sample_rate, msgq) for i in range(num_inputs): c2f = gr.complex_to_float() self.connect((self, i), c2f) self.connect((c2f, 0), (self.guts, 2 * i + 0)) self.connect((c2f, 1), (self.guts, 2 * i + 1)) self.win = scope_window( win_info(msgq, sample_rate, frame_decim, v_scale, t_scale, self.guts, title), parent) self.win.info.xy = xy_mode
def __init__(self): gr.top_block.__init__(self, "am modulator") ################################################## # Variables ################################################## self.samp_rate = samp_rate = 44100 self.freq = freq = 8000 ################################################## # Blocks ################################################## self.gr_complex_to_float_0 = gr.complex_to_float(1) self.gr_float_to_complex_0 = gr.float_to_complex() self.gr_multiply_vxx_0 = gr.multiply_vcc(1) self.gr_sig_source_x_0 = gr.sig_source_c(samp_rate, gr.GR_COS_WAVE, freq, 1, 0) self.gr_wavfile_sink_0 = gr.wavfile_sink("8k.wav", 2, samp_rate, 16) self.gr_wavfile_source_0 = gr.wavfile_source("orig.wav", False) ################################################## # Connections ################################################## self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_vxx_0, 0)) self.connect((self.gr_wavfile_source_0, 0), (self.gr_float_to_complex_0, 0)) self.connect((self.gr_float_to_complex_0, 0), (self.gr_multiply_vxx_0, 1)) self.connect((self.gr_wavfile_source_0, 1), (self.gr_float_to_complex_0, 1)) self.connect((self.gr_multiply_vxx_0, 0), (self.gr_complex_to_float_0, 0)) self.connect((self.gr_complex_to_float_0, 0), (self.gr_wavfile_sink_0, 0)) self.connect((self.gr_complex_to_float_0, 1), (self.gr_wavfile_sink_0, 1))
def __init__(self, infile="data", samp_rate=1000000, outfile="data.wav", amp=70): gr.top_block.__init__(self, "Analyze") ################################################## # Parameters ################################################## self.infile = infile self.samp_rate = samp_rate self.outfile = outfile self.amp = amp ################################################## # Blocks ################################################## self.gr_wavfile_sink_0 = gr.wavfile_sink(outfile, 3, samp_rate, 16) self.gr_multiply_const_vxx_0 = gr.multiply_const_vcc((amp, )) self.gr_file_source_0 = gr.file_source(gr.sizeof_gr_complex*1, infile, False) self.gr_complex_to_mag_0 = gr.complex_to_mag(1) self.gr_complex_to_float_0 = gr.complex_to_float(1) ################################################## # Connections ################################################## self.connect((self.gr_file_source_0, 0), (self.gr_multiply_const_vxx_0, 0)) self.connect((self.gr_multiply_const_vxx_0, 0), (self.gr_complex_to_float_0, 0)) self.connect((self.gr_multiply_const_vxx_0, 0), (self.gr_complex_to_mag_0, 0)) self.connect((self.gr_complex_to_mag_0, 0), (self.gr_wavfile_sink_0, 2)) self.connect((self.gr_complex_to_float_0, 1), (self.gr_wavfile_sink_0, 1)) self.connect((self.gr_complex_to_float_0, 0), (self.gr_wavfile_sink_0, 0))
def add_to_scope(self,source_c,show_q): c2f= gr.complex_to_float () self.connect(source_c, c2f) self.connect((c2f,0), (self.scope,self.sink_count)) self.sink_count=self.sink_count+1 if show_q: self.connect((c2f,1), (self.scope,self.sink_count)) self.sink_count=self.sink_count+1
def test_002_square2_ff (self): #src_data = (7, -3, 4, -5.5, 2, 3, 5) #src_coeff = (1, 1, 2, 2, 3) src_data0 = (0.01+0.11j, 0.02+0.22j, 0.03+0.33j, 0.04+0.44j, 0.05+0.55j, 0.06+0.66j, 0.07+0.77j, 0.08+0.88j, 0.09+0.99j) #src_data1 = (0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 0.99) src_coeff = (0.101, 0.102, 0.103, 0.104, 0.105) scale = 1000 #expected_result = (9, 16, 30.25, 4, 9) #expected_result = (49, 9, 16, 30.20000076, 4, 9, 25) expected_result = (245, 320, 395, 470, 445, 400, 334, 246, 135) src0 = gr.vector_source_c (src_data0) #src1 = gr.vector_source_f (src_data1) #sqr = dsp.fir_ccf (src_coeff, scale, 2) ftoc = gr.float_to_complex () ctof = gr.complex_to_float () gccf = gr.interp_fir_filter_ccf (2, src_coeff) dst0 = gr.vector_sink_c () #dst1 = gr.vector_sink_f () mpoints = 4 taps = gr.firdes.low_pass(1, 1, 1.0/mpoints * 0.4, 1.0/mpoints * 0.1, gr.firdes.WIN_HANN) #print "The length of FILTER is" #print len(taps) #print "The length of FILTER is %d." %len(taps) #print taps #howto.set_taps() #self.tb.connect (src0, (sqr, 0)) #self.tb.connect (src1, (sqr, 1)) #self.tb.connect ((sqr, 0), dst0) #self.tb.connect ((sqr, 1), dst1) #self.tb.connect (src0, (ftoc, 0)) #self.tb.connect (src1, (ftoc, 1)) #self.tb.connect (ftoc, gccf) #self.tb.connect (gccf, ctof) #self.tb.connect ((ctof, 0), dst0) #self.tb.connect ((ctof, 1), dst1) self.tb.connect (src0, gccf) self.tb.connect (gccf, dst0) #self.tb.connect (src0, sqr) #self.tb.connect (sqr, dst0) self.tb.run () result_data0 = dst0.data () print result_data0
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) fft_size = 256 # build our flow graph input_rate = 2048.0e3 # Generate some noise noise = gr.noise_source_c(gr.GR_UNIFORM, 1.0 / 10) # Generate a complex sinusoid # src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1) src1 = gr.sig_source_c(input_rate, gr.GR_CONST_WAVE, 57.50e3, 1) # We add these throttle blocks so that this demo doesn't # suck down all the CPU available. Normally you wouldn't use these. thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate) sink1 = fft_sink_c( panel, title="Complex Data", fft_size=fft_size, sample_rate=input_rate, baseband_freq=100e3, ref_level=0, y_per_div=20, y_divs=10, ) vbox.Add(sink1.win, 1, wx.EXPAND) combine1 = gr.add_cc() self.connect(src1, (combine1, 0)) self.connect(noise, (combine1, 1)) self.connect(combine1, thr1, sink1) # src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1) src2 = gr.sig_source_f(input_rate, gr.GR_CONST_WAVE, 57.50e3, 1) thr2 = gr.throttle(gr.sizeof_float, input_rate) sink2 = fft_sink_f( panel, title="Real Data", fft_size=fft_size * 2, sample_rate=input_rate, baseband_freq=100e3, ref_level=0, y_per_div=20, y_divs=10, ) vbox.Add(sink2.win, 1, wx.EXPAND) combine2 = gr.add_ff() c2f2 = gr.complex_to_float() self.connect(src2, (combine2, 0)) self.connect(noise, c2f2, (combine2, 1)) self.connect(combine2, thr2, sink2)
def __init__(self, fg, parent, title='', sample_rate=1, size=default_scopesink_size, frame_decim=default_frame_decim, v_scale=default_v_scale, t_scale=None): msgq = gr.msg_queue(2) # message queue that holds at most 2 messages c2f = gr.complex_to_float() self.guts = gr.oscope_sink_f(sample_rate, msgq) fg.connect((c2f, 0), (self.guts, 0)) fg.connect((c2f, 1), (self.guts, 1)) gr.hier_block.__init__(self, fg, c2f, self.guts) self.win = scope_window(win_info(msgq, sample_rate, frame_decim, v_scale, t_scale, self.guts, title), parent)
def test_complex_to_float_1 (self): src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) expected_result = (0, 1, -1, 3, -3, -3) src = gr.vector_source_c (src_data) op = gr.complex_to_float () dst = gr.vector_sink_f () self.tb.connect (src, op) self.tb.connect (op, dst) self.tb.run () # run the graph and wait for it to finish actual_result = dst.data () # fetch the contents of the sink self.assertFloatTuplesAlmostEqual (expected_result, actual_result)
def test_complex_to_float_1(self): src_data = (0, 1, -1, 3 + 4j, -3 - 4j, -3 + 4j) expected_result = (0, 1, -1, 3, -3, -3) src = gr.vector_source_c(src_data) op = gr.complex_to_float() dst = gr.vector_sink_f() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink self.assertFloatTuplesAlmostEqual(expected_result, actual_result)
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) fft_size = 256 # build our flow graph input_rate = 2048.0e3 #Generate some noise noise = gr.noise_source_c(gr.GR_UNIFORM, 1.0 / 10) # Generate a complex sinusoid #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1) src1 = gr.sig_source_c(input_rate, gr.GR_CONST_WAVE, 57.50e3, 1) # We add these throttle blocks so that this demo doesn't # suck down all the CPU available. Normally you wouldn't use these. thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate) sink1 = fft_sink_c(panel, title="Complex Data", fft_size=fft_size, sample_rate=input_rate, baseband_freq=100e3, ref_level=0, y_per_div=20, y_divs=10) vbox.Add(sink1.win, 1, wx.EXPAND) combine1 = gr.add_cc() self.connect(src1, (combine1, 0)) self.connect(noise, (combine1, 1)) self.connect(combine1, thr1, sink1) #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1) src2 = gr.sig_source_f(input_rate, gr.GR_CONST_WAVE, 57.50e3, 1) thr2 = gr.throttle(gr.sizeof_float, input_rate) sink2 = fft_sink_f(panel, title="Real Data", fft_size=fft_size * 2, sample_rate=input_rate, baseband_freq=100e3, ref_level=0, y_per_div=20, y_divs=10) vbox.Add(sink2.win, 1, wx.EXPAND) combine2 = gr.add_ff() c2f2 = gr.complex_to_float() self.connect(src2, (combine2, 0)) self.connect(noise, c2f2, (combine2, 1)) self.connect(combine2, thr2, sink2)
def graph(): sampling_freq = 19200000 fg = gr.flow_graph() src0 = gr.file_source(gr.sizeof_gr_complex, "/tmp/atsc_pipe_1") duc_coeffs = gr.firdes.low_pass(1, 19.2e6, 9e6, 1e6, gr.firdes.WIN_HAMMING) duc = gr.freq_xlating_fir_filter_ccf(1, duc_coeffs, 5.75e6, 19.2e6) c2f = gr.complex_to_float() file = gr.file_sink(gr.sizeof_float, "/tmp/atsc_pipe_2") fg.connect(src0, duc, c2f, file) fg.run()
def __init__(self, name, options): gr.hier_block2.__init__( self, "debugger: " + name, gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature(0, 0, 0*0), # output signature ) fname = "debug_" + name + ".wav" self.c_to_iq = gr.complex_to_float() self.wavdump = gr.wavfile_sink(fname, 2, options.wav_sample_rate, 16) if options.verbose: print "writing a complex stream to file: %s" % fname self.connect( self, self.c_to_iq ) self.connect( (self.c_to_iq, 0), (self.wavdump, 0)) self.connect( (self.c_to_iq, 1), (self.wavdump, 1))
def test_complex_to_float_2 (self): src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) expected_result0 = (0, 1, -1, 3, -3, -3) expected_result1 = (0, 0, 0, 4, -4, 4) src = gr.vector_source_c (src_data) op = gr.complex_to_float () dst0 = gr.vector_sink_f () dst1 = gr.vector_sink_f () self.tb.connect (src, op) self.tb.connect ((op, 0), dst0) self.tb.connect ((op, 1), dst1) self.tb.run () actual_result = dst0.data () self.assertFloatTuplesAlmostEqual (expected_result0, actual_result) actual_result = dst1.data () self.assertFloatTuplesAlmostEqual (expected_result1, actual_result)
def test_complex_to_float_2(self): src_data = (0, 1, -1, 3 + 4j, -3 - 4j, -3 + 4j) expected_result0 = (0, 1, -1, 3, -3, -3) expected_result1 = (0, 0, 0, 4, -4, 4) src = gr.vector_source_c(src_data) op = gr.complex_to_float() dst0 = gr.vector_sink_f() dst1 = gr.vector_sink_f() self.tb.connect(src, op) self.tb.connect((op, 0), dst0) self.tb.connect((op, 1), dst1) self.tb.run() actual_result = dst0.data() self.assertFloatTuplesAlmostEqual(expected_result0, actual_result) actual_result = dst1.data() self.assertFloatTuplesAlmostEqual(expected_result1, actual_result)
def __init__( self, if_rate, af_rate ): gr.hier_block2.__init__(self, "ssb_demod", gr.io_signature(1,1,gr.sizeof_gr_complex), gr.io_signature(1,1,gr.sizeof_float)) self.if_rate = int(if_rate) self.af_rate = int(af_rate) self.if_decim = int(if_rate / af_rate) self.sideband = 1 self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()]) self.audio_taps = gr.firdes.low_pass( 1.0, self.af_rate, 3e3, 600, gr.firdes.WIN_HAMMING ) self.xlate = gr.freq_xlating_fir_filter_ccc( self.if_decim, self.xlate_taps, 0, self.if_rate ) self.split = gr.complex_to_float() self.lpf = gr.fir_filter_fff( 1, self.audio_taps ) self.sum = gr.add_ff( ) self.am_sel = gr.multiply_const_ff( 0 ) self.sb_sel = gr.multiply_const_ff( 1 ) self.mixer = gr.add_ff() self.am_det = gr.complex_to_mag() self.connect(self, self.xlate) self.connect(self.xlate, self.split) self.connect((self.split, 0), (self.sum, 0)) self.connect((self.split, 1), (self.sum, 1)) self.connect(self.sum, self.sb_sel) self.connect(self.xlate, self.am_det) self.connect(self.sb_sel, (self.mixer, 0)) self.connect(self.am_det, self.am_sel) self.connect(self.am_sel, (self.mixer, 1)) self.connect(self.mixer, self.lpf) self.connect(self.lpf, self)
def test_001(self): fft_length = 260 carriers = 100 shift = 20 # select maximum estimation range estim_range = (fft_length - carriers) / 2 l = estim_range + shift r = estim_range - shift # create preambles pn1 = pn_preamble(carriers) pn2 = pn_preamble(carriers) diff_pn = concatenate( [[conjugate(math.sqrt(2) * pn2[2 * i] / pn1[2 * i]), 0.0j] for i in range(carriers / 2)]) pn1_sym = extend_symbol(pn1, l, r) pn2_sym = extend_symbol(pn2, l, r) # block under tests cfo_estimator = ofdm.schmidl_cfo_estimator(fft_length, carriers, estim_range, diff_pn) # source, conversion, sink src_1 = gr.vector_source_c(pn1_sym) src_2 = gr.vector_source_c(pn2_sym) s2v_1 = gr.stream_to_vector(gr.sizeof_gr_complex, fft_length) s2v_2 = gr.stream_to_vector(gr.sizeof_gr_complex, fft_length) v2s = gr.vector_to_stream(gr.sizeof_float, 2 * estim_range + 1) dst = gr.vector_sink_f() self.fg.connect(src_1, s2v_1, (cfo_estimator, 0)) self.fg.connect(src_2, s2v_2, (cfo_estimator, 1)) self.fg.connect(cfo_estimator, v2s, dst) # file output filesink = gr.file_sink(gr.sizeof_float, "test_cfo.float") vec_equ = vector_equalizer(2 * estim_range + 1) self.fg.connect( v2s, gr.float_to_complex(), gr.stream_to_vector(gr.sizeof_gr_complex, 2 * estim_range + 1), vec_equ, gr.vector_to_stream(gr.sizeof_gr_complex, 2 * estim_range + 1), gr.complex_to_float(), filesink) runtime = self.fg runtime.run()
def graph(): print os.getpid() sampling_freq = 19200000 tb = gr.top_block() src0 = gr.file_source(gr.sizeof_gr_complex, "/tmp/atsc_pipe_1") duc_coeffs = gr.firdes.low_pass(1, 19.2e6, 9e6, 1e6, gr.firdes.WIN_HAMMING) duc = gr.freq_xlating_fir_filter_ccf(1, duc_coeffs, 5.75e6, 19.2e6) c2f = gr.complex_to_float() file = gr.file_sink(gr.sizeof_float, "/tmp/atsc_pipe_2") tb.connect(src0, duc, c2f, file) tb.run()
def __init__(self, outputfile, options): gr.top_block.__init__(self) if options.dsp: self.dst = audio.sink( options.dsp_sample_rate ) else: self.dst = gr.wavfile_sink(outputfile, 2, options.wav_sample_rate, 16) self.c_to_iq = gr.complex_to_float() self.connect( (self.c_to_iq, 0), (self.dst, 0)) self.connect( (self.c_to_iq, 1), (self.dst, 1)) # settings for the modulator: /usr/local/lib/python2.5/site-packages/gnuradio/blks2impl/gmsk.py self.modulator = blks2.gmsk_mod(samples_per_symbol=options.samples_per_symbol) self.pkt_queue = blks2.mod_pkts( modulator=self.modulator ) if options.carrier_frequency == 0: self.mixer = self.pkt_queue else: self.mixer = gr.multiply_vcc(1) self.carrier = gr.sig_source_c( options.carrier_sample_rate, gr.GR_SIN_WAVE, options.carrier_frequency, 1.0 ) self.lowpass = gr.fir_filter_ccf(1, firdes.low_pass(1, 48000, 48000/(2*options.samples_per_symbol)+500, 500, firdes.WIN_HAMMING, 6.76)) self.connect(self.pkt_queue, self.lowpass, (self.mixer, 0) ) self.connect(self.carrier, (self.mixer, 1) ) self.amp = gr.multiply_const_cc(1); self.amp.set_k(options.amp_amplitude) self.connect(self.mixer, self.amp, self.c_to_iq) if options.debug_wavs: from myblks import debugwav self._dpassw = debugwav("tx_passband", options) self._dprefw = debugwav("tx_prefband", options) self._dbasew = debugwav("tx_baseband", options) self.connect(self.amp, self._dpassw) self.connect(self.lowpass, self._dbasew) self.connect(self.pkt_queue, self._dprefw) if options.debug_files: self._dpassf = gr.file_sink(gr.sizeof_gr_complex*1, "debug_tx_passband.d_c") self._dpreff = gr.file_sink(gr.sizeof_gr_complex*1, "debug_tx_prefband.d_c") self._dbasef = gr.file_sink(gr.sizeof_gr_complex*1, "debug_tx_baseband.d_c") self.connect(self.amp, self._dpassf) self.connect(self.pkt_queue, self._dpreff) self.connect(self.lowpass, self._dbasef)
def __init__(self, parent, title='', sample_rate=1, size=default_scopesink_size, frame_decim=default_frame_decim, v_scale=default_v_scale, t_scale=None, num_inputs=1): gr.hier_block2.__init__(self, "scope_sink_c", gr.io_signature(num_inputs, num_inputs, gr.sizeof_gr_complex), gr.io_signature(0,0,0)) msgq = gr.msg_queue(2) # message queue that holds at most 2 messages self.guts = gr.oscope_sink_f(sample_rate, msgq) for i in range(num_inputs): c2f = gr.complex_to_float() self.connect((self, i), c2f) self.connect((c2f, 0), (self.guts, 2*i+0)) self.connect((c2f, 1), (self.guts, 2*i+1)) self.win = scope_window(win_info(msgq, sample_rate, frame_decim, v_scale, t_scale, self.guts, title), parent)
def __init__( self, fg, if_rate, af_rate ): self.if_rate = if_rate self.af_rate = af_rate self.if_decim = if_rate / af_rate self.sideband = 1 self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()]) self.audio_taps = gr.firdes.low_pass( 1.0, self.af_rate, 3e3, 600, gr.firdes.WIN_HAMMING ) self.xlate = gr.freq_xlating_fir_filter_ccc( self.if_decim, self.xlate_taps, 0, self.if_rate ) self.split = gr.complex_to_float() self.lpf = gr.fir_filter_fff( 1, self.audio_taps ) self.sum = gr.add_ff( ) self.am_sel = gr.multiply_const_ff( 0 ) self.sb_sel = gr.multiply_const_ff( 1 ) self.mixer = gr.add_ff() self.am_det = gr.complex_to_mag() fg.connect( self.xlate, self.split ) fg.connect( ( self.split,0 ), ( self.sum,0 ) ) fg.connect( ( self.split,1 ), ( self.sum,1 ) ) fg.connect( self.sum, self.sb_sel ) fg.connect( self.xlate, self.am_det ) fg.connect( self.sb_sel, ( self.mixer, 0 ) ) fg.connect( self.am_det, self.am_sel ) fg.connect( self.am_sel, ( self.mixer, 1 ) ) fg.connect( self.mixer, self.lpf ) gr.hier_block.__init__( self, fg, self.xlate, self.lpf )
def __init__(self): gr.top_block.__init__(self) self.frequency = 13.56e6 self.gain = 3 # USRP settings self.u_rx = usrp.source_c() #create the USRP source for RX #try and set the LF_RX for this rx_subdev_spec = usrp.pick_subdev(self.u_rx, (usrp_dbid.LF_RX, usrp_dbid.LF_TX)) #Configure the MUX for the daughterboard self.u_rx.set_mux( usrp.determine_rx_mux_value(self.u_rx, rx_subdev_spec)) #Tell it to use the LF_RX self.subdev_rx = usrp.selected_subdev(self.u_rx, rx_subdev_spec) #Make sure it worked print "Using RX dboard %s" % (self.subdev_rx.side_and_name(), ) #Set gain.. duh self.subdev_rx.set_gain(self.gain) #Tune the center frequency self.u_rx.tune(0, self.subdev_rx, self.frequency) adc_rate = self.u_rx.adc_rate() #64 MS/s usrp_decim = 8 self.u_rx.set_decim_rate(usrp_decim) #BW = 64 MS/s / decim = 64,000,000 / 256 = 250 kHz #Not sure if this decim rate exceeds USRP capabilities, #if it does then some software decim may have to be done as well usrp_rx_rate = adc_rate / usrp_decim #self.convert = gr.short_to_float() self.snk = gr.probe_signal_f() self.convert = gr.complex_to_float() # dst = audio.sink (sample_rate, "") # stv = gr.stream_to_vector (gr.sizeof_float, fft_size) # c2m = gr.complex_to_mag_squared (fft_size) self.connect(self.u_rx, self.convert, self.snk)
def test_001(self): fft_length = 260 carriers = 100 shift = 20 # select maximum estimation range estim_range = (fft_length-carriers)/2 l = estim_range+shift r = estim_range-shift # create preambles pn1 = pn_preamble(carriers) pn2 = pn_preamble(carriers) diff_pn = concatenate([[conjugate(math.sqrt(2)*pn2[2*i]/pn1[2*i]),0.0j] for i in range(carriers/2)]) pn1_sym = extend_symbol(pn1,l,r) pn2_sym = extend_symbol(pn2,l,r) # block under tests cfo_estimator = ofdm.schmidl_cfo_estimator(fft_length,carriers,estim_range,diff_pn) # source, conversion, sink src_1 = gr.vector_source_c(pn1_sym) src_2 = gr.vector_source_c(pn2_sym) s2v_1 = gr.stream_to_vector(gr.sizeof_gr_complex,fft_length) s2v_2 = gr.stream_to_vector(gr.sizeof_gr_complex,fft_length) v2s = gr.vector_to_stream(gr.sizeof_float,2*estim_range+1) dst = gr.vector_sink_f() self.fg.connect(src_1, s2v_1, (cfo_estimator,0)) self.fg.connect(src_2, s2v_2, (cfo_estimator,1)) self.fg.connect(cfo_estimator,v2s,dst) # file output filesink = gr.file_sink(gr.sizeof_float,"test_cfo.float") vec_equ = vector_equalizer(2*estim_range+1) self.fg.connect(v2s,gr.float_to_complex(), gr.stream_to_vector(gr.sizeof_gr_complex,2*estim_range+1), vec_equ,gr.vector_to_stream(gr.sizeof_gr_complex,2*estim_range+1), gr.complex_to_float(),filesink) runtime=self.fg runtime.run()
def __init__(self, magnitude=0, phase=0): """ Parameters: amplitude: float phase: float (degree) """ gr.hier_block2.__init__( self, "IQ Imbalance Generator", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex), ) ################################################## # Parameters ################################################## self.magnitude = magnitude self.phase = phase ################################################## # Blocks ################################################## self.mag = gr.multiply_const_vff((math.pow(10, magnitude / 20.0), )) self.gr_multiply_const_vxx_0 = gr.multiply_const_vff( (math.sin(phase * math.pi / 180.0), )) self.gr_float_to_complex_0 = gr.float_to_complex(1) self.gr_complex_to_float_0 = gr.complex_to_float(1) self.gr_add_xx_0 = gr.add_vff(1) ################################################## # Connections ################################################## self.connect((self.gr_float_to_complex_0, 0), (self, 0)) self.connect((self, 0), (self.gr_complex_to_float_0, 0)) self.connect((self.gr_complex_to_float_0, 0), (self.mag, 0)) self.connect((self.mag, 0), (self.gr_float_to_complex_0, 0)) self.connect((self.gr_add_xx_0, 0), (self.gr_float_to_complex_0, 1)) self.connect((self.gr_multiply_const_vxx_0, 0), (self.gr_add_xx_0, 0)) self.connect((self.gr_complex_to_float_0, 1), (self.gr_add_xx_0, 1)) self.connect((self.gr_complex_to_float_0, 0), (self.gr_multiply_const_vxx_0, 0))
def __init__(self): gr.top_block.__init__(self) self.frequency = 13.56e6 self.gain = 3 # USRP settings self.u_rx = usrp.source_c() #create the USRP source for RX #try and set the LF_RX for this rx_subdev_spec = usrp.pick_subdev(self.u_rx, (usrp_dbid.LF_RX, usrp_dbid.LF_TX)) #Configure the MUX for the daughterboard self.u_rx.set_mux(usrp.determine_rx_mux_value(self.u_rx, rx_subdev_spec)) #Tell it to use the LF_RX self.subdev_rx = usrp.selected_subdev(self.u_rx, rx_subdev_spec) #Make sure it worked print "Using RX dboard %s" % (self.subdev_rx.side_and_name(),) #Set gain.. duh self.subdev_rx.set_gain(self.gain) #Tune the center frequency self.u_rx.tune(0, self.subdev_rx, self.frequency) adc_rate = self.u_rx.adc_rate() #64 MS/s usrp_decim = 8 self.u_rx.set_decim_rate(usrp_decim) #BW = 64 MS/s / decim = 64,000,000 / 256 = 250 kHz #Not sure if this decim rate exceeds USRP capabilities, #if it does then some software decim may have to be done as well usrp_rx_rate = adc_rate / usrp_decim #self.convert = gr.short_to_float() self.snk = gr.probe_signal_f() self.convert = gr.complex_to_float() # dst = audio.sink (sample_rate, "") # stv = gr.stream_to_vector (gr.sizeof_float, fft_size) # c2m = gr.complex_to_mag_squared (fft_size) self.connect(self.u_rx, self.convert, self.snk)
def __init__(self, if_rate, af_rate): gr.hier_block2.__init__(self, "ssb_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) self.if_rate = int(if_rate) self.af_rate = int(af_rate) self.if_decim = int(if_rate / af_rate) self.sideband = 1 self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()]) self.audio_taps = gr.firdes.low_pass(1.0, self.af_rate, 3e3, 600, gr.firdes.WIN_HAMMING) self.xlate = gr.freq_xlating_fir_filter_ccc(self.if_decim, self.xlate_taps, 0, self.if_rate) self.split = gr.complex_to_float() self.lpf = gr.fir_filter_fff(1, self.audio_taps) self.sum = gr.add_ff() self.am_sel = gr.multiply_const_ff(0) self.sb_sel = gr.multiply_const_ff(1) self.mixer = gr.add_ff() self.am_det = gr.complex_to_mag() self.connect(self, self.xlate) self.connect(self.xlate, self.split) self.connect((self.split, 0), (self.sum, 0)) self.connect((self.split, 1), (self.sum, 1)) self.connect(self.sum, self.sb_sel) self.connect(self.xlate, self.am_det) self.connect(self.sb_sel, (self.mixer, 0)) self.connect(self.am_det, self.am_sel) self.connect(self.am_sel, (self.mixer, 1)) self.connect(self.mixer, self.lpf) self.connect(self.lpf, self)
def __init__(self, infile="data", samp_rate=1000000, outfile="data.wav", amp=70): gr.top_block.__init__(self, "Analyze") ################################################## # Parameters ################################################## self.infile = infile self.samp_rate = samp_rate self.outfile = outfile self.amp = amp ################################################## # Blocks ################################################## self.gr_wavfile_sink_0 = gr.wavfile_sink(outfile, 3, samp_rate, 16) self.gr_multiply_const_vxx_0 = gr.multiply_const_vcc((amp, )) self.gr_file_source_0 = gr.file_source(gr.sizeof_gr_complex * 1, infile, False) self.gr_complex_to_mag_0 = gr.complex_to_mag(1) self.gr_complex_to_float_0 = gr.complex_to_float(1) ################################################## # Connections ################################################## self.connect((self.gr_file_source_0, 0), (self.gr_multiply_const_vxx_0, 0)) self.connect((self.gr_multiply_const_vxx_0, 0), (self.gr_complex_to_float_0, 0)) self.connect((self.gr_multiply_const_vxx_0, 0), (self.gr_complex_to_mag_0, 0)) self.connect((self.gr_complex_to_mag_0, 0), (self.gr_wavfile_sink_0, 2)) self.connect((self.gr_complex_to_float_0, 1), (self.gr_wavfile_sink_0, 1)) self.connect((self.gr_complex_to_float_0, 0), (self.gr_wavfile_sink_0, 0))
def setup_interferometer(self, setimode): self.setup_radiometer_common(2) self.di = gr.deinterleave(gr.sizeof_gr_complex) self.connect (self.u, self.di) self.corr = gr.multiply_cc() self.c2f = gr.complex_to_float() self.shead = (self.di, 0) # Channel 0 to multiply port 0 # Channel 1 to multiply port 1 if (self.use_notches == False): self.connect((self.di, 0), (self.corr, 0)) self.connect((self.di, 1), (self.corr, 1)) else: self.connect((self.di, 0), self.notch_filt1, (self.corr, 0)) self.connect((self.di, 1), self.notch_filt2, (self.corr, 0)) # # Multiplier (correlator) to complex-to-float, followed by integrator, etc # self.connect(self.corr, self.c2f, self.integrator, self.keepn, self.cal_mult, self.cal_offs, self.chart) # # FFT scope gets only 1 channel # FIX THIS, by cross-correlating the *outputs* of two different FFTs, then display # Funky! # self.connect(self.shead, self.scope) # # Output of correlator/integrator chain to probe # self.connect(self.cal_offs, self.probe) return
def __init__(self, fg, if_rate, af_rate): self.if_rate = if_rate self.af_rate = af_rate self.if_decim = if_rate / af_rate self.sideband = 1 self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()]) self.audio_taps = gr.firdes.low_pass(1.0, self.af_rate, 3e3, 600, gr.firdes.WIN_HAMMING) self.xlate = gr.freq_xlating_fir_filter_ccc(self.if_decim, self.xlate_taps, 0, self.if_rate) self.split = gr.complex_to_float() self.lpf = gr.fir_filter_fff(1, self.audio_taps) self.sum = gr.add_ff() self.am_sel = gr.multiply_const_ff(0) self.sb_sel = gr.multiply_const_ff(1) self.mixer = gr.add_ff() self.am_det = gr.complex_to_mag() fg.connect(self.xlate, self.split) fg.connect((self.split, 0), (self.sum, 0)) fg.connect((self.split, 1), (self.sum, 1)) fg.connect(self.sum, self.sb_sel) fg.connect(self.xlate, self.am_det) fg.connect(self.sb_sel, (self.mixer, 0)) fg.connect(self.am_det, self.am_sel) fg.connect(self.am_sel, (self.mixer, 1)) fg.connect(self.mixer, self.lpf) gr.hier_block.__init__(self, fg, self.xlate, self.lpf)
def __init__( self, parent, title='', sample_rate=1, size=scope_window.DEFAULT_WIN_SIZE, v_scale=0, t_scale=0, v_offset=0, xy_mode=False, ac_couple=False, num_inputs=1, trig_mode=scope_window.DEFAULT_TRIG_MODE, y_axis_label='Counts', frame_rate=scope_window.DEFAULT_FRAME_RATE, use_persistence=False, persist_alpha=None, **kwargs #do not end with a comma ): #ensure analog alpha if persist_alpha is None: actual_frame_rate=float(frame_rate) analog_cutoff_freq=0.5 # Hertz #calculate alpha from wanted cutoff freq persist_alpha = 1.0 - math.exp(-2.0*math.pi*analog_cutoff_freq/actual_frame_rate) if not t_scale: t_scale = 10.0/sample_rate #init gr.hier_block2.__init__( self, "scope_sink", gr.io_signature(num_inputs, num_inputs, self._item_size), gr.io_signature(0, 0, 0), ) #scope msgq = gr.msg_queue(2) scope = gr.oscope_sink_f(sample_rate, msgq) #controller self.controller = pubsub() self.controller.subscribe(SAMPLE_RATE_KEY, scope.set_sample_rate) self.controller.publish(SAMPLE_RATE_KEY, scope.sample_rate) self.controller.subscribe(DECIMATION_KEY, scope.set_decimation_count) self.controller.publish(DECIMATION_KEY, scope.get_decimation_count) self.controller.subscribe(TRIGGER_LEVEL_KEY, scope.set_trigger_level) self.controller.publish(TRIGGER_LEVEL_KEY, scope.get_trigger_level) self.controller.subscribe(TRIGGER_MODE_KEY, scope.set_trigger_mode) self.controller.publish(TRIGGER_MODE_KEY, scope.get_trigger_mode) self.controller.subscribe(TRIGGER_SLOPE_KEY, scope.set_trigger_slope) self.controller.publish(TRIGGER_SLOPE_KEY, scope.get_trigger_slope) self.controller.subscribe(TRIGGER_CHANNEL_KEY, scope.set_trigger_channel) self.controller.publish(TRIGGER_CHANNEL_KEY, scope.get_trigger_channel) actual_num_inputs = self._real and num_inputs or num_inputs*2 #init ac couple for i in range(actual_num_inputs): self.controller[common.index_key(AC_COUPLE_KEY, i)] = ac_couple #start input watcher common.input_watcher(msgq, self.controller, MSG_KEY) #create window self.win = scope_window.scope_window( parent=parent, controller=self.controller, size=size, title=title, frame_rate=frame_rate, num_inputs=actual_num_inputs, sample_rate_key=SAMPLE_RATE_KEY, t_scale=t_scale, v_scale=v_scale, v_offset=v_offset, xy_mode=xy_mode, trig_mode=trig_mode, y_axis_label=y_axis_label, ac_couple_key=AC_COUPLE_KEY, trigger_level_key=TRIGGER_LEVEL_KEY, trigger_mode_key=TRIGGER_MODE_KEY, trigger_slope_key=TRIGGER_SLOPE_KEY, trigger_channel_key=TRIGGER_CHANNEL_KEY, decimation_key=DECIMATION_KEY, msg_key=MSG_KEY, use_persistence=use_persistence, persist_alpha=persist_alpha, ) common.register_access_methods(self, self.win) #connect if self._real: for i in range(num_inputs): self.wxgui_connect( (self, i), ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, i), SAMPLE_RATE_KEY), (scope, i), ) else: for i in range(num_inputs): c2f = gr.complex_to_float() self.wxgui_connect((self, i), c2f) for j in range(2): self.connect( (c2f, j), ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, 2*i+j), SAMPLE_RATE_KEY), (scope, 2*i+j), )
def __init__(self, *args, **kwds): # begin wxGlade: MyFrame.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) # Menu Bar self.frame_1_menubar = wx.MenuBar() self.SetMenuBar(self.frame_1_menubar) wxglade_tmp_menu = wx.Menu() self.Exit = wx.MenuItem(wxglade_tmp_menu, ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL) wxglade_tmp_menu.AppendItem(self.Exit) self.frame_1_menubar.Append(wxglade_tmp_menu, "File") # Menu Bar end self.panel_1 = wx.Panel(self, -1) self.button_1 = wx.Button(self, ID_BUTTON_1, "LSB") self.button_2 = wx.Button(self, ID_BUTTON_2, "USB") self.button_3 = wx.Button(self, ID_BUTTON_3, "AM") self.button_4 = wx.Button(self, ID_BUTTON_4, "CW") self.button_5 = wx.ToggleButton(self, ID_BUTTON_5, "Upper") self.slider_fcutoff_hi = wx.Slider(self, ID_SLIDER_1, 0, -15798, 15799, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.button_6 = wx.ToggleButton(self, ID_BUTTON_6, "Lower") self.slider_fcutoff_lo = wx.Slider(self, ID_SLIDER_2, 0, -15799, 15798, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.panel_5 = wx.Panel(self, -1) self.label_1 = wx.StaticText(self, -1, " Band\nCenter") self.text_ctrl_1 = wx.TextCtrl(self, ID_TEXT_1, "") self.panel_6 = wx.Panel(self, -1) self.panel_7 = wx.Panel(self, -1) self.panel_2 = wx.Panel(self, -1) self.button_7 = wx.ToggleButton(self, ID_BUTTON_7, "Freq") self.slider_3 = wx.Slider(self, ID_SLIDER_3, 3000, 0, 6000) self.spin_ctrl_1 = wx.SpinCtrl(self, ID_SPIN_1, "", min=0, max=100) self.button_8 = wx.ToggleButton(self, ID_BUTTON_8, "Vol") self.slider_4 = wx.Slider(self, ID_SLIDER_4, 0, 0, 500) self.slider_5 = wx.Slider(self, ID_SLIDER_5, 0, 0, 20) self.button_9 = wx.ToggleButton(self, ID_BUTTON_9, "Time") self.button_11 = wx.Button(self, ID_BUTTON_11, "Rew") self.button_10 = wx.Button(self, ID_BUTTON_10, "Fwd") self.panel_3 = wx.Panel(self, -1) self.label_2 = wx.StaticText(self, -1, "PGA ") self.panel_4 = wx.Panel(self, -1) self.panel_8 = wx.Panel(self, -1) self.panel_9 = wx.Panel(self, -1) self.label_3 = wx.StaticText(self, -1, "AM Sync\nCarrier") self.slider_6 = wx.Slider(self, ID_SLIDER_6, 50, 0, 200, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.label_4 = wx.StaticText(self, -1, "Antenna Tune") self.slider_7 = wx.Slider(self, ID_SLIDER_7, 1575, 950, 2200, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.panel_10 = wx.Panel(self, -1) self.button_12 = wx.ToggleButton(self, ID_BUTTON_12, "Auto Tune") self.button_13 = wx.Button(self, ID_BUTTON_13, "Calibrate") self.button_14 = wx.Button(self, ID_BUTTON_14, "Reset") self.panel_11 = wx.Panel(self, -1) self.panel_12 = wx.Panel(self, -1) self.__set_properties() self.__do_layout() # end wxGlade parser = OptionParser(option_class=eng_option) parser.add_option("", "--address", type="string", default="addr=192.168.10.2", help="Address of UHD device, [default=%default]") parser.add_option("-c", "--ddc-freq", type="eng_float", default=3.9e6, help="set Rx DDC frequency to FREQ", metavar="FREQ") parser.add_option( "-s", "--samp-rate", type="eng_float", default=256e3, help="set sample rate (bandwidth) [default=%default]") parser.add_option("-a", "--audio_file", default="", help="audio output file", metavar="FILE") parser.add_option("-r", "--radio_file", default="", help="radio output file", metavar="FILE") parser.add_option("-i", "--input_file", default="", help="radio input file", metavar="FILE") parser.add_option( "-O", "--audio-output", type="string", default="", help="audio output device name. E.g., hw:0,0, /dev/dsp, or pulse") (options, args) = parser.parse_args() self.usrp_center = options.ddc_freq input_rate = options.samp_rate self.slider_range = input_rate * 0.9375 self.f_lo = self.usrp_center - (self.slider_range / 2) self.f_hi = self.usrp_center + (self.slider_range / 2) self.af_sample_rate = 32000 fir_decim = long(input_rate / self.af_sample_rate) # data point arrays for antenna tuner self.xdata = [] self.ydata = [] self.tb = gr.top_block() # radio variables, initial conditions self.frequency = self.usrp_center # these map the frequency slider (0-6000) to the actual range self.f_slider_offset = self.f_lo self.f_slider_scale = 10000 self.spin_ctrl_1.SetRange(self.f_lo, self.f_hi) self.text_ctrl_1.SetValue(str(int(self.usrp_center))) self.slider_5.SetValue(0) self.AM_mode = False self.slider_3.SetValue( (self.frequency - self.f_slider_offset) / self.f_slider_scale) self.spin_ctrl_1.SetValue(int(self.frequency)) POWERMATE = True try: self.pm = powermate.powermate(self) except: sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n") POWERMATE = False if POWERMATE: powermate.EVT_POWERMATE_ROTATE(self, self.on_rotate) powermate.EVT_POWERMATE_BUTTON(self, self.on_pmButton) self.active_button = 7 # command line options if options.audio_file == "": SAVE_AUDIO_TO_FILE = False else: SAVE_AUDIO_TO_FILE = True if options.radio_file == "": SAVE_RADIO_TO_FILE = False else: SAVE_RADIO_TO_FILE = True if options.input_file == "": self.PLAY_FROM_USRP = True else: self.PLAY_FROM_USRP = False if self.PLAY_FROM_USRP: self.src = uhd.usrp_source(device_addr=options.address, io_type=uhd.io_type.COMPLEX_FLOAT32, num_channels=1) self.src.set_samp_rate(input_rate) input_rate = self.src.get_samp_rate() self.src.set_center_freq(self.usrp_center, 0) self.tune_offset = 0 else: self.src = gr.file_source(gr.sizeof_short, options.input_file) self.tune_offset = 2200 # 2200 works for 3.5-4Mhz band # convert rf data in interleaved short int form to complex s2ss = gr.stream_to_streams(gr.sizeof_short, 2) s2f1 = gr.short_to_float() s2f2 = gr.short_to_float() src_f2c = gr.float_to_complex() self.tb.connect(self.src, s2ss) self.tb.connect((s2ss, 0), s2f1) self.tb.connect((s2ss, 1), s2f2) self.tb.connect(s2f1, (src_f2c, 0)) self.tb.connect(s2f2, (src_f2c, 1)) # save radio data to a file if SAVE_RADIO_TO_FILE: radio_file = gr.file_sink(gr.sizeof_short, options.radio_file) self.tb.connect(self.src, radio_file) # 2nd DDC xlate_taps = gr.firdes.low_pass ( \ 1.0, input_rate, 16e3, 4e3, gr.firdes.WIN_HAMMING ) self.xlate = gr.freq_xlating_fir_filter_ccf ( \ fir_decim, xlate_taps, self.tune_offset, input_rate ) # Complex Audio filter audio_coeffs = gr.firdes.complex_band_pass( 1.0, # gain self.af_sample_rate, # sample rate -3000, # low cutoff 0, # high cutoff 100, # transition gr.firdes.WIN_HAMMING) # window self.slider_fcutoff_hi.SetValue(0) self.slider_fcutoff_lo.SetValue(-3000) self.audio_filter = gr.fir_filter_ccc(1, audio_coeffs) # Main +/- 16Khz spectrum display self.fft = fftsink2.fft_sink_c(self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640, 240)) # AM Sync carrier if AM_SYNC_DISPLAY: self.fft2 = fftsink.fft_sink_c(self.tb, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640, 240)) c2f = gr.complex_to_float() # AM branch self.sel_am = gr.multiply_const_cc(0) # the following frequencies turn out to be in radians/sample # gr.pll_refout_cc(alpha,beta,min_freq,max_freq) # suggested alpha = X, beta = .25 * X * X pll = gr.pll_refout_cc(.5, .0625, (2. * math.pi * 7.5e3 / self.af_sample_rate), (2. * math.pi * 6.5e3 / self.af_sample_rate)) self.pll_carrier_scale = gr.multiply_const_cc(complex(10, 0)) am_det = gr.multiply_cc() # these are for converting +7.5kHz to -7.5kHz # for some reason gr.conjugate_cc() adds noise ?? c2f2 = gr.complex_to_float() c2f3 = gr.complex_to_float() f2c = gr.float_to_complex() phaser1 = gr.multiply_const_ff(1) phaser2 = gr.multiply_const_ff(-1) # filter for pll generated carrier pll_carrier_coeffs = gr.firdes.complex_band_pass( 2.0, # gain self.af_sample_rate, # sample rate 7400, # low cutoff 7600, # high cutoff 100, # transition gr.firdes.WIN_HAMMING) # window self.pll_carrier_filter = gr.fir_filter_ccc(1, pll_carrier_coeffs) self.sel_sb = gr.multiply_const_ff(1) combine = gr.add_ff() #AGC sqr1 = gr.multiply_ff() intr = gr.iir_filter_ffd([.004, 0], [0, .999]) offset = gr.add_const_ff(1) agc = gr.divide_ff() self.scale = gr.multiply_const_ff(0.00001) dst = audio.sink(long(self.af_sample_rate), options.audio_output) if self.PLAY_FROM_USRP: self.tb.connect(self.src, self.xlate, self.fft) else: self.tb.connect(src_f2c, self.xlate, self.fft) self.tb.connect(self.xlate, self.audio_filter, self.sel_am, (am_det, 0)) self.tb.connect(self.sel_am, pll, self.pll_carrier_scale, self.pll_carrier_filter, c2f3) self.tb.connect((c2f3, 0), phaser1, (f2c, 0)) self.tb.connect((c2f3, 1), phaser2, (f2c, 1)) self.tb.connect(f2c, (am_det, 1)) self.tb.connect(am_det, c2f2, (combine, 0)) self.tb.connect(self.audio_filter, c2f, self.sel_sb, (combine, 1)) if AM_SYNC_DISPLAY: self.tb.connect(self.pll_carrier_filter, self.fft2) self.tb.connect(combine, self.scale) self.tb.connect(self.scale, (sqr1, 0)) self.tb.connect(self.scale, (sqr1, 1)) self.tb.connect(sqr1, intr, offset, (agc, 1)) self.tb.connect(self.scale, (agc, 0)) self.tb.connect(agc, dst) if SAVE_AUDIO_TO_FILE: f_out = gr.file_sink(gr.sizeof_short, options.audio_file) sc1 = gr.multiply_const_ff(64000) f2s1 = gr.float_to_short() self.tb.connect(agc, sc1, f2s1, f_out) self.tb.start() # for mouse position reporting on fft display self.fft.win.Bind(wx.EVT_LEFT_UP, self.Mouse) # and left click to re-tune self.fft.win.Bind(wx.EVT_LEFT_DOWN, self.Click) # start a timer to check for web commands if WEB_CONTROL: self.timer = UpdateTimer(self, 1000) # every 1000 mSec, 1 Sec wx.EVT_BUTTON(self, ID_BUTTON_1, self.set_lsb) wx.EVT_BUTTON(self, ID_BUTTON_2, self.set_usb) wx.EVT_BUTTON(self, ID_BUTTON_3, self.set_am) wx.EVT_BUTTON(self, ID_BUTTON_4, self.set_cw) wx.EVT_BUTTON(self, ID_BUTTON_10, self.fwd) wx.EVT_BUTTON(self, ID_BUTTON_11, self.rew) wx.EVT_BUTTON(self, ID_BUTTON_13, self.AT_calibrate) wx.EVT_BUTTON(self, ID_BUTTON_14, self.AT_reset) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_5, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_6, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_7, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_8, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_9, self.on_button) wx.EVT_SLIDER(self, ID_SLIDER_1, self.set_filter) wx.EVT_SLIDER(self, ID_SLIDER_2, self.set_filter) wx.EVT_SLIDER(self, ID_SLIDER_3, self.slide_tune) wx.EVT_SLIDER(self, ID_SLIDER_4, self.set_volume) wx.EVT_SLIDER(self, ID_SLIDER_5, self.set_pga) wx.EVT_SLIDER(self, ID_SLIDER_6, self.am_carrier) wx.EVT_SLIDER(self, ID_SLIDER_7, self.antenna_tune) wx.EVT_SPINCTRL(self, ID_SPIN_1, self.spin_tune) wx.EVT_MENU(self, ID_EXIT, self.TimeToQuit)
def __init__(self, *args, **kwds): # begin wxGlade: MyFrame.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) # Menu Bar self.frame_1_menubar = wx.MenuBar() self.SetMenuBar(self.frame_1_menubar) wxglade_tmp_menu = wx.Menu() self.Exit = wx.MenuItem(wxglade_tmp_menu, ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL) wxglade_tmp_menu.AppendItem(self.Exit) self.frame_1_menubar.Append(wxglade_tmp_menu, "File") # Menu Bar end self.panel_1 = wx.Panel(self, -1) self.button_1 = wx.Button(self, ID_BUTTON_1, "LSB") self.button_2 = wx.Button(self, ID_BUTTON_2, "USB") self.button_3 = wx.Button(self, ID_BUTTON_3, "AM") self.button_4 = wx.Button(self, ID_BUTTON_4, "CW") self.button_5 = wx.ToggleButton(self, ID_BUTTON_5, "Upper") self.slider_1 = wx.Slider(self, ID_SLIDER_1, 0, -15799, 15799, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.button_6 = wx.ToggleButton(self, ID_BUTTON_6, "Lower") self.slider_2 = wx.Slider(self, ID_SLIDER_2, 0, -15799, 15799, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.panel_5 = wx.Panel(self, -1) self.label_1 = wx.StaticText(self, -1, " Band\nCenter") self.text_ctrl_1 = wx.TextCtrl(self, ID_TEXT_1, "") self.panel_6 = wx.Panel(self, -1) self.panel_7 = wx.Panel(self, -1) self.panel_2 = wx.Panel(self, -1) self.button_7 = wx.ToggleButton(self, ID_BUTTON_7, "Freq") self.slider_3 = wx.Slider(self, ID_SLIDER_3, 3000, 0, 6000) self.spin_ctrl_1 = wx.SpinCtrl(self, ID_SPIN_1, "", min=0, max=100) self.button_8 = wx.ToggleButton(self, ID_BUTTON_8, "Vol") self.slider_4 = wx.Slider(self, ID_SLIDER_4, 0, 0, 500) self.slider_5 = wx.Slider(self, ID_SLIDER_5, 0, 0, 20) self.button_9 = wx.ToggleButton(self, ID_BUTTON_9, "Time") self.button_11 = wx.Button(self, ID_BUTTON_11, "Rew") self.button_10 = wx.Button(self, ID_BUTTON_10, "Fwd") self.panel_3 = wx.Panel(self, -1) self.label_2 = wx.StaticText(self, -1, "PGA ") self.panel_4 = wx.Panel(self, -1) self.panel_8 = wx.Panel(self, -1) self.panel_9 = wx.Panel(self, -1) self.label_3 = wx.StaticText(self, -1, "AM Sync\nCarrier") self.slider_6 = wx.Slider(self, ID_SLIDER_6, 50, 0, 200, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.label_4 = wx.StaticText(self, -1, "Antenna Tune") self.slider_7 = wx.Slider(self, ID_SLIDER_7, 1575, 950, 2200, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.panel_10 = wx.Panel(self, -1) self.button_12 = wx.ToggleButton(self, ID_BUTTON_12, "Auto Tune") self.button_13 = wx.Button(self, ID_BUTTON_13, "Calibrate") self.button_14 = wx.Button(self, ID_BUTTON_14, "Reset") self.panel_11 = wx.Panel(self, -1) self.panel_12 = wx.Panel(self, -1) self.__set_properties() self.__do_layout() # end wxGlade parser = OptionParser(option_class=eng_option) parser.add_option( "-c", "--ddc-freq", type="eng_float", default=3.9e6, help="set Rx DDC frequency to FREQ", metavar="FREQ" ) parser.add_option("-a", "--audio_file", default="", help="audio output file", metavar="FILE") parser.add_option("-r", "--radio_file", default="", help="radio output file", metavar="FILE") parser.add_option("-i", "--input_file", default="", help="radio input file", metavar="FILE") parser.add_option("-d", "--decim", type="int", default=250, help="USRP decimation") parser.add_option( "-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=first one with a daughterboard)", ) (options, args) = parser.parse_args() self.usrp_center = options.ddc_freq usb_rate = 64e6 / options.decim self.slider_range = usb_rate * 0.9375 self.f_lo = self.usrp_center - (self.slider_range / 2) self.f_hi = self.usrp_center + (self.slider_range / 2) self.af_sample_rate = 32000 fir_decim = long(usb_rate / self.af_sample_rate) # data point arrays for antenna tuner self.xdata = [] self.ydata = [] self.tb = gr.top_block() # radio variables, initial conditions self.frequency = self.usrp_center # these map the frequency slider (0-6000) to the actual range self.f_slider_offset = self.f_lo self.f_slider_scale = 10000 / options.decim self.spin_ctrl_1.SetRange(self.f_lo, self.f_hi) self.text_ctrl_1.SetValue(str(int(self.usrp_center))) self.slider_5.SetValue(0) self.AM_mode = False self.slider_3.SetValue((self.frequency - self.f_slider_offset) / self.f_slider_scale) self.spin_ctrl_1.SetValue(int(self.frequency)) POWERMATE = True try: self.pm = powermate.powermate(self) except: sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n") POWERMATE = False if POWERMATE: powermate.EVT_POWERMATE_ROTATE(self, self.on_rotate) powermate.EVT_POWERMATE_BUTTON(self, self.on_pmButton) self.active_button = 7 # command line options if options.audio_file == "": SAVE_AUDIO_TO_FILE = False else: SAVE_AUDIO_TO_FILE = True if options.radio_file == "": SAVE_RADIO_TO_FILE = False else: SAVE_RADIO_TO_FILE = True if options.input_file == "": self.PLAY_FROM_USRP = True else: self.PLAY_FROM_USRP = False if self.PLAY_FROM_USRP: self.src = usrp.source_s(decim_rate=options.decim) if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.src) self.src.set_mux(usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec) self.src.tune(0, self.subdev, self.usrp_center) self.tune_offset = 0 # -self.usrp_center - self.src.rx_freq(0) else: self.src = gr.file_source(gr.sizeof_short, options.input_file) self.tune_offset = 2200 # 2200 works for 3.5-4Mhz band # save radio data to a file if SAVE_RADIO_TO_FILE: file = gr.file_sink(gr.sizeof_short, options.radio_file) self.tb.connect(self.src, file) # 2nd DDC xlate_taps = gr.firdes.low_pass(1.0, usb_rate, 16e3, 4e3, gr.firdes.WIN_HAMMING) self.xlate = gr.freq_xlating_fir_filter_ccf(fir_decim, xlate_taps, self.tune_offset, usb_rate) # convert rf data in interleaved short int form to complex s2ss = gr.stream_to_streams(gr.sizeof_short, 2) s2f1 = gr.short_to_float() s2f2 = gr.short_to_float() src_f2c = gr.float_to_complex() self.tb.connect(self.src, s2ss) self.tb.connect((s2ss, 0), s2f1) self.tb.connect((s2ss, 1), s2f2) self.tb.connect(s2f1, (src_f2c, 0)) self.tb.connect(s2f2, (src_f2c, 1)) # Complex Audio filter audio_coeffs = gr.firdes.complex_band_pass( 1.0, # gain self.af_sample_rate, # sample rate -3000, # low cutoff 0, # high cutoff 100, # transition gr.firdes.WIN_HAMMING, ) # window self.slider_1.SetValue(0) self.slider_2.SetValue(-3000) self.audio_filter = gr.fir_filter_ccc(1, audio_coeffs) # Main +/- 16Khz spectrum display self.fft = fftsink2.fft_sink_c( self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640, 240) ) # AM Sync carrier if AM_SYNC_DISPLAY: self.fft2 = fftsink.fft_sink_c( self.tb, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640, 240), ) c2f = gr.complex_to_float() # AM branch self.sel_am = gr.multiply_const_cc(0) # the following frequencies turn out to be in radians/sample # gr.pll_refout_cc(alpha,beta,min_freq,max_freq) # suggested alpha = X, beta = .25 * X * X pll = gr.pll_refout_cc( 0.5, 0.0625, (2.0 * math.pi * 7.5e3 / self.af_sample_rate), (2.0 * math.pi * 6.5e3 / self.af_sample_rate) ) self.pll_carrier_scale = gr.multiply_const_cc(complex(10, 0)) am_det = gr.multiply_cc() # these are for converting +7.5kHz to -7.5kHz # for some reason gr.conjugate_cc() adds noise ?? c2f2 = gr.complex_to_float() c2f3 = gr.complex_to_float() f2c = gr.float_to_complex() phaser1 = gr.multiply_const_ff(1) phaser2 = gr.multiply_const_ff(-1) # filter for pll generated carrier pll_carrier_coeffs = gr.firdes.complex_band_pass( 2.0, # gain self.af_sample_rate, # sample rate 7400, # low cutoff 7600, # high cutoff 100, # transition gr.firdes.WIN_HAMMING, ) # window self.pll_carrier_filter = gr.fir_filter_ccc(1, pll_carrier_coeffs) self.sel_sb = gr.multiply_const_ff(1) combine = gr.add_ff() # AGC sqr1 = gr.multiply_ff() intr = gr.iir_filter_ffd([0.004, 0], [0, 0.999]) offset = gr.add_const_ff(1) agc = gr.divide_ff() self.scale = gr.multiply_const_ff(0.00001) dst = audio.sink(long(self.af_sample_rate)) self.tb.connect(src_f2c, self.xlate, self.fft) self.tb.connect(self.xlate, self.audio_filter, self.sel_am, (am_det, 0)) self.tb.connect(self.sel_am, pll, self.pll_carrier_scale, self.pll_carrier_filter, c2f3) self.tb.connect((c2f3, 0), phaser1, (f2c, 0)) self.tb.connect((c2f3, 1), phaser2, (f2c, 1)) self.tb.connect(f2c, (am_det, 1)) self.tb.connect(am_det, c2f2, (combine, 0)) self.tb.connect(self.audio_filter, c2f, self.sel_sb, (combine, 1)) if AM_SYNC_DISPLAY: self.tb.connect(self.pll_carrier_filter, self.fft2) self.tb.connect(combine, self.scale) self.tb.connect(self.scale, (sqr1, 0)) self.tb.connect(self.scale, (sqr1, 1)) self.tb.connect(sqr1, intr, offset, (agc, 1)) self.tb.connect(self.scale, (agc, 0)) self.tb.connect(agc, dst) if SAVE_AUDIO_TO_FILE: f_out = gr.file_sink(gr.sizeof_short, options.audio_file) sc1 = gr.multiply_const_ff(64000) f2s1 = gr.float_to_short() self.tb.connect(agc, sc1, f2s1, f_out) self.tb.start() # for mouse position reporting on fft display em.eventManager.Register(self.Mouse, wx.EVT_MOTION, self.fft.win) # and left click to re-tune em.eventManager.Register(self.Click, wx.EVT_LEFT_DOWN, self.fft.win) # start a timer to check for web commands if WEB_CONTROL: self.timer = UpdateTimer(self, 1000) # every 1000 mSec, 1 Sec wx.EVT_BUTTON(self, ID_BUTTON_1, self.set_lsb) wx.EVT_BUTTON(self, ID_BUTTON_2, self.set_usb) wx.EVT_BUTTON(self, ID_BUTTON_3, self.set_am) wx.EVT_BUTTON(self, ID_BUTTON_4, self.set_cw) wx.EVT_BUTTON(self, ID_BUTTON_10, self.fwd) wx.EVT_BUTTON(self, ID_BUTTON_11, self.rew) wx.EVT_BUTTON(self, ID_BUTTON_13, self.AT_calibrate) wx.EVT_BUTTON(self, ID_BUTTON_14, self.AT_reset) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_5, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_6, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_7, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_8, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_9, self.on_button) wx.EVT_SLIDER(self, ID_SLIDER_1, self.set_filter) wx.EVT_SLIDER(self, ID_SLIDER_2, self.set_filter) wx.EVT_SLIDER(self, ID_SLIDER_3, self.slide_tune) wx.EVT_SLIDER(self, ID_SLIDER_4, self.set_volume) wx.EVT_SLIDER(self, ID_SLIDER_5, self.set_pga) wx.EVT_SLIDER(self, ID_SLIDER_6, self.am_carrier) wx.EVT_SLIDER(self, ID_SLIDER_7, self.antenna_tune) wx.EVT_SPINCTRL(self, ID_SPIN_1, self.spin_tune) wx.EVT_MENU(self, ID_EXIT, self.TimeToQuit)
def __init__(self, modulator, demodulator, rx_callback, options): gr.top_block.__init__(self) sense_symbol_rate=2500000 sense_samples_per_symbol=2 sense_rx_freq=2500000000 sense_rx_gain=20 options.chbw_factor=1 global bandchoose #args = demodulator.extract_kwargs_from_options(options) self.sensesource=uhd_receiver(options.args, sense_symbol_rate, sense_samples_per_symbol, sense_rx_freq, sense_rx_gain, options.spec, options.antenna, options.verbose) if(options.tx_freq is not None): # Work-around to get the modulation's bits_per_symbol args = modulator.extract_kwargs_from_options(options) symbol_rate = options.bitrate / modulator(**args).bits_per_symbol() fa = samp_rate/4 #1000000 self.sink = uhd_transmitter(options.args, symbol_rate, options.samples_per_symbol, options.tx_freq, options.tx_gain, options.spec, options.antenna, options.verbose) options.samples_per_symbol = self.sink._sps elif(options.to_file is not None): sys.stderr.write(("Saving samples to '%s'.\n\n" % (options.to_file))) self.sink = gr.file_sink(gr.sizeof_gr_complex, options.to_file) else: sys.stderr.write("No sink defined, dumping samples to null sink.\n\n") self.sink = gr.null_sink(gr.sizeof_gr_complex) self.txgate = gr.copy(gr.sizeof_gr_complex) self.sensegate = gr.copy(gr.sizeof_gr_complex) #self.msgq = gr.msg_queue() # do this after for any adjustments to the options that may # occur in the sinks (specifically the UHD sink) # do sense self.sensepath = sensing_path(options) self.tx_enabled = True self.sense_flag=False self.connect(self.sensesource, self.sensepath) # do this after for any adjustments to the options that may # occur in the sinks (specifically the UHD sink) self.txpath1 = transmit_path(modulator, options) self.txpath2 = transmit_path(modulator, options) #self.connect(self.txpath, self.sink) # Define the math operator blocks # Generate exp(jw1t) and exp(-jw1t) self.gr_multiply_xx_0 = gr.multiply_vff(1) self.gr_float_to_complex_0_0 = gr.float_to_complex(1) self.gr_float_to_complex_0 = gr.float_to_complex(1) self.const_source_x_0 = gr.sig_source_f(0, gr.GR_CONST_WAVE, 0, 0, -1) self.analog_sig_source_x_0_0 = gr.sig_source_f(samp_rate, gr.GR_SIN_WAVE, fa, 1, 0) self.analog_sig_source_x_0 = gr.sig_source_f(samp_rate, gr.GR_COS_WAVE, fa, 1, 0) # Combine signal from two subbands self.gr_multiply_xx_1 = gr.multiply_vcc(1) self.gr_multiply_xx_2 = gr.multiply_vcc(1) self.gr_c2f_1 = gr.complex_to_float(1) self.gr_c2f_2 = gr.complex_to_float(1) self.gr_add_xx_re = gr.add_vff(1) self.gr_add_xx_im = gr.add_vff(1) self.gr_f2c = gr.float_to_complex(1) self.gr_null_source_0 = gr.null_source(gr.sizeof_gr_complex*1) # output from gr_float_to_complex_0_0 is exp(-jw1t) # output from gr_float_to_complex_0 is exp(jw1t) self.connect((self.gr_multiply_xx_0, 0), (self.gr_float_to_complex_0_0, 1)) self.connect((self.analog_sig_source_x_0, 0), (self.gr_float_to_complex_0_0, 0)) self.connect((self.analog_sig_source_x_0_0, 0), (self.gr_float_to_complex_0, 1)) self.connect((self.analog_sig_source_x_0, 0), (self.gr_float_to_complex_0, 0)) self.connect((self.analog_sig_source_x_0_0, 0), (self.gr_multiply_xx_0, 0)) self.connect((self.const_source_x_0, 0), (self.gr_multiply_xx_0, 1)) # txpath1 * exp(-jw1t) #self.connect(self.txpath1, (self.gr_multiply_xx_1, 0)) self.connect((self.gr_float_to_complex_0_0, 0), (self.gr_multiply_xx_1, 1)) # txpath2 * exp(jw1t) #self.connect(self.txpath2, (self.gr_multiply_xx_2, 0)) self.connect((self.gr_float_to_complex_0, 0), (self.gr_multiply_xx_2, 1)) if bandchoose == 0: self.connect(self.txpath1, (self.gr_multiply_xx_1, 0)) self.connect(self.gr_null_source_0 , (self.gr_multiply_xx_2, 0)) elif bandchoose == 1: self.connect(self.gr_null_source_0 , (self.gr_multiply_xx_1, 0)) self.connect(self.txpath2, (self.gr_multiply_xx_2, 0)) else: self.connect(self.txpath1, (self.gr_multiply_xx_1, 0)) self.connect(self.txpath2, (self.gr_multiply_xx_2, 0)) self.connect((self.gr_multiply_xx_1, 0), self.gr_c2f_1) self.connect((self.gr_multiply_xx_2, 0), self.gr_c2f_2) self.connect((self.gr_c2f_1,0), (self.gr_add_xx_re,0)) self.connect((self.gr_c2f_2,0), (self.gr_add_xx_re,1)) self.connect((self.gr_c2f_1,1), (self.gr_add_xx_im,0)) self.connect((self.gr_c2f_2,1), (self.gr_add_xx_im,1)) self.connect(self.gr_add_xx_re, (self.gr_f2c,0)) self.connect(self.gr_add_xx_im, (self.gr_f2c,1)) self.connect(self.gr_f2c, self.sink)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-1", "--one-channel", action="store_true", default=False, help="software synthesized Q channel") parser.add_option("-c", "--calibration", type="eng_float", default=0, help="freq offset") parser.add_option("-d", "--debug", action="store_true", default=False, help="allow time at init to attach gdb") parser.add_option("-C", "--costas-alpha", type="eng_float", default=0.125, help="Costas alpha") parser.add_option("-g", "--gain", type="eng_float", default=1.0) parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") parser.add_option("-I", "--imbe", action="store_true", default=False, help="output IMBE codewords") parser.add_option("-L", "--low-pass", type="eng_float", default=6.5e3, help="low pass cut-off", metavar="Hz") parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") parser.add_option("-p", "--polarity", action="store_true", default=False, help="use reversed polarity") parser.add_option("-s", "--sample-rate", type="int", default=96000, help="input sample rate") parser.add_option("-t", "--tone-detect", action="store_true", default=False, help="use experimental tone detect algorithm") parser.add_option("-v", "--verbose", action="store_true", default=False, help="additional output") (options, args) = parser.parse_args() sample_rate = options.sample_rate symbol_rate = 4800 samples_per_symbol = sample_rate // symbol_rate IN = gr.file_source(gr.sizeof_gr_complex, options.input_file) if options.one_channel: C2F = gr.complex_to_float() F2C = gr.float_to_complex() # osc./mixer for mixing signal down to approx. zero IF LO = gr.sig_source_c (sample_rate, gr.GR_COS_WAVE, options.calibration, 1.0, 0) MIXER = gr.multiply_cc() # get signal into normalized range (-1.0 - +1.0) # FIXME: add AGC AMP = gr.multiply_const_cc(options.gain) lpf_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) decim_amt = 1 if options.tone_detect: if sample_rate != 96000: print "warning, only 96K has been tested." print "other rates may require theta to be reviewed/adjusted." step_size = 7.5e-8 theta = -4 # optimum timing sampling point cic_length = 48 DEMOD = repeater.tdetect_cc(samples_per_symbol, step_size, theta, cic_length) else: # decim by 2 to get 48k rate samples_per_symbol /= 2 # for DECIM sample_rate /= 2 # for DECIM decim_amt = 2 # create Gardner/Costas loop # the loop will not work if the sample levels aren't normalized (above) timing_error_gain = 0.025 # loop error gain gain_omega = 0.25 * timing_error_gain * timing_error_gain alpha = options.costas_alpha beta = 0.125 * alpha * alpha fmin = -0.025 # fmin and fmax are in radians/s fmax = 0.025 DEMOD = repeater.gardner_costas_cc(samples_per_symbol, timing_error_gain, gain_omega, alpha, beta, fmax, fmin) DECIM = gr.fir_filter_ccf (decim_amt, lpf_taps) # probably too much phase noise etc to attempt coherent demodulation # so we use differential DIFF = gr.diff_phasor_cc() # take angle of the phase difference (in radians) TOFLOAT = gr.complex_to_arg() # convert from radians such that signal is in [-3, -1, +1, +3] RESCALE = gr.multiply_const_ff(1 / (pi / 4.0)) # optional polarity reversal (should be unnec. - now autodetected) p = 1.0 if options.polarity: p = -1.0 POLARITY = gr.multiply_const_ff(p) # hard decision at specified points levels = [-2.0, 0.0, 2.0, 4.0 ] SLICER = repeater.fsk4_slicer_fb(levels) # assemble received frames and route to Wireshark via UDP hostname = "127.0.0.1" port = 23456 debug = 0 if options.verbose: debug = 255 do_imbe = False if options.imbe: do_imbe = True do_output = True # enable block's output stream do_msgq = False # msgq output not yet implemented msgq = gr.msg_queue(2) DECODER = repeater.p25_frame_assembler(hostname, port, debug, do_imbe, do_output, do_msgq, msgq) OUT = gr.file_sink(gr.sizeof_char, options.output_file) if options.one_channel: self.connect(IN, C2F, F2C, (MIXER, 0)) else: self.connect(IN, (MIXER, 0)) self.connect(LO, (MIXER, 1)) self.connect(MIXER, AMP, DECIM, DEMOD, DIFF, TOFLOAT, RESCALE, POLARITY, SLICER, DECODER, OUT) if options.debug: print 'Ready for GDB to attach (pid = %d)' % (os.getpid(),) raw_input("Press 'Enter' to continue...")
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel parser = OptionParser(option_class=eng_option) #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), # help="select USRP Rx side A or B (default=A)") parser.add_option( "-d", "--decim", type="int", default=128, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, help="set frequency to FREQ [default=%default])", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=20, help="set gain in dB [default=%default]") parser.add_option("-F", "--filter", action="store_true", default=True, help="Enable channel filter") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() raise SystemExit nchan = 4 if options.filter: sw_decim = 4 else: sw_decim = 1 self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") if self.u.nddcs() < nchan: sys.stderr.write( 'This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % (nchan, self.u.nddcs())) raise SystemExit if not self.u.set_nchannels(nchan): sys.stderr.write('set_nchannels(%d) failed\n' % (nchan, )) raise SystemExit input_rate = self.u.adc_freq() / self.u.decim_rate() print "USB data rate = %s" % (eng_notation.num_to_str(input_rate), ) print "Scope data rate = %s" % (eng_notation.num_to_str( input_rate / sw_decim), ) self.subdev = self.u.db(0) + self.u.db(1) if (len(self.subdev) < 4 or self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX): sys.stderr.write( 'This code requires a Basic Rx board on Sides A & B\n') sys.exit(1) self.u.set_mux(gru.hexint(0xf3f2f1f0)) # deinterleave four channels from FPGA di = gr.deinterleave(gr.sizeof_gr_complex) self.connect(self.u, di) # our destination (8 float inputs) self.scope = scopesink2.scope_sink_f(panel, sample_rate=input_rate / sw_decim, num_inputs=2 * nchan) # taps for channel filter chan_filt_coeffs = optfir.low_pass( 1, # gain input_rate, # sampling rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation #print len(chan_filt_coeffs) # bust the deinterleaved complex channels into floats for i in range(nchan): if options.filter: chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) c2f = gr.complex_to_float() self.connect((di, i), chan_filt, c2f) else: c2f = gr.complex_to_float() self.connect((di, i), c2f) self.connect((c2f, 0), (self.scope, 2 * i + 0)) self.connect((c2f, 1), (self.scope, 2 * i + 1)) self._build_gui(vbox) self.set_gain(options.gain) self.set_freq(options.freq)
def __init__(self): grc_wxgui.top_block_gui.__init__(self, title="writeToFile") _icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png" self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY)) ################################################## # Variables ################################################## self.variable_function_probe_1 = variable_function_probe_1 = 0 self.variable_function_probe_0 = variable_function_probe_0 = 0 self.samp_rate = samp_rate = 32000 self.receiveFrequency = receiveFrequency = 900000000 ################################################## # Blocks ################################################## self.gr_probe_signal_f_1 = gr.probe_signal_f() self.gr_probe_signal_f_0 = gr.probe_signal_f() self.wxgui_scopesink2_0 = scopesink2.scope_sink_c( self.GetWin(), title="Scope Plot", sample_rate=samp_rate, v_scale=0, v_offset=0, t_scale=0, ac_couple=False, xy_mode=False, num_inputs=1, trig_mode=gr.gr_TRIG_MODE_AUTO, y_axis_label="Counts", ) self.Add(self.wxgui_scopesink2_0.win) def _variable_function_probe_1_probe(): while True: val = self.gr_probe_signal_f_1.level() try: self.set_variable_function_probe_1(val) except AttributeError, e: pass # set sample rate time.sleep(1.0/(70)) # in a first test with sample rate 1000 Hz about 15 values in a row have been identical _variable_function_probe_1_thread = threading.Thread(target=_variable_function_probe_1_probe) _variable_function_probe_1_thread.daemon = True _variable_function_probe_1_thread.start() def _variable_function_probe_0_probe(): while True: val = self.gr_probe_signal_f_0.level() try: self.set_variable_function_probe_0(val) except AttributeError, e: pass # set sample rate time.sleep(1.0/(70)) # in a first test with sample rate 1000 Hz about 15 values in a row have been identical _variable_function_probe_0_thread = threading.Thread(target=_variable_function_probe_0_probe) _variable_function_probe_0_thread.daemon = True _variable_function_probe_0_thread.start() self.uhd_usrp_source_0 = uhd.usrp_source( device_addr="", stream_args=uhd.stream_args( cpu_format="fc32", channels=range(1), ), ) self.uhd_usrp_source_0.set_samp_rate(samp_rate) self.uhd_usrp_source_0.set_center_freq(receiveFrequency, 0) self.uhd_usrp_source_0.set_gain(30, 0) self.gr_complex_to_float_0 = gr.complex_to_float(1) ################################################## # Connections ################################################## self.connect((self.uhd_usrp_source_0, 0), (self.wxgui_scopesink2_0, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.gr_complex_to_float_0, 0)) self.connect((self.gr_complex_to_float_0, 0), (self.gr_probe_signal_f_0, 0)) self.connect((self.gr_complex_to_float_0, 1), (self.gr_probe_signal_f_1, 0))
def __init__( self, parent, title='', sample_rate=1, size=scope_window.DEFAULT_WIN_SIZE, v_scale=0, t_scale=0, v_offset=0, xy_mode=False, ac_couple=False, num_inputs=1, trig_mode=scope_window.DEFAULT_TRIG_MODE, y_axis_label='Counts', frame_rate=scope_window.DEFAULT_FRAME_RATE, use_persistence=False, persist_alpha=None, **kwargs #do not end with a comma ): #ensure analog alpha if persist_alpha is None: actual_frame_rate = float(frame_rate) analog_cutoff_freq = 0.5 # Hertz #calculate alpha from wanted cutoff freq persist_alpha = 1.0 - math.exp( -2.0 * math.pi * analog_cutoff_freq / actual_frame_rate) if not t_scale: t_scale = 10.0 / sample_rate #init gr.hier_block2.__init__( self, "scope_sink", gr.io_signature(num_inputs, num_inputs, self._item_size), gr.io_signature(0, 0, 0), ) #scope msgq = gr.msg_queue(2) scope = gr.oscope_sink_f(sample_rate, msgq) #controller self.controller = pubsub() self.controller.subscribe(SAMPLE_RATE_KEY, scope.set_sample_rate) self.controller.publish(SAMPLE_RATE_KEY, scope.sample_rate) self.controller.subscribe(DECIMATION_KEY, scope.set_decimation_count) self.controller.publish(DECIMATION_KEY, scope.get_decimation_count) self.controller.subscribe(TRIGGER_LEVEL_KEY, scope.set_trigger_level) self.controller.publish(TRIGGER_LEVEL_KEY, scope.get_trigger_level) self.controller.subscribe(TRIGGER_MODE_KEY, scope.set_trigger_mode) self.controller.publish(TRIGGER_MODE_KEY, scope.get_trigger_mode) self.controller.subscribe(TRIGGER_SLOPE_KEY, scope.set_trigger_slope) self.controller.publish(TRIGGER_SLOPE_KEY, scope.get_trigger_slope) self.controller.subscribe(TRIGGER_CHANNEL_KEY, scope.set_trigger_channel) self.controller.publish(TRIGGER_CHANNEL_KEY, scope.get_trigger_channel) actual_num_inputs = self._real and num_inputs or num_inputs * 2 #init ac couple for i in range(actual_num_inputs): self.controller[common.index_key(AC_COUPLE_KEY, i)] = ac_couple #start input watcher common.input_watcher(msgq, self.controller, MSG_KEY) #create window self.win = scope_window.scope_window( parent=parent, controller=self.controller, size=size, title=title, frame_rate=frame_rate, num_inputs=actual_num_inputs, sample_rate_key=SAMPLE_RATE_KEY, t_scale=t_scale, v_scale=v_scale, v_offset=v_offset, xy_mode=xy_mode, trig_mode=trig_mode, y_axis_label=y_axis_label, ac_couple_key=AC_COUPLE_KEY, trigger_level_key=TRIGGER_LEVEL_KEY, trigger_mode_key=TRIGGER_MODE_KEY, trigger_slope_key=TRIGGER_SLOPE_KEY, trigger_channel_key=TRIGGER_CHANNEL_KEY, decimation_key=DECIMATION_KEY, msg_key=MSG_KEY, use_persistence=use_persistence, persist_alpha=persist_alpha, ) common.register_access_methods(self, self.win) #connect if self._real: for i in range(num_inputs): self.wxgui_connect( (self, i), ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, i), SAMPLE_RATE_KEY), (scope, i), ) else: for i in range(num_inputs): c2f = gr.complex_to_float() self.wxgui_connect((self, i), c2f) for j in range(2): self.connect( (c2f, j), ac_couple_block( self.controller, common.index_key(AC_COUPLE_KEY, 2 * i + j), SAMPLE_RATE_KEY), (scope, 2 * i + j), )
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-1", "--one-channel", action="store_true", default=False, help="software synthesized Q channel") parser.add_option("-a", "--agc", action="store_true", default=False, help="automatic gain control (overrides --gain)") parser.add_option("-c", "--calibration", type="eng_float", default=0, help="freq offset") parser.add_option("-d", "--debug", action="store_true", default=False, help="allow time at init to attach gdb") parser.add_option("-C", "--costas-alpha", type="eng_float", default=0.125, help="Costas alpha") parser.add_option("-g", "--gain", type="eng_float", default=1.0) parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") parser.add_option("-I", "--imbe", action="store_true", default=False, help="output IMBE codewords") parser.add_option("-L", "--low-pass", type="eng_float", default=6.5e3, help="low pass cut-off", metavar="Hz") parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") parser.add_option("-p", "--polarity", action="store_true", default=False, help="use reversed polarity") parser.add_option("-r", "--raw-symbols", type="string", default=None, help="dump decoded symbols to file") parser.add_option("-s", "--sample-rate", type="int", default=96000, help="input sample rate") parser.add_option("-t", "--tone-detect", action="store_true", default=False, help="use experimental tone detect algorithm") parser.add_option("-v", "--verbose", action="store_true", default=False, help="additional output") parser.add_option("-6", "--k6k", action="store_true", default=False, help="use 6K symbol rate") (options, args) = parser.parse_args() sample_rate = options.sample_rate if options.k6k: symbol_rate = 6000 else: symbol_rate = 4800 samples_per_symbol = sample_rate // symbol_rate IN = gr.file_source(gr.sizeof_gr_complex, options.input_file) if options.one_channel: C2F = gr.complex_to_float() F2C = gr.float_to_complex() # osc./mixer for mixing signal down to approx. zero IF LO = gr.sig_source_c(sample_rate, gr.GR_COS_WAVE, options.calibration, 1.0, 0) MIXER = gr.multiply_cc() # get signal into normalized range (-1.0 - +1.0) if options.agc: AMP = gr.feedforward_agc_cc(16, 1.0) else: AMP = gr.multiply_const_cc(options.gain) lpf_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) decim_amt = 1 if options.tone_detect: if sample_rate != 96000: print "warning, only 96K has been tested." print "other rates may require theta to be reviewed/adjusted." step_size = 7.5e-8 theta = -4 # optimum timing sampling point cic_length = 48 DEMOD = repeater.tdetect_cc(samples_per_symbol, step_size, theta, cic_length) else: # decim by 2 to get 48k rate samples_per_symbol /= 2 # for DECIM sample_rate /= 2 # for DECIM decim_amt = 2 # create Gardner/Costas loop # the loop will not work if the sample levels aren't normalized (above) timing_error_gain = 0.025 # loop error gain gain_omega = 0.25 * timing_error_gain * timing_error_gain alpha = options.costas_alpha beta = 0.125 * alpha * alpha fmin = -0.025 # fmin and fmax are in radians/s fmax = 0.025 DEMOD = repeater.gardner_costas_cc(samples_per_symbol, timing_error_gain, gain_omega, alpha, beta, fmax, fmin) DECIM = gr.fir_filter_ccf(decim_amt, lpf_taps) # probably too much phase noise etc to attempt coherent demodulation # so we use differential DIFF = gr.diff_phasor_cc() # take angle of the phase difference (in radians) TOFLOAT = gr.complex_to_arg() # convert from radians such that signal is in [-3, -1, +1, +3] RESCALE = gr.multiply_const_ff(1 / (pi / 4.0)) # optional polarity reversal (should be unnec. - now autodetected) p = 1.0 if options.polarity: p = -1.0 POLARITY = gr.multiply_const_ff(p) # hard decision at specified points levels = [-2.0, 0.0, 2.0, 4.0] SLICER = repeater.fsk4_slicer_fb(levels) # assemble received frames and route to Wireshark via UDP hostname = "127.0.0.1" port = 23456 debug = 0 if options.verbose: debug = 255 do_imbe = False if options.imbe: do_imbe = True do_output = True # enable block's output stream do_msgq = False # msgq output not yet implemented msgq = gr.msg_queue(2) DECODER = repeater.p25_frame_assembler(hostname, port, debug, do_imbe, do_output, do_msgq, msgq) OUT = gr.file_sink(gr.sizeof_char, options.output_file) if options.one_channel: self.connect(IN, C2F, F2C, (MIXER, 0)) else: self.connect(IN, (MIXER, 0)) self.connect(LO, (MIXER, 1)) self.connect(MIXER, AMP, DECIM, DEMOD, DIFF, TOFLOAT, RESCALE, POLARITY, SLICER, DECODER, OUT) if options.raw_symbols: SINKC = gr.file_sink(gr.sizeof_char, options.raw_symbols) self.connect(SLICER, SINKC) if options.debug: print 'Ready for GDB to attach (pid = %d)' % (os.getpid(), ) raw_input("Press 'Enter' to continue...")
def graph(args): nargs = len(args) if nargs == 2: infile = args[0] outfile = args[1] else: raise ValueError('usage: interp.py input_file output_file\n') tb = gr.top_block() # Convert to a from shorts to a stream of complex numbers. srcf = gr.file_source(gr.sizeof_short, infile) s2ss = gr.stream_to_streams(gr.sizeof_short, 2) s2f1 = gr.short_to_float() s2f2 = gr.short_to_float() src0 = gr.float_to_complex() tb.connect(srcf, s2ss) tb.connect((s2ss, 0), s2f1, (src0, 0)) tb.connect((s2ss, 1), s2f2, (src0, 1)) # Low pass filter it and increase sample rate by a factor of 3. lp_coeffs = gr.firdes.low_pass(3, 19.2e6, 3.2e6, .5e6, gr.firdes.WIN_HAMMING) lp = gr.interp_fir_filter_ccf(3, lp_coeffs) tb.connect(src0, lp) # Upconvert it. duc_coeffs = gr.firdes.low_pass(1, 19.2e6, 9e6, 1e6, gr.firdes.WIN_HAMMING) duc = gr.freq_xlating_fir_filter_ccf(1, duc_coeffs, 5.75e6, 19.2e6) # Discard the imaginary component. c2f = gr.complex_to_float() tb.connect(lp, duc, c2f) # Frequency Phase Lock Loop input_rate = 19.2e6 IF_freq = 5.75e6 # 1/2 as wide because we're designing lp filter symbol_rate = atsc.ATSC_SYMBOL_RATE / 2. NTAPS = 279 tt = gr.firdes.root_raised_cosine(1.0, input_rate, symbol_rate, .115, NTAPS) # heterodyne the low pass coefficients up to the specified bandpass # center frequency. Note that when we do this, the filter bandwidth # is effectively twice the low pass (2.69 * 2 = 5.38) and hence # matches the diagram in the ATSC spec. arg = 2. * math.pi * IF_freq / input_rate t = [] for i in range(len(tt)): t += [tt[i] * 2. * math.cos(arg * i)] rrc = gr.fir_filter_fff(1, t) fpll = atsc.fpll() pilot_freq = IF_freq - 3e6 + 0.31e6 lower_edge = 6e6 - 0.31e6 upper_edge = IF_freq - 3e6 + pilot_freq transition_width = upper_edge - lower_edge lp_coeffs = gr.firdes.low_pass(1.0, input_rate, (lower_edge + upper_edge) * 0.5, transition_width, gr.firdes.WIN_HAMMING) lp_filter = gr.fir_filter_fff(1, lp_coeffs) alpha = 1e-5 iir = gr.single_pole_iir_filter_ff(alpha) remove_dc = gr.sub_ff() tb.connect(c2f, fpll, lp_filter) tb.connect(lp_filter, iir) tb.connect(lp_filter, (remove_dc, 0)) tb.connect(iir, (remove_dc, 1)) # Bit Timing Loop, Field Sync Checker and Equalizer btl = atsc.bit_timing_loop() fsc = atsc.fs_checker() eq = atsc.equalizer() fsd = atsc.field_sync_demux() tb.connect(remove_dc, btl) tb.connect((btl, 0), (fsc, 0), (eq, 0), (fsd, 0)) tb.connect((btl, 1), (fsc, 1), (eq, 1), (fsd, 1)) # Viterbi viterbi = atsc.viterbi_decoder() deinter = atsc.deinterleaver() rs_dec = atsc.rs_decoder() derand = atsc.derandomizer() depad = atsc.depad() dst = gr.file_sink(gr.sizeof_char, outfile) tb.connect(fsd, viterbi, deinter, rs_dec, derand, depad, dst) dst2 = gr.file_sink(gr.sizeof_gr_complex, "atsc_complex.data") tb.connect(src0, dst2) tb.run()
def complex_to_float(N): op = gr.complex_to_float() tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 2) return tb
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel parser = OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), help="select USRP Rx side A or B (default=A)") parser.add_option("-d", "--decim", type="int", default=16, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=None, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-Q", "--observing", type="eng_float", default=0.0, help="set observing frequency to FREQ") parser.add_option("-a", "--avg", type="eng_float", default=1.0, help="set spectral averaging alpha") parser.add_option("-V", "--favg", type="eng_float", default=2.0, help="set folder averaging alpha") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is midpoint)") parser.add_option("-l", "--reflevel", type="eng_float", default=30.0, help="Set pulse display reference level") parser.add_option("-L", "--lowest", type="eng_float", default=1.5, help="Lowest valid frequency bin") parser.add_option("-e", "--longitude", type="eng_float", default=-76.02, help="Set Observer Longitude") parser.add_option("-c", "--latitude", type="eng_float", default=44.85, help="Set Observer Latitude") parser.add_option("-F", "--fft_size", type="eng_float", default=1024, help="Size of FFT") parser.add_option ("-t", "--threshold", type="eng_float", default=2.5, help="pulsar threshold") parser.add_option("-p", "--lowpass", type="eng_float", default=100, help="Pulse spectra cutoff freq") parser.add_option("-P", "--prefix", default="./", help="File prefix") parser.add_option("-u", "--pulsefreq", type="eng_float", default=0.748, help="Observation pulse rate") parser.add_option("-D", "--dm", type="eng_float", default=1.0e-5, help="Dispersion Measure") parser.add_option("-O", "--doppler", type="eng_float", default=1.0, help="Doppler ratio") parser.add_option("-B", "--divbase", type="eng_float", default=20, help="Y/Div menu base") parser.add_option("-I", "--division", type="eng_float", default=100, help="Y/Div") parser.add_option("-A", "--audio_source", default="plughw:0,0", help="Audio input device spec") parser.add_option("-N", "--num_pulses", default=1, type="eng_float", help="Number of display pulses") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.show_debug_info = True self.reflevel = options.reflevel self.divbase = options.divbase self.division = options.division self.audiodev = options.audio_source self.mult = int(options.num_pulses) # Low-pass cutoff for post-detector filter # Set to 100Hz usually, since lots of pulsars fit in this # range self.lowpass = options.lowpass # What is lowest valid frequency bin in post-detector FFT? # There's some pollution very close to DC self.lowest_freq = options.lowest # What (dB) threshold to use in determining spectral candidates self.threshold = options.threshold # Filename prefix for recording file self.prefix = options.prefix # Dispersion Measure (DM) self.dm = options.dm # Doppler shift, as a ratio # 1.0 == no doppler shift # 1.005 == a little negative shift # 0.995 == a little positive shift self.doppler = options.doppler # # Input frequency and observing frequency--not necessarily the # same thing, if we're looking at the IF of some downconverter # that's ahead of the USRP and daughtercard. This distinction # is important in computing the correct de-dispersion filter. # self.frequency = options.freq if options.observing <= 0: self.observing_freq = options.freq else: self.observing_freq = options.observing # build the graph self.u = usrp.source_c(decim_rate=options.decim) self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) # # Recording file, in case we ever need to record baseband data # self.recording = gr.file_sink(gr.sizeof_char, "/dev/null") self.recording_state = False self.pulse_recording = gr.file_sink(gr.sizeof_short, "/dev/null") self.pulse_recording_state = False # # We come up with recording turned off, but the user may # request recording later on self.recording.close() self.pulse_recording.close() # # Need these two for converting 12-bit baseband signals to 8-bit # self.tofloat = gr.complex_to_float() self.tochar = gr.float_to_char() # Need this for recording pulses (post-detector) self.toshort = gr.float_to_short() # # The spectral measurer sets this when it has a valid # average spectral peak-to-peak distance # We can then use this to program the parameters for the epoch folder # # We set a sentimental value here self.pulse_freq = options.pulsefreq # Folder runs at this raw sample rate self.folder_input_rate = 20000 # Each pulse in the epoch folder is sampled at 128 times the nominal # pulse rate self.folding = 128 # # Try to find candidate parameters for rational resampler # save_i = 0 candidates = [] for i in range(20,300): input_rate = self.folder_input_rate output_rate = int(self.pulse_freq * i) interp = gru.lcm(input_rate, output_rate) / input_rate decim = gru.lcm(input_rate, output_rate) / output_rate if (interp < 500 and decim < 250000): candidates.append(i) # We didn't find anything, bail! if (len(candidates) < 1): print "Couldn't converge on resampler parameters" sys.exit(1) # # Now try to find candidate with the least sampling error # mindiff = 999.999 for i in candidates: diff = self.pulse_freq * i diff = diff - int(diff) if (diff < mindiff): mindiff = diff save_i = i # Recompute rates input_rate = self.folder_input_rate output_rate = int(self.pulse_freq * save_i) # Compute new interp and decim, based on best candidate interp = gru.lcm(input_rate, output_rate) / input_rate decim = gru.lcm(input_rate, output_rate) / output_rate # Save optimized folding parameters, used later self.folding = save_i self.interp = int(interp) self.decim = int(decim) # So that we can view N pulses in the pulse viewer window FOLD_MULT=self.mult # determine the daughterboard subdevice we're using self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) self.cardtype = self.u.daughterboard_id(0) # Compute raw input rate input_rate = self.u.adc_freq() / self.u.decim_rate() # BW==input_rate for complex data self.bw = input_rate # # Set baseband filter bandwidth if DBS_RX: # if self.cardtype == usrp_dbid.DBS_RX: lbw = input_rate / 2 if lbw < 1.0e6: lbw = 1.0e6 self.subdev.set_bw(lbw) # # We use this as a crude volume control for the audio output # #self.volume = gr.multiply_const_ff(10**(-1)) # # Create location data for ephem package # self.locality = ephem.Observer() self.locality.long = str(options.longitude) self.locality.lat = str(options.latitude) # # What is the post-detector LPF cutoff for the FFT? # PULSAR_MAX_FREQ=int(options.lowpass) # First low-pass filters down to input_rate/FIRST_FACTOR # and decimates appropriately FIRST_FACTOR=int(input_rate/(self.folder_input_rate/2)) first_filter = gr.firdes.low_pass (1.0, input_rate, input_rate/FIRST_FACTOR, input_rate/(FIRST_FACTOR*20), gr.firdes.WIN_HAMMING) # Second filter runs at the output rate of the first filter, # And low-pass filters down to PULSAR_MAX_FREQ*10 # second_input_rate = int(input_rate/(FIRST_FACTOR/2)) second_filter = gr.firdes.band_pass(1.0, second_input_rate, 0.10, PULSAR_MAX_FREQ*10, PULSAR_MAX_FREQ*1.5, gr.firdes.WIN_HAMMING) # Third filter runs at PULSAR_MAX_FREQ*20 # and filters down to PULSAR_MAX_FREQ # third_input_rate = PULSAR_MAX_FREQ*20 third_filter = gr.firdes_band_pass(1.0, third_input_rate, 0.10, PULSAR_MAX_FREQ, PULSAR_MAX_FREQ/10.0, gr.firdes.WIN_HAMMING) # # Create the appropriate FFT scope # self.scope = ra_fftsink.ra_fft_sink_f (panel, fft_size=int(options.fft_size), sample_rate=PULSAR_MAX_FREQ*2, title="Post-detector spectrum", ofunc=self.pulsarfunc, xydfunc=self.xydfunc, fft_rate=200) # # Tell scope we're looking from DC to PULSAR_MAX_FREQ # self.scope.set_baseband_freq (0.0) # # Setup stripchart for showing pulse profiles # hz = "%5.3fHz " % self.pulse_freq per = "(%5.3f sec)" % (1.0/self.pulse_freq) sr = "%d sps" % (int(self.pulse_freq*self.folding)) times = " %d Pulse Intervals" % self.mult self.chart = ra_stripchartsink.stripchart_sink_f (panel, sample_rate=1, stripsize=self.folding*FOLD_MULT, parallel=True, title="Pulse Profiles: "+hz+per+times, xlabel="Seconds @ "+sr, ylabel="Level", autoscale=True, divbase=self.divbase, scaling=1.0/(self.folding*self.pulse_freq)) self.chart.set_ref_level(self.reflevel) self.chart.set_y_per_div(self.division) # De-dispersion filter setup # # Do this here, just before creating the filter # that will use the taps. # ntaps = self.compute_disp_ntaps(self.dm,self.bw,self.observing_freq) # Taps for the de-dispersion filter self.disp_taps = Numeric.zeros(ntaps,Numeric.Complex64) # Compute the de-dispersion filter now self.compute_dispfilter(self.dm,self.doppler, self.bw,self.observing_freq) # # Call constructors for receive chains # # # Now create the FFT filter using the computed taps self.dispfilt = gr.fft_filter_ccc(1, self.disp_taps) # # Audio sink # #print "input_rate ", second_input_rate, "audiodev ", self.audiodev #self.audio = audio.sink(second_input_rate, self.audiodev) # # The three post-detector filters # Done this way to allow an audio path (up to 10Khz) # ...and also because going from xMhz down to ~100Hz # In a single filter doesn't seem to work. # self.first = gr.fir_filter_fff (FIRST_FACTOR/2, first_filter) p = second_input_rate / (PULSAR_MAX_FREQ*20) self.second = gr.fir_filter_fff (int(p), second_filter) self.third = gr.fir_filter_fff (10, third_filter) # Detector self.detector = gr.complex_to_mag_squared() self.enable_comb_filter = False # Epoch folder comb filter if self.enable_comb_filter == True: bogtaps = Numeric.zeros(512, Numeric.Float64) self.folder_comb = gr.fft_filter_ccc(1,bogtaps) # Rational resampler self.folder_rr = blks2.rational_resampler_fff(self.interp, self.decim) # Epoch folder bandpass bogtaps = Numeric.zeros(1, Numeric.Float64) self.folder_bandpass = gr.fir_filter_fff (1, bogtaps) # Epoch folder F2C/C2F self.folder_f2c = gr.float_to_complex() self.folder_c2f = gr.complex_to_float() # Epoch folder S2P self.folder_s2p = gr.serial_to_parallel (gr.sizeof_float, self.folding*FOLD_MULT) # Epoch folder IIR Filter (produces average pulse profiles) self.folder_iir = gr.single_pole_iir_filter_ff(1.0/options.favg, self.folding*FOLD_MULT) # # Set all the epoch-folder goop up # self.set_folding_params() # # Start connecting configured modules in the receive chain # # Connect raw USRP to de-dispersion filter, detector self.connect(self.u, self.dispfilt, self.detector) # Connect detector output to FIR LPF # in two stages, followed by the FFT scope self.connect(self.detector, self.first, self.second, self.third, self.scope) # Connect audio output #self.connect(self.first, self.volume) #self.connect(self.volume, (self.audio, 0)) #self.connect(self.volume, (self.audio, 1)) # Connect epoch folder if self.enable_comb_filter == True: self.connect (self.first, self.folder_bandpass, self.folder_rr, self.folder_f2c, self.folder_comb, self.folder_c2f, self.folder_s2p, self.folder_iir, self.chart) else: self.connect (self.first, self.folder_bandpass, self.folder_rr, self.folder_s2p, self.folder_iir, self.chart) # Connect baseband recording file (initially /dev/null) self.connect(self.u, self.tofloat, self.tochar, self.recording) # Connect pulse recording file (initially /dev/null) self.connect(self.first, self.toshort, self.pulse_recording) # # Build the GUI elements # self._build_gui(vbox) # Make GUI agree with command-line self.myform['average'].set_value(int(options.avg)) self.myform['foldavg'].set_value(int(options.favg)) # Make spectral averager agree with command line if options.avg != 1.0: self.scope.set_avg_alpha(float(1.0/options.avg)) self.scope.set_average(True) # set initial values if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0]+g[1])/2 if options.freq is None: # if no freq was specified, use the mid-point r = self.subdev.freq_range() options.freq = float(r[0]+r[1])/2 self.set_gain(options.gain) #self.set_volume(-10.0) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") self.myform['decim'].set_value(self.u.decim_rate()) self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) self.myform['dbname'].set_value(self.subdev.name()) self.myform['DM'].set_value(self.dm) self.myform['Doppler'].set_value(self.doppler) # # Start the timer that shows current LMST on the GUI # self.lmst_timer.Start(1000)
def graph (args): nargs = len(args) if nargs == 2: infile = args[0] outfile = args[1] else: raise ValueError('usage: interp.py input_file output_file\n') tb = gr.top_block () # Convert to a from shorts to a stream of complex numbers. srcf = gr.file_source (gr.sizeof_short,infile) s2ss = gr.stream_to_streams(gr.sizeof_short,2) s2f1 = gr.short_to_float() s2f2 = gr.short_to_float() src0 = gr.float_to_complex() tb.connect(srcf, s2ss) tb.connect((s2ss, 0), s2f1, (src0, 0)) tb.connect((s2ss, 1), s2f2, (src0, 1)) # Low pass filter it and increase sample rate by a factor of 3. lp_coeffs = gr.firdes.low_pass ( 3, 19.2e6, 3.2e6, .5e6, gr.firdes.WIN_HAMMING ) lp = gr.interp_fir_filter_ccf ( 3, lp_coeffs ) tb.connect(src0, lp) # Upconvert it. duc_coeffs = gr.firdes.low_pass ( 1, 19.2e6, 9e6, 1e6, gr.firdes.WIN_HAMMING ) duc = gr.freq_xlating_fir_filter_ccf ( 1, duc_coeffs, 5.75e6, 19.2e6 ) # Discard the imaginary component. c2f = gr.complex_to_float() tb.connect(lp, duc, c2f) # Frequency Phase Lock Loop input_rate = 19.2e6 IF_freq = 5.75e6 # 1/2 as wide because we're designing lp filter symbol_rate = atsc.ATSC_SYMBOL_RATE/2. NTAPS = 279 tt = gr.firdes.root_raised_cosine (1.0, input_rate, symbol_rate, .115, NTAPS) # heterodyne the low pass coefficients up to the specified bandpass # center frequency. Note that when we do this, the filter bandwidth # is effectively twice the low pass (2.69 * 2 = 5.38) and hence # matches the diagram in the ATSC spec. arg = 2. * math.pi * IF_freq / input_rate t=[] for i in range(len(tt)): t += [tt[i] * 2. * math.cos(arg * i)] rrc = gr.fir_filter_fff(1, t) fpll = atsc.fpll() pilot_freq = IF_freq - 3e6 + 0.31e6 lower_edge = 6e6 - 0.31e6 upper_edge = IF_freq - 3e6 + pilot_freq transition_width = upper_edge - lower_edge lp_coeffs = gr.firdes.low_pass (1.0, input_rate, (lower_edge + upper_edge) * 0.5, transition_width, gr.firdes.WIN_HAMMING); lp_filter = gr.fir_filter_fff (1,lp_coeffs) alpha = 1e-5 iir = gr.single_pole_iir_filter_ff(alpha) remove_dc = gr.sub_ff() tb.connect(c2f, fpll, lp_filter) tb.connect(lp_filter, iir) tb.connect(lp_filter, (remove_dc,0)) tb.connect(iir, (remove_dc,1)) # Bit Timing Loop, Field Sync Checker and Equalizer btl = atsc.bit_timing_loop() fsc = atsc.fs_checker() eq = atsc.equalizer() fsd = atsc.field_sync_demux() tb.connect(remove_dc, btl) tb.connect((btl, 0),(fsc, 0),(eq, 0),(fsd, 0)) tb.connect((btl, 1),(fsc, 1),(eq, 1),(fsd, 1)) # Viterbi viterbi = atsc.viterbi_decoder() deinter = atsc.deinterleaver() rs_dec = atsc.rs_decoder() derand = atsc.derandomizer() depad = atsc.depad() dst = gr.file_sink(gr.sizeof_char, outfile) tb.connect(fsd, viterbi, deinter, rs_dec, derand, depad, dst) dst2 = gr.file_sink(gr.sizeof_gr_complex, "atsc_complex.data") tb.connect(src0, dst2) tb.run ()
import mediatools; sys.path.append("."); # Construct playlist pl = mediatools.strvec(["1.mp3","2.ogg"]); # Setup sample rates dac_sample_rate = 44100; file_sample_rate = 44100; default_device = ""; # Instantiate blocks tb = gr.top_block(); src = mediatools.audiosource_s(pl); s2c = gr.interleaved_short_to_complex(); c2f = gr.complex_to_float(); mc = gr.multiply_const_cc(1.0/(32768.0)); # scale to the +1 / -1 range sink = audio.sink(dac_sample_rate,default_device); # Connect up flowgraph tb.connect(src,s2c,mc,c2f); # connect src->scalar->float conversion tb.connect(c2f,sink); # connect left channel tb.connect((c2f,1),(sink,1)); # connect right channel # And go tb.run();
def __init__( self, parent, title='', sample_rate=1, size=scope_window.DEFAULT_WIN_SIZE, v_scale=0, t_scale=0, xy_mode=False, ac_couple=False, num_inputs=1, frame_rate=scope_window.DEFAULT_FRAME_RATE, **kwargs #do not end with a comma ): if not t_scale: t_scale = 10.0/sample_rate #init gr.hier_block2.__init__( self, "scope_sink", gr.io_signature(num_inputs, num_inputs, self._item_size), gr.io_signature(0, 0, 0), ) #scope msgq = gr.msg_queue(2) scope = gr.oscope_sink_f(sample_rate, msgq) #controller self.controller = pubsub() self.controller.subscribe(SAMPLE_RATE_KEY, scope.set_sample_rate) self.controller.publish(SAMPLE_RATE_KEY, scope.sample_rate) self.controller.subscribe(DECIMATION_KEY, scope.set_decimation_count) self.controller.publish(DECIMATION_KEY, scope.get_decimation_count) self.controller.subscribe(TRIGGER_LEVEL_KEY, scope.set_trigger_level) self.controller.publish(TRIGGER_LEVEL_KEY, scope.get_trigger_level) self.controller.subscribe(TRIGGER_MODE_KEY, scope.set_trigger_mode) self.controller.publish(TRIGGER_MODE_KEY, scope.get_trigger_mode) self.controller.subscribe(TRIGGER_SLOPE_KEY, scope.set_trigger_slope) self.controller.publish(TRIGGER_SLOPE_KEY, scope.get_trigger_slope) self.controller.subscribe(TRIGGER_CHANNEL_KEY, scope.set_trigger_channel) self.controller.publish(TRIGGER_CHANNEL_KEY, scope.get_trigger_channel) #connect if self._real: for i in range(num_inputs): self.connect( (self, i), ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, i), ac_couple, SAMPLE_RATE_KEY), (scope, i), ) else: for i in range(num_inputs): c2f = gr.complex_to_float() self.connect((self, i), c2f) for j in range(2): self.connect( (c2f, j), ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, 2*i+j), ac_couple, SAMPLE_RATE_KEY), (scope, 2*i+j), ) num_inputs *= 2 #start input watcher common.input_watcher(msgq, self.controller, MSG_KEY) #create window self.win = scope_window.scope_window( parent=parent, controller=self.controller, size=size, title=title, frame_rate=frame_rate, num_inputs=num_inputs, sample_rate_key=SAMPLE_RATE_KEY, t_scale=t_scale, v_scale=v_scale, xy_mode=xy_mode, ac_couple_key=AC_COUPLE_KEY, trigger_level_key=TRIGGER_LEVEL_KEY, trigger_mode_key=TRIGGER_MODE_KEY, trigger_slope_key=TRIGGER_SLOPE_KEY, trigger_channel_key=TRIGGER_CHANNEL_KEY, decimation_key=DECIMATION_KEY, msg_key=MSG_KEY, ) common.register_access_methods(self, self.win)
def __init__(self): gr.top_block.__init__(self, "writeToFile") Qt.QWidget.__init__(self) self.setWindowTitle("writeToFile") self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) 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.bufferRE = collections.deque(400*[0], 400) # init buffer of 400 entries, max length 400 self.bufferIM = collections.deque(400*[0], 400) # init buffer of 400 entries, max length 400 ################################################## # Variables ################################################## self.variable_function_probe_1 = variable_function_probe_1 = 0 self.variable_function_probe_0 = variable_function_probe_0 = 0 self.samp_rate = samp_rate = 320000 self.receiveFrequency = receiveFrequency = 900000000 ################################################## # Blocks ################################################## self.gr_probe_signal_f_1 = gr.probe_signal_f() self.gr_probe_signal_f_0 = gr.probe_signal_f() def _variable_function_probe_1_probe(): while True: val = self.gr_probe_signal_f_1.level() try: self.set_variable_function_probe_1(val) except AttributeError, e: pass time.sleep(1.0/(100)) # Sample rate 100 Hz # starts the thread that samples the signal continuously _variable_function_probe_1_thread = threading.Thread(target=_variable_function_probe_1_probe) _variable_function_probe_1_thread.daemon = True _variable_function_probe_1_thread.start() def _variable_function_probe_0_probe(): while True: val = self.gr_probe_signal_f_0.level() try: self.set_variable_function_probe_0(val) except AttributeError, e: pass time.sleep(1.0/(100)) # Sample rate 100 Hz # starts the thread that samples the signal continuously _variable_function_probe_0_thread = threading.Thread(target=_variable_function_probe_0_probe) _variable_function_probe_0_thread.daemon = True _variable_function_probe_0_thread.start() ### TODO: Write values read from the channel continuously into a buffer ### TODO: read out the buffer continuously in another thread for classification ### TODO: output the classification def _variable_classification(): # myFile = open("classification.tab", "a") # myFile.write('mean\tmedian\tvar\tTCM\tRMS\tmax\tmin\tdiff\tcountmax10%\tdirectionchange\tzeroCross\tDirChanzeroCross\tavgzerocross\tstddeviation\tlocation-coordinator\n') # #myFile.write('mean\tmedian\tvar\tTCM\tRMS\tmax\tmin\tdiff\tcountmax10%\tdirectionchange\tEntropy\tSpecenergy\tzeroCross\tDirChanzeroCross\tavgzerocross\tavgFFT\tstddeviation\tlocation-coordinator\n') # Write a feature string to a tab file #18 features # myFile.write('c\tc\tc\tc\tc\tc\tc\tc\tc\tc\tc\tc\tc\tc\td\n') #18 # myFile.write('\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass\n') # myFile.close() while True: # TODO: do classification here classification = self.get_classification() # TODO: Write out classification time.sleep(1.0/(2)) # One classification every 0.5 seconds # starts the thread that samples the signal continuously _variable_classification_thread = threading.Thread(target=_variable_classification) _variable_classification_thread.daemon = True _variable_classification_thread.start() def _variable_featureVisualisation(*args): while True: for data in args: plot(data) show() time.sleep(1.0/(2)) _variable_featureVisualisation_thread = threading.Thread(target=_variable_featureVisualisation) _variable_featureVisualisation_thread.daemon = True _variable_featureVisualisation_thread.start() #p = Process(target=plot_graph, args=([1, 2, 3],)) #p.start() self.uhd_usrp_source_0 = uhd.usrp_source( device_addr="", stream_args=uhd.stream_args( cpu_format="fc32", channels=range(1), ), ) self.uhd_usrp_source_0.set_samp_rate(samp_rate) self.uhd_usrp_source_0.set_center_freq(receiveFrequency, 0) self.uhd_usrp_source_0.set_gain(20, 0) self.qtgui_sink_x_0 = qtgui.sink_c( 1024, #fftsize firdes.WIN_BLACKMAN_hARRIS, #wintype 0, #fc samp_rate, #bw "QT GUI Plot", #name True, #plotfreq True, #plotwaterfall True, #plottime True, #plotconst ) self.qtgui_sink_x_0.set_update_time(1.0 / 10) self._qtgui_sink_x_0_win = sip.wrapinstance(self.qtgui_sink_x_0.pyqwidget(), Qt.QWidget) self.top_layout.addWidget(self._qtgui_sink_x_0_win) self.gr_complex_to_float_0 = gr.complex_to_float(1) ################################################## # Connections ################################################## self.connect((self.uhd_usrp_source_0, 0), (self.gr_complex_to_float_0, 0)) self.connect((self.gr_complex_to_float_0, 0), (self.gr_probe_signal_f_0, 0)) self.connect((self.gr_complex_to_float_0, 1), (self.gr_probe_signal_f_1, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.qtgui_sink_x_0, 0))
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel parser = OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), help="select USRP Rx side A or B (default=A)") parser.add_option( "-d", "--decim", type="int", default=16, help="set fgpa decimation rate to DECIM [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=None, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-Q", "--observing", type="eng_float", default=0.0, help="set observing frequency to FREQ") parser.add_option("-a", "--avg", type="eng_float", default=1.0, help="set spectral averaging alpha") parser.add_option("-V", "--favg", type="eng_float", default=2.0, help="set folder averaging alpha") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is midpoint)") parser.add_option("-l", "--reflevel", type="eng_float", default=30.0, help="Set pulse display reference level") parser.add_option("-L", "--lowest", type="eng_float", default=1.5, help="Lowest valid frequency bin") parser.add_option("-e", "--longitude", type="eng_float", default=-76.02, help="Set Observer Longitude") parser.add_option("-c", "--latitude", type="eng_float", default=44.85, help="Set Observer Latitude") parser.add_option("-F", "--fft_size", type="eng_float", default=1024, help="Size of FFT") parser.add_option("-t", "--threshold", type="eng_float", default=2.5, help="pulsar threshold") parser.add_option("-p", "--lowpass", type="eng_float", default=100, help="Pulse spectra cutoff freq") parser.add_option("-P", "--prefix", default="./", help="File prefix") parser.add_option("-u", "--pulsefreq", type="eng_float", default=0.748, help="Observation pulse rate") parser.add_option("-D", "--dm", type="eng_float", default=1.0e-5, help="Dispersion Measure") parser.add_option("-O", "--doppler", type="eng_float", default=1.0, help="Doppler ratio") parser.add_option("-B", "--divbase", type="eng_float", default=20, help="Y/Div menu base") parser.add_option("-I", "--division", type="eng_float", default=100, help="Y/Div") parser.add_option("-A", "--audio_source", default="plughw:0,0", help="Audio input device spec") parser.add_option("-N", "--num_pulses", default=1, type="eng_float", help="Number of display pulses") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.show_debug_info = True self.reflevel = options.reflevel self.divbase = options.divbase self.division = options.division self.audiodev = options.audio_source self.mult = int(options.num_pulses) # Low-pass cutoff for post-detector filter # Set to 100Hz usually, since lots of pulsars fit in this # range self.lowpass = options.lowpass # What is lowest valid frequency bin in post-detector FFT? # There's some pollution very close to DC self.lowest_freq = options.lowest # What (dB) threshold to use in determining spectral candidates self.threshold = options.threshold # Filename prefix for recording file self.prefix = options.prefix # Dispersion Measure (DM) self.dm = options.dm # Doppler shift, as a ratio # 1.0 == no doppler shift # 1.005 == a little negative shift # 0.995 == a little positive shift self.doppler = options.doppler # # Input frequency and observing frequency--not necessarily the # same thing, if we're looking at the IF of some downconverter # that's ahead of the USRP and daughtercard. This distinction # is important in computing the correct de-dispersion filter. # self.frequency = options.freq if options.observing <= 0: self.observing_freq = options.freq else: self.observing_freq = options.observing # build the graph self.u = usrp.source_c(decim_rate=options.decim) self.u.set_mux( usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) # # Recording file, in case we ever need to record baseband data # self.recording = gr.file_sink(gr.sizeof_char, "/dev/null") self.recording_state = False self.pulse_recording = gr.file_sink(gr.sizeof_short, "/dev/null") self.pulse_recording_state = False # # We come up with recording turned off, but the user may # request recording later on self.recording.close() self.pulse_recording.close() # # Need these two for converting 12-bit baseband signals to 8-bit # self.tofloat = gr.complex_to_float() self.tochar = gr.float_to_char() # Need this for recording pulses (post-detector) self.toshort = gr.float_to_short() # # The spectral measurer sets this when it has a valid # average spectral peak-to-peak distance # We can then use this to program the parameters for the epoch folder # # We set a sentimental value here self.pulse_freq = options.pulsefreq # Folder runs at this raw sample rate self.folder_input_rate = 20000 # Each pulse in the epoch folder is sampled at 128 times the nominal # pulse rate self.folding = 128 # # Try to find candidate parameters for rational resampler # save_i = 0 candidates = [] for i in range(20, 300): input_rate = self.folder_input_rate output_rate = int(self.pulse_freq * i) interp = gru.lcm(input_rate, output_rate) / input_rate decim = gru.lcm(input_rate, output_rate) / output_rate if (interp < 500 and decim < 250000): candidates.append(i) # We didn't find anything, bail! if (len(candidates) < 1): print "Couldn't converge on resampler parameters" sys.exit(1) # # Now try to find candidate with the least sampling error # mindiff = 999.999 for i in candidates: diff = self.pulse_freq * i diff = diff - int(diff) if (diff < mindiff): mindiff = diff save_i = i # Recompute rates input_rate = self.folder_input_rate output_rate = int(self.pulse_freq * save_i) # Compute new interp and decim, based on best candidate interp = gru.lcm(input_rate, output_rate) / input_rate decim = gru.lcm(input_rate, output_rate) / output_rate # Save optimized folding parameters, used later self.folding = save_i self.interp = int(interp) self.decim = int(decim) # So that we can view N pulses in the pulse viewer window FOLD_MULT = self.mult # determine the daughterboard subdevice we're using self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) self.cardtype = self.u.daughterboard_id(0) # Compute raw input rate input_rate = self.u.adc_freq() / self.u.decim_rate() # BW==input_rate for complex data self.bw = input_rate # # Set baseband filter bandwidth if DBS_RX: # if self.cardtype == usrp_dbid.DBS_RX: lbw = input_rate / 2 if lbw < 1.0e6: lbw = 1.0e6 self.subdev.set_bw(lbw) # # We use this as a crude volume control for the audio output # #self.volume = gr.multiply_const_ff(10**(-1)) # # Create location data for ephem package # self.locality = ephem.Observer() self.locality.long = str(options.longitude) self.locality.lat = str(options.latitude) # # What is the post-detector LPF cutoff for the FFT? # PULSAR_MAX_FREQ = int(options.lowpass) # First low-pass filters down to input_rate/FIRST_FACTOR # and decimates appropriately FIRST_FACTOR = int(input_rate / (self.folder_input_rate / 2)) first_filter = gr.firdes.low_pass(1.0, input_rate, input_rate / FIRST_FACTOR, input_rate / (FIRST_FACTOR * 20), gr.firdes.WIN_HAMMING) # Second filter runs at the output rate of the first filter, # And low-pass filters down to PULSAR_MAX_FREQ*10 # second_input_rate = int(input_rate / (FIRST_FACTOR / 2)) second_filter = gr.firdes.band_pass(1.0, second_input_rate, 0.10, PULSAR_MAX_FREQ * 10, PULSAR_MAX_FREQ * 1.5, gr.firdes.WIN_HAMMING) # Third filter runs at PULSAR_MAX_FREQ*20 # and filters down to PULSAR_MAX_FREQ # third_input_rate = PULSAR_MAX_FREQ * 20 third_filter = gr.firdes_band_pass(1.0, third_input_rate, 0.10, PULSAR_MAX_FREQ, PULSAR_MAX_FREQ / 10.0, gr.firdes.WIN_HAMMING) # # Create the appropriate FFT scope # self.scope = ra_fftsink.ra_fft_sink_f(panel, fft_size=int(options.fft_size), sample_rate=PULSAR_MAX_FREQ * 2, title="Post-detector spectrum", ofunc=self.pulsarfunc, xydfunc=self.xydfunc, fft_rate=200) # # Tell scope we're looking from DC to PULSAR_MAX_FREQ # self.scope.set_baseband_freq(0.0) # # Setup stripchart for showing pulse profiles # hz = "%5.3fHz " % self.pulse_freq per = "(%5.3f sec)" % (1.0 / self.pulse_freq) sr = "%d sps" % (int(self.pulse_freq * self.folding)) times = " %d Pulse Intervals" % self.mult self.chart = ra_stripchartsink.stripchart_sink_f( panel, sample_rate=1, stripsize=self.folding * FOLD_MULT, parallel=True, title="Pulse Profiles: " + hz + per + times, xlabel="Seconds @ " + sr, ylabel="Level", autoscale=True, divbase=self.divbase, scaling=1.0 / (self.folding * self.pulse_freq)) self.chart.set_ref_level(self.reflevel) self.chart.set_y_per_div(self.division) # De-dispersion filter setup # # Do this here, just before creating the filter # that will use the taps. # ntaps = self.compute_disp_ntaps(self.dm, self.bw, self.observing_freq) # Taps for the de-dispersion filter self.disp_taps = Numeric.zeros(ntaps, Numeric.Complex64) # Compute the de-dispersion filter now self.compute_dispfilter(self.dm, self.doppler, self.bw, self.observing_freq) # # Call constructors for receive chains # # # Now create the FFT filter using the computed taps self.dispfilt = gr.fft_filter_ccc(1, self.disp_taps) # # Audio sink # #print "input_rate ", second_input_rate, "audiodev ", self.audiodev #self.audio = audio.sink(second_input_rate, self.audiodev) # # The three post-detector filters # Done this way to allow an audio path (up to 10Khz) # ...and also because going from xMhz down to ~100Hz # In a single filter doesn't seem to work. # self.first = gr.fir_filter_fff(FIRST_FACTOR / 2, first_filter) p = second_input_rate / (PULSAR_MAX_FREQ * 20) self.second = gr.fir_filter_fff(int(p), second_filter) self.third = gr.fir_filter_fff(10, third_filter) # Detector self.detector = gr.complex_to_mag_squared() self.enable_comb_filter = False # Epoch folder comb filter if self.enable_comb_filter == True: bogtaps = Numeric.zeros(512, Numeric.Float64) self.folder_comb = gr.fft_filter_ccc(1, bogtaps) # Rational resampler self.folder_rr = blks2.rational_resampler_fff(self.interp, self.decim) # Epoch folder bandpass bogtaps = Numeric.zeros(1, Numeric.Float64) self.folder_bandpass = gr.fir_filter_fff(1, bogtaps) # Epoch folder F2C/C2F self.folder_f2c = gr.float_to_complex() self.folder_c2f = gr.complex_to_float() # Epoch folder S2P self.folder_s2p = gr.serial_to_parallel(gr.sizeof_float, self.folding * FOLD_MULT) # Epoch folder IIR Filter (produces average pulse profiles) self.folder_iir = gr.single_pole_iir_filter_ff( 1.0 / options.favg, self.folding * FOLD_MULT) # # Set all the epoch-folder goop up # self.set_folding_params() # # Start connecting configured modules in the receive chain # # Connect raw USRP to de-dispersion filter, detector self.connect(self.u, self.dispfilt, self.detector) # Connect detector output to FIR LPF # in two stages, followed by the FFT scope self.connect(self.detector, self.first, self.second, self.third, self.scope) # Connect audio output #self.connect(self.first, self.volume) #self.connect(self.volume, (self.audio, 0)) #self.connect(self.volume, (self.audio, 1)) # Connect epoch folder if self.enable_comb_filter == True: self.connect(self.first, self.folder_bandpass, self.folder_rr, self.folder_f2c, self.folder_comb, self.folder_c2f, self.folder_s2p, self.folder_iir, self.chart) else: self.connect(self.first, self.folder_bandpass, self.folder_rr, self.folder_s2p, self.folder_iir, self.chart) # Connect baseband recording file (initially /dev/null) self.connect(self.u, self.tofloat, self.tochar, self.recording) # Connect pulse recording file (initially /dev/null) self.connect(self.first, self.toshort, self.pulse_recording) # # Build the GUI elements # self._build_gui(vbox) # Make GUI agree with command-line self.myform['average'].set_value(int(options.avg)) self.myform['foldavg'].set_value(int(options.favg)) # Make spectral averager agree with command line if options.avg != 1.0: self.scope.set_avg_alpha(float(1.0 / options.avg)) self.scope.set_average(True) # set initial values if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0] + g[1]) / 2 if options.freq is None: # if no freq was specified, use the mid-point r = self.subdev.freq_range() options.freq = float(r[0] + r[1]) / 2 self.set_gain(options.gain) #self.set_volume(-10.0) if not (self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") self.myform['decim'].set_value(self.u.decim_rate()) self.myform['fs@usb'].set_value(self.u.adc_freq() / self.u.decim_rate()) self.myform['dbname'].set_value(self.subdev.name()) self.myform['DM'].set_value(self.dm) self.myform['Doppler'].set_value(self.doppler) # # Start the timer that shows current LMST on the GUI # self.lmst_timer.Start(1000)
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) self.frame = frame self.panel = panel self.offset = 0.0 # Channel frequency offset parser = OptionParser(option_class=eng_option) parser.add_option( "-p", "--protocol", type="int", default=1, help="set protocol: 0 = RDLAP 19.2kbps; 1 = APCO25 (default)") parser.add_option("-g", "--gain", type="eng_float", default=1.0, help="set linear input gain (default: %default)") parser.add_option("-x", "--freq-translation", type="eng_float", default=0.0, help="initial channel frequency translation") parser.add_option( "-n", "--frame-decim", type="int", default=1, help="set oscope frame decimation factor to n [default=1]") parser.add_option( "-v", "--v-scale", type="eng_float", default=5000, help="set oscope initial V/div to SCALE [default=%default]") parser.add_option( "-t", "--t-scale", type="eng_float", default=49e-6, help="set oscope initial s/div to SCALE [default=50us]") parser.add_option( "-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp") parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, help="set sample rate to RATE (default: %default)") parser.add_option( "-d", "--channel-decim", type="int", default=None, help= "set channel decimation factor to n [default depends on protocol]") parser.add_option("-w", "--wav-file", type="string", default=None, help="WAV input path") parser.add_option("-f", "--data-file", type="string", default=None, help="Data input path") parser.add_option("-B", "--base-band", action="store_true", default=False) parser.add_option("-R", "--repeat", action="store_true", default=False) parser.add_option("-o", "--wav-out", type="string", default=None, help="WAV output path") parser.add_option("-G", "--wav-out-gain", type="eng_float", default=0.05, help="set WAV output gain (default: %default)") parser.add_option("-F", "--data-out", type="string", default=None, help="Data output path") parser.add_option("-C", "--carrier-freq", type="eng_float", default=None, help="set data output carrier frequency to FREQ", metavar="FREQ") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.options = options if options.wav_file is not None: #try: self.input_file = gr.wavfile_source(options.wav_file, options.repeat) #except: # print "WAV file not found or not a WAV file" # sys.exit(1) print "WAV input: %i Hz, %i bits, %i channels" % ( self.input_file.sample_rate(), self.input_file.bits_per_sample(), self.input_file.channels()) self.sample_rate = self.input_file.sample_rate() self.input_stream = gr.throttle(gr.sizeof_float, self.sample_rate) self.connect(self.input_file, self.input_stream) self.src = gr.multiply_const_ff(options.gain) elif options.data_file is not None: if options.base_band: sample_size = gr.sizeof_float print "Data file is baseband (float)" self.src = gr.multiply_const_ff(options.gain) else: sample_size = gr.sizeof_gr_complex print "Data file is IF (complex)" self.src = gr.multiply_const_cc(options.gain) self.input_file = gr.file_source(sample_size, options.data_file, options.repeat) self.sample_rate = options.sample_rate # E.g. 250000 print "Data file sampling rate = " + str(self.sample_rate) self.input_stream = gr.throttle(sample_size, self.sample_rate) self.connect(self.input_file, self.input_stream) else: self.sample_rate = options.sample_rate print "Soundcard sampling rate = " + str(self.sample_rate) self.input_stream = audio.source( self.sample_rate, options.audio_input) # float samples self.src = gr.multiply_const_ff(options.gain) print "Fixed input gain = " + str(options.gain) self.connect(self.input_stream, self.src) if options.wav_out is not None: output_rate = int(self.sample_rate) if options.channel_decim is not None: output_rate /= options.channel_decim self.wav_out = gr.wavfile_sink(options.wav_out, 1, output_rate, 16) print "Opened WAV output file: " + options.wav_out + " at rate: " + str( output_rate) else: self.wav_out = None if options.data_out is not None: if options.carrier_freq is None: self.data_out = gr.file_sink(gr.sizeof_float, options.data_out) print "Opened float data output file: " + options.data_out else: self.data_out = gr.file_sink(gr.sizeof_gr_complex, options.data_out) print "Opened complex data output file: " + options.data_out else: self.data_out = None self.num_inputs = 1 input_rate = self.sample_rate #title='IF', #size=(1024,800), if (options.data_file is not None) and (options.base_band == False): self.scope = scopesink2.scope_sink_c( panel, sample_rate=input_rate, frame_decim=options.frame_decim, v_scale=options.v_scale, t_scale=options.t_scale, num_inputs=self.num_inputs) else: self.scope = scopesink2.scope_sink_f( panel, sample_rate=input_rate, frame_decim=options.frame_decim, v_scale=options.v_scale, t_scale=options.t_scale, num_inputs=self.num_inputs) #self.di = gr.deinterleave(gr.sizeof_float) #self.di = gr.complex_to_float(1) #self.di = gr.complex_to_imag() #self.dr = gr.complex_to_real() #self.connect(self.src,self.dr) #self.connect(self.src,self.di) #self.null = gr.null_sink(gr.sizeof_double) #self.connect(self.src,self.di) #self.connect((self.di,0),(self.scope,0)) #self.connect((self.di,1),(self.scope,1)) #self.connect(self.dr,(self.scope,0)) #self.connect(self.di,(self.scope,1)) self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages self.queue_watcher = queue_watcher(self.msgq, self.adjust_freq_norm) #------------------------------------------------------------------------------- if options.protocol == 0: # ---------- RD-LAP 19.2 kbps (9600 ksps), 25kHz channel, print "RD-LAP selected" self.symbol_rate = 9600 # symbol rate; at 2 bits/symbol this corresponds to 19.2kbps if options.channel_decim is None: self.channel_decimation = 10 # decimation (final rate should be at least several symbol rate) else: self.channel_decimation = options.channel_decim self.max_frequency_offset = 12000.0 # coarse carrier tracker leash, ~ half a channel either way self.symbol_deviation = 1200.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = self.sample_rate self.protocol_processing = fsk4.rdlap_f( self.msgq, 0) # desired protocol processing block selected here self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter characteristics channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 10000, # One-sided modulation bandwidth 12000, # One-sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation # symbol shaping filter characteristics symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # alpha 500) # taps if options.protocol == 1: # ---------- APCO-25 C4FM Test Data print "APCO selected" self.symbol_rate = 4800 # symbol rate if options.channel_decim is None: self.channel_decimation = 20 # decimation else: self.channel_decimation = options.channel_decim self.max_frequency_offset = 6000.0 # coarse carrier tracker leash self.symbol_deviation = 600.0 # this is frequency offset from center of channel to +1 / -1 symbols self.input_sample_rate = self.sample_rate self.protocol_processing = fsk4.apco25_f(self.msgq, 0) self.channel_rate = self.input_sample_rate / self.channel_decimation # channel selection filter if (options.data_file is not None) and (options.base_band == False): channel_taps = optfir.low_pass( 1.0, # Filter gain self.input_sample_rate, # Sample rate 5000, # One-sided modulation bandwidth 6500, # One-sided channel bandwidth 0.2, # Passband ripple (was 0.1) 60) # Stopband attenuation else: channel_taps = None # symbol shaping filter symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain self.channel_rate, # sampling rate self.symbol_rate, # symbol rate 0.2, # alpha 500) # taps # ----------------- End of setup block print "Input rate = " + str(self.input_sample_rate) print "Channel decimation = " + str(self.channel_decimation) print "Channel rate = " + str(self.channel_rate) if channel_taps is not None: self.chan = gr.freq_xlating_fir_filter_ccf( self.channel_decimation, # Decimation rate channel_taps, # Filter taps 0.0, # Offset frequency self.input_sample_rate) # Sample rate if (options.freq_translation != 0): print "Channel center frequency = " + str( options.freq_translation) self.chan.set_center_freq(options.freq_translation) else: self.chan = None if options.carrier_freq is not None: print "Carrier frequency = " + str(options.carrier_freq) self.sig_carrier = gr.sig_source_c(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, 0) self.carrier_mul = gr.multiply_vcc(1) # cc(gr.sizeof_gr_complex) self.connect(self.sig_carrier, (self.carrier_mul, 0)) self.connect(self.chan, (self.carrier_mul, 1)) self.sig_i_carrier = gr.sig_source_f(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, 0) self.sig_q_carrier = gr.sig_source_f(self.channel_rate, gr.GR_COS_WAVE, options.carrier_freq, 1, (pi / 2.0)) self.carrier_i_mul = gr.multiply_ff(1) self.carrier_q_mul = gr.multiply_ff(1) self.iq_to_float = gr.complex_to_float(1) self.carrier_iq_add = gr.add_ff(1) self.connect(self.carrier_mul, self.iq_to_float) self.connect((self.iq_to_float, 0), (self.carrier_i_mul, 0)) self.connect((self.iq_to_float, 1), (self.carrier_q_mul, 0)) self.connect(self.sig_i_carrier, (self.carrier_i_mul, 1)) self.connect(self.sig_q_carrier, (self.carrier_q_mul, 1)) self.connect(self.carrier_i_mul, (self.carrier_iq_add, 0)) self.connect(self.carrier_q_mul, (self.carrier_iq_add, 1)) else: self.sig_carrier = None self.carrier_mul = None #lf_channel_taps = optfir.low_pass(1.0, # Filter gain # self.input_sample_rate, # Sample rate # 2500, # One-sided modulation bandwidth # 3250, # One-sided channel bandwidth # 0.1, # Passband ripple (0.1) # 60, # Stopband attenuation # 9) # Extra taps (default 2, which doesn't work at 48kHz) #self.lf = gr.fir_filter_fff(self.channel_decimation, lf_channel_taps) self.scope2 = scopesink2.scope_sink_f(panel, sample_rate=self.symbol_rate, frame_decim=1, v_scale=2, t_scale=0.025, num_inputs=self.num_inputs) # also note: this specifies the nominal frequency deviation for the 4-level fsk signal self.fm_demod_gain = self.channel_rate / (2.0 * pi * self.symbol_deviation) self.fm_demod = gr.quadrature_demod_cf(self.fm_demod_gain) symbol_decim = 1 self.symbol_filter = gr.fir_filter_fff(symbol_decim, symbol_coeffs) # eventually specify: sample rate, symbol rate self.demod_fsk4 = fsk4.demod_ff(self.msgq, self.channel_rate, self.symbol_rate) if (self.chan is not None): self.connect(self.src, self.chan, self.fm_demod, self.symbol_filter, self.demod_fsk4, self.protocol_processing) if options.wav_out is not None: print "WAV output gain = " + str(options.wav_out_gain) self.scaled_wav_data = gr.multiply_const_ff( float(options.wav_out_gain)) self.connect(self.scaled_wav_data, self.wav_out) if self.carrier_mul is None: self.connect(self.fm_demod, self.scaled_wav_data) else: self.connect(self.carrier_iq_add, self.scaled_wav_data) if self.data_out is not None: if self.carrier_mul is None: self.connect(self.fm_demod, self.data_out) else: self.connect(self.carrier_mul, self.data_out) # During signal, -4..4 #self.connect(self.fm_demod, self.scope2) else: self.connect(self.src, self.symbol_filter, self.demod_fsk4, self.protocol_processing) self.connect(self.src, self.scope) #self.connect(self.lf, self.scope) self.connect(self.demod_fsk4, self.scope2) #self.connect(self.symbol_filter, self.scope2) # --------------- End of most of the 4L-FSK hack & slash self._build_gui(vbox) # set initial values if options.gain is None: options.gain = 0 self.set_gain(options.gain)
def __init__(self, sample_rate, ber_threshold=0, # Above which to do search ber_smoothing=0, # Alpha of BER smoother (0.01) ber_duration=0, # Length before trying next combo ber_sample_decimation=1, settling_period=0, pre_lock_duration=0, #ber_sample_skip=0 **kwargs): use_throttle = False base_duration = 1024 if sample_rate > 0: use_throttle = True base_duration *= 4 # Has to be high enough for block-delay if ber_threshold == 0: ber_threshold = 512 * 4 if ber_smoothing == 0: ber_smoothing = 0.01 if ber_duration == 0: ber_duration = base_duration * 2 # 1000ms if settling_period == 0: settling_period = base_duration * 1 # 500ms if pre_lock_duration == 0: pre_lock_duration = base_duration * 2 #1000ms print "Creating Auto-FEC:" print "\tsample_rate:\t\t", sample_rate print "\tber_threshold:\t\t", ber_threshold print "\tber_smoothing:\t\t", ber_smoothing print "\tber_duration:\t\t", ber_duration print "\tber_sample_decimation:\t", ber_sample_decimation print "\tsettling_period:\t", settling_period print "\tpre_lock_duration:\t", pre_lock_duration print "" self.sample_rate = sample_rate self.ber_threshold = ber_threshold #self.ber_smoothing = ber_smoothing self.ber_duration = ber_duration self.settling_period = settling_period self.pre_lock_duration = pre_lock_duration #self.ber_sample_skip = ber_sample_skip self.data_lock = threading.Lock() gr.hier_block2.__init__(self, "auto_fec", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Post MPSK-receiver complex input gr.io_signature3(3, 3, gr.sizeof_char, gr.sizeof_float, gr.sizeof_float)) # Decoded packed bytes, BER metric, lock self.input_watcher = auto_fec_input_watcher(self) default_xform = self.input_watcher.xform_lock self.gr_conjugate_cc_0 = gr.conjugate_cc() self.connect((self, 0), (self.gr_conjugate_cc_0, 0)) # Input self.blks2_selector_0 = grc_blks2.selector( item_size=gr.sizeof_gr_complex*1, num_inputs=2, num_outputs=1, input_index=default_xform.get_conjugation_index(), output_index=0, ) self.connect((self.gr_conjugate_cc_0, 0), (self.blks2_selector_0, 0)) self.connect((self, 0), (self.blks2_selector_0, 1)) # Input self.gr_multiply_const_vxx_3 = gr.multiply_const_vcc((0.707*(1+1j), )) self.connect((self.blks2_selector_0, 0), (self.gr_multiply_const_vxx_3, 0)) self.gr_multiply_const_vxx_2 = gr.multiply_const_vcc((default_xform.get_rotation(), )) # phase_mult self.connect((self.gr_multiply_const_vxx_3, 0), (self.gr_multiply_const_vxx_2, 0)) self.gr_complex_to_float_0_0 = gr.complex_to_float(1) self.connect((self.gr_multiply_const_vxx_2, 0), (self.gr_complex_to_float_0_0, 0)) self.gr_interleave_1 = gr.interleave(gr.sizeof_float*1) self.connect((self.gr_complex_to_float_0_0, 1), (self.gr_interleave_1, 1)) self.connect((self.gr_complex_to_float_0_0, 0), (self.gr_interleave_1, 0)) self.gr_multiply_const_vxx_0 = gr.multiply_const_vff((1, )) # invert self.connect((self.gr_interleave_1, 0), (self.gr_multiply_const_vxx_0, 0)) self.baz_delay_2 = baz.delay(gr.sizeof_float*1, default_xform.get_puncture_delay()) # delay_puncture self.connect((self.gr_multiply_const_vxx_0, 0), (self.baz_delay_2, 0)) self.depuncture_ff_0 = baz.depuncture_ff((_puncture_matrices[self.input_watcher.puncture_matrix][1])) # puncture_matrix self.connect((self.baz_delay_2, 0), (self.depuncture_ff_0, 0)) self.baz_delay_1 = baz.delay(gr.sizeof_float*1, default_xform.get_viterbi_delay()) # delay_viterbi self.connect((self.depuncture_ff_0, 0), (self.baz_delay_1, 0)) self.swap_ff_0 = baz.swap_ff(default_xform.get_viterbi_swap()) # swap_viterbi self.connect((self.baz_delay_1, 0), (self.swap_ff_0, 0)) self.gr_decode_ccsds_27_fb_0 = gr.decode_ccsds_27_fb() if use_throttle: print "==> Using throttle at sample rate:", self.sample_rate self.gr_throttle_0 = gr.throttle(gr.sizeof_float, self.sample_rate) self.connect((self.swap_ff_0, 0), (self.gr_throttle_0, 0)) self.connect((self.gr_throttle_0, 0), (self.gr_decode_ccsds_27_fb_0, 0)) else: self.connect((self.swap_ff_0, 0), (self.gr_decode_ccsds_27_fb_0, 0)) self.connect((self.gr_decode_ccsds_27_fb_0, 0), (self, 0)) # Output bytes self.gr_add_const_vxx_1 = gr.add_const_vff((-4096, )) self.connect((self.gr_decode_ccsds_27_fb_0, 1), (self.gr_add_const_vxx_1, 0)) self.gr_multiply_const_vxx_1 = gr.multiply_const_vff((-1, )) self.connect((self.gr_add_const_vxx_1, 0), (self.gr_multiply_const_vxx_1, 0)) self.connect((self.gr_multiply_const_vxx_1, 0), (self, 1)) # Output BER self.gr_single_pole_iir_filter_xx_0 = gr.single_pole_iir_filter_ff(ber_smoothing, 1) self.connect((self.gr_multiply_const_vxx_1, 0), (self.gr_single_pole_iir_filter_xx_0, 0)) self.gr_keep_one_in_n_0 = blocks.keep_one_in_n(gr.sizeof_float, ber_sample_decimation) self.connect((self.gr_single_pole_iir_filter_xx_0, 0), (self.gr_keep_one_in_n_0, 0)) self.const_source_x_0 = gr.sig_source_f(0, gr.GR_CONST_WAVE, 0, 0, 0) # Last param is const value if use_throttle: lock_throttle_rate = self.sample_rate // 16 print "==> Using lock throttle rate:", lock_throttle_rate self.gr_throttle_1 = gr.throttle(gr.sizeof_float, lock_throttle_rate) self.connect((self.const_source_x_0, 0), (self.gr_throttle_1, 0)) self.connect((self.gr_throttle_1, 0), (self, 2)) else: self.connect((self.const_source_x_0, 0), (self, 2)) self.msg_q = gr.msg_queue(2*256) # message queue that holds at most 2 messages, increase to speed up process self.msg_sink = gr.message_sink(gr.sizeof_float, self.msg_q, dont_block=0) # Block to speed up process self.connect((self.gr_keep_one_in_n_0, 0), self.msg_sink) self.input_watcher.start()
def __init__( self, sample_rate, ber_threshold=0, # Above which to do search ber_smoothing=0, # Alpha of BER smoother (0.01) ber_duration=0, # Length before trying next combo ber_sample_decimation=1, settling_period=0, pre_lock_duration=0, #ber_sample_skip=0 **kwargs): use_throttle = False base_duration = 1024 if sample_rate > 0: use_throttle = True base_duration *= 4 # Has to be high enough for block-delay if ber_threshold == 0: ber_threshold = 512 * 4 if ber_smoothing == 0: ber_smoothing = 0.01 if ber_duration == 0: ber_duration = base_duration * 2 # 1000ms if settling_period == 0: settling_period = base_duration * 1 # 500ms if pre_lock_duration == 0: pre_lock_duration = base_duration * 2 #1000ms print "Creating Auto-FEC:" print "\tsample_rate:\t\t", sample_rate print "\tber_threshold:\t\t", ber_threshold print "\tber_smoothing:\t\t", ber_smoothing print "\tber_duration:\t\t", ber_duration print "\tber_sample_decimation:\t", ber_sample_decimation print "\tsettling_period:\t", settling_period print "\tpre_lock_duration:\t", pre_lock_duration print "" self.sample_rate = sample_rate self.ber_threshold = ber_threshold #self.ber_smoothing = ber_smoothing self.ber_duration = ber_duration self.settling_period = settling_period self.pre_lock_duration = pre_lock_duration #self.ber_sample_skip = ber_sample_skip self.data_lock = threading.Lock() gr.hier_block2.__init__( self, "auto_fec", gr.io_signature( 1, 1, gr.sizeof_gr_complex), # Post MPSK-receiver complex input gr.io_signature3( 3, 3, gr.sizeof_char, gr.sizeof_float, gr.sizeof_float)) # Decoded packed bytes, BER metric, lock self.input_watcher = auto_fec_input_watcher(self) default_xform = self.input_watcher.xform_lock self.gr_conjugate_cc_0 = gr.conjugate_cc() self.connect((self, 0), (self.gr_conjugate_cc_0, 0)) # Input self.blks2_selector_0 = grc_blks2.selector( item_size=gr.sizeof_gr_complex * 1, num_inputs=2, num_outputs=1, input_index=default_xform.get_conjugation_index(), output_index=0, ) self.connect((self.gr_conjugate_cc_0, 0), (self.blks2_selector_0, 0)) self.connect((self, 0), (self.blks2_selector_0, 1)) # Input self.gr_multiply_const_vxx_3 = gr.multiply_const_vcc( (0.707 * (1 + 1j), )) self.connect((self.blks2_selector_0, 0), (self.gr_multiply_const_vxx_3, 0)) self.gr_multiply_const_vxx_2 = gr.multiply_const_vcc( (default_xform.get_rotation(), )) # phase_mult self.connect((self.gr_multiply_const_vxx_3, 0), (self.gr_multiply_const_vxx_2, 0)) self.gr_complex_to_float_0_0 = gr.complex_to_float(1) self.connect((self.gr_multiply_const_vxx_2, 0), (self.gr_complex_to_float_0_0, 0)) self.gr_interleave_1 = gr.interleave(gr.sizeof_float * 1) self.connect((self.gr_complex_to_float_0_0, 1), (self.gr_interleave_1, 1)) self.connect((self.gr_complex_to_float_0_0, 0), (self.gr_interleave_1, 0)) self.gr_multiply_const_vxx_0 = gr.multiply_const_vff((1, )) # invert self.connect((self.gr_interleave_1, 0), (self.gr_multiply_const_vxx_0, 0)) self.baz_delay_2 = baz.delay( gr.sizeof_float * 1, default_xform.get_puncture_delay()) # delay_puncture self.connect((self.gr_multiply_const_vxx_0, 0), (self.baz_delay_2, 0)) self.depuncture_ff_0 = baz.depuncture_ff( (_puncture_matrices[self.input_watcher.puncture_matrix][1] )) # puncture_matrix self.connect((self.baz_delay_2, 0), (self.depuncture_ff_0, 0)) self.baz_delay_1 = baz.delay( gr.sizeof_float * 1, default_xform.get_viterbi_delay()) # delay_viterbi self.connect((self.depuncture_ff_0, 0), (self.baz_delay_1, 0)) self.swap_ff_0 = baz.swap_ff( default_xform.get_viterbi_swap()) # swap_viterbi self.connect((self.baz_delay_1, 0), (self.swap_ff_0, 0)) self.gr_decode_ccsds_27_fb_0 = gr.decode_ccsds_27_fb() if use_throttle: print "==> Using throttle at sample rate:", self.sample_rate self.gr_throttle_0 = gr.throttle(gr.sizeof_float, self.sample_rate) self.connect((self.swap_ff_0, 0), (self.gr_throttle_0, 0)) self.connect((self.gr_throttle_0, 0), (self.gr_decode_ccsds_27_fb_0, 0)) else: self.connect((self.swap_ff_0, 0), (self.gr_decode_ccsds_27_fb_0, 0)) self.connect((self.gr_decode_ccsds_27_fb_0, 0), (self, 0)) # Output bytes self.gr_add_const_vxx_1 = gr.add_const_vff((-4096, )) self.connect((self.gr_decode_ccsds_27_fb_0, 1), (self.gr_add_const_vxx_1, 0)) self.gr_multiply_const_vxx_1 = gr.multiply_const_vff((-1, )) self.connect((self.gr_add_const_vxx_1, 0), (self.gr_multiply_const_vxx_1, 0)) self.connect((self.gr_multiply_const_vxx_1, 0), (self, 1)) # Output BER self.gr_single_pole_iir_filter_xx_0 = gr.single_pole_iir_filter_ff( ber_smoothing, 1) self.connect((self.gr_multiply_const_vxx_1, 0), (self.gr_single_pole_iir_filter_xx_0, 0)) self.gr_keep_one_in_n_0 = blocks.keep_one_in_n(gr.sizeof_float, ber_sample_decimation) self.connect((self.gr_single_pole_iir_filter_xx_0, 0), (self.gr_keep_one_in_n_0, 0)) self.const_source_x_0 = gr.sig_source_f(0, gr.GR_CONST_WAVE, 0, 0, 0) # Last param is const value if use_throttle: lock_throttle_rate = self.sample_rate // 16 print "==> Using lock throttle rate:", lock_throttle_rate self.gr_throttle_1 = gr.throttle(gr.sizeof_float, lock_throttle_rate) self.connect((self.const_source_x_0, 0), (self.gr_throttle_1, 0)) self.connect((self.gr_throttle_1, 0), (self, 2)) else: self.connect((self.const_source_x_0, 0), (self, 2)) self.msg_q = gr.msg_queue( 2 * 256 ) # message queue that holds at most 2 messages, increase to speed up process self.msg_sink = gr.message_sink( gr.sizeof_float, self.msg_q, dont_block=0) # Block to speed up process self.connect((self.gr_keep_one_in_n_0, 0), self.msg_sink) self.input_watcher.start()