root / host / lib / usrp / multi_usrp.cpp @ 81b4689c
History | View | Annotate | Download (32 KB)
| 1 | c861f98c | Josh Blum | //
|
|---|---|---|---|
| 2 | 261bb80d | Josh Blum | // Copyright 2010-2011 Ettus Research LLC
|
| 3 | c861f98c | Josh Blum | //
|
| 4 | // This program is free software: you can redistribute it and/or modify
|
||
| 5 | // it under the terms of the GNU General Public License as published by
|
||
| 6 | // the Free Software Foundation, either version 3 of the License, or
|
||
| 7 | // (at your option) any later version.
|
||
| 8 | //
|
||
| 9 | // This program is distributed in the hope that it will be useful,
|
||
| 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
| 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
| 12 | // GNU General Public License for more details.
|
||
| 13 | //
|
||
| 14 | // You should have received a copy of the GNU General Public License
|
||
| 15 | // along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
| 16 | //
|
||
| 17 | |||
| 18 | ebd2ecc6 | Josh Blum | #include <uhd/property_tree.hpp> |
| 19 | c861f98c | Josh Blum | #include <uhd/usrp/multi_usrp.hpp> |
| 20 | 09be0518 | Josh Blum | #include <uhd/utils/msg.hpp> |
| 21 | 16f08844 | Josh Blum | #include <uhd/exception.hpp> |
| 22 | 7f01386f | Josh Blum | #include <uhd/utils/msg.hpp> |
| 23 | c861f98c | Josh Blum | #include <uhd/utils/gain_group.hpp> |
| 24 | #include <boost/thread.hpp> |
||
| 25 | #include <boost/foreach.hpp> |
||
| 26 | #include <boost/format.hpp> |
||
| 27 | aa619a76 | Josh Blum | #include <cmath> |
| 28 | c861f98c | Josh Blum | |
| 29 | using namespace uhd; |
||
| 30 | using namespace uhd::usrp; |
||
| 31 | |||
| 32 | 8e341caa | Josh Blum | const std::string multi_usrp::ALL_GAINS = ""; |
| 33 | |||
| 34 | c861f98c | Josh Blum | /***********************************************************************
|
| 35 | aa619a76 | Josh Blum | * Helper methods
|
| 36 | **********************************************************************/
|
||
| 37 | ebd2ecc6 | Josh Blum | static void do_samp_rate_warning_message( |
| 38 | aa619a76 | Josh Blum | double target_rate,
|
| 39 | double actual_rate,
|
||
| 40 | const std::string &xx |
||
| 41 | ){
|
||
| 42 | static const double max_allowed_error = 1.0; //Sps |
||
| 43 | if (std::abs(target_rate - actual_rate) > max_allowed_error){
|
||
| 44 | 7f01386f | Josh Blum | UHD_MSG(warning) << boost::format( |
| 45 | aa619a76 | Josh Blum | "The hardware does not support the requested %s sample rate:\n"
|
| 46 | "Target sample rate: %f MSps\n"
|
||
| 47 | "Actual sample rate: %f MSps\n"
|
||
| 48 | 7f01386f | Josh Blum | ) % xx % (target_rate/1e6) % (actual_rate/1e6); |
| 49 | aa619a76 | Josh Blum | } |
| 50 | } |
||
| 51 | |||
| 52 | ebd2ecc6 | Josh Blum | static void do_tune_freq_warning_message( |
| 53 | 3cb60c97 | Josh Blum | const tune_request_t &tune_req,
|
| 54 | aa619a76 | Josh Blum | double actual_freq,
|
| 55 | const std::string &xx |
||
| 56 | ){
|
||
| 57 | 3cb60c97 | Josh Blum | //forget the warning when manual policy
|
| 58 | if (tune_req.dsp_freq_policy == tune_request_t::POLICY_MANUAL) return; |
||
| 59 | if (tune_req.rf_freq_policy == tune_request_t::POLICY_MANUAL) return; |
||
| 60 | |||
| 61 | const double target_freq = tune_req.target_freq; |
||
| 62 | aa619a76 | Josh Blum | static const double max_allowed_error = 1.0; //Hz |
| 63 | if (std::abs(target_freq - actual_freq) > max_allowed_error){
|
||
| 64 | 7f01386f | Josh Blum | UHD_MSG(warning) << boost::format( |
| 65 | aa619a76 | Josh Blum | "The hardware does not support the requested %s frequency:\n"
|
| 66 | "Target frequency: %f MHz\n"
|
||
| 67 | "Actual frequency: %f MHz\n"
|
||
| 68 | 7f01386f | Josh Blum | ) % xx % (target_freq/1e6) % (actual_freq/1e6); |
| 69 | aa619a76 | Josh Blum | } |
| 70 | } |
||
| 71 | |||
| 72 | e033fc3d | Josh Blum | static meta_range_t make_overall_tune_range(
|
| 73 | const meta_range_t &fe_range,
|
||
| 74 | const meta_range_t &dsp_range,
|
||
| 75 | const double bw |
||
| 76 | ){
|
||
| 77 | 78e95562 | Josh Blum | meta_range_t range; |
| 78 | BOOST_FOREACH(const range_t &sub_range, fe_range){
|
||
| 79 | range.push_back(range_t( |
||
| 80 | sub_range.start() + std::max(dsp_range.start(), -bw), |
||
| 81 | sub_range.stop() + std::min(dsp_range.stop(), bw), |
||
| 82 | dsp_range.step() |
||
| 83 | )); |
||
| 84 | } |
||
| 85 | return range;
|
||
| 86 | e033fc3d | Josh Blum | } |
| 87 | |||
| 88 | adbe1a0e | Josh Blum | /***********************************************************************
|
| 89 | * Gain helper functions
|
||
| 90 | **********************************************************************/
|
||
| 91 | aa6b340f | Josh Blum | static double get_gain_value(property_tree::sptr subtree){ |
| 92 | return subtree->access<double>("value").get(); |
||
| 93 | ebd2ecc6 | Josh Blum | } |
| 94 | |||
| 95 | aa6b340f | Josh Blum | static void set_gain_value(property_tree::sptr subtree, const double gain){ |
| 96 | subtree->access<double>("value").set(gain); |
||
| 97 | ebd2ecc6 | Josh Blum | } |
| 98 | |||
| 99 | aa6b340f | Josh Blum | static meta_range_t get_gain_range(property_tree::sptr subtree){
|
| 100 | return subtree->access<meta_range_t>("range").get(); |
||
| 101 | ebd2ecc6 | Josh Blum | } |
| 102 | |||
| 103 | aa6b340f | Josh Blum | static gain_fcns_t make_gain_fcns_from_subtree(property_tree::sptr subtree){
|
| 104 | ebd2ecc6 | Josh Blum | gain_fcns_t gain_fcns; |
| 105 | aa6b340f | Josh Blum | gain_fcns.get_range = boost::bind(&get_gain_range, subtree); |
| 106 | gain_fcns.get_value = boost::bind(&get_gain_value, subtree); |
||
| 107 | gain_fcns.set_value = boost::bind(&set_gain_value, subtree, _1); |
||
| 108 | ebd2ecc6 | Josh Blum | return gain_fcns;
|
| 109 | } |
||
| 110 | |||
| 111 | aa619a76 | Josh Blum | /***********************************************************************
|
| 112 | adbe1a0e | Josh Blum | * Tune Helper Functions
|
| 113 | **********************************************************************/
|
||
| 114 | static const double RX_SIGN = +1.0; |
||
| 115 | static const double TX_SIGN = -1.0; |
||
| 116 | |||
| 117 | static tune_result_t tune_xx_subdev_and_dsp(
|
||
| 118 | const double xx_sign, |
||
| 119 | aa6b340f | Josh Blum | property_tree::sptr dsp_subtree, |
| 120 | property_tree::sptr rf_fe_subtree, |
||
| 121 | adbe1a0e | Josh Blum | const tune_request_t &tune_request
|
| 122 | ){
|
||
| 123 | //------------------------------------------------------------------
|
||
| 124 | //-- calculate the LO offset, only used with automatic policy
|
||
| 125 | //------------------------------------------------------------------
|
||
| 126 | double lo_offset = 0.0; |
||
| 127 | aa6b340f | Josh Blum | if (rf_fe_subtree->access<bool>("use_lo_offset").get()){ |
| 128 | adbe1a0e | Josh Blum | //If the local oscillator will be in the passband, use an offset.
|
| 129 | //But constrain the LO offset by the width of the filter bandwidth.
|
||
| 130 | aa6b340f | Josh Blum | const double rate = dsp_subtree->access<double>("rate/value").get(); |
| 131 | const double bw = rf_fe_subtree->access<double>("bandwidth/value").get(); |
||
| 132 | adbe1a0e | Josh Blum | if (bw > rate) lo_offset = std::min((bw - rate)/2, rate/2); |
| 133 | } |
||
| 134 | |||
| 135 | //------------------------------------------------------------------
|
||
| 136 | //-- set the RF frequency depending upon the policy
|
||
| 137 | //------------------------------------------------------------------
|
||
| 138 | double target_rf_freq = 0.0; |
||
| 139 | switch (tune_request.rf_freq_policy){
|
||
| 140 | case tune_request_t::POLICY_AUTO:
|
||
| 141 | target_rf_freq = tune_request.target_freq + lo_offset; |
||
| 142 | aa6b340f | Josh Blum | rf_fe_subtree->access<double>("freq/value").set(target_rf_freq); |
| 143 | adbe1a0e | Josh Blum | break;
|
| 144 | |||
| 145 | case tune_request_t::POLICY_MANUAL:
|
||
| 146 | target_rf_freq = tune_request.rf_freq; |
||
| 147 | aa6b340f | Josh Blum | rf_fe_subtree->access<double>("freq/value").set(target_rf_freq); |
| 148 | adbe1a0e | Josh Blum | break;
|
| 149 | |||
| 150 | case tune_request_t::POLICY_NONE: break; //does not set |
||
| 151 | } |
||
| 152 | aa6b340f | Josh Blum | const double actual_rf_freq = rf_fe_subtree->access<double>("freq/value").get(); |
| 153 | adbe1a0e | Josh Blum | |
| 154 | //------------------------------------------------------------------
|
||
| 155 | //-- calculate the dsp freq, only used with automatic policy
|
||
| 156 | //------------------------------------------------------------------
|
||
| 157 | double target_dsp_freq = actual_rf_freq - tune_request.target_freq;
|
||
| 158 | |||
| 159 | //invert the sign on the dsp freq for transmit
|
||
| 160 | target_dsp_freq *= xx_sign; |
||
| 161 | |||
| 162 | //------------------------------------------------------------------
|
||
| 163 | //-- set the dsp frequency depending upon the dsp frequency policy
|
||
| 164 | //------------------------------------------------------------------
|
||
| 165 | switch (tune_request.dsp_freq_policy){
|
||
| 166 | case tune_request_t::POLICY_AUTO:
|
||
| 167 | aa6b340f | Josh Blum | dsp_subtree->access<double>("freq/value").set(target_dsp_freq); |
| 168 | adbe1a0e | Josh Blum | break;
|
| 169 | |||
| 170 | case tune_request_t::POLICY_MANUAL:
|
||
| 171 | target_dsp_freq = tune_request.dsp_freq; |
||
| 172 | aa6b340f | Josh Blum | dsp_subtree->access<double>("freq/value").set(target_dsp_freq); |
| 173 | adbe1a0e | Josh Blum | break;
|
| 174 | |||
| 175 | case tune_request_t::POLICY_NONE: break; //does not set |
||
| 176 | } |
||
| 177 | aa6b340f | Josh Blum | const double actual_dsp_freq = dsp_subtree->access<double>("freq/value").get(); |
| 178 | adbe1a0e | Josh Blum | |
| 179 | //------------------------------------------------------------------
|
||
| 180 | //-- load and return the tune result
|
||
| 181 | //------------------------------------------------------------------
|
||
| 182 | tune_result_t tune_result; |
||
| 183 | tune_result.target_rf_freq = target_rf_freq; |
||
| 184 | tune_result.actual_rf_freq = actual_rf_freq; |
||
| 185 | tune_result.target_dsp_freq = target_dsp_freq; |
||
| 186 | tune_result.actual_dsp_freq = actual_dsp_freq; |
||
| 187 | return tune_result;
|
||
| 188 | } |
||
| 189 | |||
| 190 | static double derive_freq_from_xx_subdev_and_dsp( |
||
| 191 | const double xx_sign, |
||
| 192 | aa6b340f | Josh Blum | property_tree::sptr dsp_subtree, |
| 193 | property_tree::sptr rf_fe_subtree |
||
| 194 | adbe1a0e | Josh Blum | ){
|
| 195 | //extract actual dsp and IF frequencies
|
||
| 196 | aa6b340f | Josh Blum | const double actual_rf_freq = rf_fe_subtree->access<double>("freq/value").get(); |
| 197 | const double actual_dsp_freq = dsp_subtree->access<double>("freq/value").get(); |
||
| 198 | adbe1a0e | Josh Blum | |
| 199 | //invert the sign on the dsp freq for transmit
|
||
| 200 | return actual_rf_freq - actual_dsp_freq * xx_sign;
|
||
| 201 | } |
||
| 202 | |||
| 203 | /***********************************************************************
|
||
| 204 | aa619a76 | Josh Blum | * Multi USRP Implementation
|
| 205 | c861f98c | Josh Blum | **********************************************************************/
|
| 206 | class multi_usrp_impl : public multi_usrp{ |
||
| 207 | public:
|
||
| 208 | multi_usrp_impl(const device_addr_t &addr){
|
||
| 209 | _dev = device::make(addr); |
||
| 210 | 748e4baf | Josh Blum | _tree = _dev->get_tree(); |
| 211 | c861f98c | Josh Blum | } |
| 212 | |||
| 213 | device::sptr get_device(void){
|
||
| 214 | return _dev;
|
||
| 215 | } |
||
| 216 | |||
| 217 | /*******************************************************************
|
||
| 218 | * Mboard methods
|
||
| 219 | ******************************************************************/
|
||
| 220 | 625d5605 | Josh Blum | void set_master_clock_rate(double rate, size_t mboard){ |
| 221 | if (mboard != ALL_MBOARDS){
|
||
| 222 | ebd2ecc6 | Josh Blum | _tree->access<double>(mb_root(mboard) / "tick_rate").set(rate); |
| 223 | 625d5605 | Josh Blum | return;
|
| 224 | } |
||
| 225 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 226 | set_master_clock_rate(rate, m); |
||
| 227 | } |
||
| 228 | } |
||
| 229 | |||
| 230 | double get_master_clock_rate(size_t mboard){
|
||
| 231 | ebd2ecc6 | Josh Blum | return _tree->access<double>(mb_root(mboard) / "tick_rate").get(); |
| 232 | 625d5605 | Josh Blum | } |
| 233 | |||
| 234 | c861f98c | Josh Blum | std::string get_pp_string(void){ |
| 235 | bcd2c4e2 | Josh Blum | std::string buff = str(boost::format(
|
| 236 | "%s USRP:\n"
|
||
| 237 | " Device: %s\n"
|
||
| 238 | ) |
||
| 239 | % ((get_num_mboards() > 1)? "Multi" : "Single") |
||
| 240 | % (_tree->access<std::string>("/name").get()) |
||
| 241 | ); |
||
| 242 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 243 | buff += str(boost::format( |
||
| 244 | " Mboard %d: %s\n"
|
||
| 245 | ) % m |
||
| 246 | % (_tree->access<std::string>(mb_root(m) / "name").get()) |
||
| 247 | ); |
||
| 248 | } |
||
| 249 | |||
| 250 | //----------- rx side of life ----------------------------------
|
||
| 251 | for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ |
||
| 252 | for (; chan < (m + 1)*get_rx_subdev_spec(m).size(); chan++){ |
||
| 253 | buff += str(boost::format( |
||
| 254 | " RX Channel: %u\n"
|
||
| 255 | " RX DSP: %s\n"
|
||
| 256 | " RX Dboard: %s\n"
|
||
| 257 | " RX Subdev: %s\n"
|
||
| 258 | ) % chan |
||
| 259 | % rx_dsp_root(chan).leaf() |
||
| 260 | % rx_rf_fe_root(chan).branch_path().branch_path().leaf() |
||
| 261 | % (_tree->access<std::string>(rx_rf_fe_root(chan) / "name").get()) |
||
| 262 | ); |
||
| 263 | } |
||
| 264 | } |
||
| 265 | |||
| 266 | //----------- tx side of life ----------------------------------
|
||
| 267 | for (size_t m = 0, chan = 0; m < get_num_mboards(); m++){ |
||
| 268 | for (; chan < (m + 1)*get_tx_subdev_spec(m).size(); chan++){ |
||
| 269 | buff += str(boost::format( |
||
| 270 | " TX Channel: %u\n"
|
||
| 271 | " TX DSP: %s\n"
|
||
| 272 | " TX Dboard: %s\n"
|
||
| 273 | " TX Subdev: %s\n"
|
||
| 274 | ) % chan |
||
| 275 | % tx_dsp_root(chan).leaf() |
||
| 276 | % tx_rf_fe_root(chan).branch_path().branch_path().leaf() |
||
| 277 | % (_tree->access<std::string>(tx_rf_fe_root(chan) / "name").get()) |
||
| 278 | ); |
||
| 279 | } |
||
| 280 | } |
||
| 281 | |||
| 282 | return buff;
|
||
| 283 | c861f98c | Josh Blum | } |
| 284 | |||
| 285 | std::string get_mboard_name(size_t mboard){
|
||
| 286 | ebd2ecc6 | Josh Blum | return _tree->access<std::string>(mb_root(mboard) / "name").get(); |
| 287 | c861f98c | Josh Blum | } |
| 288 | |||
| 289 | 24c626a1 | Josh Blum | time_spec_t get_time_now(size_t mboard = 0){
|
| 290 | ebd2ecc6 | Josh Blum | return _tree->access<time_spec_t>(mb_root(mboard) / "time/now").get(); |
| 291 | c861f98c | Josh Blum | } |
| 292 | |||
| 293 | 24c626a1 | Josh Blum | time_spec_t get_time_last_pps(size_t mboard = 0){
|
| 294 | ebd2ecc6 | Josh Blum | return _tree->access<time_spec_t>(mb_root(mboard) / "time/pps").get(); |
| 295 | 76c8b7fa | Josh Blum | } |
| 296 | |||
| 297 | e1644548 | Josh Blum | void set_time_now(const time_spec_t &time_spec, size_t mboard){ |
| 298 | if (mboard != ALL_MBOARDS){
|
||
| 299 | ebd2ecc6 | Josh Blum | _tree->access<time_spec_t>(mb_root(mboard) / "time/now").set(time_spec);
|
| 300 | e1644548 | Josh Blum | return;
|
| 301 | } |
||
| 302 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 303 | set_time_now(time_spec, m); |
||
| 304 | } |
||
| 305 | } |
||
| 306 | |||
| 307 | 84ebf02b | Josh Blum | void set_time_next_pps(const time_spec_t &time_spec, size_t mboard){ |
| 308 | if (mboard != ALL_MBOARDS){
|
||
| 309 | _tree->access<time_spec_t>(mb_root(mboard) / "time/pps").set(time_spec);
|
||
| 310 | return;
|
||
| 311 | } |
||
| 312 | c861f98c | Josh Blum | for (size_t m = 0; m < get_num_mboards(); m++){ |
| 313 | 84ebf02b | Josh Blum | set_time_next_pps(time_spec, m); |
| 314 | c861f98c | Josh Blum | } |
| 315 | } |
||
| 316 | |||
| 317 | void set_time_unknown_pps(const time_spec_t &time_spec){ |
||
| 318 | 09be0518 | Josh Blum | UHD_MSG(status) << " 1) catch time transition at pps edge" << std::endl;
|
| 319 | 76c8b7fa | Josh Blum | time_spec_t time_start = get_time_now(); |
| 320 | time_spec_t time_start_last_pps = get_time_last_pps(); |
||
| 321 | while(true){ |
||
| 322 | if (get_time_last_pps() != time_start_last_pps) break; |
||
| 323 | if ((get_time_now() - time_start) > time_spec_t(1.1)){ |
||
| 324 | 4357f5d3 | Josh Blum | throw uhd::runtime_error(
|
| 325 | 64263e44 | Josh Blum | "Board 0 may not be getting a PPS signal!\n"
|
| 326 | "No PPS detected within the time interval.\n"
|
||
| 327 | "See the application notes for your device.\n"
|
||
| 328 | 76c8b7fa | Josh Blum | ); |
| 329 | } |
||
| 330 | c861f98c | Josh Blum | } |
| 331 | |||
| 332 | 09be0518 | Josh Blum | UHD_MSG(status) << " 2) set times next pps (synchronously)" << std::endl;
|
| 333 | 84ebf02b | Josh Blum | set_time_next_pps(time_spec, ALL_MBOARDS); |
| 334 | c861f98c | Josh Blum | boost::this_thread::sleep(boost::posix_time::seconds(1));
|
| 335 | |||
| 336 | //verify that the time registers are read to be within a few RTT
|
||
| 337 | for (size_t m = 1; m < get_num_mboards(); m++){ |
||
| 338 | ebd2ecc6 | Josh Blum | time_spec_t time_0 = this->get_time_now(0); |
| 339 | time_spec_t time_i = this->get_time_now(m);
|
||
| 340 | c861f98c | Josh Blum | if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big |
| 341 | 7f01386f | Josh Blum | UHD_MSG(warning) << boost::format( |
| 342 | c861f98c | Josh Blum | "Detected time deviation between board %d and board 0.\n"
|
| 343 | "Board 0 time is %f seconds.\n"
|
||
| 344 | "Board %d time is %f seconds.\n"
|
||
| 345 | 7f01386f | Josh Blum | ) % m % time_0.get_real_secs() % m % time_i.get_real_secs(); |
| 346 | c861f98c | Josh Blum | } |
| 347 | } |
||
| 348 | } |
||
| 349 | |||
| 350 | 211e1906 | Josh Blum | bool get_time_synchronized(void){ |
| 351 | for (size_t m = 1; m < get_num_mboards(); m++){ |
||
| 352 | ebd2ecc6 | Josh Blum | time_spec_t time_0 = this->get_time_now(0); |
| 353 | time_spec_t time_i = this->get_time_now(m);
|
||
| 354 | 211e1906 | Josh Blum | if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)) return false; |
| 355 | } |
||
| 356 | return true; |
||
| 357 | } |
||
| 358 | |||
| 359 | 5cdbf5b3 | Josh Blum | void set_command_time(const time_spec_t &, size_t){ |
| 360 | throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); |
||
| 361 | } |
||
| 362 | |||
| 363 | void clear_command_time(size_t){
|
||
| 364 | 7f815e12 | Josh Blum | throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); |
| 365 | } |
||
| 366 | |||
| 367 | 1628434a | Josh Blum | void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan){ |
| 368 | if (chan != ALL_CHANS){
|
||
| 369 | ebd2ecc6 | Josh Blum | _tree->access<stream_cmd_t>(rx_dsp_root(chan) / "stream_cmd").set(stream_cmd);
|
| 370 | 1628434a | Josh Blum | return;
|
| 371 | } |
||
| 372 | e128948a | Josh Blum | for (size_t c = 0; c < get_rx_num_channels(); c++){ |
| 373 | 1628434a | Josh Blum | issue_stream_cmd(stream_cmd, c); |
| 374 | c861f98c | Josh Blum | } |
| 375 | } |
||
| 376 | |||
| 377 | void set_clock_config(const clock_config_t &clock_config, size_t mboard){ |
||
| 378 | 93692591 | Josh Blum | //set the reference source...
|
| 379 | std::string clock_source;
|
||
| 380 | switch(clock_config.ref_source){
|
||
| 381 | case clock_config_t::REF_INT: clock_source = "internal"; break; |
||
| 382 | case clock_config_t::PPS_SMA: clock_source = "external"; break; |
||
| 383 | case clock_config_t::PPS_MIMO: clock_source = "mimo"; break; |
||
| 384 | default: clock_source = "unknown"; |
||
| 385 | } |
||
| 386 | this->set_clock_source(clock_source, mboard);
|
||
| 387 | |||
| 388 | //set the time source
|
||
| 389 | std::string time_source;
|
||
| 390 | switch(clock_config.pps_source){
|
||
| 391 | case clock_config_t::PPS_INT: time_source = "internal"; break; |
||
| 392 | case clock_config_t::PPS_SMA: time_source = "external"; break; |
||
| 393 | case clock_config_t::PPS_MIMO: time_source = "mimo"; break; |
||
| 394 | default: time_source = "unknown"; |
||
| 395 | } |
||
| 396 | if (time_source == "external" and clock_config.pps_polarity == clock_config_t::PPS_NEG) time_source = "_external_"; |
||
| 397 | this->set_time_source(time_source, mboard);
|
||
| 398 | } |
||
| 399 | |||
| 400 | void set_time_source(const std::string &source, const size_t mboard){ |
||
| 401 | c861f98c | Josh Blum | if (mboard != ALL_MBOARDS){
|
| 402 | 93692591 | Josh Blum | _tree->access<std::string>(mb_root(mboard) / "time_source" / "value").set(source); |
| 403 | c861f98c | Josh Blum | return;
|
| 404 | } |
||
| 405 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 406 | 93692591 | Josh Blum | return this->set_time_source(source, m); |
| 407 | c861f98c | Josh Blum | } |
| 408 | } |
||
| 409 | |||
| 410 | 93692591 | Josh Blum | std::string get_time_source(const size_t mboard){ |
| 411 | return _tree->access<std::string>(mb_root(mboard) / "time_source" / "value").get(); |
||
| 412 | } |
||
| 413 | |||
| 414 | std::vector<std::string> get_time_sources(const size_t mboard){ |
||
| 415 | return _tree->access<std::vector<std::string> >(mb_root(mboard) / "time_source" / "options").get(); |
||
| 416 | } |
||
| 417 | |||
| 418 | void set_clock_source(const std::string &source, const size_t mboard){ |
||
| 419 | if (mboard != ALL_MBOARDS){
|
||
| 420 | _tree->access<std::string>(mb_root(mboard) / "clock_source" / "value").set(source); |
||
| 421 | return;
|
||
| 422 | } |
||
| 423 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 424 | return this->set_clock_source(source, m); |
||
| 425 | } |
||
| 426 | } |
||
| 427 | |||
| 428 | std::string get_clock_source(const size_t mboard){ |
||
| 429 | return _tree->access<std::string>(mb_root(mboard) / "clock_source" / "value").get(); |
||
| 430 | } |
||
| 431 | |||
| 432 | std::vector<std::string> get_clock_sources(const size_t mboard){ |
||
| 433 | return _tree->access<std::vector<std::string> >(mb_root(mboard) / "clock_source" / "options").get(); |
||
| 434 | } |
||
| 435 | |||
| 436 | c861f98c | Josh Blum | size_t get_num_mboards(void){
|
| 437 | ebd2ecc6 | Josh Blum | return _tree->list("/mboards").size(); |
| 438 | c861f98c | Josh Blum | } |
| 439 | |||
| 440 | e4b45cca | Josh Blum | sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard){ |
| 441 | ebd2ecc6 | Josh Blum | return _tree->access<sensor_value_t>(mb_root(mboard) / "sensors" / name).get(); |
| 442 | e4b45cca | Josh Blum | } |
| 443 | |||
| 444 | std::vector<std::string> get_mboard_sensor_names(size_t mboard){
|
||
| 445 | ebd2ecc6 | Josh Blum | return _tree->list(mb_root(mboard) / "sensors"); |
| 446 | e4b45cca | Josh Blum | } |
| 447 | ebd2ecc6 | Josh Blum | |
| 448 | 781cafa8 | Josh Blum | void set_user_register(const boost::uint8_t addr, const boost::uint32_t data, size_t mboard){ |
| 449 | if (mboard != ALL_MBOARDS){
|
||
| 450 | typedef std::pair<boost::uint8_t, boost::uint32_t> user_reg_t;
|
||
| 451 | _tree->access<user_reg_t>(mb_root(mboard) / "user/reg").set(user_reg_t(addr, data));
|
||
| 452 | return;
|
||
| 453 | } |
||
| 454 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 455 | set_user_register(addr, data, m); |
||
| 456 | } |
||
| 457 | } |
||
| 458 | |||
| 459 | c861f98c | Josh Blum | /*******************************************************************
|
| 460 | * RX methods
|
||
| 461 | ******************************************************************/
|
||
| 462 | void set_rx_subdev_spec(const subdev_spec_t &spec, size_t mboard){ |
||
| 463 | if (mboard != ALL_MBOARDS){
|
||
| 464 | ebd2ecc6 | Josh Blum | _tree->access<subdev_spec_t>(mb_root(mboard) / "rx_subdev_spec").set(spec);
|
| 465 | c861f98c | Josh Blum | return;
|
| 466 | } |
||
| 467 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 468 | set_rx_subdev_spec(spec, m); |
||
| 469 | } |
||
| 470 | } |
||
| 471 | |||
| 472 | subdev_spec_t get_rx_subdev_spec(size_t mboard){
|
||
| 473 | ebd2ecc6 | Josh Blum | return _tree->access<subdev_spec_t>(mb_root(mboard) / "rx_subdev_spec").get(); |
| 474 | c861f98c | Josh Blum | } |
| 475 | |||
| 476 | size_t get_rx_num_channels(void){
|
||
| 477 | ede85c10 | Josh Blum | size_t sum = 0;
|
| 478 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 479 | sum += get_rx_subdev_spec(m).size(); |
||
| 480 | } |
||
| 481 | return sum;
|
||
| 482 | c861f98c | Josh Blum | } |
| 483 | |||
| 484 | std::string get_rx_subdev_name(size_t chan){
|
||
| 485 | ebd2ecc6 | Josh Blum | return _tree->access<std::string>(rx_rf_fe_root(chan) / "name").get(); |
| 486 | c861f98c | Josh Blum | } |
| 487 | |||
| 488 | e128948a | Josh Blum | void set_rx_rate(double rate, size_t chan){ |
| 489 | 1628434a | Josh Blum | if (chan != ALL_CHANS){
|
| 490 | ebd2ecc6 | Josh Blum | _tree->access<double>(rx_dsp_root(chan) / "rate" / "value").set(rate); |
| 491 | 1628434a | Josh Blum | do_samp_rate_warning_message(rate, get_rx_rate(chan), "RX");
|
| 492 | return;
|
||
| 493 | } |
||
| 494 | e128948a | Josh Blum | for (size_t c = 0; c < get_rx_num_channels(); c++){ |
| 495 | 1628434a | Josh Blum | set_rx_rate(rate, c); |
| 496 | c861f98c | Josh Blum | } |
| 497 | } |
||
| 498 | |||
| 499 | 1628434a | Josh Blum | double get_rx_rate(size_t chan){
|
| 500 | ebd2ecc6 | Josh Blum | return _tree->access<double>(rx_dsp_root(chan) / "rate" / "value").get(); |
| 501 | c861f98c | Josh Blum | } |
| 502 | |||
| 503 | ae9e89d7 | Josh Blum | meta_range_t get_rx_rates(size_t chan){
|
| 504 | return _tree->access<meta_range_t>(rx_dsp_root(chan) / "rate" / "range").get(); |
||
| 505 | } |
||
| 506 | |||
| 507 | 359c4e16 | Josh Blum | tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){
|
| 508 | aa6b340f | Josh Blum | 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); |
| 509 | 3cb60c97 | Josh Blum | do_tune_freq_warning_message(tune_request, get_rx_freq(chan), "RX");
|
| 510 | adbe1a0e | Josh Blum | return r;
|
| 511 | c861f98c | Josh Blum | } |
| 512 | |||
| 513 | double get_rx_freq(size_t chan){
|
||
| 514 | aa6b340f | Josh Blum | return derive_freq_from_xx_subdev_and_dsp(RX_SIGN, _tree->subtree(rx_dsp_root(chan)), _tree->subtree(rx_rf_fe_root(chan)));
|
| 515 | c861f98c | Josh Blum | } |
| 516 | |||
| 517 | freq_range_t get_rx_freq_range(size_t chan){
|
||
| 518 | e033fc3d | Josh Blum | return make_overall_tune_range(
|
| 519 | _tree->access<meta_range_t>(rx_rf_fe_root(chan) / "freq" / "range").get(), |
||
| 520 | _tree->access<meta_range_t>(rx_dsp_root(chan) / "freq" / "range").get(), |
||
| 521 | this->get_rx_bandwidth(chan)
|
||
| 522 | ); |
||
| 523 | c861f98c | Josh Blum | } |
| 524 | |||
| 525 | 395bbbbc | Josh Blum | void set_rx_gain(double gain, const std::string &name, size_t chan){ |
| 526 | ebd2ecc6 | Josh Blum | return rx_gain_group(chan)->set_value(gain, name);
|
| 527 | 8e341caa | Josh Blum | } |
| 528 | |||
| 529 | 395bbbbc | Josh Blum | double get_rx_gain(const std::string &name, size_t chan){ |
| 530 | ebd2ecc6 | Josh Blum | return rx_gain_group(chan)->get_value(name);
|
| 531 | c861f98c | Josh Blum | } |
| 532 | |||
| 533 | 8e341caa | Josh Blum | gain_range_t get_rx_gain_range(const std::string &name, size_t chan){ |
| 534 | ebd2ecc6 | Josh Blum | return rx_gain_group(chan)->get_range(name);
|
| 535 | c861f98c | Josh Blum | } |
| 536 | |||
| 537 | 8e341caa | Josh Blum | std::vector<std::string> get_rx_gain_names(size_t chan){
|
| 538 | ebd2ecc6 | Josh Blum | return rx_gain_group(chan)->get_names();
|
| 539 | c861f98c | Josh Blum | } |
| 540 | |||
| 541 | void set_rx_antenna(const std::string &ant, size_t chan){ |
||
| 542 | ebd2ecc6 | Josh Blum | _tree->access<std::string>(rx_rf_fe_root(chan) / "antenna" / "value").set(ant); |
| 543 | c861f98c | Josh Blum | } |
| 544 | |||
| 545 | std::string get_rx_antenna(size_t chan){
|
||
| 546 | ebd2ecc6 | Josh Blum | return _tree->access<std::string>(rx_rf_fe_root(chan) / "antenna" / "value").get(); |
| 547 | c861f98c | Josh Blum | } |
| 548 | |||
| 549 | std::vector<std::string> get_rx_antennas(size_t chan){
|
||
| 550 | ebd2ecc6 | Josh Blum | return _tree->access<std::vector<std::string> >(rx_rf_fe_root(chan) / "antenna" / "options").get(); |
| 551 | c861f98c | Josh Blum | } |
| 552 | |||
| 553 | 799d5059 | Josh Blum | void set_rx_bandwidth(double bandwidth, size_t chan){ |
| 554 | ebd2ecc6 | Josh Blum | _tree->access<double>(rx_rf_fe_root(chan) / "bandwidth" / "value").set(bandwidth); |
| 555 | 799d5059 | Josh Blum | } |
| 556 | |||
| 557 | double get_rx_bandwidth(size_t chan){
|
||
| 558 | ebd2ecc6 | Josh Blum | return _tree->access<double>(rx_rf_fe_root(chan) / "bandwidth" / "value").get(); |
| 559 | 799d5059 | Josh Blum | } |
| 560 | |||
| 561 | 3a9edd27 | Josh Blum | meta_range_t get_rx_bandwidth_range(size_t chan){
|
| 562 | return _tree->access<meta_range_t>(rx_rf_fe_root(chan) / "bandwidth" / "range").get(); |
||
| 563 | } |
||
| 564 | |||
| 565 | c861f98c | Josh Blum | dboard_iface::sptr get_rx_dboard_iface(size_t chan){
|
| 566 | ebd2ecc6 | Josh Blum | return _tree->access<dboard_iface::sptr>(rx_rf_fe_root(chan).branch_path().branch_path() / "iface").get(); |
| 567 | c861f98c | Josh Blum | } |
| 568 | |||
| 569 | e4b45cca | Josh Blum | sensor_value_t get_rx_sensor(const std::string &name, size_t chan){ |
| 570 | ebd2ecc6 | Josh Blum | return _tree->access<sensor_value_t>(rx_rf_fe_root(chan) / "sensors" / name).get(); |
| 571 | e4b45cca | Josh Blum | } |
| 572 | |||
| 573 | std::vector<std::string> get_rx_sensor_names(size_t chan){
|
||
| 574 | ebd2ecc6 | Josh Blum | return _tree->list(rx_rf_fe_root(chan) / "sensors"); |
| 575 | e4b45cca | Josh Blum | } |
| 576 | |||
| 577 | 07ba9464 | Josh Blum | void set_rx_dc_offset(const bool enb, size_t chan){ |
| 578 | if (chan != ALL_CHANS){
|
||
| 579 | dedfa652 | Josh Blum | _tree->access<bool>(rx_fe_root(chan) / "dc_offset" / "enable").set(enb); |
| 580 | 07ba9464 | Josh Blum | return;
|
| 581 | } |
||
| 582 | for (size_t c = 0; c < get_rx_num_channels(); c++){ |
||
| 583 | this->set_rx_dc_offset(enb, c);
|
||
| 584 | } |
||
| 585 | } |
||
| 586 | |||
| 587 | void set_rx_dc_offset(const std::complex<double> &offset, size_t chan){ |
||
| 588 | if (chan != ALL_CHANS){
|
||
| 589 | dedfa652 | Josh Blum | _tree->access<std::complex<double> >(rx_fe_root(chan) / "dc_offset" / "value").set(offset); |
| 590 | 07ba9464 | Josh Blum | return;
|
| 591 | } |
||
| 592 | for (size_t c = 0; c < get_rx_num_channels(); c++){ |
||
| 593 | this->set_rx_dc_offset(offset, c);
|
||
| 594 | } |
||
| 595 | } |
||
| 596 | |||
| 597 | a6264508 | Josh Blum | void set_rx_iq_balance(const std::complex<double> &offset, size_t chan){ |
| 598 | c63a38e1 | Josh Blum | if (chan != ALL_CHANS){
|
| 599 | dedfa652 | Josh Blum | _tree->access<std::complex<double> >(rx_fe_root(chan) / "iq_balance" / "value").set(offset); |
| 600 | c63a38e1 | Josh Blum | return;
|
| 601 | } |
||
| 602 | for (size_t c = 0; c < get_rx_num_channels(); c++){ |
||
| 603 | a6264508 | Josh Blum | this->set_rx_iq_balance(offset, c);
|
| 604 | c63a38e1 | Josh Blum | } |
| 605 | } |
||
| 606 | |||
| 607 | c861f98c | Josh Blum | /*******************************************************************
|
| 608 | * TX methods
|
||
| 609 | ******************************************************************/
|
||
| 610 | void set_tx_subdev_spec(const subdev_spec_t &spec, size_t mboard){ |
||
| 611 | if (mboard != ALL_MBOARDS){
|
||
| 612 | ebd2ecc6 | Josh Blum | _tree->access<subdev_spec_t>(mb_root(mboard) / "tx_subdev_spec").set(spec);
|
| 613 | c861f98c | Josh Blum | return;
|
| 614 | } |
||
| 615 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 616 | set_tx_subdev_spec(spec, m); |
||
| 617 | } |
||
| 618 | } |
||
| 619 | |||
| 620 | subdev_spec_t get_tx_subdev_spec(size_t mboard){
|
||
| 621 | ebd2ecc6 | Josh Blum | return _tree->access<subdev_spec_t>(mb_root(mboard) / "tx_subdev_spec").get(); |
| 622 | c861f98c | Josh Blum | } |
| 623 | |||
| 624 | std::string get_tx_subdev_name(size_t chan){
|
||
| 625 | ebd2ecc6 | Josh Blum | return _tree->access<std::string>(tx_rf_fe_root(chan) / "name").get(); |
| 626 | c861f98c | Josh Blum | } |
| 627 | |||
| 628 | size_t get_tx_num_channels(void){
|
||
| 629 | ede85c10 | Josh Blum | size_t sum = 0;
|
| 630 | for (size_t m = 0; m < get_num_mboards(); m++){ |
||
| 631 | sum += get_tx_subdev_spec(m).size(); |
||
| 632 | } |
||
| 633 | return sum;
|
||
| 634 | c861f98c | Josh Blum | } |
| 635 | |||
| 636 | e128948a | Josh Blum | void set_tx_rate(double rate, size_t chan){ |
| 637 | 1628434a | Josh Blum | if (chan != ALL_CHANS){
|
| 638 | ebd2ecc6 | Josh Blum | _tree->access<double>(tx_dsp_root(chan) / "rate" / "value").set(rate); |
| 639 | 1628434a | Josh Blum | do_samp_rate_warning_message(rate, get_tx_rate(chan), "TX");
|
| 640 | return;
|
||
| 641 | } |
||
| 642 | e128948a | Josh Blum | for (size_t c = 0; c < get_tx_num_channels(); c++){ |
| 643 | 1628434a | Josh Blum | set_tx_rate(rate, c); |
| 644 | c861f98c | Josh Blum | } |
| 645 | } |
||
| 646 | |||
| 647 | 1628434a | Josh Blum | double get_tx_rate(size_t chan){
|
| 648 | ebd2ecc6 | Josh Blum | return _tree->access<double>(tx_dsp_root(chan) / "rate" / "value").get(); |
| 649 | c861f98c | Josh Blum | } |
| 650 | |||
| 651 | ae9e89d7 | Josh Blum | meta_range_t get_tx_rates(size_t chan){
|
| 652 | return _tree->access<meta_range_t>(tx_dsp_root(chan) / "rate" / "range").get(); |
||
| 653 | } |
||
| 654 | |||
| 655 | 359c4e16 | Josh Blum | tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){
|
| 656 | aa6b340f | Josh Blum | 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); |
| 657 | 3cb60c97 | Josh Blum | do_tune_freq_warning_message(tune_request, get_tx_freq(chan), "TX");
|
| 658 | adbe1a0e | Josh Blum | return r;
|
| 659 | c861f98c | Josh Blum | } |
| 660 | |||
| 661 | double get_tx_freq(size_t chan){
|
||
| 662 | aa6b340f | Josh Blum | return derive_freq_from_xx_subdev_and_dsp(TX_SIGN, _tree->subtree(tx_dsp_root(chan)), _tree->subtree(tx_rf_fe_root(chan)));
|
| 663 | c861f98c | Josh Blum | } |
| 664 | |||
| 665 | freq_range_t get_tx_freq_range(size_t chan){
|
||
| 666 | e033fc3d | Josh Blum | return make_overall_tune_range(
|
| 667 | _tree->access<meta_range_t>(tx_rf_fe_root(chan) / "freq" / "range").get(), |
||
| 668 | _tree->access<meta_range_t>(tx_dsp_root(chan) / "freq" / "range").get(), |
||
| 669 | this->get_tx_bandwidth(chan)
|
||
| 670 | ); |
||
| 671 | c861f98c | Josh Blum | } |
| 672 | |||
| 673 | 395bbbbc | Josh Blum | void set_tx_gain(double gain, const std::string &name, size_t chan){ |
| 674 | ebd2ecc6 | Josh Blum | return tx_gain_group(chan)->set_value(gain, name);
|
| 675 | 8e341caa | Josh Blum | } |
| 676 | |||
| 677 | 395bbbbc | Josh Blum | double get_tx_gain(const std::string &name, size_t chan){ |
| 678 | ebd2ecc6 | Josh Blum | return tx_gain_group(chan)->get_value(name);
|
| 679 | c861f98c | Josh Blum | } |
| 680 | |||
| 681 | 8e341caa | Josh Blum | gain_range_t get_tx_gain_range(const std::string &name, size_t chan){ |
| 682 | ebd2ecc6 | Josh Blum | return tx_gain_group(chan)->get_range(name);
|
| 683 | c861f98c | Josh Blum | } |
| 684 | |||
| 685 | 8e341caa | Josh Blum | std::vector<std::string> get_tx_gain_names(size_t chan){
|
| 686 | ebd2ecc6 | Josh Blum | return tx_gain_group(chan)->get_names();
|
| 687 | c861f98c | Josh Blum | } |
| 688 | |||
| 689 | void set_tx_antenna(const std::string &ant, size_t chan){ |
||
| 690 | ebd2ecc6 | Josh Blum | _tree->access<std::string>(tx_rf_fe_root(chan) / "antenna" / "value").set(ant); |
| 691 | c861f98c | Josh Blum | } |
| 692 | |||
| 693 | std::string get_tx_antenna(size_t chan){
|
||
| 694 | ebd2ecc6 | Josh Blum | return _tree->access<std::string>(tx_rf_fe_root(chan) / "antenna" / "value").get(); |
| 695 | c861f98c | Josh Blum | } |
| 696 | |||
| 697 | std::vector<std::string> get_tx_antennas(size_t chan){
|
||
| 698 | ebd2ecc6 | Josh Blum | return _tree->access<std::vector<std::string> >(tx_rf_fe_root(chan) / "antenna" / "options").get(); |
| 699 | c861f98c | Josh Blum | } |
| 700 | |||
| 701 | 799d5059 | Josh Blum | void set_tx_bandwidth(double bandwidth, size_t chan){ |
| 702 | ebd2ecc6 | Josh Blum | _tree->access<double>(tx_rf_fe_root(chan) / "bandwidth" / "value").set(bandwidth); |
| 703 | 799d5059 | Josh Blum | } |
| 704 | |||
| 705 | double get_tx_bandwidth(size_t chan){
|
||
| 706 | ebd2ecc6 | Josh Blum | return _tree->access<double>(tx_rf_fe_root(chan) / "bandwidth" / "value").get(); |
| 707 | 799d5059 | Josh Blum | } |
| 708 | |||
| 709 | 3a9edd27 | Josh Blum | meta_range_t get_tx_bandwidth_range(size_t chan){
|
| 710 | return _tree->access<meta_range_t>(tx_rf_fe_root(chan) / "bandwidth" / "range").get(); |
||
| 711 | } |
||
| 712 | |||
| 713 | c861f98c | Josh Blum | dboard_iface::sptr get_tx_dboard_iface(size_t chan){
|
| 714 | ebd2ecc6 | Josh Blum | return _tree->access<dboard_iface::sptr>(tx_rf_fe_root(chan).branch_path().branch_path() / "iface").get(); |
| 715 | c861f98c | Josh Blum | } |
| 716 | |||
| 717 | e4b45cca | Josh Blum | sensor_value_t get_tx_sensor(const std::string &name, size_t chan){ |
| 718 | ebd2ecc6 | Josh Blum | return _tree->access<sensor_value_t>(tx_rf_fe_root(chan) / "sensors" / name).get(); |
| 719 | e4b45cca | Josh Blum | } |
| 720 | |||
| 721 | std::vector<std::string> get_tx_sensor_names(size_t chan){
|
||
| 722 | ebd2ecc6 | Josh Blum | return _tree->list(tx_rf_fe_root(chan) / "sensors"); |
| 723 | e4b45cca | Josh Blum | } |
| 724 | |||
| 725 | 07ba9464 | Josh Blum | void set_tx_dc_offset(const std::complex<double> &offset, size_t chan){ |
| 726 | if (chan != ALL_CHANS){
|
||
| 727 | dedfa652 | Josh Blum | _tree->access<std::complex<double> >(tx_fe_root(chan) / "dc_offset" / "value").set(offset); |
| 728 | 07ba9464 | Josh Blum | return;
|
| 729 | } |
||
| 730 | for (size_t c = 0; c < get_tx_num_channels(); c++){ |
||
| 731 | this->set_tx_dc_offset(offset, c);
|
||
| 732 | } |
||
| 733 | } |
||
| 734 | |||
| 735 | a6264508 | Josh Blum | void set_tx_iq_balance(const std::complex<double> &offset, size_t chan){ |
| 736 | c63a38e1 | Josh Blum | if (chan != ALL_CHANS){
|
| 737 | dedfa652 | Josh Blum | _tree->access<std::complex<double> >(tx_fe_root(chan) / "iq_balance" / "value").set(offset); |
| 738 | c63a38e1 | Josh Blum | return;
|
| 739 | } |
||
| 740 | for (size_t c = 0; c < get_tx_num_channels(); c++){ |
||
| 741 | a6264508 | Josh Blum | this->set_tx_iq_balance(offset, c);
|
| 742 | c63a38e1 | Josh Blum | } |
| 743 | } |
||
| 744 | |||
| 745 | c861f98c | Josh Blum | private:
|
| 746 | device::sptr _dev; |
||
| 747 | ebd2ecc6 | Josh Blum | property_tree::sptr _tree; |
| 748 | 982ac435 | Josh Blum | |
| 749 | ede85c10 | Josh Blum | struct mboard_chan_pair{
|
| 750 | size_t mboard, chan; |
||
| 751 | mboard_chan_pair(void): mboard(0), chan(0){} |
||
| 752 | }; |
||
| 753 | |||
| 754 | mboard_chan_pair rx_chan_to_mcp(size_t chan){
|
||
| 755 | mboard_chan_pair mcp; |
||
| 756 | mcp.chan = chan; |
||
| 757 | for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){ |
||
| 758 | size_t sss = get_rx_subdev_spec(mcp.mboard).size(); |
||
| 759 | if (mcp.chan < sss) break; |
||
| 760 | mcp.chan -= sss; |
||
| 761 | 083413de | Josh Blum | } |
| 762 | ede85c10 | Josh Blum | return mcp;
|
| 763 | 982ac435 | Josh Blum | } |
| 764 | |||
| 765 | ede85c10 | Josh Blum | mboard_chan_pair tx_chan_to_mcp(size_t chan){
|
| 766 | mboard_chan_pair mcp; |
||
| 767 | mcp.chan = chan; |
||
| 768 | for (mcp.mboard = 0; mcp.mboard < get_num_mboards(); mcp.mboard++){ |
||
| 769 | size_t sss = get_tx_subdev_spec(mcp.mboard).size(); |
||
| 770 | if (mcp.chan < sss) break; |
||
| 771 | mcp.chan -= sss; |
||
| 772 | 083413de | Josh Blum | } |
| 773 | ede85c10 | Josh Blum | return mcp;
|
| 774 | 982ac435 | Josh Blum | } |
| 775 | |||
| 776 | da40a1ae | Josh Blum | fs_path mb_root(const size_t mboard){
|
| 777 | ebd2ecc6 | Josh Blum | const std::string name = _tree->list("/mboards").at(mboard); |
| 778 | return "/mboards/" + name; |
||
| 779 | c861f98c | Josh Blum | } |
| 780 | ebd2ecc6 | Josh Blum | |
| 781 | da40a1ae | Josh Blum | fs_path rx_dsp_root(const size_t chan){
|
| 782 | ede85c10 | Josh Blum | mboard_chan_pair mcp = rx_chan_to_mcp(chan); |
| 783 | ebd2ecc6 | Josh Blum | const std::string name = _tree->list(mb_root(mcp.mboard) / "rx_dsps").at(mcp.chan); |
| 784 | return mb_root(mcp.mboard) / "rx_dsps" / name; |
||
| 785 | c861f98c | Josh Blum | } |
| 786 | ebd2ecc6 | Josh Blum | |
| 787 | da40a1ae | Josh Blum | fs_path tx_dsp_root(const size_t chan){
|
| 788 | ede85c10 | Josh Blum | mboard_chan_pair mcp = tx_chan_to_mcp(chan); |
| 789 | ebd2ecc6 | Josh Blum | const std::string name = _tree->list(mb_root(mcp.mboard) / "tx_dsps").at(mcp.chan); |
| 790 | return mb_root(mcp.mboard) / "tx_dsps" / name; |
||
| 791 | c861f98c | Josh Blum | } |
| 792 | ebd2ecc6 | Josh Blum | |
| 793 | dedfa652 | Josh Blum | fs_path rx_fe_root(const size_t chan){
|
| 794 | mboard_chan_pair mcp = rx_chan_to_mcp(chan); |
||
| 795 | const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan);
|
||
| 796 | return mb_root(mcp.mboard) / "rx_frontends" / spec.db_name; |
||
| 797 | } |
||
| 798 | |||
| 799 | fs_path tx_fe_root(const size_t chan){
|
||
| 800 | mboard_chan_pair mcp = tx_chan_to_mcp(chan); |
||
| 801 | const subdev_spec_pair_t spec = get_tx_subdev_spec(mcp.mboard).at(mcp.chan);
|
||
| 802 | return mb_root(mcp.mboard) / "tx_frontends" / spec.db_name; |
||
| 803 | } |
||
| 804 | |||
| 805 | da40a1ae | Josh Blum | fs_path rx_rf_fe_root(const size_t chan){
|
| 806 | ede85c10 | Josh Blum | mboard_chan_pair mcp = rx_chan_to_mcp(chan); |
| 807 | ebd2ecc6 | Josh Blum | const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan);
|
| 808 | return mb_root(mcp.mboard) / "dboards" / spec.db_name / "rx_frontends" / spec.sd_name; |
||
| 809 | c861f98c | Josh Blum | } |
| 810 | ebd2ecc6 | Josh Blum | |
| 811 | da40a1ae | Josh Blum | fs_path tx_rf_fe_root(const size_t chan){
|
| 812 | ede85c10 | Josh Blum | mboard_chan_pair mcp = tx_chan_to_mcp(chan); |
| 813 | ebd2ecc6 | Josh Blum | const subdev_spec_pair_t spec = get_tx_subdev_spec(mcp.mboard).at(mcp.chan);
|
| 814 | return mb_root(mcp.mboard) / "dboards" / spec.db_name / "tx_frontends" / spec.sd_name; |
||
| 815 | c861f98c | Josh Blum | } |
| 816 | ebd2ecc6 | Josh Blum | |
| 817 | gain_group::sptr rx_gain_group(size_t chan){
|
||
| 818 | ede85c10 | Josh Blum | mboard_chan_pair mcp = rx_chan_to_mcp(chan); |
| 819 | ebd2ecc6 | Josh Blum | const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan);
|
| 820 | gain_group::sptr gg = gain_group::make(); |
||
| 821 | BOOST_FOREACH(const std::string &name, _tree->list(mb_root(mcp.mboard) / "rx_codecs" / spec.db_name / "gains")){ |
||
| 822 | aa6b340f | Josh Blum | 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 */); |
| 823 | ebd2ecc6 | Josh Blum | } |
| 824 | BOOST_FOREACH(const std::string &name, _tree->list(rx_rf_fe_root(chan) / "gains")){ |
||
| 825 | aa6b340f | Josh Blum | gg->register_fcns(name, make_gain_fcns_from_subtree(_tree->subtree(rx_rf_fe_root(chan) / "gains" / name)), 1 /* high prio */); |
| 826 | ebd2ecc6 | Josh Blum | } |
| 827 | return gg;
|
||
| 828 | c861f98c | Josh Blum | } |
| 829 | ebd2ecc6 | Josh Blum | |
| 830 | gain_group::sptr tx_gain_group(size_t chan){
|
||
| 831 | ede85c10 | Josh Blum | mboard_chan_pair mcp = tx_chan_to_mcp(chan); |
| 832 | ebd2ecc6 | Josh Blum | const subdev_spec_pair_t spec = get_tx_subdev_spec(mcp.mboard).at(mcp.chan);
|
| 833 | gain_group::sptr gg = gain_group::make(); |
||
| 834 | BOOST_FOREACH(const std::string &name, _tree->list(mb_root(mcp.mboard) / "tx_codecs" / spec.db_name / "gains")){ |
||
| 835 | aa6b340f | Josh Blum | gg->register_fcns("ADC-"+name, make_gain_fcns_from_subtree(_tree->subtree(mb_root(mcp.mboard) / "tx_codecs" / spec.db_name / "gains" / name)), 1 /* high prio */); |
| 836 | ebd2ecc6 | Josh Blum | } |
| 837 | BOOST_FOREACH(const std::string &name, _tree->list(tx_rf_fe_root(chan) / "gains")){ |
||
| 838 | aa6b340f | Josh Blum | gg->register_fcns(name, make_gain_fcns_from_subtree(_tree->subtree(tx_rf_fe_root(chan) / "gains" / name)), 0 /* low prio */); |
| 839 | ebd2ecc6 | Josh Blum | } |
| 840 | return gg;
|
||
| 841 | c861f98c | Josh Blum | } |
| 842 | }; |
||
| 843 | |||
| 844 | /***********************************************************************
|
||
| 845 | * The Make Function
|
||
| 846 | **********************************************************************/
|
||
| 847 | multi_usrp::sptr multi_usrp::make(const device_addr_t &dev_addr){
|
||
| 848 | return sptr(new multi_usrp_impl(dev_addr)); |
||
| 849 | } |