From 726f930f3967c14220317ea81bcc1eb1f6a29501 Mon Sep 17 00:00:00 2001 From: mleech Date: Mon, 18 Aug 2008 23:32:23 +0000 Subject: [PATCH] Added support for dual_mode (for dual-polarization) removed two layers of filtering in the post-detector chain. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9319 221aa14e-8319-0410-a670-987f0aec2ac5 --- .../src/python/usrp_ra_receiver.py | 225 ++++++++++-------- 1 file changed, 120 insertions(+), 105 deletions(-) diff --git a/gr-radio-astronomy/src/python/usrp_ra_receiver.py b/gr-radio-astronomy/src/python/usrp_ra_receiver.py index e424e9c9..37422149 100755 --- a/gr-radio-astronomy/src/python/usrp_ra_receiver.py +++ b/gr-radio-astronomy/src/python/usrp_ra_receiver.py @@ -34,12 +34,6 @@ import time import numpy.fft import ephem -class continuum_calibration(gr.feval_dd): - def eval(self, x): - str = globals()["calibration_codelet"] - exec(str) - return(x) - class app_flow_graph(stdgui2.std_top_block): def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) @@ -82,29 +76,15 @@ class app_flow_graph(stdgui2.std_top_block): parser.add_option("-S", "--setimode", action="store_true", default=False, help="Enable SETI processing of spectral data") parser.add_option("-K", "--setik", type="eng_float", default=1.5, help="K value for SETI analysis") parser.add_option("-T", "--setibandwidth", type="eng_float", default=12500, help="Instantaneous SETI observing bandwidth--must be divisor of 250Khz") - parser.add_option("-n", "--notches", action="store_true", default=False, - help="Notches appear after all other arguments") parser.add_option("-Q", "--seti_range", type="eng_float", default=1.0e6, help="Total scan width, in Hz for SETI scans") + parser.add_option("-Z", "--dual_mode", action="store_true", + default=False, help="Dual-polarization mode") + parser.add_option("-I", "--interferometer", action="store_true", default=False, help="Interferometer mode") (options, args) = parser.parse_args() - self.notches = Numeric.zeros(64,Numeric.Float64) - if len(args) != 0 and options.notches == False: - parser.print_help() - sys.exit(1) - - if len(args) == 0 and options.notches != False: - parser.print_help() - sys.exit() - - self.use_notches = options.notches - - # Get notch locations - j = 0 - for i in args: - self.notches[j] = float(i) - j = j+1 - - self.notch_count = j + #if (len(args) == 0): + #parser.print_help() + #sys.exit() self.show_debug_info = True @@ -184,24 +164,43 @@ class app_flow_graph(stdgui2.std_top_block): # Set initial values for datalogging timed-output self.continuum_then = time.time() self.spectral_then = time.time() + + self.dual_mode = options.dual_mode # build the graph + self.subdev = [(0, 0), (0,0)] # # If SETI mode, we always run at maximum USRP decimation # if (self.setimode): options.decim = 256 - - self.u = usrp.source_c(decim_rate=options.decim) - self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + if (self.dual_mode == False): + self.u = usrp.source_c(decim_rate=options.decim) + self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) + # determine the daughterboard subdevice we're using + self.subdev[0] = usrp.selected_subdev(self.u, options.rx_subdev_spec) + self.subdev[1] = self.subdev[0] + self.cardtype = self.subdev[0].dbid() + else: + self.u=usrp.source_c(decim_rate=options.decim, nchan=2) + self.subdev[0] = usrp.selected_subdev(self.u, (0, 0)) + self.subdev[1] = usrp.selected_subdev(self.u, (1, 0)) + self.cardtype = self.subdev[0].dbid() + self.u.set_mux(0x32103210) + + + # + # Set 8-bit mode + # + width = 8 + shift = 8 + format = self.u.make_format(width, shift) + r = self.u.set_format(format) + # Set initial declination self.decln = options.decln - # determine the daughterboard subdevice we're using - self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) - self.cardtype = self.subdev.dbid() - input_rate = self.u.adc_freq() / self.u.decim_rate() # @@ -270,11 +269,14 @@ class app_flow_graph(stdgui2.std_top_block): self.sunstate = "??" # Set up stripchart display + tit = "Continuum" + if (self.dual_mode != False): + tit = "H+V Continuum" self.stripsize = int(options.stripsize) if self.setimode == False: self.chart = ra_stripchartsink.stripchart_sink_f (panel, stripsize=self.stripsize, - title="Continuum", + title=tit, xlabel="LMST Offset (Seconds)", scaling=1.0, ylabel=options.ylabel, divbase=options.divbase) @@ -289,32 +291,12 @@ class app_flow_graph(stdgui2.std_top_block): else: self.observing = options.observing + # Remember our input bandwidth self.bw = input_rate - # We setup the first two integrators to produce a fixed integration - # Down to 1Hz, with output at 1 samples/sec - N = input_rate/5000 - - # Second stage runs on decimated output of first - M = (input_rate/N) - - # Create taps for first integrator - t = range(0,N-1) - tapsN = [] - for i in t: - tapsN.append(1.0/N) - - # Create taps for second integrator - t = range(0,M-1) - tapsM = [] - for i in t: - tapsM.append(1.0/M) - # - # The 3rd integrator is variable, and user selectable at runtime - # This integrator doesn't decimate, but is used to set the - # final integration time based on the constant 1Hz input samples - # The strip chart is fed at a constant 1Hz rate as a result + # + # The strip chart is fed at a constant 1Hz rate # # @@ -322,56 +304,88 @@ class app_flow_graph(stdgui2.std_top_block): # if self.setimode == False: - # The three integrators--two FIR filters, and an IIR final filter - self.integrator1 = gr.fir_filter_fff (N, tapsN) - self.integrator2 = gr.fir_filter_fff (M, tapsM) - self.integrator3 = gr.single_pole_iir_filter_ff(1.0) - - # The detector - self.detector = gr.complex_to_mag_squared() + # The IIR integration filter for post-detection + self.integrator = gr.single_pole_iir_filter_ff(1.0) + self.integrator.set_taps (1.0/self.bw) + if (self.dual_mode == False): + # The detector + self.detector = gr.complex_to_mag_squared() # Signal probe - self.probe = gr.probe_signal_f(); + self.probe = gr.probe_signal_f() # # Continuum calibration stuff # x = self.calib_coeff/100.0 - self.cal_mult = gr.multiply_const_ff(self.calib_coeff/100.0); - self.cal_offs = gr.add_const_ff(self.calib_offset*(x*8000)); - - if self.use_notches == True: - self.compute_notch_taps(self.notches) - self.notch_filt = gr.fft_filter_ccc(1, self.notch_taps) + self.cal_mult = gr.multiply_const_ff(self.calib_coeff/100.0) + self.cal_offs = gr.add_const_ff(self.calib_offset*(x*8000)) + + # + # Mega decimator after IIR filter + # + self.keepn = gr.keep_one_in_n(gr.sizeof_float, self.bw) # # Start connecting configured modules in the receive chain # + + + # + # Handle dual-polarization mode + # + if (self.dual_mode == False): + self.head = self.u + self.shead = self.u + + else: + self.di = gr.deinterleave(gr.sizeof_gr_complex) + self.addchans = gr.add_cc () + self.h_power = gr.complex_to_mag_squared() + self.v_power = gr.complex_to_mag_squared() + self.connect (self.u, self.di) + + # + # For spectral, adding the two channels works, assuming no gross + # phase or amplitude error + self.connect ((self.di, 0), (self.addchans, 0)) + self.connect ((self.di, 1), (self.addchans, 1)) + + # + # Connect heads of spectral and total-power chains + # + self.head = self.di + self.shead = self.addchans + + # + # For dual-polarization mode, we compute the sum of the + # powers on each channel, after they've been detected + # + self.detector = gr.add_ff() # The scope--handle SETI mode if (self.setimode == False): - if (self.use_notches == True): - self.connect(self.u, self.notch_filt, self.scope) - else: - self.connect(self.u, self.scope) + self.connect(self.shead, self.scope) else: - if (self.use_notches == True): - self.connect(self.u, self.notch_filt, - self.fft_bandpass, self.scope) - else: - self.connect(self.u, self.fft_bandpass, self.scope) + self.connect(self.shead, self.fft_bandpass, self.scope) - if self.setimode == False: - if (self.use_notches == True): - self.connect(self.notch_filt, self.detector, - self.integrator1, self.integrator2, - self.integrator3, self.cal_mult, self.cal_offs, self.chart) + if (self.setimode == False): + if (self.dual_mode == False): + self.connect(self.head, self.detector, + self.integrator, self.keepn, self.cal_mult, self.cal_offs, self.chart) else: - self.connect(self.u, self.detector, - self.integrator1, self.integrator2, - self.integrator3, self.cal_mult, self.cal_offs, self.chart) - + # + # In dual-polarization mode, we compute things a little differently + # In effect, we have two radiometer chains, terminating in an adder + # + self.connect((self.di, 0), self.h_power) + self.connect((self.di, 1), self.v_power) + self.connect(self.h_power, (self.detector, 0)) + self.connect(self.v_power, (self.detector, 1)) + self.connect(self.detector, + self.integrator, self.keepn, self.cal_mult, self.cal_offs, self.chart) + # current instantaneous integrated detector value self.connect(self.cal_offs, self.probe) @@ -407,12 +421,12 @@ class app_flow_graph(stdgui2.std_top_block): if options.gain is None: # if no gain was specified, use the mid-point in dB - g = self.subdev.gain_range() + g = self.subdev[0].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() + r = self.subdev[0].freq_range() options.freq = float(r[0]+r[1])/2 # Set the initial gain control @@ -427,16 +441,19 @@ class app_flow_graph(stdgui2.std_top_block): # RF hardware information 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['USB BW'].set_value(self.u.adc_freq() / self.u.decim_rate()) + if (self.dual_mode == True): + self.myform['dbname'].set_value(self.subdev[0].name()+'/'+self.subdev[1].name()) + else: + self.myform['dbname'].set_value(self.subdev[0].name()) # Set analog baseband filtering, if DBS_RX if self.cardtype in (usrp_dbid.DBS_RX, usrp_dbid.DBS_RX_REV_2_1): lbw = (self.u.adc_freq() / self.u.decim_rate()) / 2 if lbw < 1.0e6: lbw = 1.0e6 - self.subdev.set_bw(lbw) - + self.subdev[0].set_bw(lbw) + self.subdev[1].set_bw(lbw) # Start the timer for the LMST display and datalogging self.lmst_timer.Start(1000) @@ -493,7 +510,7 @@ class app_flow_graph(stdgui2.std_top_block): vbox2 = wx.BoxSizer(wx.VERTICAL) if self.setimode == False: vbox3 = wx.BoxSizer(wx.VERTICAL) - g = self.subdev.gain_range() + g = self.subdev[0].gain_range() myform['gain'] = form.slider_field(parent=self.panel, sizer=vbox2, label="RF Gain", weight=1, min=int(g[0]), max=int(g[1]), @@ -576,8 +593,8 @@ class app_flow_graph(stdgui2.std_top_block): parent=panel, sizer=hbox, label="Decim") hbox.Add((5,0), 1) - myform['fs@usb'] = form.static_float_field( - parent=panel, sizer=hbox, label="Fs@USB") + myform['USB BW'] = form.static_float_field( + parent=panel, sizer=hbox, label="USB BW") hbox.Add((5,0), 1) myform['dbname'] = form.static_text_field( @@ -612,7 +629,8 @@ class app_flow_graph(stdgui2.std_top_block): # Everything except BASIC_RX should support usrp.tune() # if not (self.cardtype == usrp_dbid.BASIC_RX): - r = usrp.tune(self.u, 0, self.subdev, target_freq) + r = usrp.tune(self.u, self.subdev[0]._which, self.subdev[0], target_freq) + r = usrp.tune(self.u, self.subdev[1]._which, self.subdev[1], target_freq) else: r = self.u.set_rx_freq(0, target_freq) f = self.u.rx_freq(0) @@ -633,10 +651,6 @@ class app_flow_graph(stdgui2.std_top_block): self.myform['baseband'].set_value(r.baseband_freq) self.myform['ddc'].set_value(r.dxc_freq) - if self.use_notches == True: - self.compute_notch_taps(self.notches) - self.notch_filt.set_taps(self.notch_taps) - return True return False @@ -647,7 +661,8 @@ class app_flow_graph(stdgui2.std_top_block): def set_gain(self, gain): self.myform['gain'].set_value(gain) # update displayed value - self.subdev.set_gain(gain) + self.subdev[0].set_gain(gain) + self.subdev[1].set_gain(gain) self.gain = gain def set_averaging(self, avval): @@ -658,7 +673,7 @@ class app_flow_graph(stdgui2.std_top_block): def set_integration(self, integval): if self.setimode == False: - self.integrator3.set_taps(1.0/integval) + self.integrator.set_taps(1.0/((integval)*(self.bw/2))) self.myform['integration'].set_value(integval) self.integ = integval -- 2.39.5