diff options
| author | Trung N Tran <trung.tran@ettus.com> | 2017-11-09 17:32:32 -0800 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:05:57 -0800 | 
| commit | 7df29f6ee62d44eaeed878700ddbaeeb1d7fda46 (patch) | |
| tree | bc1ac0a1e4e09bd9ad3e6fbb23d7b459b9bf0449 /host/lib/usrp/dboard/magnesium | |
| parent | b9a0cf1467e89000658f69089bb773722e41ea89 (diff) | |
| download | uhd-7df29f6ee62d44eaeed878700ddbaeeb1d7fda46.tar.gz uhd-7df29f6ee62d44eaeed878700ddbaeeb1d7fda46.tar.bz2 uhd-7df29f6ee62d44eaeed878700ddbaeeb1d7fda46.zip | |
mg: Add LO specific properties and methods
This change adds extra hooks to the property tree to make LOs accessible
thru the property tree.
These can be used by multi_usrp api.
Reviewed-By: Martin Braun <martin.braun@ettus.com>
Diffstat (limited to 'host/lib/usrp/dboard/magnesium')
4 files changed, 515 insertions, 57 deletions
| diff --git a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp index 581b1cc97..94b7c52d2 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp @@ -13,6 +13,12 @@  static const size_t FPGPIO_MASTER_RADIO = 0; +static const double AD9371_MIN_FREQ = 300.0e6; // Hz +static const double AD9371_MAX_FREQ = 6.0e9; // Hz + +static const double ADF4351_MIN_FREQ = 35.0e6; +static const double ADF4351_MAX_FREQ = 4.4e9; +  static const double MAGNESIUM_RADIO_RATE = 125e6; // Hz  static const double MAGNESIUM_MIN_FREQ = 1e6; // Hz  static const double MAGNESIUM_MAX_FREQ = 6e9; // Hz @@ -50,6 +56,11 @@ static const double MAGNESIUM_CENTER_FREQ = 2.5e9; // Hz  static const std::vector<std::string> MAGNESIUM_RX_ANTENNAS = {      "TX/RX", "RX2", "CAL", "LOCAL"  }; +//! AD9371 LO (for direct conversion) +static const char* MAGNESIUM_LO1 = "rfic"; +//! Low-band LO (for IF conversion) +static const char* MAGNESIUM_LO2 = "low_synth"; +  static const double MAGNESIUM_DEFAULT_BANDWIDTH = 40e6; // Hz TODO: fix  // Note: MAGNESIUM_NUM_CHANS is independent of the number of chans per  // RFNoC block. TODO: When we go to one radio per dboard, this comment can diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp index db372ebfb..6d55662f4 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp @@ -18,6 +18,7 @@  #include <boost/make_shared.hpp>  #include <boost/format.hpp>  #include <sstream> +#include <cmath>  using namespace uhd;  using namespace uhd::usrp; @@ -178,7 +179,6 @@ void magnesium_radio_ctrl_impl::set_rx_antenna(          const size_t chan  ) {      UHD_ASSERT_THROW(chan <= MAGNESIUM_NUM_CHANS); -    std::lock_guard<std::mutex> l(_set_lock);      if (std::find(MAGNESIUM_RX_ANTENNAS.begin(),                    MAGNESIUM_RX_ANTENNAS.end(),                    ant) == MAGNESIUM_RX_ANTENNAS.end()) { @@ -201,12 +201,10 @@ double magnesium_radio_ctrl_impl::set_tx_frequency(          const double freq,          const size_t chan  ) { -    // Note: There is only one LO per tx or TX, so changing frequency will -    // affect the adjacent channel in the same direction. We have to make sure -    // that getters will always tell the truth! This is true for low and high -    // bands. +    // FIXME bounds checking + clipping!!!      UHD_LOG_TRACE(unique_id(),          "set_tx_frequency(f=" << freq << ", chan=" << chan << ")"); +    _desired_rf_freq[TX_DIRECTION]=freq;      if (not _master) {          const fs_path master_tx_fe_path =              master_fe_base_path(_radio_slot) / fs_path("tx_frontends") / chan; @@ -223,26 +221,31 @@ double magnesium_radio_ctrl_impl::set_tx_frequency(      // This way, if we tune channel 0 it will not put channel 1 into a bad      // state.      _update_tx_freq_switches(freq, _tx_bypass_amp, magnesium_cpld_ctrl::BOTH); -    //double ad9371_freq = freq; -    double if_freq = 0.0; -    auto lo_iface = _tx_lo; +    const std::string ad9371_source = this->get_tx_lo_source(MAGNESIUM_LO1, chan); +    const std::string adf4351_source = this->get_tx_lo_source(MAGNESIUM_LO2, chan); +    UHD_ASSERT_THROW(adf4351_source == "internal"); +    double coerced_if_freq = freq;      if (freq < MAGNESIUM_LOWBAND_FREQ) { // Low band -        if_freq = MAGNESIUM_TX_IF_FREQ ; -        const double lo_freq = if_freq - freq; -        const bool int_n_mode = false; // FIXME no hardcode -        //const double actual_lo_freq = -            _lo_enable(lo_iface, lo_freq, _master_clock_rate, int_n_mode); -        //ad9371_freq = actual_lo_freq - freq; +        _is_low_band[TX_DIRECTION] = true; +        const double desired_low_freq = MAGNESIUM_TX_IF_FREQ - freq; +        coerced_if_freq = +            this->set_tx_lo_freq(desired_low_freq, MAGNESIUM_LO2, chan) + freq; +        UHD_LOG_TRACE(unique_id(), "coerced_if_freq = " << coerced_if_freq);      } else { -        _lo_disable(lo_iface); +        _is_low_band[TX_DIRECTION] = false; +        _lo_disable(_tx_lo);      } +    // external LO required to tune at 2xdesired_frequency. +    const double desired_if_freq = (ad9371_source == "internal") ? +        coerced_if_freq : +        2*coerced_if_freq; + +    this->set_tx_lo_freq(desired_if_freq, MAGNESIUM_LO1, chan); -    //const double actual_ad9371_freq = -    _ad9371->set_frequency(freq, chan, TX_DIRECTION); -    radio_ctrl_impl::set_tx_frequency(freq, chan) +    this->_update_freq(chan, TX_DIRECTION);      this->_update_gain(chan, TX_DIRECTION); -    return freq; // FIXME calc the actual frequency +    return radio_ctrl_impl::get_tx_frequency(chan);  }  void magnesium_radio_ctrl_impl::_update_gain( @@ -260,19 +263,37 @@ void magnesium_radio_ctrl_impl::_update_gain(      this->_set_all_gain(this->_get_all_gain(chan, dir), freq, chan, dir);      // now we need update gain on slave      _tree->access<double>(slave_fe_path / "gains" / "all" / "value").update(); +} +void magnesium_radio_ctrl_impl::_update_freq( +        const size_t chan, +        const uhd::direction_t dir +) { +    const double rf_freq = _is_low_band[dir] ? +        _ad9371_freq[dir] - _adf4351_freq[dir] : +        _ad9371_freq[dir]; +    UHD_LOG_TRACE(unique_id(), +         "RF freq = " << rf_freq); +        UHD_ASSERT_THROW(rf_freq >= 0); +        UHD_ASSERT_THROW( +            std::abs(rf_freq - _desired_rf_freq[dir]) <= _master_clock_rate/2); +    if (dir == RX_DIRECTION){ +        radio_ctrl_impl::set_rx_frequency(rf_freq, chan); +    }else if (dir == TX_DIRECTION){ +        radio_ctrl_impl::set_tx_frequency(rf_freq, chan); +    }else{ +        UHD_THROW_INVALID_CODE_PATH(); +    }  }  double magnesium_radio_ctrl_impl::set_rx_frequency(          const double freq,          const size_t chan  ) { -    // Note: There is only one LO per RX or TX, so changing frequency will -    // affect the adjacent channel in the same direction. We have to make sure -    // that getters will always tell the truth! This is true for low and high -    // bands. +    // FIXME bounds checking + clipping!!!      UHD_LOG_TRACE(unique_id(),          "set_rx_frequency(f=" << freq << ", chan=" << chan << ")"); +    _desired_rf_freq[RX_DIRECTION]=freq;      if (not _master) {          const fs_path master_rx_fe_path =              master_fe_base_path(_radio_slot) / fs_path("rx_frontends") / chan; @@ -288,26 +309,32 @@ double magnesium_radio_ctrl_impl::set_rx_frequency(      // This way, if we tune channel 0 it will not put channel 1 into a bad      // state.      _update_rx_freq_switches(freq, _rx_bypass_lnas, magnesium_cpld_ctrl::BOTH); -    //double ad9371_freq = freq; -    double if_freq = 0.0; -    auto lo_iface = _rx_lo; +    const std::string ad9371_source = this->get_rx_lo_source(MAGNESIUM_LO1, chan); +    const std::string adf4351_source = this->get_rx_lo_source(MAGNESIUM_LO2, chan); +    UHD_ASSERT_THROW(adf4351_source == "internal"); +    double coerced_if_freq = freq;      if (freq < MAGNESIUM_LOWBAND_FREQ) { // Low band -        if_freq = MAGNESIUM_RX_IF_FREQ ; -        const double lo_freq = if_freq - freq; -        const bool int_n_mode = false; // FIXME no hardcode -        //const double actual_lo_freq = -            _lo_enable(lo_iface, lo_freq, _master_clock_rate, int_n_mode); -        //ad9371_freq = actual_lo_freq - freq; +        _is_low_band[RX_DIRECTION] = true; +        const double desired_low_freq = MAGNESIUM_RX_IF_FREQ - freq; +        coerced_if_freq = +             this->_set_rx_lo_freq(adf4351_source, MAGNESIUM_LO2, desired_low_freq, chan) + freq; +        UHD_LOG_TRACE(unique_id(), "coerced_if_freq = " << coerced_if_freq);      } else { -        _lo_disable(lo_iface); +        _is_low_band[RX_DIRECTION] = false; +        _lo_disable(_rx_lo);      } +    // external LO required to tune at 2xdesired_frequency. +    const double desired_if_freq = ad9371_source == "internal" ? +        coerced_if_freq : +        2*coerced_if_freq; + +    this->_set_rx_lo_freq(ad9371_source, MAGNESIUM_LO1, desired_if_freq, chan); -    //const double actual_ad9371_freq = -    _ad9371->set_frequency(freq, chan, RX_DIRECTION); -    radio_ctrl_impl::set_rx_frequency(freq, chan); +    this->_update_freq(chan, RX_DIRECTION);      this->_update_gain(chan, RX_DIRECTION); -    return freq; // FIXME calc the actual frequency + +    return radio_ctrl_impl::get_rx_frequency(chan);  }  double magnesium_radio_ctrl_impl::get_tx_frequency( @@ -393,55 +420,304 @@ double magnesium_radio_ctrl_impl::set_rx_gain(  std::vector<std::string> magnesium_radio_ctrl_impl::get_rx_lo_names(          const size_t /*chan*/  ) { -    return std::vector<std::string>{}; +    return std::vector<std::string>  {MAGNESIUM_LO1, MAGNESIUM_LO2};  }  std::vector<std::string> magnesium_radio_ctrl_impl::get_rx_lo_sources( -        const std::string &/*name*/, +        const std::string &name,          const size_t /*chan*/  ) { -    return std::vector<std::string>{}; +   if (name == MAGNESIUM_LO2){ +       return std::vector<std::string> { "internal" }; +   }else if (name == MAGNESIUM_LO1){ +       return std::vector<std::string> { "internal", "external" }; +   }else { +        throw uhd::value_error("Could not find LO stage " + name); +   }  }  freq_range_t magnesium_radio_ctrl_impl::get_rx_lo_freq_range( -        const std::string &/*name*/, -        const size_t /*chan*/ +        const std::string & name, +        const size_t  /*chan*/  ) { -    return freq_range_t{}; +    if (name == MAGNESIUM_LO1){ +        return freq_range_t{ADF4351_MIN_FREQ, ADF4351_MAX_FREQ}; +    } +    else if(name == MAGNESIUM_LO2){ +        return freq_range_t{AD9371_MIN_FREQ, AD9371_MAX_FREQ}; +    } +    else { +        throw uhd::value_error("Could not find LO stage " + name); +    }  }  void magnesium_radio_ctrl_impl::set_rx_lo_source( -        const std::string &/*src*/, -        const std::string &/*name*/, -        const size_t /*chan*/ +        const std::string &src, +        const std::string &name, +        const size_t chan  ) { +    UHD_LOG_TRACE(unique_id(),"Attempting to set rx LO." <<"LO "<<name<<" to "<<src << " at "<<chan); +    //TODO: checking what options are there      std::lock_guard<std::mutex> l(_set_lock); -    // FIXME +    if (not _master) { +        const fs_path master_rx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("rx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), +                "Slave setting lo source"); +        _tree->access<std::string>(master_rx_fe_path / "los" / name /"source"/"value").set(src); +        return; +    } +    UHD_LOG_TRACE(unique_id(), "Master set LO source." <<"LO "<<name<<" to "<<src << " at "<<chan); + +    if (name == MAGNESIUM_LO1){ +        _ad9371->set_lo_source(src, RX_DIRECTION); +    }else{ +        UHD_LOG_ERROR(unique_id(), "This LO " <<name <<" does not support set_lo_source to "<< src); +    }  }  const std::string magnesium_radio_ctrl_impl::get_rx_lo_source( -        const std::string &/*name*/, -        const size_t /*chan*/ +        const std::string &name, +        const size_t chan  ) { -    return ""; // FIXME +     if (not _master) { +        const fs_path master_rx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("rx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), "Slave getting lo source"); +        return _tree->access<std::string>(master_rx_fe_path / "los" / name /"source"/"value").get(); +    } +    UHD_LOG_DEBUG(unique_id(),"Master getting lo source"); +    if (name == MAGNESIUM_LO1){ +        //TODO: should we use this from cache? +         return _ad9371->get_lo_source(RX_DIRECTION); +     } +    return "internal"; +} + +double magnesium_radio_ctrl_impl::_set_rx_lo_freq( +    const std::string source, +    const std::string name, +    const double freq, +    const size_t chan +){ +    double coerced_lo_freq = freq; +    if (source != "internal"){ +        UHD_LOG_WARNING(unique_id(),"LO source is not internal. This set frequency will be ignored"); +        if(name == MAGNESIUM_LO1){ +            // handle ad9371 external LO case +            coerced_lo_freq = freq; +            _ad9371_freq[RX_DIRECTION] = coerced_lo_freq; +        } +    }else { +        if(name == MAGNESIUM_LO1){ +            coerced_lo_freq = _ad9371->set_frequency(freq, chan, RX_DIRECTION); +            _ad9371_freq[RX_DIRECTION] = coerced_lo_freq; +        }else if (name == MAGNESIUM_LO2 ){ +            // TODO: no hardcode the init_n_mode +             coerced_lo_freq = _lo_enable(_rx_lo, freq, _master_clock_rate, false); +            _adf4351_freq[RX_DIRECTION] = coerced_lo_freq; +        }else { +            UHD_LOG_WARNING(unique_id(), "There's no LO with this name of "<<name << " in the system. This set rx lo freq will be ignored"); +        }; +    } +    return coerced_lo_freq;  }  double magnesium_radio_ctrl_impl::set_rx_lo_freq( -        double /*freq*/, -        const std::string &/*name*/, -        const size_t /*chan*/ +        double freq, +        const std::string &name, +        const size_t chan  ) { +    UHD_LOG_TRACE(unique_id(),"Setting rx lo frequency for " <<name << " with freq = " <<freq);      std::lock_guard<std::mutex> l(_set_lock); -    return 0.0; // FIXME +    if (not _master) { +        const fs_path master_rx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("rx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), "Slave getting lo freq"); +       return  _tree->access<double>(master_rx_fe_path / "los" / name /"freq"/"value").set(freq).get(); +    } +    std::string source = this->get_rx_lo_source(name, chan); +    const double coerced_lo_freq = this->_set_rx_lo_freq(source, name, freq, chan); +    this->_update_freq(chan,TX_DIRECTION); +    this->_update_gain(chan,RX_DIRECTION); +    return coerced_lo_freq;  }  double magnesium_radio_ctrl_impl::get_rx_lo_freq( -        const std::string &/*name*/, +        const std::string & name, +        const size_t chan +) { + +    UHD_LOG_TRACE(unique_id(),"Getting rx lo frequency for " <<name); +    if (not _master) { +        const fs_path master_rx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("rx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), "Slave getting lo freq"); +        return _tree->access<double>(master_rx_fe_path / "los" / name /"freq"/"value").get(); +    } +    std::string source = this->get_rx_lo_source(name,chan); +    if(name == MAGNESIUM_LO1){ +        return _ad9371_freq[RX_DIRECTION]; +    }else if (name == "adf4531" ){ +        return _adf4351_freq[RX_DIRECTION]; +    }else { +            UHD_LOG_ERROR(unique_id(), "There's no LO with this name of "<<name << " in the system. This set rx lo freq will be ignored"); +    } +    UHD_THROW_INVALID_CODE_PATH(); +} + +//TX LO +std::vector<std::string> magnesium_radio_ctrl_impl::get_tx_lo_names(          const size_t /*chan*/  ) { -    return 0.0; // FIXME +    return std::vector<std::string>  {MAGNESIUM_LO1, MAGNESIUM_LO2};  } +std::vector<std::string> magnesium_radio_ctrl_impl::get_tx_lo_sources( +        const std::string &name, +        const size_t /*chan*/ +) { +   if (name == MAGNESIUM_LO2){ +       return std::vector<std::string> { "internal" }; +   }else if (name == MAGNESIUM_LO1){ +       return std::vector<std::string> { "internal", "external" }; +   }else { +        throw uhd::value_error("Could not find LO stage " + name); +   } +} + +freq_range_t magnesium_radio_ctrl_impl::get_tx_lo_freq_range( +        const std::string &name, +        const size_t /*chan*/ +) { +    if (name == MAGNESIUM_LO2){ +        return freq_range_t{ADF4351_MIN_FREQ, ADF4351_MAX_FREQ}; +    } +    else if(name == MAGNESIUM_LO1){ +        return freq_range_t{AD9371_MIN_FREQ, AD9371_MAX_FREQ}; +    } +    else { +        throw uhd::value_error("Could not find LO stage " + name); +    } +} + +void magnesium_radio_ctrl_impl::set_tx_lo_source( +        const std::string &src, +        const std::string &name, +        const size_t chan +) { +    UHD_LOG_TRACE(unique_id(),"Attempting to set tx LO." <<"LO "<<name<<" to "<<src << " at "<<chan); +    //TODO: checking what options are there +    std::lock_guard<std::mutex> l(_set_lock); +    if (not _master) { +        const fs_path master_tx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("tx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), +                "Slave setting lo source"); +        _tree->access<std::string>(master_tx_fe_path / "los" / name /"source"/"value").set(src); +    } +    UHD_LOG_TRACE(unique_id(), "Master set LO source." <<"LO "<<name<<" to "<<src << " at "<<chan); + + +    if (name == MAGNESIUM_LO1){ +        _ad9371->set_lo_source(src, TX_DIRECTION); +    }else{ +        UHD_LOG_ERROR(unique_id(), "This LO " <<name <<" does not support set_lo_source to "<< src); +    } +} + +const std::string magnesium_radio_ctrl_impl::get_tx_lo_source( +        const std::string &name, +        const size_t chan +) { +     if (not _master) { +        const fs_path master_tx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("tx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), "Slave getting lo source"); +        return _tree->access<std::string>(master_tx_fe_path / "los" / name /"source"/"value").get(); +    } +    UHD_LOG_DEBUG(unique_id(),"Master getting lo source"); +    if (name == MAGNESIUM_LO1){ +        //TODO: should we use this from cache? +         return _ad9371->get_lo_source(TX_DIRECTION); +     } +    return "internal"; +} + +double magnesium_radio_ctrl_impl::_set_tx_lo_freq( +    const std::string source, +    const std::string name, +    const double freq, +    const size_t chan +){ +    double coerced_lo_freq = freq; +    if (source != "internal"){ +        UHD_LOG_WARNING(unique_id(),"LO source is not internal. This set frequency will be ignored"); +        if(name == MAGNESIUM_LO1){ +            // handle ad9371 external LO case +            coerced_lo_freq = freq; +            _ad9371_freq[TX_DIRECTION] = coerced_lo_freq; +        } +    }else { +        if(name == MAGNESIUM_LO1){ +            coerced_lo_freq = _ad9371->set_frequency(freq, chan, TX_DIRECTION); +            _ad9371_freq[TX_DIRECTION] = coerced_lo_freq; +        }else if (name == MAGNESIUM_LO2 ){ +            // TODO: no hardcode the int_n_mode +            const bool int_n_mode = false; +            coerced_lo_freq = _lo_enable(_tx_lo, freq, _master_clock_rate, int_n_mode); +            _adf4351_freq[TX_DIRECTION] = coerced_lo_freq; +        }else { +            UHD_LOG_WARNING(unique_id(), "There's no LO with this name of "<<name << " in the system. This set tx lo freq will be ignored"); +        }; +    } +    return coerced_lo_freq; +} + +double magnesium_radio_ctrl_impl::set_tx_lo_freq( +        double freq, +        const std::string &name, +        const size_t chan +) { +    UHD_LOG_TRACE(unique_id(),"Setting tx lo frequency for " <<name << " with freq = " <<freq); +    if (not _master) { +        const fs_path master_tx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("tx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), "Slave getting lo freq"); +       return  _tree->access<double>(master_tx_fe_path / "los" / name /"freq"/"value").set(freq).get(); +    } +    std::string source = this->get_tx_lo_source(name,chan); +    const double return_freq = this->_set_tx_lo_freq(source, name, freq, chan); +    this->_update_freq(chan, TX_DIRECTION); +    this->_update_gain(chan, TX_DIRECTION); +    return return_freq; +} + +double magnesium_radio_ctrl_impl::get_tx_lo_freq( +        const std::string & name, +        const size_t chan +) { +    UHD_LOG_TRACE(unique_id(),"Getting tx lo frequency for " <<name); +    if (not _master) { +        const fs_path master_tx_fe_path = +            master_fe_base_path(_radio_slot) / fs_path("tx_frontends") / chan; +        UHD_LOG_DEBUG(unique_id(), "Slave getting lo freq"); +        return _tree->access<double>(master_tx_fe_path / "los" / name /"freq"/"value").get(); +    } +    std::string source = this->get_tx_lo_source(name,chan); +    if(name == MAGNESIUM_LO1){ +        return _ad9371_freq[TX_DIRECTION]; +    }else if (name == MAGNESIUM_LO2){ +        return _adf4351_freq[TX_DIRECTION]; +    }else { +        UHD_LOG_ERROR(unique_id(), "There's no LO with this name of "<<name << " in the system."); +    }; + +    UHD_THROW_INVALID_CODE_PATH(); +} + + +  size_t magnesium_radio_ctrl_impl::get_chan_from_dboard_fe(      const std::string &fe, const direction_t /* dir */  ) { diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp index c4c07cf97..c68ec5ef9 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp @@ -62,6 +62,8 @@ public:      double get_tx_frequency(const size_t chan);      double set_tx_bandwidth(const double bandwidth, const size_t chan);      double set_rx_bandwidth(const double bandwidth, const size_t chan); + +    // RX LO      std::vector<std::string> get_rx_lo_names(const size_t chan);      std::vector<std::string> get_rx_lo_sources(              const std::string &name, @@ -89,8 +91,38 @@ public:      );      double get_rx_lo_freq(const std::string &name, const size_t chan); +    // TX LO +    std::vector<std::string> get_tx_lo_names(const size_t chan); +    std::vector<std::string> get_tx_lo_sources( +            const std::string &name, +            const size_t chan +    ); +    freq_range_t get_tx_lo_freq_range( +            const std::string &name, +            const size_t chan +    ); + +    void set_tx_lo_source( +            const std::string &src, +            const std::string &name, +            const size_t chan +    ); +    const std::string get_tx_lo_source( +            const std::string &name, +            const size_t chan +    ); + +    double set_tx_lo_freq( +            double freq, +            const std::string &name, +            const size_t chan +    ); +    double get_tx_lo_freq(const std::string &name, const size_t chan); + +    // gain      double set_tx_gain(const double gain, const size_t chan);      double set_rx_gain(const double gain, const size_t chan); +      size_t get_chan_from_dboard_fe(const std::string &fe, const direction_t dir);      std::string get_dboard_fe_from_chan(const size_t chan, const direction_t dir); @@ -171,6 +203,10 @@ private:      void _update_gain(const size_t chan, direction_t dir); +    void _update_freq( +        const size_t chan, +        const uhd::direction_t dir +    );      /**************************************************************************       * CPLD Controls (implemented in magnesium_radio_ctrl_cpld.cpp)       *************************************************************************/ @@ -192,6 +228,19 @@ private:          const std::string &ant      ); +    double _set_rx_lo_freq( +        const std::string source, +        const std::string name, +        const double freq, +        const size_t chan +    ); + +    double _set_tx_lo_freq( +        const std::string source, +        const std::string name, +        const double freq, +        const size_t chan +    );      /**************************************************************************       * Private attributes       *************************************************************************/ @@ -243,7 +292,15 @@ private:      //! Sampling rate, and also ref clock frequency for the lowband LOs.      double _master_clock_rate = 1.0; - +     //! Desired RF frequency +    std::map<direction_t,double> _desired_rf_freq = { {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9} }; +    //! Coerced adf4351 frequency +    //! Coerced ad9371 frequency +    std::map<direction_t,double> _ad9371_freq = { {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9} }; +    //! Coerced adf4351 frequency +    std::map<direction_t,double> _adf4351_freq = { {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9} }; +    //! Low band enable +    std::map<direction_t,bool> _is_low_band = { {RX_DIRECTION, false}, {TX_DIRECTION, false} };      //! AD9371 gain      double _ad9371_rx_gain = 0.0;      double _ad9371_tx_gain = 0.0; @@ -266,6 +323,11 @@ private:          {magnesium_cpld_ctrl::CHAN2,              magnesium_cpld_ctrl::SW_TRX_FROMLOWERFILTERBANKTXSW1}      }; + +    //! RX LO SOURCE +    // NOTE for magnesium only ad9371 LO that can be connected to the external LO so we only need one var here +    std::string _rx_lo_source = "internal"; +  }; /* class radio_ctrl_impl */  }} /* namespace uhd::rfnoc */ diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp index 191218133..1b9e7f90e 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp @@ -366,6 +366,115 @@ void magnesium_radio_ctrl_impl::_init_frontend_subtree(              );          })      ; +    //LO Specific +    //RX LO +    subtree->create<meta_range_t>(rx_fe_path / "los"/MAGNESIUM_LO1/"freq/range") +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_freq_range(MAGNESIUM_LO1, chan_idx); +        }) +    ; +    subtree->create<std::vector<std::string>>(rx_fe_path / "los"/MAGNESIUM_LO1/"source/options") +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_sources(MAGNESIUM_LO1, chan_idx); +        }) +    ; +    subtree->create<std::string>(rx_fe_path / "los"/MAGNESIUM_LO1/"source/value") +        .add_coerced_subscriber([this,chan_idx](std::string src){ +            this->set_rx_lo_source(src, MAGNESIUM_LO1,chan_idx); +        }) +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_source(MAGNESIUM_LO1, chan_idx); +        }) +    ; +    subtree->create<double>(rx_fe_path / "los"/MAGNESIUM_LO1/"freq/value") +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_freq(MAGNESIUM_LO1, chan_idx); +        }) +        .set_coercer([this,chan_idx](const double freq){ +            return this->set_rx_lo_freq(freq, MAGNESIUM_LO1, chan_idx); +        }) +    ; + +    subtree->create<meta_range_t>(rx_fe_path / "los"/MAGNESIUM_LO2/"freq/range") +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_freq_range(MAGNESIUM_LO2, chan_idx); +        }) +    ; +    subtree->create<std::vector<std::string>>(rx_fe_path / "los"/MAGNESIUM_LO2/"source/options") +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_sources(MAGNESIUM_LO2, chan_idx); +        }) +    ; + +    subtree->create<std::string>(rx_fe_path / "los"/MAGNESIUM_LO2/"source/value") +        .add_coerced_subscriber([this,chan_idx](std::string src){ +            this->set_rx_lo_source(src, MAGNESIUM_LO2, chan_idx); +        }) +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_source(MAGNESIUM_LO2, chan_idx); +        }) +    ; +    subtree->create<double>(rx_fe_path / "los"/MAGNESIUM_LO2/"freq/value") +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_freq(MAGNESIUM_LO2, chan_idx); +        }) +        .set_coercer([this,chan_idx](double freq){ +            return this->set_rx_lo_freq(freq, MAGNESIUM_LO2, chan_idx); +        }); +    //TX LO +     subtree->create<meta_range_t>(tx_fe_path / "los"/MAGNESIUM_LO1/"freq/range") +        .set_publisher([this,chan_idx](){ +            return this->get_rx_lo_freq_range(MAGNESIUM_LO1, chan_idx); +        }) +    ; +    subtree->create<std::vector<std::string>>(tx_fe_path / "los"/MAGNESIUM_LO1/"source/options") +        .set_publisher([this,chan_idx](){ +            return this->get_tx_lo_sources(MAGNESIUM_LO1, chan_idx); +        }) +    ; +    subtree->create<std::string>(tx_fe_path / "los"/MAGNESIUM_LO1/"source/value") +        .add_coerced_subscriber([this,chan_idx](std::string src){ +            this->set_tx_lo_source(src, MAGNESIUM_LO1, chan_idx); +        }) +        .set_publisher([this,chan_idx](){ +            return this->get_tx_lo_source(MAGNESIUM_LO1, chan_idx); +        }) +    ; +    subtree->create<double>(tx_fe_path / "los"/MAGNESIUM_LO1/"freq/value ") +        .set_publisher([this,chan_idx](){ +            return this->get_tx_lo_freq(MAGNESIUM_LO1, chan_idx); +        }) +        .set_coercer([this,chan_idx](double freq){ +            return this->set_tx_lo_freq(freq, MAGNESIUM_LO1, chan_idx); +        }) +    ; + +    subtree->create<meta_range_t>(tx_fe_path / "los"/MAGNESIUM_LO2/"freq/range") +        .set_publisher([this,chan_idx](){ +            return this->get_tx_lo_freq_range(MAGNESIUM_LO2,chan_idx); +        }) +    ; +    subtree->create<std::vector<std::string>>(tx_fe_path / "los"/MAGNESIUM_LO2/"source/options") +        .set_publisher([this,chan_idx](){ +            return this->get_tx_lo_sources(MAGNESIUM_LO2, chan_idx); +        }) +    ; + +    subtree->create<std::string>(tx_fe_path / "los"/MAGNESIUM_LO2/"source/value") +        .add_coerced_subscriber([this,chan_idx](std::string src){ +            this->set_tx_lo_source(src, MAGNESIUM_LO2, chan_idx); +        }) +        .set_publisher([this,chan_idx](){ +            return this->get_tx_lo_source(MAGNESIUM_LO2, chan_idx); +        }) +    ; +    subtree->create<double>(tx_fe_path / "los"/MAGNESIUM_LO2/"freq/value") +        .set_publisher([this,chan_idx](){ +            return this->get_tx_lo_freq(MAGNESIUM_LO2, chan_idx); +        }) +        .set_coercer([this,chan_idx](double freq){ +            return this->set_tx_lo_freq(freq, MAGNESIUM_LO2, chan_idx); +        });  }  void magnesium_radio_ctrl_impl::_init_prop_tree() | 
