aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorAlex Williams <alex.williams@ni.com>2017-10-20 11:51:24 -0700
committerMartin Braun <martin.braun@ettus.com>2017-12-22 15:04:03 -0800
commit479159352290aa925a7f2f5b428a0d78f150869c (patch)
tree1e57548d733e79395c66ab1115051565b31a3172 /host/lib
parentf721787d8183ee3fa980fb8131e813b23f1bc5c9 (diff)
downloaduhd-479159352290aa925a7f2f5b428a0d78f150869c.tar.gz
uhd-479159352290aa925a7f2f5b428a0d78f150869c.tar.bz2
uhd-479159352290aa925a7f2f5b428a0d78f150869c.zip
mg: Add support for low band LOs and RX switches
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp270
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp6
2 files changed, 272 insertions, 4 deletions
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 2c0f82aa8..4298df5b0 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp
@@ -32,7 +32,7 @@ namespace {
const double MAGNESIUM_TICK_RATE = 125e6; // Hz
const double MAGNESIUM_RADIO_RATE = 125e6; // Hz
- const double MAGNESIUM_MIN_FREQ = 300e6; // Hz
+ const double MAGNESIUM_MIN_FREQ = 1e6; // Hz
const double MAGNESIUM_MAX_FREQ = 6e9; // Hz
const double MAGNESIUM_MIN_RX_GAIN = 0.0; // dB
const double MAGNESIUM_MAX_RX_GAIN = 30.0; // dB
@@ -47,6 +47,49 @@ namespace {
const double MAGNESIUM_DEFAULT_BANDWIDTH = 40e6; // Hz TODO: fix
const size_t MAGNESIUM_NUM_TX_CHANS = 1;
const size_t MAGNESIUM_NUM_RX_CHANS = 1;
+ const double MAGNESIUM_RX_IF_FREQ = 2.44e9;
+ const double MAGNESIUM_TX_IF_FREQ = 1.95e9;
+ const double MAGNESIUM_LOWBAND_FREQ = 300e6;
+/*
+Magnesium Rev C frequency bands:
+
+RX IF frequency is 2.4418 GHz. Have 80 MHz of bandwidth for loband.
+TX IF frequency is 1.8-2.1 GHz (1.95 GHz is best).
+
+For RX:
+ Band SW2-AB SW3-ABC SW4-ABC SW5-ABCD SW6-ABC SW7-AB SW8-AB MIX
+ WB RF1 01 OFF 111 NA --- NA ---- RF3 001 RF2 01 RF2 01 0
+ LB RF2 10 RF5 100 NA --- RF3 0010 RF1 100 RF1 10 RF1 10 1
+ 440-530 RF2 10 RF2 001 NA --- RF1 1000 RF1 100 RF2 01 RF2 01 0
+ 650-1000 RF2 10 RF6 101 NA --- RF4 0001 RF1 100 RF2 01 RF2 01 0
+ 1100-1575 RF2 10 RF4 011 NA --- RF2 0100 RF1 100 RF2 01 RF2 01 0
+ 1600-2250 RF2 10 RF3 010 RF2 010 NA ---- RF2 010 RF2 01 RF2 01 0
+ 2100-2850 RF2 10 RF1 000 RF1 100 NA ---- RF2 010 RF2 01 RF2 01 0
+ 2700+ RF3 11 OFF 111 RF3 001 NA ---- RF2 010 RF2 01 RF2 01 0
+
+For TX:
+ Band SW5-AB SW4-AB SW3-X SW2-ABCD SW1-AB SWTRX-AB MIX
+ WB RF1 10 RF2 01 RF1 0 NA ---- SHD 00 RF4 11 0
+ LB RF2 01 RF1 10 RF2 1 RF3 0010 RF3 11 RF1 00 1
+ <800 RF1 10 RF2 01 RF2 1 RF3 0010 RF3 11 RF1 00 0
+ 800-1700 RF1 10 RF2 01 RF2 1 RF2 0100 RF2 10 RF1 00 0
+ 1700-3400 RF1 10 RF2 01 RF2 1 RF1 1000 RF1 01 RF1 00 0
+ 3400-6400 RF1 10 RF2 01 RF2 1 RF4 0001 SHD 00 RF2 10 0
+
+*/
+
+
+ const double MAGNESIUM_RX_BAND1_MIN_FREQ = MAGNESIUM_LOWBAND_FREQ;
+ const double MAGNESIUM_RX_BAND2_MIN_FREQ = 600e6;
+ const double MAGNESIUM_RX_BAND3_MIN_FREQ = 1050e6;
+ const double MAGNESIUM_RX_BAND4_MIN_FREQ = 1600e6;
+ const double MAGNESIUM_RX_BAND5_MIN_FREQ = 2100e6;
+ const double MAGNESIUM_RX_BAND6_MIN_FREQ = 2700e6;
+
+ const double MAGNESIUM_TX_BAND1_MIN_FREQ = MAGNESIUM_LOWBAND_FREQ;
+ const double MAGNESIUM_TX_BAND2_MIN_FREQ = 800e6;
+ const double MAGNESIUM_TX_BAND3_MIN_FREQ = 1700e6;
+ const double MAGNESIUM_TX_BAND4_MIN_FREQ = 3400e6;
const size_t FPGPIO_MASTER_RADIO = 0;
@@ -58,6 +101,16 @@ namespace {
{
UHD_ASSERT_THROW(dir == RX_DIRECTION or dir == TX_DIRECTION);
UHD_ASSERT_THROW(chan == 0 or chan == 1);
+ size_t chan = 0;
+ if (_radio_slot == "A" or _radio_slot == "C")
+ {
+ chan = 0;
+ }
+ if (_radio_slot == "B" or _radio_slot == "D")
+ {
+ chan = 1;
+ }
+ UHD_LOG_WARNING("MAGNESIUM_MYKONOS","board slot to chan map " << _radio_slot << " "<<chan)
return str(boost::format("%s%d")
% (dir == RX_DIRECTION ? "RX" : "TX")
% (chan+1)
@@ -224,7 +277,12 @@ void magnesium_radio_ctrl_impl::_init_peripherals()
fs_path cpld_path = _root_path.branch_path()
/ str(boost::format("Radio_%d") % ((get_block_id().get_block_count()/2)*2))
/ "cpld";
-
+ fs_path rx_lo_path = _root_path.branch_path()
+ / str(boost::format("Radio_%d") % ((get_block_id().get_block_count()/2)*2))
+ / "rx_lo";
+ fs_path tx_lo_path = _root_path.branch_path()
+ / str(boost::format("Radio_%d") % ((get_block_id().get_block_count()/2)*2))
+ / "tx_lo";
// TODO: When we move back to 2 chans per RFNoC block, this needs to be
// non-conditional, and the else-branch goes away:
if (_radio_slot == "A" or _radio_slot == "C") {
@@ -301,6 +359,20 @@ void magnesium_radio_ctrl_impl::_init_peripherals()
} else {
UHD_LOG_TRACE("MAGNESIUM", "Not a master radio, no LOs.");
}
+ if (not _tree->exists(rx_lo_path)) {
+ _tree->create<adf435x_iface::sptr>(rx_lo_path).set(_rx_lo);
+ }else
+ {
+ UHD_LOG_TRACE("MAGNESIUM", "Not a master radio. Getting LO from master" );
+ _rx_lo = _tree->access<adf435x_iface::sptr>(rx_lo_path).get();
+ }
+ if (not _tree->exists(tx_lo_path)) {
+ _tree->create<adf435x_iface::sptr>(tx_lo_path).set(_tx_lo);
+ }else
+ {
+ UHD_LOG_TRACE("MAGNESIUM", "Not a master radio. Getting LO from master" );
+ _tx_lo = _tree->access<adf435x_iface::sptr>(tx_lo_path).get();
+ }
_gpio.clear(); // Following the as-if rule, this can get optimized out
for (size_t radio_idx = 0; radio_idx < _get_num_radios(); radio_idx++) {
@@ -536,11 +608,172 @@ double magnesium_radio_ctrl_impl::_myk_set_frequency(
// affect the adjacent channel in the same direction. We have to make sure
// that getters will always tell the truth!
auto which = _get_which(dir, chan);
+ UHD_LOG_TRACE("MAGNESIUM", "requested frequency of " << freq);
+ double ad9371_freq = freq;
+ auto lo_iface = (dir == RX_DIRECTION) ? _rx_lo : _tx_lo;
+
+ if (freq < MAGNESIUM_LOWBAND_FREQ) { // Low band
+ double if_freq = (dir == RX_DIRECTION) ? MAGNESIUM_RX_IF_FREQ
+ : MAGNESIUM_TX_IF_FREQ;
+ double lo_freq = if_freq - freq;
+ _lo_set_frequency(lo_iface, lo_freq, chan);
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, true); // TODO: Find correct value
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, true); // TODO: Find correct value
+ lo_iface->commit();
+ ad9371_freq = if_freq;
+ } else {
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, false); // TODO: Find correct value
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, false); // TODO: Find correct value
+ lo_iface->commit();
+ }
+
+ UHD_LOG_TRACE("MAGNESIUM",
+ "Calling " << _rpc_prefix << "set_freq on " << which << " with " << ad9371_freq);
+ auto retval = _rpcc->request_with_token<double>(_rpc_prefix + "set_freq", which, ad9371_freq, false);
+ UHD_LOG_TRACE("MAGNESIUM",
+ _rpc_prefix << "set_freq returned " << retval);
+
+
+ // Set filters based on frequency
+ if (dir == RX_DIRECTION) {
+ if (freq < MAGNESIUM_RX_BAND1_MIN_FREQ) {
+ _cpld->set_rx_switches(
+ magnesium_cpld_ctrl::BOTH,
+ magnesium_cpld_ctrl::RX_SW1_RX2INPUT, /* FIXME hard coded */
+ magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3,
+ magnesium_cpld_ctrl::RX_SW3_FILTER0490LPMHZ,
+ magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ,
+ magnesium_cpld_ctrl::RX_SW5_FILTER0490LPMHZFROM,
+ magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5,
+ magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_LOBAND,
+ true
+ );
+ } else if (freq < MAGNESIUM_RX_BAND2_MIN_FREQ) {
+ _cpld->set_rx_switches(
+ magnesium_cpld_ctrl::BOTH,
+ magnesium_cpld_ctrl::RX_SW1_RX2INPUT, /* FIXME hard coded */
+ magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3,
+ magnesium_cpld_ctrl::RX_SW3_FILTER0440X0530MHZ,
+ magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ,
+ magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM,
+ magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5,
+ magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS,
+ false
+ );
+ } else if (freq < MAGNESIUM_RX_BAND3_MIN_FREQ) {
+ _cpld->set_rx_switches(
+ magnesium_cpld_ctrl::BOTH,
+ magnesium_cpld_ctrl::RX_SW1_RX2INPUT, /* FIXME hard coded */
+ magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3,
+ magnesium_cpld_ctrl::RX_SW3_FILTER0650X1000MHZ,
+ magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ,
+ magnesium_cpld_ctrl::RX_SW5_FILTER0650X1000MHZFROM,
+ magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5,
+ magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS,
+ false
+ );
+ } else if (freq < MAGNESIUM_RX_BAND4_MIN_FREQ) {
+ _cpld->set_rx_switches(
+ magnesium_cpld_ctrl::BOTH,
+ magnesium_cpld_ctrl::RX_SW1_RX2INPUT, /* FIXME hard coded */
+ magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3,
+ magnesium_cpld_ctrl::RX_SW3_FILTER1100X1575MHZ,
+ magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ,
+ magnesium_cpld_ctrl::RX_SW5_FILTER1100X1575MHZFROM,
+ magnesium_cpld_ctrl::RX_SW6_LOWERFILTERBANKFROMSWITCH5,
+ magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS,
+ false
+ );
+ } else if (freq < MAGNESIUM_RX_BAND5_MIN_FREQ) {
+ _cpld->set_rx_switches(
+ magnesium_cpld_ctrl::BOTH,
+ magnesium_cpld_ctrl::RX_SW1_RX2INPUT, /* FIXME hard coded */
+ magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3,
+ magnesium_cpld_ctrl::RX_SW3_FILTER1600X2250MHZ,
+ magnesium_cpld_ctrl::RX_SW4_FILTER1600X2250MHZFROM,
+ magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM,
+ magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4,
+ magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS,
+ false
+ );
+ } else if (freq < MAGNESIUM_RX_BAND6_MIN_FREQ) {
+ _cpld->set_rx_switches(
+ magnesium_cpld_ctrl::BOTH,
+ magnesium_cpld_ctrl::RX_SW1_RX2INPUT, /* FIXME hard coded */
+ magnesium_cpld_ctrl::RX_SW2_LOWERFILTERBANKTOSWITCH3,
+ magnesium_cpld_ctrl::RX_SW3_FILTER2100X2850MHZ,
+ magnesium_cpld_ctrl::RX_SW4_FILTER2100X2850MHZFROM,
+ magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM,
+ magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4,
+ magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS,
+ false
+ );
+ } else {
+ _cpld->set_rx_switches(
+ magnesium_cpld_ctrl::BOTH,
+ magnesium_cpld_ctrl::RX_SW1_RX2INPUT, /* FIXME hard coded */
+ magnesium_cpld_ctrl::RX_SW2_UPPERFILTERBANKTOSWITCH4,
+ magnesium_cpld_ctrl::RX_SW3_SHUTDOWNSW3,
+ magnesium_cpld_ctrl::RX_SW4_FILTER2700HPMHZ,
+ magnesium_cpld_ctrl::RX_SW5_FILTER0440X0530MHZFROM,
+ magnesium_cpld_ctrl::RX_SW6_UPPERFILTERBANKFROMSWITCH4,
+ magnesium_cpld_ctrl::LOWBAND_MIXER_PATH_SEL_BYPASS,
+ false
+ );
+ }
+ } else {
+ if (freq < MAGNESIUM_TX_BAND1_MIN_FREQ) {
+ } else if (freq < MAGNESIUM_TX_BAND2_MIN_FREQ) {
+ } else if (freq < MAGNESIUM_TX_BAND3_MIN_FREQ) {
+ } else if (freq < MAGNESIUM_TX_BAND4_MIN_FREQ) {
+ } else {
+ }
+ }
+ UHD_LOG_INFO("MAGNESIUM", "Update all freq related switches for " << freq <<" finished!.");
+}
+/******************************************************************************
+ * AD9371 Controls
+ *****************************************************************************/
+double magnesium_radio_ctrl_impl::_myk_set_frequency(
+ const double freq,
+ const size_t chan,
+ const direction_t dir
+) {
+
+
+ // 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!
+ auto which = _get_which(dir,_radio_slot);
+ UHD_LOG_TRACE("MAGNESIUM", "requested frequency of " << freq);
+ _update_freq_switches(freq,chan,dir);
+ double ad9371_freq = freq;
+ auto lo_iface = (dir == RX_DIRECTION) ? _rx_lo : _tx_lo;
+
+ if (freq < MAGNESIUM_LOWBAND_FREQ) { // Low band
+ UHD_LOG_WARNING("LO BAND", "requested frequency of " << freq);
+ double if_freq = (dir == RX_DIRECTION) ? MAGNESIUM_RX_IF_FREQ
+ : MAGNESIUM_TX_IF_FREQ;
+ double lo_freq = if_freq - freq;
+ _lo_set_frequency(lo_iface, lo_freq, chan);
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, true); // TODO: Find correct value
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, true); // TODO: Find correct value
+ lo_iface->commit();
+ ad9371_freq = if_freq;
+ } else {
+ UHD_LOG_WARNING("HI BAND", "requested frequency of " << freq);
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_A, false); // TODO: Find correct value
+ lo_iface->set_output_enable(adf435x_iface::RF_OUTPUT_B, false); // TODO: Find correct value
+ lo_iface->commit();
+ }
+
UHD_LOG_TRACE("MAGNESIUM",
- "Calling " << _rpc_prefix << "set_freq on " << which << " with " << freq);
- auto retval = _rpcc->request_with_token<double>(_rpc_prefix + "set_freq", which, freq, false);
+ "Calling " << _rpc_prefix << "set_freq on " << which << " with " << ad9371_freq);
+ auto retval = _rpcc->request_with_token<double>(_rpc_prefix + "set_freq", which, ad9371_freq, false);
UHD_LOG_TRACE("MAGNESIUM",
_rpc_prefix << "set_freq returned " << retval);
+
+
return retval;
}
@@ -606,4 +839,33 @@ double magnesium_radio_ctrl_impl::_myk_get_bandwidth(const size_t chan, const di
return MAGNESIUM_DEFAULT_BANDWIDTH;
}
+/******************************************************************************
+ * ADF4351 Controls
+ *****************************************************************************/
+double magnesium_radio_ctrl_impl::_lo_set_frequency(
+ adf435x_iface::sptr lo_iface,
+ const double freq,
+ const size_t chan
+) {
+
+ UHD_LOG_TRACE("MAGNESIUM", "attempting to tune low band LO to " << freq);
+ lo_iface->set_feedback_select(adf435x_iface::FB_SEL_DIVIDED);
+ lo_iface->set_reference_freq(100e6); // FIXME: How to get refclk freq? This can change.
+ lo_iface->set_prescaler(adf435x_iface::PRESCALER_4_5);
+
+ double actual_freq = 0.0;
+ actual_freq = lo_iface->set_frequency(freq, false); // FIXME: always fractional-n mode
+ UHD_LOG_TRACE("MAGNESIUM", "actual low band LO is " << actual_freq);
+ lo_iface->set_output_power(adf435x_iface::RF_OUTPUT_A, adf435x_iface::OUTPUT_POWER_2DBM); // TODO: Find correct value
+ lo_iface->set_output_power(adf435x_iface::RF_OUTPUT_B, adf435x_iface::OUTPUT_POWER_2DBM); // TODO: Find correct value
+ lo_iface->set_charge_pump_current(adf435x_iface::CHARGE_PUMP_CURRENT_0_31MA);
+
+ // TODO: Check for PLL lock
+ //sleep(1);
+ //auto lock_det = _rpcc->request_with_token<uint16_t>(_slot_prefix + "cpld_peek", 0x12);
+ //UHD_LOG_TRACE("MAGNESIUM", "lock detect is " << lock_det);
+
+ return actual_freq;
+}
+
UHD_RFNOC_BLOCK_REGISTER(magnesium_radio_ctrl, "MagnesiumRadio");
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 4e31886f7..5bcb83024 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp
@@ -138,6 +138,12 @@ private:
const direction_t dir
);
+ double _lo_set_frequency(
+ adf435x_iface::sptr lo_iface,
+ const double freq,
+ const size_t chan
+ );
+
//! Letter representation of the radio we're currently running
std::string _radio_slot;