2010-10-17 01:07:10 +00:00
//
2013-07-15 22:48:51 +00:00
// Copyright 2010-2013 Ettus Research LLC
2010-10-17 01:07:10 +00:00
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
2011-06-29 02:10:55 +00:00
# include <uhd/property_tree.hpp>
2010-10-17 01:07:10 +00:00
# include <uhd/usrp/multi_usrp.hpp>
2011-05-05 02:53:01 +00:00
# include <uhd/utils/msg.hpp>
2011-02-24 22:54:24 +00:00
# include <uhd/exception.hpp>
2013-07-15 22:48:51 +00:00
# include <uhd/utils/log.hpp>
2010-10-17 01:07:10 +00:00
# include <uhd/utils/gain_group.hpp>
2012-04-05 00:03:35 +00:00
# include <uhd/usrp/dboard_id.hpp>
# include <uhd/usrp/mboard_eeprom.hpp>
# include <uhd/usrp/dboard_eeprom.hpp>
2014-02-28 17:14:31 +00:00
# include <uhd/convert.hpp>
2012-04-05 00:03:35 +00:00
# include <boost/assign/list_of.hpp>
2010-10-17 01:07:10 +00:00
# include <boost/thread.hpp>
# include <boost/foreach.hpp>
# include <boost/format.hpp>
2011-03-10 19:56:52 +00:00
# include <cmath>
2010-10-17 01:07:10 +00:00
using namespace uhd ;
using namespace uhd : : usrp ;
2010-10-20 23:20:36 +00:00
const std : : string multi_usrp : : ALL_GAINS = " " ;
2014-02-22 02:08:56 +00:00
UHD_INLINE std : : string string_vector_to_string ( std : : vector < std : : string > values , std : : string delimiter = std : : string ( " " ) )
2014-01-30 23:20:49 +00:00
{
std : : string out = " " ;
for ( std : : vector < std : : string > : : iterator iter = values . begin ( ) ; iter ! = values . end ( ) ; iter + + )
2014-02-22 02:08:56 +00:00
{
out + = ( iter ! = values . begin ( ) ? delimiter : " " ) + * iter ;
}
2014-01-30 23:20:49 +00:00
return out ;
}
2014-02-22 02:08:56 +00:00
# define THROW_GAIN_NAME_ERROR(name,chan,dir) throw uhd::exception::runtime_error( \
( boost : : format ( " %s: gain \" %s \" not found for channel %d. \n Available gains: %s \n " ) % \
__FUNCTION__ % name % chan % string_vector_to_string ( get_ # # dir # # _gain_names ( chan ) ) ) . str ( ) ) ;
2010-10-17 01:07:10 +00:00
/***********************************************************************
2011-03-10 19:56:52 +00:00
* Helper methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-06-29 02:10:55 +00:00
static void do_samp_rate_warning_message (
2011-03-10 19:56:52 +00:00
double target_rate ,
double actual_rate ,
const std : : string & xx
) {
static const double max_allowed_error = 1.0 ; //Sps
if ( std : : abs ( target_rate - actual_rate ) > max_allowed_error ) {
2011-05-05 01:36:10 +00:00
UHD_MSG ( warning ) < < boost : : format (
2011-03-10 19:56:52 +00:00
" The hardware does not support the requested %s sample rate: \n "
" Target sample rate: %f MSps \n "
" Actual sample rate: %f MSps \n "
2011-05-05 01:36:10 +00:00
) % xx % ( target_rate / 1e6 ) % ( actual_rate / 1e6 ) ;
2011-03-10 19:56:52 +00:00
}
}
2011-06-29 02:10:55 +00:00
static void do_tune_freq_warning_message (
2011-11-11 01:29:18 +00:00
const tune_request_t & tune_req ,
2011-03-10 19:56:52 +00:00
double actual_freq ,
const std : : string & xx
) {
2011-11-11 01:29:18 +00:00
//forget the warning when manual policy
if ( tune_req . dsp_freq_policy = = tune_request_t : : POLICY_MANUAL ) return ;
if ( tune_req . rf_freq_policy = = tune_request_t : : POLICY_MANUAL ) return ;
const double target_freq = tune_req . target_freq ;
2011-03-10 19:56:52 +00:00
static const double max_allowed_error = 1.0 ; //Hz
if ( std : : abs ( target_freq - actual_freq ) > max_allowed_error ) {
2011-05-05 01:36:10 +00:00
UHD_MSG ( warning ) < < boost : : format (
2011-03-10 19:56:52 +00:00
" The hardware does not support the requested %s frequency: \n "
" Target frequency: %f MHz \n "
" Actual frequency: %f MHz \n "
2011-05-05 01:36:10 +00:00
) % xx % ( target_freq / 1e6 ) % ( actual_freq / 1e6 ) ;
2011-03-10 19:56:52 +00:00
}
}
2011-08-18 00:09:55 +00:00
static meta_range_t make_overall_tune_range (
const meta_range_t & fe_range ,
const meta_range_t & dsp_range ,
const double bw
) {
2011-08-29 16:43:54 +00:00
meta_range_t range ;
BOOST_FOREACH ( const range_t & sub_range , fe_range ) {
range . push_back ( range_t (
2013-08-23 22:16:52 +00:00
sub_range . start ( ) + std : : max ( dsp_range . start ( ) , - bw / 2 ) ,
sub_range . stop ( ) + std : : min ( dsp_range . stop ( ) , bw / 2 ) ,
2011-08-29 16:43:54 +00:00
dsp_range . step ( )
) ) ;
}
return range ;
2011-08-18 00:09:55 +00:00
}
2014-02-28 17:14:31 +00:00
2011-06-29 17:54:28 +00:00
/***********************************************************************
* Gain helper functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-07-08 17:08:43 +00:00
static double get_gain_value ( property_tree : : sptr subtree ) {
return subtree - > access < double > ( " value " ) . get ( ) ;
2011-06-29 02:10:55 +00:00
}
2011-07-08 17:08:43 +00:00
static void set_gain_value ( property_tree : : sptr subtree , const double gain ) {
subtree - > access < double > ( " value " ) . set ( gain ) ;
2011-06-29 02:10:55 +00:00
}
2011-07-08 17:08:43 +00:00
static meta_range_t get_gain_range ( property_tree : : sptr subtree ) {
return subtree - > access < meta_range_t > ( " range " ) . get ( ) ;
2011-06-29 02:10:55 +00:00
}
2011-07-08 17:08:43 +00:00
static gain_fcns_t make_gain_fcns_from_subtree ( property_tree : : sptr subtree ) {
2011-06-29 02:10:55 +00:00
gain_fcns_t gain_fcns ;
2011-07-08 17:08:43 +00:00
gain_fcns . get_range = boost : : bind ( & get_gain_range , subtree ) ;
gain_fcns . get_value = boost : : bind ( & get_gain_value , subtree ) ;
gain_fcns . set_value = boost : : bind ( & set_gain_value , subtree , _1 ) ;
2011-06-29 02:10:55 +00:00
return gain_fcns ;
}
2011-06-29 17:54:28 +00:00
/***********************************************************************
* Tune Helper Functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const double RX_SIGN = + 1.0 ;
static const double TX_SIGN = - 1.0 ;
static tune_result_t tune_xx_subdev_and_dsp (
const double xx_sign ,
2011-07-08 17:08:43 +00:00
property_tree : : sptr dsp_subtree ,
property_tree : : sptr rf_fe_subtree ,
2011-06-29 17:54:28 +00:00
const tune_request_t & tune_request
) {
//------------------------------------------------------------------
//-- calculate the LO offset, only used with automatic policy
//------------------------------------------------------------------
double lo_offset = 0.0 ;
2011-07-08 17:08:43 +00:00
if ( rf_fe_subtree - > access < bool > ( " use_lo_offset " ) . get ( ) ) {
2011-12-13 16:15:02 +00:00
//If the frontend has lo_offset value and range properties, trust it for lo_offset
if ( rf_fe_subtree - > exists ( " lo_offset/value " ) ) lo_offset = rf_fe_subtree - > access < double > ( " lo_offset/value " ) . get ( ) ;
2011-06-29 17:54:28 +00:00
//If the local oscillator will be in the passband, use an offset.
//But constrain the LO offset by the width of the filter bandwidth.
2011-07-08 17:08:43 +00:00
const double rate = dsp_subtree - > access < double > ( " rate/value " ) . get ( ) ;
const double bw = rf_fe_subtree - > access < double > ( " bandwidth/value " ) . get ( ) ;
2011-06-29 17:54:28 +00:00
if ( bw > rate ) lo_offset = std : : min ( ( bw - rate ) / 2 , rate / 2 ) ;
}
2012-11-09 02:46:57 +00:00
//------------------------------------------------------------------
//-- poke the tune request args into the dboard
//------------------------------------------------------------------
if ( rf_fe_subtree - > exists ( " tune_args " ) )
{
rf_fe_subtree - > access < device_addr_t > ( " tune_args " ) . set ( tune_request . args ) ;
}
2011-06-29 17:54:28 +00:00
//------------------------------------------------------------------
//-- set the RF frequency depending upon the policy
//------------------------------------------------------------------
double target_rf_freq = 0.0 ;
switch ( tune_request . rf_freq_policy ) {
case tune_request_t : : POLICY_AUTO :
target_rf_freq = tune_request . target_freq + lo_offset ;
2011-07-08 17:08:43 +00:00
rf_fe_subtree - > access < double > ( " freq/value " ) . set ( target_rf_freq ) ;
2011-06-29 17:54:28 +00:00
break ;
case tune_request_t : : POLICY_MANUAL :
2011-12-13 16:15:02 +00:00
//If the rf_fe understands lo_offset settings, infer the desired lo_offset and set it
// Side effect: In TVRX2 for example, after setting the lo_offset (if_freq) with a
// POLICY_MANUAL, there is no way for the user to automatically get back to default
// if_freq without deconstruct/reconstruct the rf_fe objects.
if ( rf_fe_subtree - > exists ( " lo_offset/value " ) ) {
rf_fe_subtree - > access < double > ( " lo_offset/value " ) . set ( tune_request . rf_freq - tune_request . target_freq ) ;
}
2011-06-29 17:54:28 +00:00
target_rf_freq = tune_request . rf_freq ;
2011-07-08 17:08:43 +00:00
rf_fe_subtree - > access < double > ( " freq/value " ) . set ( target_rf_freq ) ;
2011-06-29 17:54:28 +00:00
break ;
case tune_request_t : : POLICY_NONE : break ; //does not set
}
2011-07-08 17:08:43 +00:00
const double actual_rf_freq = rf_fe_subtree - > access < double > ( " freq/value " ) . get ( ) ;
2011-06-29 17:54:28 +00:00
//------------------------------------------------------------------
//-- calculate the dsp freq, only used with automatic policy
//------------------------------------------------------------------
double target_dsp_freq = actual_rf_freq - tune_request . target_freq ;
//invert the sign on the dsp freq for transmit
target_dsp_freq * = xx_sign ;
//------------------------------------------------------------------
//-- set the dsp frequency depending upon the dsp frequency policy
//------------------------------------------------------------------
switch ( tune_request . dsp_freq_policy ) {
case tune_request_t : : POLICY_AUTO :
2011-07-08 17:08:43 +00:00
dsp_subtree - > access < double > ( " freq/value " ) . set ( target_dsp_freq ) ;
2011-06-29 17:54:28 +00:00
break ;
case tune_request_t : : POLICY_MANUAL :
target_dsp_freq = tune_request . dsp_freq ;
2011-07-08 17:08:43 +00:00
dsp_subtree - > access < double > ( " freq/value " ) . set ( target_dsp_freq ) ;
2011-06-29 17:54:28 +00:00
break ;
case tune_request_t : : POLICY_NONE : break ; //does not set
}
2011-07-08 17:08:43 +00:00
const double actual_dsp_freq = dsp_subtree - > access < double > ( " freq/value " ) . get ( ) ;
2011-06-29 17:54:28 +00:00
//------------------------------------------------------------------
//-- load and return the tune result
//------------------------------------------------------------------
tune_result_t tune_result ;
tune_result . target_rf_freq = target_rf_freq ;
tune_result . actual_rf_freq = actual_rf_freq ;
tune_result . target_dsp_freq = target_dsp_freq ;
tune_result . actual_dsp_freq = actual_dsp_freq ;
return tune_result ;
}
static double derive_freq_from_xx_subdev_and_dsp (
const double xx_sign ,
2011-07-08 17:08:43 +00:00
property_tree : : sptr dsp_subtree ,
property_tree : : sptr rf_fe_subtree
2011-06-29 17:54:28 +00:00
) {
//extract actual dsp and IF frequencies
2011-07-08 17:08:43 +00:00
const double actual_rf_freq = rf_fe_subtree - > access < double > ( " freq/value " ) . get ( ) ;
const double actual_dsp_freq = dsp_subtree - > access < double > ( " freq/value " ) . get ( ) ;
2011-06-29 17:54:28 +00:00
//invert the sign on the dsp freq for transmit
return actual_rf_freq - actual_dsp_freq * xx_sign ;
}
2011-03-10 19:56:52 +00:00
/***********************************************************************
* Multi USRP Implementation
2010-10-17 01:07:10 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class multi_usrp_impl : public multi_usrp {
public :
multi_usrp_impl ( const device_addr_t & addr ) {
2014-07-17 18:50:50 +00:00
_dev = device : : make ( addr , device : : USRP ) ;
2011-09-14 17:14:29 +00:00
_tree = _dev - > get_tree ( ) ;
2010-10-17 01:07:10 +00:00
}
device : : sptr get_device ( void ) {
return _dev ;
}
2012-04-05 00:03:35 +00:00
dict < std : : string , std : : string > get_usrp_rx_info ( size_t chan ) {
mboard_chan_pair mcp = rx_chan_to_mcp ( chan ) ;
dict < std : : string , std : : string > usrp_info ;
mboard_eeprom_t mb_eeprom = _tree - > access < mboard_eeprom_t > ( mb_root ( mcp . mboard ) / " eeprom " ) . get ( ) ;
dboard_eeprom_t db_eeprom = _tree - > access < dboard_eeprom_t > ( rx_rf_fe_root ( mcp . chan ) . branch_path ( ) . branch_path ( ) / " rx_eeprom " ) . get ( ) ;
usrp_info [ " mboard_id " ] = _tree - > access < std : : string > ( mb_root ( mcp . mboard ) / " name " ) . get ( ) ;
usrp_info [ " mboard_name " ] = mb_eeprom [ " name " ] ;
usrp_info [ " mboard_serial " ] = mb_eeprom [ " serial " ] ;
usrp_info [ " rx_id " ] = db_eeprom . id . to_pp_string ( ) ;
2012-04-05 17:40:07 +00:00
usrp_info [ " rx_subdev_name " ] = _tree - > access < std : : string > ( rx_rf_fe_root ( mcp . chan ) / " name " ) . get ( ) ;
usrp_info [ " rx_subdev_spec " ] = _tree - > access < subdev_spec_t > ( mb_root ( mcp . mboard ) / " rx_subdev_spec " ) . get ( ) . to_string ( ) ;
2012-04-05 00:03:35 +00:00
usrp_info [ " rx_serial " ] = db_eeprom . serial ;
2012-04-05 17:40:07 +00:00
usrp_info [ " rx_antenna " ] = _tree - > access < std : : string > ( rx_rf_fe_root ( mcp . chan ) / " antenna " / " value " ) . get ( ) ;
2012-04-05 00:03:35 +00:00
return usrp_info ;
}
dict < std : : string , std : : string > get_usrp_tx_info ( size_t chan ) {
mboard_chan_pair mcp = tx_chan_to_mcp ( chan ) ;
dict < std : : string , std : : string > usrp_info ;
mboard_eeprom_t mb_eeprom = _tree - > access < mboard_eeprom_t > ( mb_root ( mcp . mboard ) / " eeprom " ) . get ( ) ;
2012-04-17 19:19:05 +00:00
dboard_eeprom_t db_eeprom = _tree - > access < dboard_eeprom_t > ( tx_rf_fe_root ( mcp . chan ) . branch_path ( ) . branch_path ( ) / " tx_eeprom " ) . get ( ) ;
2012-04-05 00:03:35 +00:00
usrp_info [ " mboard_id " ] = _tree - > access < std : : string > ( mb_root ( mcp . mboard ) / " name " ) . get ( ) ;
usrp_info [ " mboard_name " ] = mb_eeprom [ " name " ] ;
usrp_info [ " mboard_serial " ] = mb_eeprom [ " serial " ] ;
usrp_info [ " tx_id " ] = db_eeprom . id . to_pp_string ( ) ;
usrp_info [ " tx_subdev_name " ] = _tree - > access < std : : string > ( tx_rf_fe_root ( mcp . chan ) / " name " ) . get ( ) ;
2012-04-05 17:40:07 +00:00
usrp_info [ " tx_subdev_spec " ] = _tree - > access < subdev_spec_t > ( mb_root ( mcp . mboard ) / " tx_subdev_spec " ) . get ( ) . to_string ( ) ;
2012-04-05 00:03:35 +00:00
usrp_info [ " tx_serial " ] = db_eeprom . serial ;
2012-04-05 18:18:23 +00:00
usrp_info [ " tx_antenna " ] = _tree - > access < std : : string > ( tx_rf_fe_root ( mcp . chan ) / " antenna " / " value " ) . get ( ) ;
2012-04-05 00:03:35 +00:00
return usrp_info ;
}
2010-10-17 01:07:10 +00:00
/*******************************************************************
* Mboard methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-02-01 00:29:12 +00:00
void set_master_clock_rate ( double rate , size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
2011-06-29 02:10:55 +00:00
_tree - > access < double > ( mb_root ( mboard ) / " tick_rate " ) . set ( rate ) ;
2011-02-01 00:29:12 +00:00
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
set_master_clock_rate ( rate , m ) ;
}
}
double get_master_clock_rate ( size_t mboard ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < double > ( mb_root ( mboard ) / " tick_rate " ) . get ( ) ;
2011-02-01 00:29:12 +00:00
}
2010-10-17 01:07:10 +00:00
std : : string get_pp_string ( void ) {
2011-06-29 18:03:20 +00:00
std : : string buff = str ( boost : : format (
" %s USRP: \n "
" Device: %s \n "
)
% ( ( get_num_mboards ( ) > 1 ) ? " Multi " : " Single " )
% ( _tree - > access < std : : string > ( " /name " ) . get ( ) )
) ;
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
buff + = str ( boost : : format (
" Mboard %d: %s \n "
) % m
% ( _tree - > access < std : : string > ( mb_root ( m ) / " name " ) . get ( ) )
) ;
}
//----------- rx side of life ----------------------------------
for ( size_t m = 0 , chan = 0 ; m < get_num_mboards ( ) ; m + + ) {
for ( ; chan < ( m + 1 ) * get_rx_subdev_spec ( m ) . size ( ) ; chan + + ) {
buff + = str ( boost : : format (
" RX Channel: %u \n "
" RX DSP: %s \n "
" RX Dboard: %s \n "
" RX Subdev: %s \n "
) % chan
% rx_dsp_root ( chan ) . leaf ( )
% rx_rf_fe_root ( chan ) . branch_path ( ) . branch_path ( ) . leaf ( )
% ( _tree - > access < std : : string > ( rx_rf_fe_root ( chan ) / " name " ) . get ( ) )
) ;
}
}
//----------- tx side of life ----------------------------------
for ( size_t m = 0 , chan = 0 ; m < get_num_mboards ( ) ; m + + ) {
for ( ; chan < ( m + 1 ) * get_tx_subdev_spec ( m ) . size ( ) ; chan + + ) {
buff + = str ( boost : : format (
" TX Channel: %u \n "
" TX DSP: %s \n "
" TX Dboard: %s \n "
" TX Subdev: %s \n "
) % chan
% tx_dsp_root ( chan ) . leaf ( )
% tx_rf_fe_root ( chan ) . branch_path ( ) . branch_path ( ) . leaf ( )
% ( _tree - > access < std : : string > ( tx_rf_fe_root ( chan ) / " name " ) . get ( ) )
) ;
}
}
return buff ;
2010-10-17 01:07:10 +00:00
}
std : : string get_mboard_name ( size_t mboard ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < std : : string > ( mb_root ( mboard ) / " name " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-02-11 18:29:59 +00:00
time_spec_t get_time_now ( size_t mboard = 0 ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < time_spec_t > ( mb_root ( mboard ) / " time/now " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-02-11 18:29:59 +00:00
time_spec_t get_time_last_pps ( size_t mboard = 0 ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < time_spec_t > ( mb_root ( mboard ) / " time/pps " ) . get ( ) ;
2010-12-31 00:41:38 +00:00
}
2011-01-27 23:24:47 +00:00
void set_time_now ( const time_spec_t & time_spec , size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
2011-06-29 02:10:55 +00:00
_tree - > access < time_spec_t > ( mb_root ( mboard ) / " time/now " ) . set ( time_spec ) ;
2011-01-27 23:24:47 +00:00
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
set_time_now ( time_spec , m ) ;
}
}
2011-12-12 20:49:40 +00:00
void set_time_next_pps ( const time_spec_t & time_spec , size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
_tree - > access < time_spec_t > ( mb_root ( mboard ) / " time/pps " ) . set ( time_spec ) ;
return ;
}
2010-10-17 01:07:10 +00:00
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
2011-12-12 20:49:40 +00:00
set_time_next_pps ( time_spec , m ) ;
2010-10-17 01:07:10 +00:00
}
}
void set_time_unknown_pps ( const time_spec_t & time_spec ) {
2011-05-05 02:53:01 +00:00
UHD_MSG ( status ) < < " 1) catch time transition at pps edge " < < std : : endl ;
2014-08-09 00:40:54 +00:00
boost : : system_time end_time = boost : : get_system_time ( ) + boost : : posix_time : : milliseconds ( 1100 ) ;
2010-12-31 00:41:38 +00:00
time_spec_t time_start_last_pps = get_time_last_pps ( ) ;
2014-08-09 00:40:54 +00:00
while ( time_start_last_pps = = get_time_last_pps ( ) )
{
if ( boost : : get_system_time ( ) > end_time )
{
2011-02-25 00:35:29 +00:00
throw uhd : : runtime_error (
2011-01-07 20:07:06 +00:00
" Board 0 may not be getting a PPS signal! \n "
" No PPS detected within the time interval. \n "
" See the application notes for your device. \n "
2010-12-31 00:41:38 +00:00
) ;
}
2014-08-09 00:40:54 +00:00
boost : : this_thread : : sleep ( boost : : posix_time : : milliseconds ( 1 ) ) ;
2010-10-17 01:07:10 +00:00
}
2011-05-05 02:53:01 +00:00
UHD_MSG ( status ) < < " 2) set times next pps (synchronously) " < < std : : endl ;
2011-12-12 20:49:40 +00:00
set_time_next_pps ( time_spec , ALL_MBOARDS ) ;
2010-10-17 01:07:10 +00:00
boost : : this_thread : : sleep ( boost : : posix_time : : seconds ( 1 ) ) ;
//verify that the time registers are read to be within a few RTT
for ( size_t m = 1 ; m < get_num_mboards ( ) ; m + + ) {
2011-06-29 02:10:55 +00:00
time_spec_t time_0 = this - > get_time_now ( 0 ) ;
time_spec_t time_i = this - > get_time_now ( m ) ;
2010-10-17 01:07:10 +00:00
if ( time_i < time_0 or ( time_i - time_0 ) > time_spec_t ( 0.01 ) ) { //10 ms: greater than RTT but not too big
2011-05-05 01:36:10 +00:00
UHD_MSG ( warning ) < < boost : : format (
2010-10-17 01:07:10 +00:00
" Detected time deviation between board %d and board 0. \n "
" Board 0 time is %f seconds. \n "
" Board %d time is %f seconds. \n "
2011-05-05 01:36:10 +00:00
) % m % time_0 . get_real_secs ( ) % m % time_i . get_real_secs ( ) ;
2010-10-17 01:07:10 +00:00
}
}
}
2010-10-27 17:45:15 +00:00
bool get_time_synchronized ( void ) {
for ( size_t m = 1 ; m < get_num_mboards ( ) ; m + + ) {
2011-06-29 02:10:55 +00:00
time_spec_t time_0 = this - > get_time_now ( 0 ) ;
time_spec_t time_i = this - > get_time_now ( m ) ;
2010-10-27 17:45:15 +00:00
if ( time_i < time_0 or ( time_i - time_0 ) > time_spec_t ( 0.01 ) ) return false ;
}
return true ;
}
2012-03-02 02:35:12 +00:00
void set_command_time ( const time_spec_t & time_spec , size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
2012-03-12 01:35:52 +00:00
if ( not _tree - > exists ( mb_root ( mboard ) / " time/cmd " ) ) {
throw uhd : : not_implemented_error ( " timed command feature not implemented on this hardware " ) ;
}
2012-03-02 02:35:12 +00:00
_tree - > access < time_spec_t > ( mb_root ( mboard ) / " time/cmd " ) . set ( time_spec ) ;
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
set_command_time ( time_spec , m ) ;
}
2011-11-04 03:29:18 +00:00
}
2012-03-02 02:35:12 +00:00
void clear_command_time ( size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
_tree - > access < time_spec_t > ( mb_root ( mboard ) / " time/cmd " ) . set ( time_spec_t ( 0.0 ) ) ;
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
clear_command_time ( m ) ;
}
2011-10-26 01:04:32 +00:00
}
2011-02-18 00:44:31 +00:00
void issue_stream_cmd ( const stream_cmd_t & stream_cmd , size_t chan ) {
if ( chan ! = ALL_CHANS ) {
2011-06-29 02:10:55 +00:00
_tree - > access < stream_cmd_t > ( rx_dsp_root ( chan ) / " stream_cmd " ) . set ( stream_cmd ) ;
2011-02-18 00:44:31 +00:00
return ;
}
2011-02-18 02:55:55 +00:00
for ( size_t c = 0 ; c < get_rx_num_channels ( ) ; c + + ) {
2011-02-18 00:44:31 +00:00
issue_stream_cmd ( stream_cmd , c ) ;
2010-10-17 01:07:10 +00:00
}
}
void set_clock_config ( const clock_config_t & clock_config , size_t mboard ) {
2011-10-12 16:59:41 +00:00
//set the reference source...
std : : string clock_source ;
switch ( clock_config . ref_source ) {
case clock_config_t : : REF_INT : clock_source = " internal " ; break ;
2012-04-06 19:07:15 +00:00
case clock_config_t : : REF_SMA : clock_source = " external " ; break ;
case clock_config_t : : REF_MIMO : clock_source = " mimo " ; break ;
2011-10-12 16:59:41 +00:00
default : clock_source = " unknown " ;
}
this - > set_clock_source ( clock_source , mboard ) ;
//set the time source
std : : string time_source ;
switch ( clock_config . pps_source ) {
case clock_config_t : : PPS_INT : time_source = " internal " ; break ;
case clock_config_t : : PPS_SMA : time_source = " external " ; break ;
case clock_config_t : : PPS_MIMO : time_source = " mimo " ; break ;
default : time_source = " unknown " ;
}
if ( time_source = = " external " and clock_config . pps_polarity = = clock_config_t : : PPS_NEG ) time_source = " _external_ " ;
this - > set_time_source ( time_source , mboard ) ;
}
void set_time_source ( const std : : string & source , const size_t mboard ) {
2010-10-17 01:07:10 +00:00
if ( mboard ! = ALL_MBOARDS ) {
2011-10-12 16:59:41 +00:00
_tree - > access < std : : string > ( mb_root ( mboard ) / " time_source " / " value " ) . set ( source ) ;
2010-10-17 01:07:10 +00:00
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
2012-03-12 19:10:41 +00:00
this - > set_time_source ( source , m ) ;
2010-10-17 01:07:10 +00:00
}
}
2011-10-12 16:59:41 +00:00
std : : string get_time_source ( const size_t mboard ) {
return _tree - > access < std : : string > ( mb_root ( mboard ) / " time_source " / " value " ) . get ( ) ;
}
std : : vector < std : : string > get_time_sources ( const size_t mboard ) {
return _tree - > access < std : : vector < std : : string > > ( mb_root ( mboard ) / " time_source " / " options " ) . get ( ) ;
}
void set_clock_source ( const std : : string & source , const size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
_tree - > access < std : : string > ( mb_root ( mboard ) / " clock_source " / " value " ) . set ( source ) ;
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
2012-03-12 19:10:41 +00:00
this - > set_clock_source ( source , m ) ;
2011-10-12 16:59:41 +00:00
}
}
std : : string get_clock_source ( const size_t mboard ) {
return _tree - > access < std : : string > ( mb_root ( mboard ) / " clock_source " / " value " ) . get ( ) ;
}
std : : vector < std : : string > get_clock_sources ( const size_t mboard ) {
return _tree - > access < std : : vector < std : : string > > ( mb_root ( mboard ) / " clock_source " / " options " ) . get ( ) ;
}
2014-02-04 19:04:07 +00:00
void set_clock_source_out ( const bool enb , const size_t mboard )
{
if ( mboard ! = ALL_MBOARDS )
{
if ( _tree - > exists ( mb_root ( mboard ) / " clock_source " / " output " ) )
{
_tree - > access < bool > ( mb_root ( mboard ) / " clock_source " / " output " ) . set ( enb ) ;
}
else
{
throw uhd : : runtime_error ( " multi_usrp::set_clock_source_out - not supported on this device " ) ;
}
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + )
{
this - > set_clock_source_out ( enb , m ) ;
}
}
void set_time_source_out ( const bool enb , const size_t mboard )
{
if ( mboard ! = ALL_MBOARDS )
{
if ( _tree - > exists ( mb_root ( mboard ) / " time_source " / " output " ) )
{
_tree - > access < bool > ( mb_root ( mboard ) / " time_source " / " output " ) . set ( enb ) ;
}
else
{
throw uhd : : runtime_error ( " multi_usrp::set_time_source_out - not supported on this device " ) ;
}
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + )
{
this - > set_time_source_out ( enb , m ) ;
}
}
2010-10-17 01:07:10 +00:00
size_t get_num_mboards ( void ) {
2011-06-29 02:10:55 +00:00
return _tree - > list ( " /mboards " ) . size ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-02-12 02:07:24 +00:00
sensor_value_t get_mboard_sensor ( const std : : string & name , size_t mboard ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < sensor_value_t > ( mb_root ( mboard ) / " sensors " / name ) . get ( ) ;
2011-02-12 02:07:24 +00:00
}
std : : vector < std : : string > get_mboard_sensor_names ( size_t mboard ) {
2011-06-29 02:10:55 +00:00
return _tree - > list ( mb_root ( mboard ) / " sensors " ) ;
2011-02-12 02:07:24 +00:00
}
2011-06-29 02:10:55 +00:00
2012-01-29 01:21:40 +00:00
void set_user_register ( const boost : : uint8_t addr , const boost : : uint32_t data , size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
typedef std : : pair < boost : : uint8_t , boost : : uint32_t > user_reg_t ;
2012-03-22 01:13:36 +00:00
_tree - > access < user_reg_t > ( mb_root ( mboard ) / " user/regs " ) . set ( user_reg_t ( addr , data ) ) ;
2012-01-29 01:21:40 +00:00
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
set_user_register ( addr , data , m ) ;
}
}
2010-10-17 01:07:10 +00:00
/*******************************************************************
* RX methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-02-28 17:14:31 +00:00
rx_streamer : : sptr get_rx_stream ( const stream_args_t & args ) {
_check_link_rate ( args , false ) ;
return this - > get_device ( ) - > get_rx_stream ( args ) ;
}
2010-10-17 01:07:10 +00:00
void set_rx_subdev_spec ( const subdev_spec_t & spec , size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
2011-06-29 02:10:55 +00:00
_tree - > access < subdev_spec_t > ( mb_root ( mboard ) / " rx_subdev_spec " ) . set ( spec ) ;
2010-10-17 01:07:10 +00:00
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
set_rx_subdev_spec ( spec , m ) ;
}
}
2013-07-15 22:48:51 +00:00
subdev_spec_t get_rx_subdev_spec ( size_t mboard )
{
subdev_spec_t spec = _tree - > access < subdev_spec_t > ( mb_root ( mboard ) / " rx_subdev_spec " ) . get ( ) ;
if ( spec . empty ( ) )
{
try
{
const std : : string db_name = _tree - > list ( mb_root ( mboard ) / " dboards " ) . at ( 0 ) ;
const std : : string fe_name = _tree - > list ( mb_root ( mboard ) / " dboards " / db_name / " rx_frontends " ) . at ( 0 ) ;
spec . push_back ( subdev_spec_pair_t ( db_name , fe_name ) ) ;
_tree - > access < subdev_spec_t > ( mb_root ( mboard ) / " rx_subdev_spec " ) . set ( spec ) ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::get_rx_subdev_spec(%u) failed to make default spec - %s " ) % mboard % e . what ( ) ) ) ;
}
UHD_MSG ( status ) < < " Selecting default RX front end spec: " < < spec . to_pp_string ( ) < < std : : endl ;
}
return spec ;
2010-10-17 01:07:10 +00:00
}
size_t get_rx_num_channels ( void ) {
2011-02-18 07:06:48 +00:00
size_t sum = 0 ;
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
sum + = get_rx_subdev_spec ( m ) . size ( ) ;
}
return sum ;
2010-10-17 01:07:10 +00:00
}
std : : string get_rx_subdev_name ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < std : : string > ( rx_rf_fe_root ( chan ) / " name " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-02-18 02:55:55 +00:00
void set_rx_rate ( double rate , size_t chan ) {
2011-02-18 00:44:31 +00:00
if ( chan ! = ALL_CHANS ) {
2011-06-29 02:10:55 +00:00
_tree - > access < double > ( rx_dsp_root ( chan ) / " rate " / " value " ) . set ( rate ) ;
2011-02-18 00:44:31 +00:00
do_samp_rate_warning_message ( rate , get_rx_rate ( chan ) , " RX " ) ;
return ;
}
2011-02-18 02:55:55 +00:00
for ( size_t c = 0 ; c < get_rx_num_channels ( ) ; c + + ) {
2011-02-18 00:44:31 +00:00
set_rx_rate ( rate , c ) ;
2010-10-17 01:07:10 +00:00
}
}
2011-02-18 00:44:31 +00:00
double get_rx_rate ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < double > ( rx_dsp_root ( chan ) / " rate " / " value " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-10-16 17:43:48 +00:00
meta_range_t get_rx_rates ( size_t chan ) {
return _tree - > access < meta_range_t > ( rx_dsp_root ( chan ) / " rate " / " range " ) . get ( ) ;
}
2010-10-25 20:41:40 +00:00
tune_result_t set_rx_freq ( const tune_request_t & tune_request , size_t chan ) {
2011-07-08 17:08:43 +00:00
tune_result_t r = tune_xx_subdev_and_dsp ( RX_SIGN , _tree - > subtree ( rx_dsp_root ( chan ) ) , _tree - > subtree ( rx_rf_fe_root ( chan ) ) , tune_request ) ;
2011-11-11 01:29:18 +00:00
do_tune_freq_warning_message ( tune_request , get_rx_freq ( chan ) , " RX " ) ;
2011-06-29 17:54:28 +00:00
return r ;
2010-10-17 01:07:10 +00:00
}
double get_rx_freq ( size_t chan ) {
2011-07-08 17:08:43 +00:00
return derive_freq_from_xx_subdev_and_dsp ( RX_SIGN , _tree - > subtree ( rx_dsp_root ( chan ) ) , _tree - > subtree ( rx_rf_fe_root ( chan ) ) ) ;
2010-10-17 01:07:10 +00:00
}
freq_range_t get_rx_freq_range ( size_t chan ) {
2011-08-18 00:09:55 +00:00
return make_overall_tune_range (
_tree - > access < meta_range_t > ( rx_rf_fe_root ( chan ) / " freq " / " range " ) . get ( ) ,
_tree - > access < meta_range_t > ( rx_dsp_root ( chan ) / " freq " / " range " ) . get ( ) ,
this - > get_rx_bandwidth ( chan )
) ;
2010-10-17 01:07:10 +00:00
}
2012-05-10 19:14:59 +00:00
freq_range_t get_fe_rx_freq_range ( size_t chan ) {
return _tree - > access < meta_range_t > ( rx_rf_fe_root ( chan ) / " freq " / " range " ) . get ( ) ;
}
2011-01-12 03:46:45 +00:00
void set_rx_gain ( double gain , const std : : string & name , size_t chan ) {
2014-01-30 23:20:49 +00:00
try {
return rx_gain_group ( chan ) - > set_value ( gain , name ) ;
} catch ( uhd : : key_error & e ) {
2014-02-22 02:08:56 +00:00
THROW_GAIN_NAME_ERROR ( name , chan , rx ) ;
2014-01-30 23:20:49 +00:00
}
2010-10-20 23:20:36 +00:00
}
2011-01-12 03:46:45 +00:00
double get_rx_gain ( const std : : string & name , size_t chan ) {
2014-01-30 23:20:49 +00:00
try {
return rx_gain_group ( chan ) - > get_value ( name ) ;
} catch ( uhd : : key_error & e ) {
2014-02-22 02:08:56 +00:00
THROW_GAIN_NAME_ERROR ( name , chan , rx ) ;
2014-01-30 23:20:49 +00:00
}
2010-10-17 01:07:10 +00:00
}
2010-10-20 23:20:36 +00:00
gain_range_t get_rx_gain_range ( const std : : string & name , size_t chan ) {
2014-01-30 23:20:49 +00:00
try {
return rx_gain_group ( chan ) - > get_range ( name ) ;
} catch ( uhd : : key_error & e ) {
2014-02-22 02:08:56 +00:00
THROW_GAIN_NAME_ERROR ( name , chan , rx ) ;
2014-01-30 23:20:49 +00:00
}
2010-10-17 01:07:10 +00:00
}
2010-10-20 23:20:36 +00:00
std : : vector < std : : string > get_rx_gain_names ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return rx_gain_group ( chan ) - > get_names ( ) ;
2010-10-17 01:07:10 +00:00
}
void set_rx_antenna ( const std : : string & ant , size_t chan ) {
2011-06-29 02:10:55 +00:00
_tree - > access < std : : string > ( rx_rf_fe_root ( chan ) / " antenna " / " value " ) . set ( ant ) ;
2010-10-17 01:07:10 +00:00
}
std : : string get_rx_antenna ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < std : : string > ( rx_rf_fe_root ( chan ) / " antenna " / " value " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
std : : vector < std : : string > get_rx_antennas ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < std : : vector < std : : string > > ( rx_rf_fe_root ( chan ) / " antenna " / " options " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2010-10-19 22:42:21 +00:00
void set_rx_bandwidth ( double bandwidth , size_t chan ) {
2011-06-29 02:10:55 +00:00
_tree - > access < double > ( rx_rf_fe_root ( chan ) / " bandwidth " / " value " ) . set ( bandwidth ) ;
2010-10-19 22:42:21 +00:00
}
double get_rx_bandwidth ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < double > ( rx_rf_fe_root ( chan ) / " bandwidth " / " value " ) . get ( ) ;
2010-10-19 22:42:21 +00:00
}
2011-10-26 17:21:11 +00:00
meta_range_t get_rx_bandwidth_range ( size_t chan ) {
return _tree - > access < meta_range_t > ( rx_rf_fe_root ( chan ) / " bandwidth " / " range " ) . get ( ) ;
}
2010-10-17 01:07:10 +00:00
dboard_iface : : sptr get_rx_dboard_iface ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < dboard_iface : : sptr > ( rx_rf_fe_root ( chan ) . branch_path ( ) . branch_path ( ) / " iface " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-02-12 02:07:24 +00:00
sensor_value_t get_rx_sensor ( const std : : string & name , size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < sensor_value_t > ( rx_rf_fe_root ( chan ) / " sensors " / name ) . get ( ) ;
2011-02-12 02:07:24 +00:00
}
std : : vector < std : : string > get_rx_sensor_names ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > list ( rx_rf_fe_root ( chan ) / " sensors " ) ;
2011-02-12 02:07:24 +00:00
}
2011-10-21 23:38:27 +00:00
void set_rx_dc_offset ( const bool enb , size_t chan ) {
if ( chan ! = ALL_CHANS ) {
2014-04-30 12:19:21 +00:00
if ( _tree - > exists ( rx_fe_root ( chan ) / " dc_offset " / " enable " ) ) {
_tree - > access < bool > ( rx_fe_root ( chan ) / " dc_offset " / " enable " ) . set ( enb ) ;
} else {
UHD_MSG ( warning ) < < " Setting DC offset compensation is not possible on this device. " < < std : : endl ;
}
2011-10-21 23:38:27 +00:00
return ;
}
for ( size_t c = 0 ; c < get_rx_num_channels ( ) ; c + + ) {
this - > set_rx_dc_offset ( enb , c ) ;
}
}
void set_rx_dc_offset ( const std : : complex < double > & offset , size_t chan ) {
if ( chan ! = ALL_CHANS ) {
2014-04-30 12:19:21 +00:00
if ( _tree - > exists ( rx_fe_root ( chan ) / " dc_offset " / " value " ) ) {
_tree - > access < std : : complex < double > > ( rx_fe_root ( chan ) / " dc_offset " / " value " ) . set ( offset ) ;
} else {
UHD_MSG ( warning ) < < " Setting DC offset is not possible on this device. " < < std : : endl ;
}
2011-10-21 23:38:27 +00:00
return ;
}
for ( size_t c = 0 ; c < get_rx_num_channels ( ) ; c + + ) {
this - > set_rx_dc_offset ( offset , c ) ;
}
}
2011-10-24 17:36:41 +00:00
void set_rx_iq_balance ( const std : : complex < double > & offset , size_t chan ) {
2011-10-24 01:02:43 +00:00
if ( chan ! = ALL_CHANS ) {
2014-04-30 12:19:21 +00:00
if ( _tree - > exists ( rx_fe_root ( chan ) / " iq_balance " / " value " ) ) {
_tree - > access < std : : complex < double > > ( rx_fe_root ( chan ) / " iq_balance " / " value " ) . set ( offset ) ;
} else {
UHD_MSG ( warning ) < < " Setting IQ balance is not possible on this device. " < < std : : endl ;
}
2011-10-24 01:02:43 +00:00
return ;
}
for ( size_t c = 0 ; c < get_rx_num_channels ( ) ; c + + ) {
2011-10-24 17:36:41 +00:00
this - > set_rx_iq_balance ( offset , c ) ;
2011-10-24 01:02:43 +00:00
}
}
2010-10-17 01:07:10 +00:00
/*******************************************************************
* TX methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-02-28 17:14:31 +00:00
tx_streamer : : sptr get_tx_stream ( const stream_args_t & args ) {
_check_link_rate ( args , true ) ;
return this - > get_device ( ) - > get_tx_stream ( args ) ;
}
2010-10-17 01:07:10 +00:00
void set_tx_subdev_spec ( const subdev_spec_t & spec , size_t mboard ) {
if ( mboard ! = ALL_MBOARDS ) {
2011-06-29 02:10:55 +00:00
_tree - > access < subdev_spec_t > ( mb_root ( mboard ) / " tx_subdev_spec " ) . set ( spec ) ;
2010-10-17 01:07:10 +00:00
return ;
}
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
set_tx_subdev_spec ( spec , m ) ;
}
}
2013-07-15 22:48:51 +00:00
subdev_spec_t get_tx_subdev_spec ( size_t mboard )
{
subdev_spec_t spec = _tree - > access < subdev_spec_t > ( mb_root ( mboard ) / " tx_subdev_spec " ) . get ( ) ;
if ( spec . empty ( ) )
{
try
{
const std : : string db_name = _tree - > list ( mb_root ( mboard ) / " dboards " ) . at ( 0 ) ;
const std : : string fe_name = _tree - > list ( mb_root ( mboard ) / " dboards " / db_name / " tx_frontends " ) . at ( 0 ) ;
spec . push_back ( subdev_spec_pair_t ( db_name , fe_name ) ) ;
_tree - > access < subdev_spec_t > ( mb_root ( mboard ) / " tx_subdev_spec " ) . set ( spec ) ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::get_tx_subdev_spec(%u) failed to make default spec - %s " ) % mboard % e . what ( ) ) ) ;
}
UHD_MSG ( status ) < < " Selecting default TX front end spec: " < < spec . to_pp_string ( ) < < std : : endl ;
}
return spec ;
2010-10-17 01:07:10 +00:00
}
size_t get_tx_num_channels ( void ) {
2011-02-18 07:06:48 +00:00
size_t sum = 0 ;
for ( size_t m = 0 ; m < get_num_mboards ( ) ; m + + ) {
sum + = get_tx_subdev_spec ( m ) . size ( ) ;
}
return sum ;
2010-10-17 01:07:10 +00:00
}
2012-04-05 00:03:35 +00:00
std : : string get_tx_subdev_name ( size_t chan ) {
return _tree - > access < std : : string > ( tx_rf_fe_root ( chan ) / " name " ) . get ( ) ;
}
2011-02-18 02:55:55 +00:00
void set_tx_rate ( double rate , size_t chan ) {
2011-02-18 00:44:31 +00:00
if ( chan ! = ALL_CHANS ) {
2011-06-29 02:10:55 +00:00
_tree - > access < double > ( tx_dsp_root ( chan ) / " rate " / " value " ) . set ( rate ) ;
2011-02-18 00:44:31 +00:00
do_samp_rate_warning_message ( rate , get_tx_rate ( chan ) , " TX " ) ;
return ;
}
2011-02-18 02:55:55 +00:00
for ( size_t c = 0 ; c < get_tx_num_channels ( ) ; c + + ) {
2011-02-18 00:44:31 +00:00
set_tx_rate ( rate , c ) ;
2010-10-17 01:07:10 +00:00
}
}
2011-02-18 00:44:31 +00:00
double get_tx_rate ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < double > ( tx_dsp_root ( chan ) / " rate " / " value " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-10-16 17:43:48 +00:00
meta_range_t get_tx_rates ( size_t chan ) {
return _tree - > access < meta_range_t > ( tx_dsp_root ( chan ) / " rate " / " range " ) . get ( ) ;
}
2010-10-25 20:41:40 +00:00
tune_result_t set_tx_freq ( const tune_request_t & tune_request , size_t chan ) {
2011-07-08 17:08:43 +00:00
tune_result_t r = tune_xx_subdev_and_dsp ( TX_SIGN , _tree - > subtree ( tx_dsp_root ( chan ) ) , _tree - > subtree ( tx_rf_fe_root ( chan ) ) , tune_request ) ;
2011-11-11 01:29:18 +00:00
do_tune_freq_warning_message ( tune_request , get_tx_freq ( chan ) , " TX " ) ;
2011-06-29 17:54:28 +00:00
return r ;
2010-10-17 01:07:10 +00:00
}
double get_tx_freq ( size_t chan ) {
2011-07-08 17:08:43 +00:00
return derive_freq_from_xx_subdev_and_dsp ( TX_SIGN , _tree - > subtree ( tx_dsp_root ( chan ) ) , _tree - > subtree ( tx_rf_fe_root ( chan ) ) ) ;
2010-10-17 01:07:10 +00:00
}
freq_range_t get_tx_freq_range ( size_t chan ) {
2011-08-18 00:09:55 +00:00
return make_overall_tune_range (
_tree - > access < meta_range_t > ( tx_rf_fe_root ( chan ) / " freq " / " range " ) . get ( ) ,
_tree - > access < meta_range_t > ( tx_dsp_root ( chan ) / " freq " / " range " ) . get ( ) ,
this - > get_tx_bandwidth ( chan )
) ;
2010-10-17 01:07:10 +00:00
}
2012-05-10 19:14:59 +00:00
freq_range_t get_fe_tx_freq_range ( size_t chan ) {
return _tree - > access < meta_range_t > ( tx_rf_fe_root ( chan ) / " freq " / " range " ) . get ( ) ;
}
2011-01-12 03:46:45 +00:00
void set_tx_gain ( double gain , const std : : string & name , size_t chan ) {
2014-01-30 23:20:49 +00:00
try {
return tx_gain_group ( chan ) - > set_value ( gain , name ) ;
} catch ( uhd : : key_error & e ) {
2014-02-22 02:08:56 +00:00
THROW_GAIN_NAME_ERROR ( name , chan , tx ) ;
2014-01-30 23:20:49 +00:00
}
2010-10-20 23:20:36 +00:00
}
2011-01-12 03:46:45 +00:00
double get_tx_gain ( const std : : string & name , size_t chan ) {
2014-01-30 23:20:49 +00:00
try {
return tx_gain_group ( chan ) - > get_value ( name ) ;
} catch ( uhd : : key_error & e ) {
2014-02-22 02:08:56 +00:00
THROW_GAIN_NAME_ERROR ( name , chan , tx ) ;
2014-01-30 23:20:49 +00:00
}
2010-10-17 01:07:10 +00:00
}
2010-10-20 23:20:36 +00:00
gain_range_t get_tx_gain_range ( const std : : string & name , size_t chan ) {
2014-01-30 23:20:49 +00:00
try {
return tx_gain_group ( chan ) - > get_range ( name ) ;
} catch ( uhd : : key_error & e ) {
2014-02-22 02:08:56 +00:00
THROW_GAIN_NAME_ERROR ( name , chan , tx ) ;
2014-01-30 23:20:49 +00:00
}
2010-10-17 01:07:10 +00:00
}
2010-10-20 23:20:36 +00:00
std : : vector < std : : string > get_tx_gain_names ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return tx_gain_group ( chan ) - > get_names ( ) ;
2010-10-17 01:07:10 +00:00
}
void set_tx_antenna ( const std : : string & ant , size_t chan ) {
2011-06-29 02:10:55 +00:00
_tree - > access < std : : string > ( tx_rf_fe_root ( chan ) / " antenna " / " value " ) . set ( ant ) ;
2010-10-17 01:07:10 +00:00
}
std : : string get_tx_antenna ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < std : : string > ( tx_rf_fe_root ( chan ) / " antenna " / " value " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
std : : vector < std : : string > get_tx_antennas ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < std : : vector < std : : string > > ( tx_rf_fe_root ( chan ) / " antenna " / " options " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2010-10-19 22:42:21 +00:00
void set_tx_bandwidth ( double bandwidth , size_t chan ) {
2011-06-29 02:10:55 +00:00
_tree - > access < double > ( tx_rf_fe_root ( chan ) / " bandwidth " / " value " ) . set ( bandwidth ) ;
2010-10-19 22:42:21 +00:00
}
double get_tx_bandwidth ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < double > ( tx_rf_fe_root ( chan ) / " bandwidth " / " value " ) . get ( ) ;
2010-10-19 22:42:21 +00:00
}
2011-10-26 17:21:11 +00:00
meta_range_t get_tx_bandwidth_range ( size_t chan ) {
return _tree - > access < meta_range_t > ( tx_rf_fe_root ( chan ) / " bandwidth " / " range " ) . get ( ) ;
}
2010-10-17 01:07:10 +00:00
dboard_iface : : sptr get_tx_dboard_iface ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < dboard_iface : : sptr > ( tx_rf_fe_root ( chan ) . branch_path ( ) . branch_path ( ) / " iface " ) . get ( ) ;
2010-10-17 01:07:10 +00:00
}
2011-02-12 02:07:24 +00:00
sensor_value_t get_tx_sensor ( const std : : string & name , size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > access < sensor_value_t > ( tx_rf_fe_root ( chan ) / " sensors " / name ) . get ( ) ;
2011-02-12 02:07:24 +00:00
}
std : : vector < std : : string > get_tx_sensor_names ( size_t chan ) {
2011-06-29 02:10:55 +00:00
return _tree - > list ( tx_rf_fe_root ( chan ) / " sensors " ) ;
2011-02-12 02:07:24 +00:00
}
2011-10-21 23:38:27 +00:00
void set_tx_dc_offset ( const std : : complex < double > & offset , size_t chan ) {
if ( chan ! = ALL_CHANS ) {
2014-04-30 12:19:21 +00:00
if ( _tree - > exists ( tx_fe_root ( chan ) / " dc_offset " / " value " ) ) {
_tree - > access < std : : complex < double > > ( tx_fe_root ( chan ) / " dc_offset " / " value " ) . set ( offset ) ;
} else {
UHD_MSG ( warning ) < < " Setting DC offset is not possible on this device. " < < std : : endl ;
}
2011-10-21 23:38:27 +00:00
return ;
}
for ( size_t c = 0 ; c < get_tx_num_channels ( ) ; c + + ) {
this - > set_tx_dc_offset ( offset , c ) ;
}
}
2011-10-24 17:36:41 +00:00
void set_tx_iq_balance ( const std : : complex < double > & offset , size_t chan ) {
2011-10-24 01:02:43 +00:00
if ( chan ! = ALL_CHANS ) {
2014-04-30 12:19:21 +00:00
if ( _tree - > exists ( tx_fe_root ( chan ) / " iq_balance " / " value " ) ) {
_tree - > access < std : : complex < double > > ( tx_fe_root ( chan ) / " iq_balance " / " value " ) . set ( offset ) ;
} else {
UHD_MSG ( warning ) < < " Setting IQ balance is not possible on this device. " < < std : : endl ;
}
2011-10-24 01:02:43 +00:00
return ;
}
for ( size_t c = 0 ; c < get_tx_num_channels ( ) ; c + + ) {
2011-10-24 17:36:41 +00:00
this - > set_tx_iq_balance ( offset , c ) ;
2011-10-24 01:02:43 +00:00
}
}
2014-02-04 19:04:07 +00:00
/*******************************************************************
* GPIO methods
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
std : : vector < std : : string > get_gpio_banks ( const size_t mboard )
{
std : : vector < std : : string > banks ;
if ( _tree - > exists ( mb_root ( mboard ) / " gpio " ) )
{
BOOST_FOREACH ( const std : : string & name , _tree - > list ( mb_root ( mboard ) / " gpio " ) )
{
banks . push_back ( name ) ;
}
}
BOOST_FOREACH ( const std : : string & name , _tree - > list ( mb_root ( mboard ) / " dboards " ) )
{
banks . push_back ( " RX " + name ) ;
banks . push_back ( " TX " + name ) ;
}
return banks ;
}
void set_gpio_attr ( const std : : string & bank , const std : : string & attr , const boost : : uint32_t value , const boost : : uint32_t mask , const size_t mboard )
{
if ( _tree - > exists ( mb_root ( mboard ) / " gpio " / bank ) )
{
const boost : : uint32_t current = _tree - > access < boost : : uint32_t > ( mb_root ( mboard ) / " gpio " / bank / attr ) . get ( ) ;
const boost : : uint32_t new_value = ( current & ~ mask ) | ( value & mask ) ;
_tree - > access < boost : : uint32_t > ( mb_root ( mboard ) / " gpio " / bank / attr ) . set ( new_value ) ;
return ;
}
if ( bank . size ( ) > 2 and bank [ 1 ] = = ' X ' )
{
const std : : string name = bank . substr ( 2 ) ;
const dboard_iface : : unit_t unit = ( bank [ 0 ] = = ' R ' ) ? dboard_iface : : UNIT_RX : dboard_iface : : UNIT_TX ;
dboard_iface : : sptr iface = _tree - > access < dboard_iface : : sptr > ( mb_root ( mboard ) / " dboards " / name / " iface " ) . get ( ) ;
if ( attr = = " CTRL " ) iface - > set_pin_ctrl ( unit , boost : : uint16_t ( value ) , boost : : uint16_t ( mask ) ) ;
if ( attr = = " DDR " ) iface - > set_gpio_ddr ( unit , boost : : uint16_t ( value ) , boost : : uint16_t ( mask ) ) ;
if ( attr = = " OUT " ) iface - > set_gpio_out ( unit , boost : : uint16_t ( value ) , boost : : uint16_t ( mask ) ) ;
if ( attr = = " ATR_0X " ) iface - > set_atr_reg ( unit , dboard_iface : : ATR_REG_IDLE , boost : : uint16_t ( value ) , boost : : uint16_t ( mask ) ) ;
if ( attr = = " ATR_RX " ) iface - > set_atr_reg ( unit , dboard_iface : : ATR_REG_RX_ONLY , boost : : uint16_t ( value ) , boost : : uint16_t ( mask ) ) ;
if ( attr = = " ATR_TX " ) iface - > set_atr_reg ( unit , dboard_iface : : ATR_REG_TX_ONLY , boost : : uint16_t ( value ) , boost : : uint16_t ( mask ) ) ;
if ( attr = = " ATR_XX " ) iface - > set_atr_reg ( unit , dboard_iface : : ATR_REG_FULL_DUPLEX , boost : : uint16_t ( value ) , boost : : uint16_t ( mask ) ) ;
}
}
boost : : uint32_t get_gpio_attr ( const std : : string & bank , const std : : string & attr , const size_t mboard )
{
if ( _tree - > exists ( mb_root ( mboard ) / " gpio " / bank ) )
{
return _tree - > access < boost : : uint64_t > ( mb_root ( mboard ) / " gpio " / bank / attr ) . get ( ) ;
}
if ( bank . size ( ) > 2 and bank [ 1 ] = = ' X ' )
{
const std : : string name = bank . substr ( 2 ) ;
const dboard_iface : : unit_t unit = ( bank [ 0 ] = = ' R ' ) ? dboard_iface : : UNIT_RX : dboard_iface : : UNIT_TX ;
dboard_iface : : sptr iface = _tree - > access < dboard_iface : : sptr > ( mb_root ( mboard ) / " dboards " / name / " iface " ) . get ( ) ;
if ( attr = = " CTRL " ) return iface - > get_pin_ctrl ( unit ) ;
if ( attr = = " DDR " ) return iface - > get_gpio_ddr ( unit ) ;
if ( attr = = " OUT " ) return iface - > get_gpio_out ( unit ) ;
if ( attr = = " ATR_0X " ) return iface - > get_atr_reg ( unit , dboard_iface : : ATR_REG_IDLE ) ;
if ( attr = = " ATR_RX " ) return iface - > get_atr_reg ( unit , dboard_iface : : ATR_REG_RX_ONLY ) ;
if ( attr = = " ATR_TX " ) return iface - > get_atr_reg ( unit , dboard_iface : : ATR_REG_TX_ONLY ) ;
if ( attr = = " ATR_XX " ) return iface - > get_atr_reg ( unit , dboard_iface : : ATR_REG_FULL_DUPLEX ) ;
if ( attr = = " READBACK " ) return iface - > read_gpio ( unit ) ;
}
return 0 ;
}
2010-10-17 01:07:10 +00:00
private :
device : : sptr _dev ;
2011-06-29 02:10:55 +00:00
property_tree : : sptr _tree ;
2010-10-19 01:24:53 +00:00
2011-02-18 07:06:48 +00:00
struct mboard_chan_pair {
size_t mboard , chan ;
mboard_chan_pair ( void ) : mboard ( 0 ) , chan ( 0 ) { }
} ;
mboard_chan_pair rx_chan_to_mcp ( size_t chan ) {
mboard_chan_pair mcp ;
mcp . chan = chan ;
for ( mcp . mboard = 0 ; mcp . mboard < get_num_mboards ( ) ; mcp . mboard + + ) {
size_t sss = get_rx_subdev_spec ( mcp . mboard ) . size ( ) ;
if ( mcp . chan < sss ) break ;
mcp . chan - = sss ;
2010-10-19 20:04:07 +00:00
}
2013-07-15 22:48:51 +00:00
if ( mcp . mboard > = get_num_mboards ( ) )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp: RX channel %u out of range for configured RX frontends " ) % chan ) ) ;
}
2011-02-18 07:06:48 +00:00
return mcp ;
2010-10-19 01:24:53 +00:00
}
2011-02-18 07:06:48 +00:00
mboard_chan_pair tx_chan_to_mcp ( size_t chan ) {
mboard_chan_pair mcp ;
mcp . chan = chan ;
for ( mcp . mboard = 0 ; mcp . mboard < get_num_mboards ( ) ; mcp . mboard + + ) {
size_t sss = get_tx_subdev_spec ( mcp . mboard ) . size ( ) ;
if ( mcp . chan < sss ) break ;
mcp . chan - = sss ;
2010-10-19 20:04:07 +00:00
}
2013-07-15 22:48:51 +00:00
if ( mcp . mboard > = get_num_mboards ( ) )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp: TX channel %u out of range for configured TX frontends " ) % chan ) ) ;
}
2011-02-18 07:06:48 +00:00
return mcp ;
2010-10-19 01:24:53 +00:00
}
2013-07-15 22:48:51 +00:00
fs_path mb_root ( const size_t mboard )
{
try
{
const std : : string name = _tree - > list ( " /mboards " ) . at ( mboard ) ;
return " /mboards/ " + name ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::mb_root(%u) - %s " ) % mboard % e . what ( ) ) ) ;
}
2010-10-17 01:07:10 +00:00
}
2011-06-29 02:10:55 +00:00
2013-07-15 22:48:51 +00:00
fs_path rx_dsp_root ( const size_t chan )
{
2011-02-18 07:06:48 +00:00
mboard_chan_pair mcp = rx_chan_to_mcp ( chan ) ;
2014-02-21 14:12:44 +00:00
if ( _tree - > exists ( mb_root ( mcp . mboard ) / " rx_chan_dsp_mapping " ) ) {
std : : vector < size_t > map = _tree - > access < std : : vector < size_t > > ( mb_root ( mcp . mboard ) / " rx_chan_dsp_mapping " ) . get ( ) ;
2014-03-13 16:38:16 +00:00
UHD_ASSERT_THROW ( map . size ( ) > mcp . chan ) ;
2014-02-21 14:12:44 +00:00
mcp . chan = map [ mcp . chan ] ;
}
2013-07-15 22:48:51 +00:00
try
{
const std : : string name = _tree - > list ( mb_root ( mcp . mboard ) / " rx_dsps " ) . at ( mcp . chan ) ;
return mb_root ( mcp . mboard ) / " rx_dsps " / name ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::rx_dsp_root(%u) - mcp(%u) - %s " ) % chan % mcp . chan % e . what ( ) ) ) ;
}
2010-10-17 01:07:10 +00:00
}
2011-06-29 02:10:55 +00:00
2013-07-15 22:48:51 +00:00
fs_path tx_dsp_root ( const size_t chan )
{
2011-02-18 07:06:48 +00:00
mboard_chan_pair mcp = tx_chan_to_mcp ( chan ) ;
2014-02-21 14:12:44 +00:00
if ( _tree - > exists ( mb_root ( mcp . mboard ) / " tx_chan_dsp_mapping " ) ) {
std : : vector < size_t > map = _tree - > access < std : : vector < size_t > > ( mb_root ( mcp . mboard ) / " tx_chan_dsp_mapping " ) . get ( ) ;
2014-03-13 16:38:16 +00:00
UHD_ASSERT_THROW ( map . size ( ) > mcp . chan ) ;
2014-02-21 14:12:44 +00:00
mcp . chan = map [ mcp . chan ] ;
}
2013-07-15 22:48:51 +00:00
try
{
const std : : string name = _tree - > list ( mb_root ( mcp . mboard ) / " tx_dsps " ) . at ( mcp . chan ) ;
return mb_root ( mcp . mboard ) / " tx_dsps " / name ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::tx_dsp_root(%u) - mcp(%u) - %s " ) % chan % mcp . chan % e . what ( ) ) ) ;
}
2010-10-17 01:07:10 +00:00
}
2011-06-29 02:10:55 +00:00
2013-07-15 22:48:51 +00:00
fs_path rx_fe_root ( const size_t chan )
{
2011-10-26 02:26:11 +00:00
mboard_chan_pair mcp = rx_chan_to_mcp ( chan ) ;
2013-07-15 22:48:51 +00:00
try
{
const subdev_spec_pair_t spec = get_rx_subdev_spec ( mcp . mboard ) . at ( mcp . chan ) ;
return mb_root ( mcp . mboard ) / " rx_frontends " / spec . db_name ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::rx_fe_root(%u) - mcp(%u) - %s " ) % chan % mcp . chan % e . what ( ) ) ) ;
}
2011-10-26 02:26:11 +00:00
}
2013-07-15 22:48:51 +00:00
fs_path tx_fe_root ( const size_t chan )
{
2011-10-26 02:26:11 +00:00
mboard_chan_pair mcp = tx_chan_to_mcp ( chan ) ;
2013-07-15 22:48:51 +00:00
try
{
const subdev_spec_pair_t spec = get_tx_subdev_spec ( mcp . mboard ) . at ( mcp . chan ) ;
return mb_root ( mcp . mboard ) / " tx_frontends " / spec . db_name ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::tx_fe_root(%u) - mcp(%u) - %s " ) % chan % mcp . chan % e . what ( ) ) ) ;
}
2011-10-26 02:26:11 +00:00
}
2013-07-15 22:48:51 +00:00
fs_path rx_rf_fe_root ( const size_t chan )
{
2011-02-18 07:06:48 +00:00
mboard_chan_pair mcp = rx_chan_to_mcp ( chan ) ;
2013-07-15 22:48:51 +00:00
try
{
const subdev_spec_pair_t spec = get_rx_subdev_spec ( mcp . mboard ) . at ( mcp . chan ) ;
return mb_root ( mcp . mboard ) / " dboards " / spec . db_name / " rx_frontends " / spec . sd_name ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::rx_rf_fe_root(%u) - mcp(%u) - %s " ) % chan % mcp . chan % e . what ( ) ) ) ;
}
2010-10-17 01:07:10 +00:00
}
2011-06-29 02:10:55 +00:00
2013-07-15 22:48:51 +00:00
fs_path tx_rf_fe_root ( const size_t chan )
{
2011-02-18 07:06:48 +00:00
mboard_chan_pair mcp = tx_chan_to_mcp ( chan ) ;
2013-07-15 22:48:51 +00:00
try
{
const subdev_spec_pair_t spec = get_tx_subdev_spec ( mcp . mboard ) . at ( mcp . chan ) ;
return mb_root ( mcp . mboard ) / " dboards " / spec . db_name / " tx_frontends " / spec . sd_name ;
}
catch ( const std : : exception & e )
{
throw uhd : : index_error ( str ( boost : : format ( " multi_usrp::tx_rf_fe_root(%u) - mcp(%u) - %s " ) % chan % mcp . chan % e . what ( ) ) ) ;
}
2010-10-17 01:07:10 +00:00
}
2011-06-29 02:10:55 +00:00
gain_group : : sptr rx_gain_group ( size_t chan ) {
2011-02-18 07:06:48 +00:00
mboard_chan_pair mcp = rx_chan_to_mcp ( chan ) ;
2011-06-29 02:10:55 +00:00
const subdev_spec_pair_t spec = get_rx_subdev_spec ( mcp . mboard ) . at ( mcp . chan ) ;
gain_group : : sptr gg = gain_group : : make ( ) ;
BOOST_FOREACH ( const std : : string & name , _tree - > list ( mb_root ( mcp . mboard ) / " rx_codecs " / spec . db_name / " gains " ) ) {
2011-07-08 17:08:43 +00:00
gg - > register_fcns ( " ADC- " + name , make_gain_fcns_from_subtree ( _tree - > subtree ( mb_root ( mcp . mboard ) / " rx_codecs " / spec . db_name / " gains " / name ) ) , 0 /* low prio */ ) ;
2011-06-29 02:10:55 +00:00
}
BOOST_FOREACH ( const std : : string & name , _tree - > list ( rx_rf_fe_root ( chan ) / " gains " ) ) {
2011-07-08 17:08:43 +00:00
gg - > register_fcns ( name , make_gain_fcns_from_subtree ( _tree - > subtree ( rx_rf_fe_root ( chan ) / " gains " / name ) ) , 1 /* high prio */ ) ;
2011-06-29 02:10:55 +00:00
}
return gg ;
2010-10-17 01:07:10 +00:00
}
2011-06-29 02:10:55 +00:00
gain_group : : sptr tx_gain_group ( size_t chan ) {
2011-02-18 07:06:48 +00:00
mboard_chan_pair mcp = tx_chan_to_mcp ( chan ) ;
2011-06-29 02:10:55 +00:00
const subdev_spec_pair_t spec = get_tx_subdev_spec ( mcp . mboard ) . at ( mcp . chan ) ;
gain_group : : sptr gg = gain_group : : make ( ) ;
BOOST_FOREACH ( const std : : string & name , _tree - > list ( mb_root ( mcp . mboard ) / " tx_codecs " / spec . db_name / " gains " ) ) {
2012-09-13 01:24:28 +00:00
gg - > register_fcns ( " DAC- " + name , make_gain_fcns_from_subtree ( _tree - > subtree ( mb_root ( mcp . mboard ) / " tx_codecs " / spec . db_name / " gains " / name ) ) , 1 /* high prio */ ) ;
2011-06-29 02:10:55 +00:00
}
BOOST_FOREACH ( const std : : string & name , _tree - > list ( tx_rf_fe_root ( chan ) / " gains " ) ) {
2011-07-08 17:08:43 +00:00
gg - > register_fcns ( name , make_gain_fcns_from_subtree ( _tree - > subtree ( tx_rf_fe_root ( chan ) / " gains " / name ) ) , 0 /* low prio */ ) ;
2011-06-29 02:10:55 +00:00
}
return gg ;
2010-10-17 01:07:10 +00:00
}
2014-02-28 17:14:31 +00:00
//! \param is_tx True for tx
// Assumption is that all mboards use the same link
bool _check_link_rate ( const stream_args_t & args , bool is_tx ) {
bool link_rate_is_ok = true ;
2014-04-15 15:50:42 +00:00
size_t bytes_per_sample = convert : : get_bytes_per_item ( args . otw_format . empty ( ) ? " sc16 " : args . otw_format ) ;
2014-02-28 17:14:31 +00:00
double max_link_rate = 0 ;
double sum_rate = 0 ;
BOOST_FOREACH ( const size_t chan , args . channels ) {
mboard_chan_pair mcp = is_tx ? tx_chan_to_mcp ( chan ) : rx_chan_to_mcp ( chan ) ;
if ( _tree - > exists ( mb_root ( mcp . mboard ) / " link_max_rate " ) ) {
max_link_rate = std : : max (
max_link_rate ,
_tree - > access < double > ( mb_root ( mcp . mboard ) / " link_max_rate " ) . get ( )
) ;
}
sum_rate + = is_tx ? get_tx_rate ( chan ) : get_rx_rate ( chan ) ;
}
if ( max_link_rate > 0 and ( max_link_rate / bytes_per_sample ) < sum_rate ) {
UHD_MSG ( warning ) < < boost : : format (
" The total sum of rates (%f MSps on %u channels) exceeds the maximum capacity of the connection. \n "
" This can cause %s. "
) % ( sum_rate / 1e6 ) % args . channels . size ( ) % ( is_tx ? " underruns (U) " : " overflows (O) " ) < < std : : endl ;
link_rate_is_ok = false ;
}
return link_rate_is_ok ;
}
2010-10-17 01:07:10 +00:00
} ;
/***********************************************************************
* The Make Function
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
multi_usrp : : sptr multi_usrp : : make ( const device_addr_t & dev_addr ) {
2013-07-15 22:48:51 +00:00
UHD_LOG < < " multi_usrp::make with args " < < dev_addr . to_pp_string ( ) < < std : : endl ;
2010-10-17 01:07:10 +00:00
return sptr ( new multi_usrp_impl ( dev_addr ) ) ;
}