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 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("-a", "--avg", type="eng_float", default=1.0, help="set spectral averaging alpha") parser.add_option("-i", "--integ", type="eng_float", default=1.0, help="set integration time") 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 Total power reference level") parser.add_option("-y", "--division", type="eng_float", default=0.5, help="Set Total power Y division size") 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("-o", "--observing", type="eng_float", default=0.0, help="Set observing frequency") parser.add_option("-x", "--ylabel", default="dB", help="Y axis label") parser.add_option("-z", "--divbase", type="eng_float", default=0.025, help="Y Division increment base") parser.add_option("-v", "--stripsize", type="eng_float", default=2400, help="Size of stripchart, in 2Hz samples") parser.add_option("-F", "--fft_size", type="eng_float", default=1024, help="Size of FFT") parser.add_option("-N", "--decln", type="eng_float", default=999.99, help="Observing declination") parser.add_option("-X", "--prefix", default="./") parser.add_option("-M", "--fft_rate", type="eng_float", default=8.0, help="FFT Rate") parser.add_option("-A", "--calib_coeff", type="eng_float", default=1.0, help="Calibration coefficient") parser.add_option("-B", "--calib_offset", type="eng_float", default=0.0, help="Calibration coefficient") parser.add_option("-W", "--waterfall", action="store_true", default=False, help="Use Waterfall FFT display") 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("-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") parser.add_option("-D", "--switch_mode", action="store_true", default=False, help="Dicke Switching mode") parser.add_option("-P", "--reference_divisor", type="eng_float", default=1.0, help="Reference Divisor") parser.add_option("-U", "--ref_fifo", default=None) parser.add_option("-k", "--notch_taps", type="int", default=64, help="Number of notch taps") parser.add_option("-n", "--notches", action="store_true", default=False, help="Notch frequencies after all other args") parser.add_option("-Y", "--interface", default=None) parser.add_option("-H", "--mac_addr", default=None) # Added this documentation (options, args) = parser.parse_args() self.setimode = options.setimode self.dual_mode = options.dual_mode self.interferometer = options.interferometer self.normal_mode = False self.switch_mode = options.switch_mode self.switch_state = 0 self.reference_divisor = options.reference_divisor self.ref_fifo = options.ref_fifo self.usrp2 = False self.decim = options.decim self.rx_subdev_spec = options.rx_subdev_spec if (options.interface != None and options.mac_addr != None): self.mac_addr = options.mac_addr self.interface = options.interface self.usrp2 = True self.NOTCH_TAPS = options.notch_taps self.notches = Numeric.zeros(self.NOTCH_TAPS,Numeric.Float64) # Get notch locations j = 0 for i in args: self.notches[j] = float(i) j = j + 1 self.use_notches = options.notches if (self.ref_fifo != None): self.ref_fifo_file = open (self.ref_fifo, "r") modecount = 0 for modes in (self.dual_mode, self.interferometer): if (modes == True): modecount = modecount + 1 if (modecount > 1): print "must select only 1 of --dual_mode, or --interferometer" sys.exit(1) self.chartneeded = True if (self.setimode == True): self.chartneeded = False if (self.setimode == True and self.interferometer == True): print "can't pick both --setimode and --interferometer" sys.exit(1) if (self.setimode == True and self.switch_mode == True): print "can't pick both --setimode and --switch_mode" sys.exit(1) if (self.interferometer == True and self.switch_mode == True): print "can't pick both --interferometer and --switch_mode" sys.exit(1) if (modecount == 0): self.normal_mode = True self.show_debug_info = True # Pick up waterfall option self.waterfall = options.waterfall # SETI mode stuff self.setimode = options.setimode self.seticounter = 0 self.setik = options.setik self.seti_fft_bandwidth = int(options.setibandwidth) # Calculate binwidth binwidth = self.seti_fft_bandwidth / options.fft_size # Use binwidth, and knowledge of likely chirp rates to set reasonable # values for SETI analysis code. We assume that SETI signals will # chirp at somewhere between 0.10Hz/sec and 0.25Hz/sec. # # upper_limit is the "worst case"--that is, the case for which we have # to wait the longest to actually see any drift, due to the quantizing # on FFT bins. upper_limit = binwidth / 0.10 self.setitimer = int(upper_limit * 2.00) self.scanning = True # Calculate the CHIRP values based on Hz/sec self.CHIRP_LOWER = 0.10 * self.setitimer self.CHIRP_UPPER = 0.25 * self.setitimer # Reset hit counters to 0 self.hitcounter = 0 self.s1hitcounter = 0 self.s2hitcounter = 0 self.avgdelta = 0 # We scan through 2Mhz of bandwidth around the chosen center freq self.seti_freq_range = options.seti_range # Calculate lower edge self.setifreq_lower = options.freq - (self.seti_freq_range/2) self.setifreq_current = options.freq # Calculate upper edge self.setifreq_upper = options.freq + (self.seti_freq_range/2) # Maximum "hits" in a line self.nhits = 20 # Number of lines for analysis self.nhitlines = 4 # We change center frequencies based on nhitlines and setitimer self.setifreq_timer = self.setitimer * (self.nhitlines * 5) # Create actual timer self.seti_then = time.time() # The hits recording array self.hits_array = Numeric.zeros((self.nhits,self.nhitlines), Numeric.Float64) self.hit_intensities = Numeric.zeros((self.nhits,self.nhitlines), Numeric.Float64) # Calibration coefficient and offset self.calib_coeff = options.calib_coeff self.calib_offset = options.calib_offset if self.calib_offset < -750: self.calib_offset = -750 if self.calib_offset > 750: self.calib_offset = 750 if self.calib_coeff < 1: self.calib_coeff = 1 if self.calib_coeff > 100: self.calib_coeff = 100 self.integ = options.integ self.avg_alpha = options.avg self.gain = options.gain self.decln = options.decln # Set initial values for datalogging timed-output self.continuum_then = time.time() self.spectral_then = time.time() # 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 if (self.dual_mode == True and self.decim <= 4): print "Cannot use decim <= 4 with dual_mode" sys.exit(1) self.setup_usrp() # Set initial declination self.decln = options.decln input_rate = self.u.adc_freq() / self.u.decim_rate() self.bw = input_rate # # Set prefix for data files # self.prefix = options.prefix # # The lower this number, the fewer sample frames are dropped # in computing the FFT. A sampled approach is taken to # computing the FFT of the incoming data, which reduces # sensitivity. Increasing sensitivity inreases CPU loading. # self.fft_rate = options.fft_rate self.fft_size = int(options.fft_size) # This buffer is used to remember the most-recent FFT display # values. Used later by self.write_spectral_data() to write # spectral data to datalogging files, and by the SETI analysis # function. # self.fft_outbuf = Numeric.zeros(self.fft_size, Numeric.Float64) # # If SETI mode, only look at seti_fft_bandwidth # at a time. # if (self.setimode): self.fft_input_rate = self.seti_fft_bandwidth # # Build a decimating bandpass filter # self.fft_input_taps = gr.firdes.complex_band_pass (1.0, input_rate, -(int(self.fft_input_rate/2)), int(self.fft_input_rate/2), 200, gr.firdes.WIN_HAMMING, 0) # # Compute required decimation factor # decimation = int(input_rate/self.fft_input_rate) self.fft_bandpass = gr.fir_filter_ccc (decimation, self.fft_input_taps) else: self.fft_input_rate = input_rate # Set up FFT display if self.waterfall == False: self.scope = ra_fftsink.ra_fft_sink_c (panel, fft_size=int(self.fft_size), sample_rate=self.fft_input_rate, fft_rate=int(self.fft_rate), title="Spectral", ofunc=self.fft_outfunc, xydfunc=self.xydfunc) else: self.scope = ra_waterfallsink.waterfall_sink_c (panel, fft_size=int(self.fft_size), sample_rate=self.fft_input_rate, fft_rate=int(self.fft_rate), title="Spectral", ofunc=self.fft_outfunc, size=(1100, 600), xydfunc=self.xydfunc, ref_level=0, span=10) # Set up ephemeris data self.locality = ephem.Observer() self.locality.long = str(options.longitude) self.locality.lat = str(options.latitude) # We make notes about Sunset/Sunrise in Continuum log files self.sun = ephem.Sun() self.sunstate = "??" # Set up stripchart display tit = "Continuum" if (self.dual_mode != False): tit = "H+V Continuum" if (self.interferometer != False): tit = "East x West Correlation" self.stripsize = int(options.stripsize) if self.chartneeded == True: self.chart = ra_stripchartsink.stripchart_sink_f (panel, stripsize=self.stripsize, title=tit, xlabel="LMST Offset (Seconds)", scaling=1.0, ylabel=options.ylabel, divbase=options.divbase) # Set center frequency self.centerfreq = options.freq # Set observing frequency (might be different from actual programmed # RF frequency) if options.observing == 0.0: self.observing = options.freq else: self.observing = options.observing # Remember our input bandwidth self.bw = input_rate # # # The strip chart is fed at a constant 1Hz rate # # # Call constructors for receive chains # if (self.dual_mode == True): self.setup_dual (self.setimode) if (self.interferometer == True): self.setup_interferometer(self.setimode) if (self.normal_mode == True): self.setup_normal(self.setimode) if (self.setimode == True): self.setup_seti() self._build_gui(vbox) # Make GUI agree with command-line self.integ = options.integ if self.setimode == False: self.myform['integration'].set_value(int(options.integ)) self.myform['offset'].set_value(self.calib_offset) self.myform['dcgain'].set_value(self.calib_coeff) self.myform['average'].set_value(int(options.avg)) if self.setimode == False: # Make integrator agree with command line self.set_integration(int(options.integ)) self.avg_alpha = options.avg # 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) if self.setimode == False: # Set division size self.chart.set_y_per_div(options.division) # Set reference(MAX) level self.chart.set_ref_level(options.reflevel) # set initial values if options.gain is None: # if no gain was specified, use the mid-point in dB 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[0].freq_range() options.freq = float(r[0]+r[1])/2 # Set the initial gain control self.set_gain(options.gain) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") # Set declination self.set_decln (self.decln) # RF hardware information self.myform['decim'].set_value(self.u.decim_rate()) 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 == usrp_dbid.DBS_RX: lbw = (self.u.adc_freq() / self.u.decim_rate()) / 2 if lbw < 1.0e6: lbw = 1.0e6 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) if (self.switch_mode == True): self.other_timer.Start(330)
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): stdgui.gui_flow_graph.__init__(self) 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("-a", "--avg", type="eng_float", default=1.0, help="set spectral averaging alpha") parser.add_option("-i", "--integ", type="eng_float", default=1.0, help="set integration time") 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 Total power reference level") parser.add_option("-y", "--division", type="eng_float", default=0.5, help="Set Total power Y division size") 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("-o", "--observing", type="eng_float", default=0.0, help="Set observing frequency") parser.add_option("-x", "--ylabel", default="dB", help="Y axis label") parser.add_option("-z", "--divbase", type="eng_float", default=0.025, help="Y Division increment base") parser.add_option("-v", "--stripsize", type="eng_float", default=2400, help="Size of stripchart, in 2Hz samples") parser.add_option("-F", "--fft_size", type="eng_float", default=1024, help="Size of FFT") parser.add_option("-N", "--decln", type="eng_float", default=999.99, help="Observing declination") parser.add_option("-X", "--prefix", default="./") parser.add_option("-M", "--fft_rate", type="eng_float", default=8.0, help="FFT Rate") parser.add_option("-A", "--calib_coeff", type="eng_float", default=1.0, help="Calibration coefficient") parser.add_option("-B", "--calib_offset", type="eng_float", default=0.0, help="Calibration coefficient") parser.add_option("-W", "--waterfall", action="store_true", default=False, help="Use Waterfall FFT display") 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") (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 self.show_debug_info = True # Pick up waterfall option self.waterfall = options.waterfall # SETI mode stuff self.setimode = options.setimode self.seticounter = 0 self.setik = options.setik self.seti_fft_bandwidth = int(options.setibandwidth) # Calculate binwidth binwidth = self.seti_fft_bandwidth / options.fft_size # Use binwidth, and knowledge of likely chirp rates to set reasonable # values for SETI analysis code. We assume that SETI signals will # chirp at somewhere between 0.10Hz/sec and 0.25Hz/sec. # # upper_limit is the "worst case"--that is, the case for which we have # to wait the longest to actually see any drift, due to the quantizing # on FFT bins. upper_limit = binwidth / 0.10 self.setitimer = int(upper_limit * 2.00) self.scanning = True # Calculate the CHIRP values based on Hz/sec self.CHIRP_LOWER = 0.10 * self.setitimer self.CHIRP_UPPER = 0.25 * self.setitimer # Reset hit counters to 0 self.hitcounter = 0 self.s1hitcounter = 0 self.s2hitcounter = 0 self.avgdelta = 0 # We scan through 2Mhz of bandwidth around the chosen center freq self.seti_freq_range = options.seti_range # Calculate lower edge self.setifreq_lower = options.freq - (self.seti_freq_range/2) self.setifreq_current = options.freq # Calculate upper edge self.setifreq_upper = options.freq + (self.seti_freq_range/2) # Maximum "hits" in a line self.nhits = 20 # Number of lines for analysis self.nhitlines = 4 # We change center frequencies based on nhitlines and setitimer self.setifreq_timer = self.setitimer * (self.nhitlines * 5) # Create actual timer self.seti_then = time.time() # The hits recording array self.hits_array = Numeric.zeros((self.nhits,self.nhitlines), Numeric.Float64) self.hit_intensities = Numeric.zeros((self.nhits,self.nhitlines), Numeric.Float64) # Calibration coefficient and offset self.calib_coeff = options.calib_coeff self.calib_offset = options.calib_offset if self.calib_offset < -750: self.calib_offset = -750 if self.calib_offset > 750: self.calib_offset = 750 if self.calib_coeff < 1: self.calib_coeff = 1 if self.calib_coeff > 100: self.calib_coeff = 100 self.integ = options.integ self.avg_alpha = options.avg self.gain = options.gain self.decln = options.decln # Set initial values for datalogging timed-output self.continuum_then = time.time() self.spectral_then = time.time() # build the graph # # 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)) # 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() # # Set prefix for data files # self.prefix = options.prefix # # The lower this number, the fewer sample frames are dropped # in computing the FFT. A sampled approach is taken to # computing the FFT of the incoming data, which reduces # sensitivity. Increasing sensitivity inreases CPU loading. # self.fft_rate = options.fft_rate self.fft_size = int(options.fft_size) # This buffer is used to remember the most-recent FFT display # values. Used later by self.write_spectral_data() to write # spectral data to datalogging files, and by the SETI analysis # function. # self.fft_outbuf = Numeric.zeros(self.fft_size, Numeric.Float64) # # If SETI mode, only look at seti_fft_bandwidth # at a time. # if (self.setimode): self.fft_input_rate = self.seti_fft_bandwidth # # Build a decimating bandpass filter # self.fft_input_taps = gr.firdes.complex_band_pass (1.0, input_rate, -(int(self.fft_input_rate/2)), int(self.fft_input_rate/2), 200, gr.firdes.WIN_HAMMING, 0) # # Compute required decimation factor # decimation = int(input_rate/self.fft_input_rate) self.fft_bandpass = gr.fir_filter_ccc (decimation, self.fft_input_taps) else: self.fft_input_rate = input_rate # Set up FFT display if self.waterfall == False: self.scope = ra_fftsink.ra_fft_sink_c (self, panel, fft_size=int(self.fft_size), sample_rate=self.fft_input_rate, fft_rate=int(self.fft_rate), title="Spectral", ofunc=self.fft_outfunc, xydfunc=self.xydfunc) else: self.scope = ra_waterfallsink.waterfall_sink_c (self, panel, fft_size=int(self.fft_size), sample_rate=self.fft_input_rate, fft_rate=int(self.fft_rate), title="Spectral", ofunc=self.fft_outfunc, size=(1100, 600), xydfunc=self.xydfunc, ref_level=0, span=10) # Set up ephemeris data self.locality = ephem.Observer() self.locality.long = str(options.longitude) self.locality.lat = str(options.latitude) # We make notes about Sunset/Sunrise in Continuum log files self.sun = ephem.Sun() self.sunstate = "??" # Set up stripchart display self.stripsize = int(options.stripsize) if self.setimode == False: self.chart = ra_stripchartsink.stripchart_sink_f (self, panel, stripsize=self.stripsize, title="Continuum", xlabel="LMST Offset (Seconds)", scaling=1.0, ylabel=options.ylabel, divbase=options.divbase) # Set center frequency self.centerfreq = options.freq # Set observing frequency (might be different from actual programmed # RF frequency) if options.observing == 0.0: self.observing = options.freq else: self.observing = options.observing 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 # # # Call constructors for receive chains # 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() # Signal probe 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) # # Start connecting configured modules in the receive chain # # 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) 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) 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) else: self.connect(self.u, self.detector, self.integrator1, self.integrator2, self.integrator3, self.cal_mult, self.cal_offs, self.chart) # current instantaneous integrated detector value self.connect(self.cal_offs, self.probe) self._build_gui(vbox) # Make GUI agree with command-line self.integ = options.integ if self.setimode == False: self.myform['integration'].set_value(int(options.integ)) self.myform['offset'].set_value(self.calib_offset) self.myform['dcgain'].set_value(self.calib_coeff) self.myform['average'].set_value(int(options.avg)) if self.setimode == False: # Make integrator agree with command line self.set_integration(int(options.integ)) self.avg_alpha = options.avg # 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) if self.setimode == False: # Set division size self.chart.set_y_per_div(options.division) # Set reference(MAX) level self.chart.set_ref_level(options.reflevel) # 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 # Set the initial gain control self.set_gain(options.gain) if not(self.set_freq(options.freq)): self._set_status_msg("Failed to set initial frequency") # Set declination self.set_decln (self.decln) # 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()) # 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) # Start the timer for the LMST display and datalogging self.lmst_timer.Start(1000)