diff options
Diffstat (limited to 'gr-uhd')
-rw-r--r-- | gr-uhd/apps/uhd_app.py | 85 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_fft | 24 | ||||
-rw-r--r-- | gr-uhd/doc/uhd.dox | 8 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_sink_impl.cc | 10 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_source_impl.cc | 10 |
5 files changed, 105 insertions, 32 deletions
diff --git a/gr-uhd/apps/uhd_app.py b/gr-uhd/apps/uhd_app.py index 8e377f0b4d..f9b08a6457 100644 --- a/gr-uhd/apps/uhd_app.py +++ b/gr-uhd/apps/uhd_app.py @@ -135,6 +135,15 @@ class UHDApp(object): )) return specs + def normalize_lo_source_export_sel(self, args): + lo_source = [x.strip() for x in args.lo_source.split(",")] + lo_export = [x.strip() for x in args.lo_export.split(",")] + if len(lo_source) != len(self.channels): + raise ValueError("Invalid number of lo-source settings {n} for {c} channels. Must be one argument per channel.".format(n=len(lo_source), c=len(args.channels))) + if len(lo_export) != len(self.channels): + raise ValueError("Invalid number of lo-export settings {n} for {c} channels. Must be one argument per channel.".format(n=len(lo_source), c=len(args.channels))) + return (lo_source, lo_export) + def async_callback(self, msg): """ Call this when USRP async metadata needs printing. @@ -187,23 +196,49 @@ class UHDApp(object): self.antenna = self.normalize_antenna_sel(args) if self.antenna is not None: for i, chan in enumerate(self.channels): - if not self.antenna[i] in self.usrp.get_antennas(chan): + if not self.antenna[i] in self.usrp.get_antennas(i): self.vprint("[ERROR] {} is not a valid antenna name for this USRP device!".format(self.antenna[i])) exit(1) - self.usrp.set_antenna(self.antenna[i], chan) + self.usrp.set_antenna(self.antenna[i], i) self.vprint("[{prefix}] Channel {chan}: Using antenna {ant}.".format( - prefix=self.prefix, chan=chan, ant=self.usrp.get_antenna(chan) + prefix=self.prefix, chan=chan, ant=self.usrp.get_antenna(i) )) - self.antenna = self.usrp.get_antenna(self.channels[0]) + self.antenna = self.usrp.get_antenna(0) # Set receive daughterboard gain: self.set_gain(args.gain) - self.gain_range = self.usrp.get_gain_range(self.channels[0]) + self.gain_range = self.usrp.get_gain_range(0) # Set frequency (tune request takes lo_offset): if hasattr(args, 'lo_offset') and args.lo_offset is not None: treq = uhd.tune_request(args.freq, args.lo_offset) else: treq = uhd.tune_request(args.freq) self.has_lo_sensor = 'lo_locked' in self.usrp.get_sensor_names() + # Set LO export and LO source operation + if (args.lo_export is not None) and (args.lo_source is not None): + (args.lo_source,args.lo_export) = self.normalize_lo_source_export_sel(args) + for chan,lo_source,lo_export in zip(self.channels,args.lo_source,args.lo_export): + if (lo_source == "None") or (lo_export == "None"): + continue + if lo_export == "True": + #If channel is LO source set frequency and store response + self.usrp.set_lo_export_enabled(True, uhd.ALL_LOS, chan) + if lo_source == "internal": + self.lo_source_channel = chan + tune_resp = self.usrp.set_center_freq(treq,chan) + self.usrp.set_lo_source(lo_source, uhd.ALL_LOS,chan) + # Use lo source tune response to tune dsp_freq on remaining channels + if getattr(args, 'lo_offset', None) is not None: + treq = uhd.tune_request(target_freq=args.freq, rf_freq=args.freq+args.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL, + dsp_freq=tune_resp.actual_dsp_freq, + dsp_freq_policy=uhd.tune_request.POLICY_MANUAL) + else: + treq = uhd.tune_request(target_freq=args.freq, rf_freq=args.freg, rf_freq_policy=uhd.tune_request.POLICY_MANUAL, + dsp_freq=tune_resp.actual_dsp_freq, + dsp_freq_policy=uhd.tune_request.POLICY_MANUAL) + for chan in args.channels: + if chan == self.lo_source_channel: + continue + self.usrp.set_center_freq(treq,chan) # Make sure tuning is synched: command_time_set = False if len(self.channels) > 1: @@ -216,8 +251,8 @@ class UHDApp(object): command_time_set = True except RuntimeError: sys.stderr.write('[{prefix}] [WARNING] Failed to set command times.\n'.format(prefix=self.prefix)) - for chan in self.channels: - self.tr = self.usrp.set_center_freq(treq, chan) + for i, chan in enumerate(self.channels): + self.tr = self.usrp.set_center_freq(treq, i) if self.tr == None: sys.stderr.write('[{prefix}] [ERROR] Failed to set center frequency on channel {chan}\n'.format( prefix=self.prefix, chan=chan @@ -228,7 +263,7 @@ class UHDApp(object): self.usrp.clear_command_time(mb_idx) self.vprint("Syncing channels...".format(prefix=self.prefix)) time.sleep(COMMAND_DELAY) - self.freq = self.usrp.get_center_freq(self.channels[0]) + self.freq = self.usrp.get_center_freq(0) if args.show_async_msg: self.async_msgq = gr.msg_queue(0) self.async_src = uhd.amsg_source("", self.async_msgq) @@ -243,17 +278,17 @@ class UHDApp(object): if gain is None: if self.args.verbose: self.vprint("Defaulting to mid-point gains:".format(prefix=self.prefix)) - for chan in self.channels: - self.usrp.set_normalized_gain(.5, chan) + for i, chan in enumerate(self.channels): + self.usrp.set_normalized_gain(.5, i) if self.args.verbose: self.vprint("Channel {chan} gain: {g} dB".format( - prefix=self.prefix, chan=chan, g=self.usrp.get_gain(chan) + prefix=self.prefix, chan=chan, g=self.usrp.get_gain(i) )) else: self.vprint("Setting gain to {g} dB.".format(g=gain)) - for chan in self.channels: + for chan in range( len( self.channels ) ): self.usrp.set_gain(gain, chan) - self.gain = self.usrp.get_gain(self.channels[0]) + self.gain = self.usrp.get_gain(0) def set_freq(self, freq, skip_sync=False): """ @@ -265,6 +300,22 @@ class UHDApp(object): treq = uhd.tune_request(freq, self.args.lo_offset) else: treq = uhd.tune_request(freq) + # Special TwinRX tuning due to LO sharing + if getattr(self, 'lo_source_channel', None) is not None: + tune_resp = self.usrp.set_center_freq(treq, self.lo_source_channel) + if getattr(self.args, 'lo_offset', None) is not None: + treq = uhd.tune_request(target_freq=freq, rf_freq=freq+self.args.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL, + dsp_freq=tune_resp.actual_dsp_freq, + dsp_freq_policy=uhd.tune_request.POLICY_MANUAL) + else: + treq = uhd.tune_request(target_freq=freq, rf_freq=freq, rf_freq_policy=uhd.tune_reqest.POLICY_MANUAL, + dsp_freq=tune_resp.actual_dsp_freq, + dsp_freq_policy=uhd.tune_request.POLICY_MANUAL) + for chan in self.channels: + if chan == self.lo_source_channel: + continue + self.usrp.set_center_freq(treq,chan) + # Make sure tuning is synched: command_time_set = False if len(self.channels) > 1 and not skip_sync: @@ -275,8 +326,8 @@ class UHDApp(object): command_time_set = True except RuntimeError: sys.stderr.write('[{prefix}] [WARNING] Failed to set command times.\n'.format(prefix=self.prefix)) - for chan in self.channels: - self.tr = self.usrp.set_center_freq(treq, chan) + for i, chan in enumerate(self.channels ): + self.tr = self.usrp.set_center_freq(treq, i) if self.tr == None: sys.stderr.write('[{prefix}] [ERROR] Failed to set center frequency on channel {chan}\n'.format( prefix=self.prefix, chan=chan @@ -287,7 +338,7 @@ class UHDApp(object): self.usrp.clear_command_time(mb_idx) self.vprint("Syncing channels...".format(prefix=self.prefix)) time.sleep(COMMAND_DELAY) - self.freq = self.usrp.get_center_freq(self.channels[0]) + self.freq = self.usrp.get_center_freq(0) self.vprint("First channel has freq: {freq} MHz.".format(freq=self.freq/1e6)) @staticmethod @@ -333,6 +384,8 @@ class UHDApp(object): if allow_mimo: group.add_argument("-c", "--channels", default=[0,], type=cslist, help="Select {xx} Channels".format(xx=tx_or_rx)) + group.add_argument("--lo-export", help="Set TwinRX LO export {None, True, False} for each channel with a comma-separated list. None skips a channel.") + group.add_argument("--lo-source", help="Set TwinRX LO source {None, internal, companion, external} for each channel with a comma-separated list. None skips this channel. ") group.add_argument("--otw-format", choices=['sc16', 'sc12', 'sc8'], default='sc16', help="Choose over-the-wire data format") group.add_argument("--stream-args", default="", help="Set additional stream arguments") diff --git a/gr-uhd/apps/uhd_fft b/gr-uhd/apps/uhd_fft index aa10cdf900..b65bb7a062 100755 --- a/gr-uhd/apps/uhd_fft +++ b/gr-uhd/apps/uhd_fft @@ -126,8 +126,8 @@ class uhd_fft(gr.top_block, Qt.QWidget, UHDApp): # Blocks ################################################## self.setup_usrp(uhd.usrp_source, args) - self._ant_options = self.usrp.get_antennas(self.channels[0]) - for c in self.channels: + self._ant_options = self.usrp.get_antennas(0) + for c in range(len(self.channels)): self.usrp.set_bandwidth(self.samp_rate, c) self.usrp_device_info = self.get_usrp_info_string(compact=True, tx_or_rx='rx') @@ -320,7 +320,7 @@ class uhd_fft(gr.top_block, Qt.QWidget, UHDApp): self.top_grid_layout.addWidget(self._lo_locked_probe_tool_bar, 4,0,1,2) def _current_freq_probe(): while True: - val = self.usrp.get_center_freq(self.channels[0]) + val = self.usrp.get_center_freq(0) try: if val != self.freq: self.set_freq_qt(val, tune_source='freqsink_msg') @@ -347,15 +347,15 @@ class uhd_fft(gr.top_block, Qt.QWidget, UHDApp): ################################################## self.msg_connect((self.qtgui_freq_sink_x_0, 'freq'), (self.qtgui_freq_sink_x_0, 'freq')) self.msg_connect((self.qtgui_freq_sink_x_0, 'freq'), (self.usrp, 'command')) - for c, idx in enumerate(self.channels): - self.connect((self.usrp, c), (self.qtgui_freq_sink_x_0, idx)) - self.connect((self.usrp, c), (self.qtgui_time_sink_x_0, idx)) - self.connect((self.usrp, c), (self.qtgui_waterfall_sink_x_0, idx)) + for idx in range(len(self.channels)): + self.connect((self.usrp, idx), (self.qtgui_freq_sink_x_0, idx)) + self.connect((self.usrp, idx), (self.qtgui_time_sink_x_0, idx)) + self.connect((self.usrp, idx), (self.qtgui_waterfall_sink_x_0, idx)) if args.phase_relations and len(self.channels) > 1: - for c, idx in enumerate(self.channels[:-1]): + for idx in range(len(self.channels[:-1])): self.connect_phase_plot( - (self.usrp, c), - (self.usrp, self.channels[idx+1]), + (self.usrp, idx), + (self.usrp, idx+1), (self.qtgui_phase_plot, idx) ) @@ -430,7 +430,7 @@ class uhd_fft(gr.top_block, Qt.QWidget, UHDApp): self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate) self.qtgui_waterfall_sink_x_0.set_frequency_range(self.freq, self.samp_rate) self.usrp.set_samp_rate(self.samp_rate) - for c in self.channels: + for c in range(len(self.channels)): self.usrp.set_bandwidth(self.samp_rate, c) def set_lo_locked_probe(self, lo_locked_probe): @@ -440,7 +440,7 @@ class uhd_fft(gr.top_block, Qt.QWidget, UHDApp): def set_ant(self, ant): self.antenna = ant self._ant_callback(self.antenna) - for c in self.channels: + for c in range(len(self.channels)): self.usrp.set_antenna(self.antenna, c) diff --git a/gr-uhd/doc/uhd.dox b/gr-uhd/doc/uhd.dox index 27a1475566..a3de8e3a24 100644 --- a/gr-uhd/doc/uhd.dox +++ b/gr-uhd/doc/uhd.dox @@ -57,8 +57,8 @@ which automatically sets the PMT types. Assume we only want to set the frequency (i.e. the second channel). In this case, we must construct a dictionary: \code{.cpp} pmt::pmt_t command = pmt::make_dict(); -pmt::dict_add(command, pmt::mp("freq"), pmt::mp(1.1e9)); // Specify frequency -pmt::dict_add(command, pmt::mp("chan"), pmt::mp(1)); // Specify channel +command = pmt::dict_add(command, pmt::mp("freq"), pmt::mp(1.1e9)); // Specify frequency +command = pmt::dict_add(command, pmt::mp("chan"), pmt::mp(1)); // Specify channel // Now pass 'command' into the USRP block's command port \endcode @@ -72,8 +72,8 @@ The main difference is that we can add more properties to the same command PMT, e.g. as such: \code{.cpp} // 'command' is the same PMT as in the previous example -pmt::dict_add(command, pmt::mp("gain"), pmt::mp(23.0)); // Specify gain -pmt::dict_add(command, pmt::mp("antenna"), pmt::mp("TX/RX")); // Switch antenna +command = pmt::dict_add(command, pmt::mp("gain"), pmt::mp(23.0)); // Specify gain +command = pmt::dict_add(command, pmt::mp("antenna"), pmt::mp("TX/RX")); // Switch antenna // Now pass 'command' into the USRP block's command port \endcode When the USRP block interprets this command PMT, all properties will be diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc index 6288b80cc8..4e2e9467dd 100644 --- a/gr-uhd/lib/usrp_sink_impl.cc +++ b/gr-uhd/lib/usrp_sink_impl.cc @@ -141,12 +141,16 @@ namespace gr { void usrp_sink_impl::set_normalized_gain(double norm_gain, size_t chan) { +#ifdef UHD_USRP_MULTI_USRP_NORMALIZED_GAIN + _dev->set_normalized_tx_gain(norm_gain, chan); +#else if (norm_gain > 1.0 || norm_gain < 0.0) { throw std::runtime_error("Normalized gain out of range, must be in [0, 1]."); } ::uhd::gain_range_t gain_range = get_gain_range(chan); double abs_gain = (norm_gain * (gain_range.stop() - gain_range.start())) + gain_range.start(); set_gain(abs_gain, chan); +#endif } double @@ -166,6 +170,9 @@ namespace gr { double usrp_sink_impl::get_normalized_gain(size_t chan) { +#ifdef UHD_USRP_MULTI_USRP_NORMALIZED_GAIN + return _dev->get_normalized_tx_gain(chan); +#else ::uhd::gain_range_t gain_range = get_gain_range(chan); double norm_gain = (get_gain(chan) - gain_range.start()) / @@ -174,6 +181,7 @@ namespace gr { if (norm_gain > 1.0) return 1.0; if (norm_gain < 0.0) return 0.0; return norm_gain; +#endif } std::vector<std::string> @@ -329,9 +337,11 @@ namespace gr { } //send all ninput_items with metadata + boost::this_thread::disable_interruption disable_interrupt; const size_t num_sent = _tx_stream->send( input_items, ninput_items, _metadata, 1.0 ); + boost::this_thread::restore_interruption restore_interrupt(disable_interrupt); //if using length_tags, decrement items left to send by the number of samples sent if(not pmt::is_null(_length_tag_key) && _nitems_to_send > 0) { diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc index c840c43db1..8cdaebc4ca 100644 --- a/gr-uhd/lib/usrp_source_impl.cc +++ b/gr-uhd/lib/usrp_source_impl.cc @@ -154,12 +154,16 @@ namespace gr { void usrp_source_impl::set_normalized_gain(double norm_gain, size_t chan) { +#ifdef UHD_USRP_MULTI_USRP_NORMALIZED_GAIN + _dev->set_normalized_rx_gain(norm_gain, chan); +#else if (norm_gain > 1.0 || norm_gain < 0.0) { throw std::runtime_error("Normalized gain out of range, must be in [0, 1]."); } ::uhd::gain_range_t gain_range = get_gain_range(chan); double abs_gain = (norm_gain * (gain_range.stop() - gain_range.start())) + gain_range.start(); set_gain(abs_gain, chan); +#endif } double @@ -179,6 +183,9 @@ namespace gr { double usrp_source_impl::get_normalized_gain(size_t chan) { +#ifdef UHD_USRP_MULTI_USRP_NORMALIZED_GAIN + return _dev->get_normalized_rx_gain(chan); +#else ::uhd::gain_range_t gain_range = get_gain_range(chan); double norm_gain = (get_gain(chan) - gain_range.start()) / @@ -187,6 +194,7 @@ namespace gr { if (norm_gain > 1.0) return 1.0; if (norm_gain < 0.0) return 0.0; return norm_gain; +#endif } std::vector<std::string> @@ -553,6 +561,7 @@ namespace gr { gr_vector_void_star &output_items) { boost::recursive_mutex::scoped_lock lock(d_mutex); + boost::this_thread::disable_interruption disable_interrupt; //In order to allow for low-latency: //We receive all available packets without timeout. //This call can timeout under regular operation... @@ -563,6 +572,7 @@ namespace gr { _recv_timeout, true /* one packet -> minimize latency */ ); + boost::this_thread::restore_interruption restore_interrupt(disable_interrupt); //handle possible errors conditions switch(_metadata.error_code) { |