diff options
author | Alex Williams <alex.williams@ni.com> | 2017-10-20 11:51:24 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:04:03 -0800 |
commit | 479159352290aa925a7f2f5b428a0d78f150869c (patch) | |
tree | 1e57548d733e79395c66ab1115051565b31a3172 /host | |
parent | f721787d8183ee3fa980fb8131e813b23f1bc5c9 (diff) | |
download | uhd-479159352290aa925a7f2f5b428a0d78f150869c.tar.gz uhd-479159352290aa925a7f2f5b428a0d78f150869c.tar.bz2 uhd-479159352290aa925a7f2f5b428a0d78f150869c.zip |
mg: Add support for low band LOs and RX switches
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.cpp | 270 | ||||
-rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_radio_ctrl_impl.hpp | 6 |
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; |