diff options
-rw-r--r-- | host/docs/dboards.rst | 40 | ||||
-rw-r--r-- | host/docs/usrp1.rst | 9 | ||||
-rw-r--r-- | host/docs/usrp_e1xx.rst | 16 | ||||
-rw-r--r-- | host/examples/rx_timed_samples.cpp | 9 | ||||
-rw-r--r-- | host/include/uhd/types/clock_config.hpp | 2 | ||||
-rw-r--r-- | host/include/uhd/types/tune_request.hpp | 12 | ||||
-rw-r--r-- | host/include/uhd/types/tune_result.hpp | 10 | ||||
-rw-r--r-- | host/lib/types/tune.cpp | 18 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_rfx.cpp | 35 | ||||
-rw-r--r-- | host/lib/usrp/mboard_eeprom.cpp | 58 | ||||
-rw-r--r-- | host/lib/usrp/tune_helper.cpp | 26 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/clock_ctrl.cpp | 14 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/mboard_impl.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/usrp1_ctrl.cpp | 26 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 38 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 23 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/clock_ctrl.cpp | 19 | ||||
-rw-r--r-- | host/lib/usrp/usrp_e100/mboard_impl.cpp | 4 | ||||
-rw-r--r-- | host/tests/tune_helper_test.cpp | 12 |
19 files changed, 277 insertions, 98 deletions
diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 373189441..42965b32f 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -130,6 +130,7 @@ Bandwidths (Hz): Sensors: * **lo_locked**: boolean for LO lock state +* **rssi**: float for rssi in dBm ^^^^^^^^^^^^^^^^^^^^^^^^^^^ XCVR 2450 @@ -204,6 +205,45 @@ Sensors: * **lo_locked**: boolean for LO lock state ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +SBX Series +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The SBX Series boards have 2 quadrature subdevices, one transmit, one receive. +Transmit and Receive default to direct conversion but +can be used in low IF mode through lo_offset in uhd::tune_request_t + +The SBX Series boards have independent receive and transmit LO's and synthesizers +allowing full-duplex operation on different transmit and receive frequencies. + +Transmit Antennas: **TX/RX** + +Receive Antennas: **TX/RX** or **RX2** + +The user may set the receive antenna to be TX/RX or RX2. +However, when using an SBX board in full-duplex mode, +the receive antenna will always be set to RX2, regardless of the settings. + +Transmit Gains: **PGA0**, Range: 0-31.5dB + +Receive Gains: **PGA0**, Range: 0-31.5dB + +Bandwidths (Hz): + +* **RX**: 40M +* **TX**: 40M + +Sensors: + +* **lo_locked**: boolean for LO lock state + +LEDs: + +* All LEDs flash when dboard control is initialized +* **TX LD**: Transmit Synthesizer Lock Detect +* **TX/RX**: Receiver on TX/RX antenna port (No TX) +* **RX LD**: Receive Synthesizer Lock Detect +* **RX1/RX2**: Receiver on RX2 antenna port + +^^^^^^^^^^^^^^^^^^^^^^^^^^^ TVRX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The TVRX board has 1 real-mode subdevice. diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index f77a26e0a..97a8c3bb5 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -136,6 +136,11 @@ The USRP can be modified to accept an external clock reference instead of the 64 The new external clock needs to be a square wave between +7dBm and +15dBm -For the correct clock settings, call usrp->set_master_clock_rate(EXT_CLOCK_FREQUENCY) -before any other parameters are set in your application. +After the hardware modification, +the user should burn the setting into the EEPROM, +so UHD can initialize with the correct clock rate. +Run the following commands to record the setting into the EEPROM: +:: + cd <install-path>/share/uhd/utils + ./usrp_burn_mb_eeprom --args=<optional device args> --key=mcr --val=<rate> diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst index 2818a0a65..036d2c02c 100644 --- a/host/docs/usrp_e1xx.rst +++ b/host/docs/usrp_e1xx.rst @@ -20,7 +20,6 @@ Example device address string representations to specify non-standard FPGA image Changing the master clock rate ------------------------------------------------------------------------ The master clock rate of the USRP embedded feeds both the FPGA DSP and the codec chip. -UHD can dynamically reconfigure the clock rate though the set_master_clock_rate() API call. Hundreds of rates between 32MHz and 64MHz are available. A few notable rates are: @@ -36,8 +35,12 @@ To use the 61.44MHz clock rate, the USRP embedded will require two jumpers to be * J16 is a two pin header, remove the jumper (or leave it on pin1 only) * J15 is a three pin header, move the jumper to (pin1, pin2) -For the correct clock settings, call usrp->set_master_clock_rate(61.44e6) -before any other parameters are set in your application. +Then run the following commands to record the setting into the EEPROM: +:: + + cd <install-path>/share/uhd/utils + ./usrp_burn_mb_eeprom --key=mcr --val=61.44e6 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Set other rates - uses internal VCO @@ -47,8 +50,11 @@ To use other clock rates, the jumpers will need to be in the default position. * J16 is a two pin header, move the jumper to (pin1, pin2) * J15 is a three pin header, move the jumper to (pin2, pin3) -For the correct clock settings, call usrp->set_master_clock_rate(rate) -before any other parameters are set in your application. +Then run the following commands to record the setting into the EEPROM: +:: + + cd <install-path>/share/uhd/utils + ./usrp_burn_mb_eeprom --key=mcr --val=<rate> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clock rate recovery - unbricking diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 28d7ee466..05cc0717b 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -32,7 +32,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::string args; double seconds_in_future; size_t total_num_samps; - double rate, clock; + double rate; //setup the program options po::options_description desc("Allowed options"); @@ -41,7 +41,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args") ("secs", po::value<double>(&seconds_in_future)->default_value(1.5), "number of seconds in the future to receive") ("nsamps", po::value<size_t>(&total_num_samps)->default_value(10000), "total number of samples to receive") - ("clock", po::value<double>(&clock), "master clock frequency in Hz") ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples") ("dilv", "specify to disable inner-loop verbose") ; @@ -63,12 +62,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; - //optionally set the clock rate (do before setting anything else) - if (vm.count("clock")){ - std::cout << boost::format("Setting master clock rate: %f MHz...") % (clock/1e6) << std::endl; - usrp->set_master_clock_rate(clock); - } - //set the rx sample rate std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_rx_rate(rate); diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 577416d77..24bd96d14 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -44,10 +44,12 @@ namespace uhd{ REF_AUTO = int('a'), //automatic (device specific) REF_INT = int('i'), //internal reference REF_SMA = int('s'), //external sma port + REF_MIMO = int('m'), //reference from mimo cable } ref_source; enum pps_source_t { PPS_INT = int('i'), //there is no internal PPS_SMA = int('s'), //external sma port + PPS_MIMO = int('m'), //time sync from mimo cable } pps_source; enum pps_polarity_t { PPS_NEG = int('n'), //negative edge diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp index b59f37c2e..9c498bfe9 100644 --- a/host/include/uhd/types/tune_request.hpp +++ b/host/include/uhd/types/tune_request.hpp @@ -32,7 +32,7 @@ namespace uhd{ struct UHD_API tune_request_t{ /*! * Make a new tune request for a particular center frequency. - * Use an automatic policy for the intermediate and DSP frequency + * Use an automatic policy for the RF and DSP frequency * to tune the chain as close as possible to the target frequency. * \param target_freq the target frequency in Hz */ @@ -40,7 +40,7 @@ namespace uhd{ /*! * Make a new tune request for a particular center frequency. - * Use a manual policy for the intermediate frequency, + * Use a manual policy for the RF frequency, * and an automatic policy for the DSP frequency, * to tune the chain as close as possible to the target frequency. * \param target_freq the target frequency in Hz @@ -65,16 +65,16 @@ namespace uhd{ double target_freq; /*! - * The policy for the intermediate frequency. + * The policy for the RF frequency. * Automatic behavior: the target frequency + default LO offset. */ - policy_t inter_freq_policy; + policy_t rf_freq_policy; /*! - * The intermediate frequency in Hz. + * The RF frequency in Hz. * Set when the policy is set to manual. */ - double inter_freq; + double rf_freq; /*! * The policy for the DSP frequency. diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp index 9eebc161a..e51473085 100644 --- a/host/include/uhd/types/tune_result.hpp +++ b/host/include/uhd/types/tune_result.hpp @@ -24,15 +24,11 @@ namespace uhd{ /*! - * The tune result struct holds result of a 2-phase tuning: - * The struct hold the result of tuning the dboard as - * the target and actual intermediate frequency. - * The struct hold the result of tuning the DSP as - * the target and actual digital converter frequency. + * The tune result struct holds result of a 2-phase tuning. */ struct UHD_API tune_result_t{ - double target_inter_freq; - double actual_inter_freq; + double target_rf_freq; + double actual_rf_freq; double target_dsp_freq; double actual_dsp_freq; diff --git a/host/lib/types/tune.cpp b/host/lib/types/tune.cpp index 601bc20e8..154f0990f 100644 --- a/host/lib/types/tune.cpp +++ b/host/lib/types/tune.cpp @@ -23,7 +23,7 @@ using namespace uhd; tune_request_t::tune_request_t(double target_freq): target_freq(target_freq), - inter_freq_policy(POLICY_AUTO), + rf_freq_policy(POLICY_AUTO), dsp_freq_policy(POLICY_AUTO) { /* NOP */ @@ -31,8 +31,8 @@ tune_request_t::tune_request_t(double target_freq): tune_request_t::tune_request_t(double target_freq, double lo_off): target_freq(target_freq), - inter_freq_policy(POLICY_MANUAL), - inter_freq(target_freq + lo_off), + rf_freq_policy(POLICY_MANUAL), + rf_freq(target_freq + lo_off), dsp_freq_policy(POLICY_AUTO) { /* NOP */ @@ -41,12 +41,12 @@ tune_request_t::tune_request_t(double target_freq, double lo_off): std::string tune_result_t::to_pp_string(void) const{ return str(boost::format( "Tune Result:\n" - " Target Intermediate Freq: %f (MHz)\n" - " Actual Intermediate Freq: %f (MHz)\n" - " Target DSP Freq Shift: %f (MHz)\n" - " Actual DSP Freq Shift: %f (MHz)\n" + " Target RF Freq: %f (MHz)\n" + " Actual RF Freq: %f (MHz)\n" + " Target DSP Freq: %f (MHz)\n" + " Actual DSP Freq: %f (MHz)\n" ) - % (target_inter_freq/1e6) % (actual_inter_freq/1e6) - % (target_dsp_freq/1e6) % (actual_dsp_freq/1e6) + % (target_rf_freq/1e6) % (actual_rf_freq/1e6) + % (target_dsp_freq/1e6) % (actual_dsp_freq/1e6) ); } diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 725b5cc03..231757365 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -121,6 +121,22 @@ private: bool get_locked(dboard_iface::unit_t unit){ return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; } + + /*! + * Read the RSSI from the aux adc + * \return the rssi in dB + */ + double get_rssi(void){ + //RSSI from VAGC vs RF Power, Fig 34, pg 13 + double max_power = -3.0; + + //constants for the rssi calculation + static const double min_v = 0.35, max_v = 1.0; + static const double rssi_dyn_range = 60; + //calculate the rssi from the voltage + double voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B); + return max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + } }; /*********************************************************************** @@ -454,12 +470,19 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); + if (key.name == "lo_locked") + val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); + else if ((key.name == "rssi") and (get_rx_id() != 0x0024)) + val = sensor_value_t("RSSI", this->get_rssi(), "dBm"); + else + UHD_THROW_INVALID_CODE_PATH(); + return; + + case SUBDEV_PROP_SENSOR_NAMES:{ + prop_names_t names = list_of("lo_locked"); + if (get_rx_id() != 0x0024) names.push_back("rssi"); + val = names; + } return; case SUBDEV_PROP_BANDWIDTH: diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 869a38478..297de990f 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -23,6 +23,7 @@ #include <boost/lexical_cast.hpp> #include <boost/foreach.hpp> #include <algorithm> +#include <iostream> #include <cstddef> using namespace uhd; @@ -181,6 +182,7 @@ static const size_t B000_SERIAL_LEN = 8; static const uhd::dict<std::string, boost::uint8_t> USRP_B000_OFFSETS = boost::assign::map_list_of ("serial", 0xf8) ("name", 0xf8 - NAME_MAX_LEN) + ("mcr", 0xf8 - NAME_MAX_LEN - sizeof(boost::uint32_t)) ; static void load_b000(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -193,6 +195,21 @@ static void load_b000(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ mb_eeprom["name"] = bytes_to_string(iface.read_eeprom( B000_EEPROM_ADDR, USRP_B000_OFFSETS["name"], NAME_MAX_LEN )); + + //extract master clock rate as a 32-bit uint in Hz + boost::uint32_t master_clock_rate; + const byte_vector_t rate_bytes = iface.read_eeprom( + B000_EEPROM_ADDR, USRP_B000_OFFSETS["mcr"], sizeof(master_clock_rate) + ); + std::copy( + rate_bytes.begin(), rate_bytes.end(), //input + reinterpret_cast<boost::uint8_t *>(&master_clock_rate) //output + ); + master_clock_rate = ntohl(master_clock_rate); + if (master_clock_rate > 1e6 and master_clock_rate < 1e9){ + mb_eeprom["mcr"] = boost::lexical_cast<std::string>(master_clock_rate); + } + else mb_eeprom["mcr"] = ""; } static void store_b000(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -207,6 +224,19 @@ static void store_b000(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ B000_EEPROM_ADDR, USRP_B000_OFFSETS["name"], string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN) ); + + //store the master clock rate as a 32-bit uint in Hz + if (mb_eeprom.has_key("mcr")){ + boost::uint32_t master_clock_rate = boost::uint32_t(boost::lexical_cast<double>(mb_eeprom["mcr"])); + master_clock_rate = htonl(master_clock_rate); + const byte_vector_t rate_bytes( + reinterpret_cast<const boost::uint8_t *>(&master_clock_rate), + reinterpret_cast<const boost::uint8_t *>(&master_clock_rate) + sizeof(master_clock_rate) + ); + iface.write_eeprom( + B000_EEPROM_ADDR, USRP_B000_OFFSETS["mcr"], rate_bytes + ); + } } /*********************************************************************** * Implementation of E100 load/store @@ -222,7 +252,8 @@ struct e100_eeprom_map{ unsigned char env_var[16]; unsigned char env_setting[64]; unsigned char serial[10]; - unsigned char name[NAME_MAX_LEN]; + unsigned char name[16]; + unsigned char mcr[sizeof(float)]; }; template <typename T> static const byte_vector_t to_bytes(const T &item){ @@ -254,6 +285,20 @@ static void load_e100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ load_e100_string_xx(env_setting); load_e100_string_xx(serial); load_e100_string_xx(name); + + //extract the master clock rate + float master_clock_rate = 0; + const byte_vector_t rate_bytes = iface.read_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, mcr), sizeof(master_clock_rate) + ); + std::copy( + rate_bytes.begin(), rate_bytes.end(), //source + reinterpret_cast<boost::uint8_t *>(&master_clock_rate) //destination + ); + if (master_clock_rate > 1e6 and master_clock_rate < 1e9){ + mb_eeprom["mcr"] = boost::lexical_cast<std::string>(master_clock_rate); + } + else mb_eeprom["mcr"] = ""; } static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -289,6 +334,17 @@ static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ store_e100_string_xx(serial); store_e100_string_xx(name); + //store the master clock rate + if (mb_eeprom.has_key("mcr")){ + const float master_clock_rate = float(boost::lexical_cast<double>(mb_eeprom["mcr"])); + const byte_vector_t rate_bytes( + reinterpret_cast<const boost::uint8_t *>(&master_clock_rate), + reinterpret_cast<const boost::uint8_t *>(&master_clock_rate) + sizeof(master_clock_rate) + ); + iface.write_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, mcr), rate_bytes + ); + } } /*********************************************************************** diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index 9637301ad..264e6c04b 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -49,28 +49,28 @@ static tune_result_t tune_xx_subdev_and_dsp( } //------------------------------------------------------------------ - //-- set the intermediate frequency depending upon the IF policy + //-- set the RF frequency depending upon the policy //------------------------------------------------------------------ - double target_inter_freq = 0.0; - switch (tune_request.inter_freq_policy){ + double target_rf_freq = 0.0; + switch (tune_request.rf_freq_policy){ case tune_request_t::POLICY_AUTO: - target_inter_freq = tune_request.target_freq + lo_offset; - subdev_freq_proxy = target_inter_freq; + target_rf_freq = tune_request.target_freq + lo_offset; + subdev_freq_proxy = target_rf_freq; break; case tune_request_t::POLICY_MANUAL: - target_inter_freq = tune_request.inter_freq; - subdev_freq_proxy = target_inter_freq; + target_rf_freq = tune_request.rf_freq; + subdev_freq_proxy = target_rf_freq; break; case tune_request_t::POLICY_NONE: break; //does not set } - double actual_inter_freq = subdev_freq_proxy.as<double>(); + double actual_rf_freq = subdev_freq_proxy.as<double>(); //------------------------------------------------------------------ //-- calculate the dsp freq, only used with automatic policy //------------------------------------------------------------------ - double target_dsp_freq = actual_inter_freq - tune_request.target_freq; + double target_dsp_freq = actual_rf_freq - tune_request.target_freq; //invert the sign on the dsp freq given the following conditions if (unit == dboard_iface::UNIT_TX) target_dsp_freq *= -1.0; @@ -96,8 +96,8 @@ static tune_result_t tune_xx_subdev_and_dsp( //-- load and return the tune result //------------------------------------------------------------------ tune_result_t tune_result; - tune_result.target_inter_freq = target_inter_freq; - tune_result.actual_inter_freq = actual_inter_freq; + tune_result.target_rf_freq = target_rf_freq; + tune_result.actual_rf_freq = actual_rf_freq; tune_result.target_dsp_freq = target_dsp_freq; tune_result.actual_dsp_freq = actual_dsp_freq; return tune_result; @@ -107,13 +107,13 @@ static double derive_freq_from_xx_subdev_and_dsp( dboard_iface::unit_t unit, wax::obj subdev, wax::obj dsp ){ //extract actual dsp and IF frequencies - double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>(); + double actual_rf_freq = subdev[SUBDEV_PROP_FREQ].as<double>(); double actual_dsp_freq = dsp[DSP_PROP_FREQ_SHIFT].as<double>(); //invert the sign on the dsp freq given the following conditions if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0; - return actual_inter_freq - actual_dsp_freq; + return actual_rf_freq - actual_dsp_freq; } /*********************************************************************** diff --git a/host/lib/usrp/usrp1/clock_ctrl.cpp b/host/lib/usrp/usrp1/clock_ctrl.cpp index df5353b54..154e6a316 100644 --- a/host/lib/usrp/usrp1/clock_ctrl.cpp +++ b/host/lib/usrp/usrp1/clock_ctrl.cpp @@ -16,6 +16,9 @@ // #include "clock_ctrl.hpp" +#include <boost/lexical_cast.hpp> +#include <boost/format.hpp> +#include <iostream> using namespace uhd; @@ -31,6 +34,17 @@ class usrp1_clock_ctrl_impl : public usrp1_clock_ctrl { public: usrp1_clock_ctrl_impl(usrp1_iface::sptr iface): _iface(iface){ this->set_master_clock_freq(default_master_clock_rate); + try{ + if (not _iface->mb_eeprom["mcr"].empty()){ + std::cout << "Read FPGA clock rate from EEPROM setting." << std::endl; + const double master_clock_rate = boost::lexical_cast<double>(_iface->mb_eeprom["mcr"]); + std::cout << boost::format("Initializing FPGA clock to %fMHz...") % (master_clock_rate/1e6) << std::endl; + this->set_master_clock_freq(master_clock_rate); + } + } + catch(const std::exception &e){ + std::cerr << "Error setting FPGA clock rate from EEPROM: " << e.what() << std::endl; + } } void set_master_clock_freq(double freq){ diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 870956568..eecae3fa7 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -378,6 +378,10 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) return; case MBOARD_PROP_CLOCK_RATE: + std::cerr << "Helpful message:" << std::endl; + std::cerr << " I see that you are setting the master clock rate from the API." << std::endl; + std::cerr << " You may find it more convenient to burn this setting into the EEPROM." << std::endl; + std::cerr << " See the application notes for USRP1 for further instructions." << std::endl; _clock_ctrl->set_master_clock_freq(val.as<double>()); return; diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 22e9fd1ce..c6be28f5f 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -201,18 +201,19 @@ public: } void usrp_init(void){ - /* not calling because this causes junk to come at init - * and it does not seem to be necessary to call anyway + //disable usrp_rx_enable(false); - usrp_rx_reset(true); - usrp_rx_reset(false); - usrp_rx_enable(true); - */ - usrp_tx_enable(false); + + //toggle resets + usrp_rx_reset(true); usrp_tx_reset(true); + usrp_rx_reset(false); usrp_tx_reset(false); - usrp_tx_enable(true); + + //enable + //usrp_rx_enable(true); //dont enable, enable means dont work + //usrp_tx_enable(true); } void usrp_load_fpga(std::string filestring) @@ -234,6 +235,8 @@ public: throw uhd::io_error("usrp_load_fpga: cannot open fpga input file"); } + usrp_fpga_reset(true); //holding the fpga in reset while loading + if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_BEGIN) < 0) { throw uhd::io_error("usrp_load_fpga: fpga load error"); } @@ -252,6 +255,9 @@ public: } usrp_set_fpga_hash(hash); + + usrp_fpga_reset(false); //done loading, take fpga out of reset + file.close(); if (load_img_msg) std::cout << " done" << std::endl; } @@ -355,6 +361,10 @@ public: UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_RX_RESET, on, 0) >= 0); } + void usrp_fpga_reset(bool on) + { + UHD_ASSERT_THROW(usrp_control_write_cmd(VRQ_FPGA_SET_RESET, on, 0) >= 0); + } int usrp_control_write(boost::uint8_t request, boost::uint16_t value, diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 7705037dd..8582fca38 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -194,9 +194,25 @@ usrp2_mboard_impl::~usrp2_mboard_impl(void){ void usrp2_mboard_impl::update_clock_config(void){ boost::uint32_t pps_flags = 0; + //slave mode overrides clock config settings + if (not _mimo_clocking_mode_is_master){ + _clock_config.ref_source = clock_config_t::REF_MIMO; + _clock_config.pps_source = clock_config_t::PPS_MIMO; + } + //translate pps source enums switch(_clock_config.pps_source){ - case clock_config_t::PPS_SMA: pps_flags |= U2_FLAG_TIME64_PPS_SMA; break; + case clock_config_t::PPS_MIMO: + _iface->poke32(_iface->regs.time64_mimo_sync, + (1 << 8) | (mimo_clock_sync_delay_cycles & 0xff) + ); + break; + + case clock_config_t::PPS_SMA: + _iface->poke32(_iface->regs.time64_mimo_sync, 0); + pps_flags |= U2_FLAG_TIME64_PPS_SMA; + break; + default: throw uhd::value_error("unhandled clock configuration pps source"); } @@ -217,6 +233,7 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; + case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; default: throw uhd::value_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO @@ -227,6 +244,7 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; + case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; default: throw uhd::value_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(_clock_config.ref_source != clock_config_t::REF_INT); @@ -235,12 +253,11 @@ void usrp2_mboard_impl::update_clock_config(void){ case usrp2_iface::USRP_NXXX: break; } - //Handle the serdes clocking based on master/slave mode: - // - Masters always drive the clock over serdes. - // - Slaves always lock to this serdes clock. - // - Slaves lock their time over the serdes. + //masters always drive the clock over serdes + _clock_ctrl->enable_mimo_clock_out(_mimo_clocking_mode_is_master); + + //set the mimo clock delay over the serdes if (_mimo_clocking_mode_is_master){ - _clock_ctrl->enable_mimo_clock_out(true); switch(_iface->get_rev()){ case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: @@ -253,15 +270,6 @@ void usrp2_mboard_impl::update_clock_config(void){ default: break; //not handled } - _iface->poke32(_iface->regs.time64_mimo_sync, 0); - } - else{ - _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); - _clock_ctrl->enable_external_ref(true); - _clock_ctrl->enable_mimo_clock_out(false); - _iface->poke32(_iface->regs.time64_mimo_sync, - (1 << 8) | (mimo_clock_sync_delay_cycles & 0xff) - ); } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2d1f901d7..9c3fb9268 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -165,7 +165,7 @@ struct mtu_result_t{ size_t recv_mtu, send_mtu; }; -static mtu_result_t determine_mtu(const std::string &addr){ +static mtu_result_t determine_mtu(const std::string &addr, const mtu_result_t &user_mtu){ udp_simple::sptr udp_sock = udp_simple::make_connected( addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT) ); @@ -173,8 +173,8 @@ static mtu_result_t determine_mtu(const std::string &addr){ //The FPGA offers 4K buffers, and the user may manually request this. //However, multiple simultaneous receives (2DSP slave + 2DSP master), //require that buffering to be used internally, and this is a safe setting. - boost::uint8_t buffer[2000]; - usrp2_ctrl_data_t *ctrl_data = reinterpret_cast<usrp2_ctrl_data_t *>(buffer); + std::vector<boost::uint8_t> buffer(std::max(user_mtu.recv_mtu, user_mtu.send_mtu)); + usrp2_ctrl_data_t *ctrl_data = reinterpret_cast<usrp2_ctrl_data_t *>(&buffer.front()); static const double echo_timeout = 0.020; //20 ms //test holler - check if its supported in this fw version @@ -186,8 +186,8 @@ static mtu_result_t determine_mtu(const std::string &addr){ if (ntohl(ctrl_data->id) != USRP2_CTRL_ID_HOLLER_BACK_DUDE) throw uhd::not_implemented_error("holler protocol not implemented"); - size_t min_recv_mtu = sizeof(usrp2_ctrl_data_t), max_recv_mtu = sizeof(buffer); - size_t min_send_mtu = sizeof(usrp2_ctrl_data_t), max_send_mtu = sizeof(buffer); + size_t min_recv_mtu = sizeof(usrp2_ctrl_data_t), max_recv_mtu = user_mtu.recv_mtu; + size_t min_send_mtu = sizeof(usrp2_ctrl_data_t), max_send_mtu = user_mtu.send_mtu; while (min_recv_mtu < max_recv_mtu){ @@ -248,19 +248,20 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ device_addrs_t device_args = separate_device_addr(device_addr); + //extract the user's requested MTU size or default + mtu_result_t user_mtu; + user_mtu.recv_mtu = size_t(device_addr.cast<double>("recv_frame_size", udp_simple::mtu)); + user_mtu.send_mtu = size_t(device_addr.cast<double>("recv_frame_size", udp_simple::mtu)); + try{ //calculate the minimum send and recv mtu of all devices - mtu_result_t mtu = determine_mtu(device_args[0]["addr"]); + mtu_result_t mtu = determine_mtu(device_args[0]["addr"], user_mtu); for (size_t i = 1; i < device_args.size(); i++){ - mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"]); + mtu_result_t mtu_i = determine_mtu(device_args[i]["addr"], user_mtu); mtu.recv_mtu = std::min(mtu.recv_mtu, mtu_i.recv_mtu); mtu.send_mtu = std::min(mtu.send_mtu, mtu_i.send_mtu); } - //use the discovered mtu or clip the users requested mtu - mtu.recv_mtu = std::min(size_t(device_addr.cast<double>("recv_frame_size", 9000)), mtu.recv_mtu); - mtu.send_mtu = std::min(size_t(device_addr.cast<double>("send_frame_size", 9000)), mtu.send_mtu); - device_addr["recv_frame_size"] = boost::lexical_cast<std::string>(mtu.recv_mtu); device_addr["send_frame_size"] = boost::lexical_cast<std::string>(mtu.send_mtu); diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index 1ac2b804c..2e3eb5cb9 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -184,7 +184,24 @@ public: this->use_internal_ref(); - this->set_fpga_clock_rate(DEFAULT_OUTPUT_RATE); //initialize to something + //initialize the FPGA clock to something + bool fpga_clock_initialized = false; + try{ + if (not _iface->mb_eeprom["mcr"].empty()){ + std::cout << "Read FPGA clock rate from EEPROM setting." << std::endl; + const double master_clock_rate = boost::lexical_cast<double>(_iface->mb_eeprom["mcr"]); + std::cout << boost::format("Initializing FPGA clock to %fMHz...") % (master_clock_rate/1e6) << std::endl; + this->set_fpga_clock_rate(master_clock_rate); + fpga_clock_initialized = true; + } + } + catch(const std::exception &e){ + std::cerr << "Error setting FPGA clock rate from EEPROM: " << e.what() << std::endl; + } + if (not fpga_clock_initialized){ //was not set... use the default rate + std::cout << boost::format("Initializing FPGA clock to %fMHz...") % (DEFAULT_OUTPUT_RATE/1e6) << std::endl; + this->set_fpga_clock_rate(DEFAULT_OUTPUT_RATE); + } this->enable_test_clock(ENABLE_THE_TEST_OUT); this->enable_rx_dboard_clock(false); diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp index 29e3c5da2..5f4a208d3 100644 --- a/host/lib/usrp/usrp_e100/mboard_impl.cpp +++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp @@ -207,6 +207,10 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; case MBOARD_PROP_CLOCK_RATE: + std::cerr << "Helpful message:" << std::endl; + std::cerr << " I see that you are setting the master clock rate from the API." << std::endl; + std::cerr << " You may find it more convenient to burn this setting into the EEPROM." << std::endl; + std::cerr << " See the application notes for USRP-E1XX for further instructions." << std::endl; _clock_ctrl->set_fpga_clock_rate(val.as<double>()); return; diff --git a/host/tests/tune_helper_test.cpp b/host/tests/tune_helper_test.cpp index 51d216825..9147cd310 100644 --- a/host/tests/tune_helper_test.cpp +++ b/host/tests/tune_helper_test.cpp @@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){ std::cout << "Testing tune helper RX automatic IF offset" << std::endl; tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); std::cout << tr.to_pp_string() << std::endl; - BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); + BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.345e9, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance); double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); @@ -202,7 +202,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){ std::cout << "Testing tune helper TX automatic IF offset" << std::endl; tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); std::cout << tr.to_pp_string() << std::endl; - BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); + BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.345e9, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance); double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); @@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){ std::cout << "Testing tune helper RX dummy basic board" << std::endl; tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6); std::cout << tr.to_pp_string() << std::endl; - BOOST_CHECK_CLOSE(tr.actual_inter_freq, 0.0, tolerance); + BOOST_CHECK_CLOSE(tr.actual_rf_freq, 0.0, tolerance); BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance); double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); @@ -233,19 +233,19 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){ dsp[DSP_PROP_HOST_RATE] = double(4e6); tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9); std::cout << tr.to_pp_string() << std::endl; - BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance); + BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.45e9+4e6/2, tolerance); std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl; subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6); dsp[DSP_PROP_HOST_RATE] = double(25e6); tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9); std::cout << tr.to_pp_string() << std::endl; - BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance); + BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.45e9+(40e6-25e6)/2, tolerance); std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl; subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6); dsp[DSP_PROP_HOST_RATE] = double(25e6); tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.45e9); std::cout << tr.to_pp_string() << std::endl; - BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance); + BOOST_CHECK_CLOSE(tr.actual_rf_freq, 2.45e9, tolerance); } |