aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/docs/dboards.rst40
-rw-r--r--host/docs/usrp1.rst9
-rw-r--r--host/docs/usrp_e1xx.rst16
-rw-r--r--host/examples/rx_timed_samples.cpp9
-rw-r--r--host/include/uhd/types/clock_config.hpp2
-rw-r--r--host/include/uhd/types/tune_request.hpp12
-rw-r--r--host/include/uhd/types/tune_result.hpp10
-rw-r--r--host/lib/types/tune.cpp18
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp35
-rw-r--r--host/lib/usrp/mboard_eeprom.cpp58
-rw-r--r--host/lib/usrp/tune_helper.cpp26
-rw-r--r--host/lib/usrp/usrp1/clock_ctrl.cpp14
-rw-r--r--host/lib/usrp/usrp1/mboard_impl.cpp4
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.cpp26
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp38
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp23
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.cpp19
-rw-r--r--host/lib/usrp/usrp_e100/mboard_impl.cpp4
-rw-r--r--host/tests/tune_helper_test.cpp12
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);
}