aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard
diff options
context:
space:
mode:
authorTrung N Tran <trung.tran@ettus.com>2018-01-04 11:32:24 -0800
committerMartin Braun <martin.braun@ettus.com>2018-01-12 16:26:03 -0800
commit00402669d08b206f3b0367f5f4e3383d25e7944b (patch)
tree1ab5948382dde42f164499ce8e1cd68c3c4d959c /host/lib/usrp/dboard
parent7ffea3746be77cf926db946987ee83d48a33c798 (diff)
downloaduhd-00402669d08b206f3b0367f5f4e3383d25e7944b.tar.gz
uhd-00402669d08b206f3b0367f5f4e3383d25e7944b.tar.bz2
uhd-00402669d08b206f3b0367f5f4e3383d25e7944b.zip
mg: add facility that handle individual gain
-Create name for each gain/att element -Create property tree entry for each gain and their handlers. -Create gain profile that control how gain distributed. Right now, it is either "default" or "manual".
Diffstat (limited to 'host/lib/usrp/dboard')
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_constants.hpp16
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp18
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp89
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp24
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp213
5 files changed, 348 insertions, 12 deletions
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp
index 72a708165..0d914636e 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp
@@ -31,6 +31,9 @@ static const double AD9371_RX_GAIN_STEP = 0.5;
static const double DSA_MIN_GAIN = 0; // dB
static const double DSA_MAX_GAIN = 31.5; // dB
static const double DSA_GAIN_STEP = 0.5; // db
+static const double AMP_MIN_GAIN = 0; // dB
+static const double AMP_MAX_GAIN = 10; // dB
+static const double AMP_GAIN_STEP = 10;// dB
static const double AD9371_MIN_TX_GAIN = 0.0; // dB
static const double AD9371_MAX_TX_GAIN = 41.95; // dB
static const double AD9371_TX_GAIN_STEP = 0.05;
@@ -40,14 +43,27 @@ static const double ALL_RX_GAIN_STEP = 0.5;
static const double ALL_TX_MIN_GAIN = 0.0;
static const double ALL_TX_MAX_GAIN = 65.0;
static const double ALL_TX_GAIN_STEP = 0.5;
+
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 = "lowband";
+//! Magnesium gain profile options
+static const std::vector<std::string> MAGNESIUM_GP_OPTIONS = {
+ "manual",
+ "default"
+};
+//! AD9371 attenuation
+static const char* MAGNESIUM_GAIN1 = "rfic";
+//! DSA attenuation
+static const char* MAGNESIUM_GAIN2 = "dsa";
+//! Amplifier gain
+static const char* MAGNESIUM_AMP = "amp";
static const double MAGNESIUM_DEFAULT_BANDWIDTH = 40e6; // Hz TODO: fix
// Note: MAGNESIUM_NUM_CHANS is independent of the number of chans per
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp
index 449b772b3..f934e5794 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_gain.cpp
@@ -28,9 +28,21 @@ double magnesium_radio_ctrl_impl::_set_all_gain(
const size_t ad9371_chan = _master ? 0 : 1; ;// FIXME: use chan when 2 radios
const magnesium_cpld_ctrl::chan_sel_t chan_sel =
_master ? magnesium_cpld_ctrl::CHAN1 : magnesium_cpld_ctrl::CHAN2;
- const auto gain_tuple = (dir == RX_DIRECTION) ?
- get_rx_gain_tuple(gain, _map_freq_to_rx_band(freq)) :
- get_tx_gain_tuple(gain, _map_freq_to_tx_band(freq));
+ gain_tuple_t gain_tuple = (dir == RX_DIRECTION) ?
+ get_rx_gain_tuple(gain, _map_freq_to_rx_band(freq)):
+ get_tx_gain_tuple(gain, _map_freq_to_tx_band(freq));
+
+ if (_gain_profile[dir] == "manual"){
+ UHD_LOG_TRACE(unique_id(), "Manual gain mode. Getting gain from property tree.");
+ gain_tuple = {
+ DSA_MAX_GAIN - _dsa_att[dir],
+ ((dir == RX_DIRECTION) ? AD9371_MAX_RX_GAIN : AD9371_MAX_TX_GAIN) - _ad9371_att[dir],
+ _amp_bypass[dir]};
+ }else if (_gain_profile[dir] == "default"){
+ UHD_LOG_TRACE(unique_id(), "Getting gain from gain table.");
+ }else {
+ UHD_LOG_ERROR(unique_id(), "Unsupported gain mode: " << _gain_profile[dir])
+ }
const double ad9371_gain =
((dir == RX_DIRECTION) ? AD9371_MAX_RX_GAIN : AD9371_MAX_TX_GAIN)
- gain_tuple.ad9371_att;
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 2c7121c5c..eb4894e19 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp
@@ -412,6 +412,50 @@ double magnesium_radio_ctrl_impl::set_tx_gain(
return coerced_gain;
}
+double magnesium_radio_ctrl_impl::_set_tx_gain(
+ const std::string &name,
+ const double gain,
+ const size_t chan
+) {
+ std::lock_guard<std::mutex> l(_set_lock);
+ UHD_LOG_TRACE(unique_id(),
+ "_set_tx_gain(name=" << name << ", gain=" << gain << ", chan=" << chan << ")");
+ if (name == MAGNESIUM_GAIN1){
+ _ad9371_att[TX_DIRECTION] = gain;
+ }else if (name == MAGNESIUM_GAIN2){
+ _dsa_att[TX_DIRECTION] = gain;
+ }else if (name == MAGNESIUM_AMP){
+ _amp_bypass[TX_DIRECTION] = gain == 0.0;
+ }else {
+ throw uhd::value_error("Could not find gain element " + name);
+ }
+ UHD_LOG_TRACE(unique_id(),
+ "_set_tx_gain calling update gain");
+ this->_set_all_gain(
+ this->_get_all_gain(chan, TX_DIRECTION),
+ this->get_tx_frequency(chan),
+ chan,
+ TX_DIRECTION
+ );
+ return gain; // not really any coreced here for individual gain
+}
+
+double magnesium_radio_ctrl_impl::_get_tx_gain(
+ const std::string &name,
+ const size_t chan
+) {
+ std::lock_guard<std::mutex> l(_set_lock);
+ if (name == MAGNESIUM_GAIN1){
+ return _ad9371_att[TX_DIRECTION];
+ }else if (name == MAGNESIUM_GAIN2){
+ return _dsa_att[TX_DIRECTION];
+ }else if (name == MAGNESIUM_AMP){
+ return _amp_bypass[TX_DIRECTION]? AMP_MIN_GAIN : AMP_MAX_GAIN;
+ }else {
+ throw uhd::value_error("Could not find gain element " + name);
+ }
+}
+
double magnesium_radio_ctrl_impl::set_rx_gain(
const double gain,
const size_t chan
@@ -429,6 +473,51 @@ double magnesium_radio_ctrl_impl::set_rx_gain(
return coerced_gain;
}
+double magnesium_radio_ctrl_impl::_set_rx_gain(
+ const std::string &name,
+ const double gain,
+ const size_t chan
+) {
+ std::lock_guard<std::mutex> l(_set_lock);
+ UHD_LOG_TRACE(unique_id(),
+ "_set_rx_gain(name=" << name << ", gain=" << gain << ", chan=" << chan << ")");
+ if (name == MAGNESIUM_GAIN1){
+ _ad9371_att[RX_DIRECTION] = gain;
+ }else if (name == MAGNESIUM_GAIN2){
+ _dsa_att[RX_DIRECTION] = gain;
+ }else if (name == MAGNESIUM_AMP){
+ _amp_bypass[RX_DIRECTION] = gain == 0.0;
+ }else {
+ throw uhd::value_error("Could not find gain element " + name);
+ }
+ UHD_LOG_TRACE(unique_id(),
+ "_set_rx_gain calling update gain");
+ this->_set_all_gain(
+ this->_get_all_gain(chan, RX_DIRECTION),
+ this->get_rx_frequency(chan),
+ chan,
+ RX_DIRECTION
+ );
+ return gain; // not really any coreced here for individual gain
+}
+
+double magnesium_radio_ctrl_impl::_get_rx_gain(
+ const std::string &name,
+ const size_t chan
+) {
+ std::lock_guard<std::mutex> l(_set_lock);
+
+ if (name == MAGNESIUM_GAIN1){
+ return _ad9371_att[RX_DIRECTION];
+ }else if (name == MAGNESIUM_GAIN2){
+ return _dsa_att[RX_DIRECTION];
+ }else if (name == MAGNESIUM_AMP){
+ return _amp_bypass[RX_DIRECTION]? AMP_MIN_GAIN : AMP_MAX_GAIN;
+ }else{
+ throw uhd::value_error("Could not find gain element " + name);
+ }
+}
+
std::vector<std::string> magnesium_radio_ctrl_impl::get_rx_lo_names(
const size_t /*chan*/
) {
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 49affaa6f..d12666ce7 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp
@@ -134,6 +134,10 @@ public:
// gain
double set_tx_gain(const double gain, const size_t chan);
double set_rx_gain(const double gain, const size_t chan);
+ void set_tx_gain_source(const std::string& src, const std::string& name, const size_t chan);
+ std::string get_tx_gain_source(const std::string& name, const size_t chan);
+ void set_rx_gain_source(const std::string& src, const std::string& name, const size_t chan);
+ std::string get_rx_gain_source(const std::string& name, 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);
@@ -147,6 +151,18 @@ private:
/**************************************************************************
* Helpers
*************************************************************************/
+ //! Set tx gain on each gain element
+ double _set_tx_gain(const std::string &name, const double gain, const size_t chan);
+
+ //! Set rx gain on each gain element
+ double _set_rx_gain(const std::string &name, const double gain, const size_t chan);
+
+ //! Get tx gain on each gain element
+ double _get_tx_gain(const std::string &name, const size_t chan);
+
+ //! Get rx gain on each gain element
+ double _get_rx_gain(const std::string &name, const size_t chan);
+
//! Initialize all the peripherals connected to this block
void _init_peripherals();
@@ -328,14 +344,18 @@ private:
//! AD9371 gain
double _ad9371_rx_gain = 0.0;
double _ad9371_tx_gain = 0.0;
-
+ std::map<direction_t,double> _ad9371_att = { {RX_DIRECTION, 0.0}, {TX_DIRECTION, 0.0} };
//! DSA attenuation
double _dsa_rx_att = 0.0;
double _dsa_tx_att = 0.0;
-
+ std::map<direction_t,double> _dsa_att = { {RX_DIRECTION, 0.0}, {TX_DIRECTION, 0.0} };
+ //! amp gain
+ std::map<direction_t,bool> _amp_bypass = { {RX_DIRECTION, true}, {TX_DIRECTION, true} };
//! All gain
double _all_rx_gain = 0.0;
double _all_tx_gain = 0.0;
+ //! Gain profile
+ std::map<direction_t,std::string> _gain_profile = { {RX_DIRECTION, "default"}, {TX_DIRECTION, "default"} };
bool _rx_bypass_lnas = true;
bool _tx_bypass_amp = true;
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 5858995b0..5eb3cacd0 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_init.cpp
@@ -315,33 +315,232 @@ void magnesium_radio_ctrl_impl::_init_frontend_subtree(
return this->set_tx_gain(gain, chan_idx);
})
.set_publisher([this, chan_idx](){
- return this->get_tx_gain(chan_idx);
+ return radio_ctrl_impl::get_tx_gain(chan_idx);
})
;
subtree->create<meta_range_t>(tx_fe_path / "gains" / "all" / "range")
- .set(meta_range_t(ALL_TX_MIN_GAIN, ALL_TX_MAX_GAIN, ALL_TX_GAIN_STEP))
.add_coerced_subscriber([](const meta_range_t &){
throw uhd::runtime_error(
- "Attempting to update bandwidth range!");
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[TX_DIRECTION] == "manual") {
+ return meta_range_t(0.0, 0.0, 0.0);
+ }else{
+ return meta_range_t(ALL_TX_MIN_GAIN, ALL_TX_MAX_GAIN, ALL_TX_GAIN_STEP);
+ }
})
;
+
+ subtree->create<std::vector<std::string> >(tx_fe_path / "gains/all/profile/options")
+ .set(boost::assign::list_of("manual")("default"));
+
+ subtree->create<std::string>(tx_fe_path / "gains/all/profile/value")
+ .set_coercer([this, chan_idx](const std::string& profile){
+ std::string return_profile = profile;
+ if (std::find(MAGNESIUM_GP_OPTIONS.begin(),
+ MAGNESIUM_GP_OPTIONS.end(),
+ profile
+ ) == MAGNESIUM_GP_OPTIONS.end())
+ {
+ return_profile = "default";
+ }
+ _gain_profile[TX_DIRECTION] = return_profile;
+ return return_profile;
+ })
+ .set_publisher([this, chan_idx](){
+ return _gain_profile[TX_DIRECTION];
+ })
+ ;
+
// RX gains
subtree->create<double>(rx_fe_path / "gains" / "all" / "value")
.set_coercer([this, chan_idx](const double gain){
return this->set_rx_gain(gain, chan_idx);
})
.set_publisher([this, chan_idx](){
- return this->get_rx_gain(chan_idx);
+ return radio_ctrl_impl::get_rx_gain(chan_idx);
})
;
+
subtree->create<meta_range_t>(rx_fe_path / "gains" / "all" / "range")
- .set(meta_range_t(ALL_RX_MIN_GAIN, ALL_RX_MAX_GAIN, ALL_RX_GAIN_STEP))
.add_coerced_subscriber([](const meta_range_t &){
throw uhd::runtime_error(
- "Attempting to update bandwidth range!");
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[RX_DIRECTION] == "manual") {
+ return meta_range_t(0.0, 0.0, 0.0);
+ }else{
+ return meta_range_t(ALL_RX_MIN_GAIN, ALL_RX_MAX_GAIN, ALL_RX_GAIN_STEP);
+ }
+ })
+ ;
+
+ subtree->create<std::vector<std::string> >(rx_fe_path / "gains/all/profile/options")
+ .set(MAGNESIUM_GP_OPTIONS);
+
+ subtree->create<std::string>(rx_fe_path / "gains/all/profile/value")
+ .set_coercer([this, chan_idx](const std::string& profile){
+ std::string return_profile = profile;
+ if (std::find(MAGNESIUM_GP_OPTIONS.begin(),
+ MAGNESIUM_GP_OPTIONS.end(),
+ profile
+ ) == MAGNESIUM_GP_OPTIONS.end())
+ {
+ return_profile = "default";
+ }
+ _gain_profile[RX_DIRECTION] = return_profile;
+ return return_profile;
+ })
+ .set_publisher([this, chan_idx](){
+ return _gain_profile[RX_DIRECTION];
})
;
- // FIXME separate DSA and Myk gains
+
+ // TX mykonos attenuation
+ subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_GAIN1 / "value")
+ .set_coercer([this, chan_idx](const double gain){
+ return _set_tx_gain(MAGNESIUM_GAIN1, gain, chan_idx);
+ })
+ .set_publisher([this, chan_idx](){
+ return this->_get_tx_gain(MAGNESIUM_GAIN1, chan_idx);
+ })
+ ;
+
+ subtree->create<meta_range_t>(tx_fe_path / "gains" / MAGNESIUM_GAIN1 / "range")
+ .add_coerced_subscriber([](const meta_range_t &){
+ throw uhd::runtime_error(
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[TX_DIRECTION] == "manual") {
+ return meta_range_t(AD9371_MIN_TX_GAIN, AD9371_MAX_TX_GAIN, AD9371_TX_GAIN_STEP);
+ }else{
+ return meta_range_t(0.0, 0.0, 0.0);
+ }
+ })
+ ;
+ // TX DSA
+ subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_GAIN2 / "value")
+ .set_coercer([this, chan_idx](const double gain){
+ return this->_set_tx_gain(MAGNESIUM_GAIN2, gain, chan_idx);
+ })
+ .set_publisher([this, chan_idx](){
+ return this->_get_tx_gain(MAGNESIUM_GAIN2, chan_idx);
+ })
+ ;
+
+ subtree->create<meta_range_t>(tx_fe_path / "gains" / MAGNESIUM_GAIN2 / "range")
+ .add_coerced_subscriber([](const meta_range_t &){
+ throw uhd::runtime_error(
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[TX_DIRECTION] == "manual") {
+ return meta_range_t(DSA_MIN_GAIN, DSA_MAX_GAIN, DSA_GAIN_STEP);
+ }else{
+ return meta_range_t(0.0, 0.0, 0.0);
+ }
+ })
+ ;
+ //TX amp
+ subtree->create<double>(tx_fe_path / "gains" / MAGNESIUM_AMP / "value")
+ .set_coercer([this, chan_idx](const double gain) {
+ return this->_set_tx_gain(MAGNESIUM_AMP, gain, chan_idx);
+ })
+ .set_publisher([this, chan_idx]() {
+ return this->_get_tx_gain(MAGNESIUM_AMP, chan_idx);
+ })
+ ;
+
+ subtree->create<meta_range_t>(tx_fe_path / "gains" / MAGNESIUM_AMP / "range")
+ .add_coerced_subscriber([](const meta_range_t &) {
+ throw uhd::runtime_error(
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[TX_DIRECTION] == "manual") {
+ return meta_range_t(AMP_MIN_GAIN, AMP_MAX_GAIN, AMP_GAIN_STEP);
+ }else{
+ return meta_range_t(0.0, 0.0, 0.0);
+ }
+ })
+ ;
+
+ // RX mykonos attenuation
+ subtree->create<double>(rx_fe_path / "gains" / MAGNESIUM_GAIN1 / "value")
+ .set_coercer([this, chan_idx](const double gain){
+ UHD_VAR(gain);
+ return this->_set_rx_gain(MAGNESIUM_GAIN1, gain, chan_idx);
+ })
+ .set_publisher([this, chan_idx](){
+ return this->_get_rx_gain(MAGNESIUM_GAIN1, chan_idx);
+ })
+ ;
+
+ subtree->create<meta_range_t>(rx_fe_path / "gains" / MAGNESIUM_GAIN1 / "range")
+ .add_coerced_subscriber([](const meta_range_t &) {
+ throw uhd::runtime_error(
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[RX_DIRECTION] == "manual") {
+ return meta_range_t(AD9371_MIN_RX_GAIN, AD9371_MAX_RX_GAIN, AD9371_RX_GAIN_STEP);
+ }else{
+ return meta_range_t(0.0, 0.0, 0.0);
+ }
+ })
+ ;
+ //RX DSA
+ subtree->create<double>(rx_fe_path / "gains" / MAGNESIUM_GAIN2 / "value")
+ .set_coercer([this, chan_idx](const double gain) {
+ UHD_VAR(gain);
+ return this->_set_rx_gain(MAGNESIUM_GAIN2, gain, chan_idx);
+ })
+ .set_publisher([this, chan_idx]() {
+ return this->_get_rx_gain(MAGNESIUM_GAIN2, chan_idx);
+ })
+ ;
+
+ subtree->create<meta_range_t>(rx_fe_path / "gains" / MAGNESIUM_GAIN2 / "range")
+ .add_coerced_subscriber([](const meta_range_t &){
+ throw uhd::runtime_error(
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[RX_DIRECTION] == "manual") {
+ return meta_range_t(DSA_MIN_GAIN, DSA_MAX_GAIN, DSA_MAX_GAIN);
+ }else{
+ return meta_range_t(0.0, 0.0, 0.0);
+ }
+ })
+ ;
+
+ //RX amp
+ subtree->create<double>(rx_fe_path / "gains" / MAGNESIUM_AMP / "value")
+ .set_coercer([this, chan_idx](const double gain) {
+ return this->_set_rx_gain(MAGNESIUM_AMP, gain, chan_idx);
+ })
+ .set_publisher([this, chan_idx]() {
+ return this->_get_rx_gain(MAGNESIUM_AMP, chan_idx);
+ })
+ ;
+
+ subtree->create<meta_range_t>(rx_fe_path / "gains" / MAGNESIUM_AMP / "range")
+ .add_coerced_subscriber([](const meta_range_t &) {
+ throw uhd::runtime_error(
+ "Attempting to update gain range!");
+ })
+ .set_publisher([this, chan_idx](){
+ if (_gain_profile[RX_DIRECTION] == "manual") {
+ return meta_range_t(AMP_MIN_GAIN, AMP_MAX_GAIN, AMP_GAIN_STEP);
+ }else{
+ return meta_range_t(0.0, 0.0, 0.0);
+ }
+ })
+ ;
+
// TX LO lock sensor //////////////////////////////////////////////////////
// Note: The lowband and AD9371 LO lock sensors are generated
// programmatically in set_rpc_client(). The actual lo_locked publisher is