From 46b20f25556620433c89b16984dc1633221ae28b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 28 Apr 2011 15:35:28 -0700 Subject: usrp2: use default mtu as upper limit unless user specifies --- host/lib/usrp/usrp2/usrp2_impl.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 48443bba4..77370a7fd 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -163,7 +163,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) ); @@ -171,8 +171,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(buffer); + std::vector buffer(std::max(user_mtu.recv_mtu, user_mtu.send_mtu)); + usrp2_ctrl_data_t *ctrl_data = reinterpret_cast(&buffer.front()); static const double echo_timeout = 0.020; //20 ms //test holler - check if its supported in this fw version @@ -184,8 +184,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){ @@ -246,19 +246,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("recv_frame_size", udp_simple::mtu)); + user_mtu.send_mtu = size_t(device_addr.cast("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("recv_frame_size", 9000)), mtu.recv_mtu); - mtu.send_mtu = std::min(size_t(device_addr.cast("send_frame_size", 9000)), mtu.send_mtu); - device_addr["recv_frame_size"] = boost::lexical_cast(mtu.recv_mtu); device_addr["send_frame_size"] = boost::lexical_cast(mtu.send_mtu); -- cgit v1.2.3 From 4b18ab84921a88f0448632355e8165ecaff4ed6f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 1 May 2011 09:38:30 -0700 Subject: uhd: fixed typo in tune request/result inter_freq -> rf_freq For some reason, the code said intermediate frequency, however, it was used and treated as RF frequency. It was always intended to be the RF frequency, but was misnamed due to a cognitive distortion. --- host/include/uhd/types/tune_request.hpp | 12 ++++++------ host/include/uhd/types/tune_result.hpp | 10 +++------- host/lib/types/tune.cpp | 18 +++++++++--------- host/lib/usrp/tune_helper.cpp | 26 +++++++++++++------------- host/tests/tune_helper_test.cpp | 12 ++++++------ 5 files changed, 37 insertions(+), 41 deletions(-) (limited to 'host') 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/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 actual_rf_freq = subdev_freq_proxy.as(); //------------------------------------------------------------------ //-- 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 actual_rf_freq = subdev[SUBDEV_PROP_FREQ].as(); double actual_dsp_freq = dsp[DSP_PROP_FREQ_SHIFT].as(); //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/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); } -- cgit v1.2.3 From 5c6c179689ef76ccd25d09ac4faeb9a836a066c8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 1 May 2011 17:26:15 -0700 Subject: usrp-e100: add ability to set/get default master clock rate from EEPROM Mboard eeprom map class can parse the setting (4 byte float). The clock control will try to set the eeprom rate if present, otherwise or under failure condition, it sets the default. Updated docs, example, and provided helpful verbose. I would prefer that users burn the desired rate to the eeprom (and they may too). --- host/docs/usrp_e1xx.rst | 16 +++++++++++----- host/examples/rx_timed_samples.cpp | 9 +-------- host/lib/usrp/mboard_eeprom.cpp | 25 +++++++++++++++++++++++++ host/lib/usrp/usrp_e100/clock_ctrl.cpp | 19 ++++++++++++++++++- host/lib/usrp/usrp_e100/mboard_impl.cpp | 4 ++++ 5 files changed, 59 insertions(+), 14 deletions(-) (limited to 'host') diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst index 2818a0a65..b2a6ff08c 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 in the EEPROM: +:: + + cd /share/uhd/utils + ./usrp_burn_mb_eeprom --key=master_clock_rate --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 in the EEPROM: +:: + + cd /share/uhd/utils + ./usrp_burn_mb_eeprom --key=master_clock_rate --val= ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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(&args)->default_value(""), "single uhd device address args") ("secs", po::value(&seconds_in_future)->default_value(1.5), "number of seconds in the future to receive") ("nsamps", po::value(&total_num_samps)->default_value(10000), "total number of samples to receive") - ("clock", po::value(&clock), "master clock frequency in Hz") ("rate", po::value(&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/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 869a38478..03096691e 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -223,6 +223,7 @@ struct e100_eeprom_map{ unsigned char env_setting[64]; unsigned char serial[10]; unsigned char name[NAME_MAX_LEN]; + float master_clock_rate; }; template static const byte_vector_t to_bytes(const T &item){ @@ -254,6 +255,19 @@ 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, master_clock_rate), sizeof(master_clock_rate) + ); + std::copy( + rate_bytes.begin(), rate_bytes.end(), //source + reinterpret_cast(&master_clock_rate) //destination + ); + if (master_clock_rate > 1e6 and master_clock_rate < 1e9){ + mb_eeprom["master_clock_rate"] = boost::lexical_cast(master_clock_rate); + } } static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -289,6 +303,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("master_clock_rate")){ + const float master_clock_rate = float(boost::lexical_cast(mb_eeprom["master_clock_rate"])); + const byte_vector_t rate_bytes( + reinterpret_cast(&master_clock_rate), + reinterpret_cast(&master_clock_rate) + sizeof(master_clock_rate) + ); + iface.write_eeprom( + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, master_clock_rate), rate_bytes + ); + } } /*********************************************************************** diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index 1ac2b804c..851ce29b0 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 (_iface->mb_eeprom.has_key("master_clock_rate")){ + std::cout << "Read FPGA clock rate from EEPROM setting." << std::endl; + const double master_clock_rate = boost::lexical_cast(_iface->mb_eeprom["master_clock_rate"]); + 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()); return; -- cgit v1.2.3 From 6f0a98ee2e9e2090c6bf7d56260cb95b0eb1fbb3 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 1 May 2011 18:21:29 -0700 Subject: USRP1: added support for setting clock rate from EEPROM Basically, same deal as the previous changeset but for USRP1. Modified previous changes so that the key is shorter (mcr = master_clock_rate) --- host/docs/usrp1.rst | 9 ++++++-- host/docs/usrp_e1xx.rst | 8 +++---- host/lib/usrp/mboard_eeprom.cpp | 42 +++++++++++++++++++++++++++++----- host/lib/usrp/usrp1/clock_ctrl.cpp | 14 ++++++++++++ host/lib/usrp/usrp1/mboard_impl.cpp | 4 ++++ host/lib/usrp/usrp_e100/clock_ctrl.cpp | 4 ++-- 6 files changed, 67 insertions(+), 14 deletions(-) (limited to 'host') 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 /share/uhd/utils + ./usrp_burn_mb_eeprom --args= --key=mcr --val= diff --git a/host/docs/usrp_e1xx.rst b/host/docs/usrp_e1xx.rst index b2a6ff08c..036d2c02c 100644 --- a/host/docs/usrp_e1xx.rst +++ b/host/docs/usrp_e1xx.rst @@ -35,11 +35,11 @@ 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) -Then run the following commands to record the setting in the EEPROM: +Then run the following commands to record the setting into the EEPROM: :: cd /share/uhd/utils - ./usrp_burn_mb_eeprom --key=master_clock_rate --val=61.44e6 + ./usrp_burn_mb_eeprom --key=mcr --val=61.44e6 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,11 +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) -Then run the following commands to record the setting in the EEPROM: +Then run the following commands to record the setting into the EEPROM: :: cd /share/uhd/utils - ./usrp_burn_mb_eeprom --key=master_clock_rate --val= + ./usrp_burn_mb_eeprom --key=mcr --val= ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clock rate recovery - unbricking diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 03096691e..29bc5ee32 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -181,6 +181,7 @@ static const size_t B000_SERIAL_LEN = 8; static const uhd::dict 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 +194,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(&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(master_clock_rate); + } + else mb_eeprom["mcr"] = ""; } static void store_b000(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -207,6 +223,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(mb_eeprom["mcr"])); + master_clock_rate = htonl(master_clock_rate); + const byte_vector_t rate_bytes( + reinterpret_cast(&master_clock_rate), + reinterpret_cast(&master_clock_rate) + sizeof(master_clock_rate) + ); + iface.write_eeprom( + B000_EEPROM_ADDR, USRP_B000_OFFSETS["mcr"], rate_bytes + ); + } } /*********************************************************************** * Implementation of E100 load/store @@ -223,7 +252,7 @@ struct e100_eeprom_map{ unsigned char env_setting[64]; unsigned char serial[10]; unsigned char name[NAME_MAX_LEN]; - float master_clock_rate; + float mcr; }; template static const byte_vector_t to_bytes(const T &item){ @@ -259,15 +288,16 @@ static void load_e100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ //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, master_clock_rate), sizeof(master_clock_rate) + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, mcr), sizeof(master_clock_rate) ); std::copy( rate_bytes.begin(), rate_bytes.end(), //source reinterpret_cast(&master_clock_rate) //destination ); if (master_clock_rate > 1e6 and master_clock_rate < 1e9){ - mb_eeprom["master_clock_rate"] = boost::lexical_cast(master_clock_rate); + mb_eeprom["mcr"] = boost::lexical_cast(master_clock_rate); } + else mb_eeprom["mcr"] = ""; } static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ @@ -304,14 +334,14 @@ static void store_e100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ store_e100_string_xx(name); //store the master clock rate - if (mb_eeprom.has_key("master_clock_rate")){ - const float master_clock_rate = float(boost::lexical_cast(mb_eeprom["master_clock_rate"])); + if (mb_eeprom.has_key("mcr")){ + const float master_clock_rate = float(boost::lexical_cast(mb_eeprom["mcr"])); const byte_vector_t rate_bytes( reinterpret_cast(&master_clock_rate), reinterpret_cast(&master_clock_rate) + sizeof(master_clock_rate) ); iface.write_eeprom( - E100_EEPROM_ADDR, offsetof(e100_eeprom_map, master_clock_rate), rate_bytes + E100_EEPROM_ADDR, offsetof(e100_eeprom_map, mcr), rate_bytes ); } } 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 +#include +#include 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(_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()); return; diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp index 851ce29b0..2e3eb5cb9 100644 --- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp @@ -187,9 +187,9 @@ public: //initialize the FPGA clock to something bool fpga_clock_initialized = false; try{ - if (_iface->mb_eeprom.has_key("master_clock_rate")){ + 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(_iface->mb_eeprom["master_clock_rate"]); + const double master_clock_rate = boost::lexical_cast(_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; -- cgit v1.2.3 From cf5b7b0307c12303abd24b16dadf95dfddb4b340 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Apr 2011 01:37:07 +0100 Subject: usrp-e100: shrink name field to git mcr into eeprom --- host/lib/usrp/mboard_eeprom.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 29bc5ee32..297de990f 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include using namespace uhd; @@ -251,8 +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]; - float mcr; + unsigned char name[16]; + unsigned char mcr[sizeof(float)]; }; template static const byte_vector_t to_bytes(const T &item){ -- cgit v1.2.3 From 3ac502d0bb89d88b1f24cafe8a34256a70662ea9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 1 May 2011 23:09:20 -0700 Subject: usrp1: toggle the FPGA reset and RX reset registers at init --- host/lib/usrp/usrp1/usrp1_ctrl.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'host') 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, -- cgit v1.2.3 From cbf580374dbc131febdd7f65efc65879ee3842ac Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 2 May 2011 15:38:55 -0700 Subject: Added RSSI sensor for RFX series (not rfx400) --- host/docs/dboards.rst | 1 + host/lib/usrp/dboard/db_rfx.cpp | 35 +++++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) (limited to 'host') diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 373189441..402f0cd8c 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 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: -- cgit v1.2.3 From 4c6394f1dc4529f84febb3c02e2db9319c061003 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 2 May 2011 16:51:02 -0700 Subject: Added docs for sbx --- host/docs/dboards.rst | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'host') diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 373189441..d9f8069ad 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -203,6 +203,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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From b4fc0d61bb6cbd1a5614745bab9aeb0abc22cb6f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 3 May 2011 13:35:15 -0700 Subject: usrp2: added REF_MIMO and PPS_MIMO for USRP2 clock config Basically, one can tell a MIMO master to lock to MIMO ref and/or time. This is an alternative to the mimo_mode=slave/master device args. When using this alternative, one should always set the mimo_mode to maser. When in master mode, any clock config settings can be used. When in slave mode, the clock config setting are forced to MIMO_REF/PPS --- host/include/uhd/types/clock_config.hpp | 2 ++ host/lib/usrp/usrp2/mboard_impl.cpp | 38 ++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 15 deletions(-) (limited to 'host') 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/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index ae098dba6..d4ae27763 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -191,9 +191,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"); } @@ -214,6 +230,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 @@ -224,6 +241,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); @@ -232,12 +250,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: @@ -250,15 +267,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) - ); } } -- cgit v1.2.3