summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-05-01 17:26:15 -0700
committerJosh Blum <josh@joshknows.com>2011-05-01 17:26:15 -0700
commit5c6c179689ef76ccd25d09ac4faeb9a836a066c8 (patch)
tree28c23bb2ec6c70abbe9d5c18d77902d822cf56d2 /host
parent4b18ab84921a88f0448632355e8165ecaff4ed6f (diff)
downloaduhd-5c6c179689ef76ccd25d09ac4faeb9a836a066c8.tar.gz
uhd-5c6c179689ef76ccd25d09ac4faeb9a836a066c8.tar.bz2
uhd-5c6c179689ef76ccd25d09ac4faeb9a836a066c8.zip
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).
Diffstat (limited to 'host')
-rw-r--r--host/docs/usrp_e1xx.rst16
-rw-r--r--host/examples/rx_timed_samples.cpp9
-rw-r--r--host/lib/usrp/mboard_eeprom.cpp25
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.cpp19
-rw-r--r--host/lib/usrp/usrp_e100/mboard_impl.cpp4
5 files changed, 59 insertions, 14 deletions
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 <install-path>/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 <install-path>/share/uhd/utils
+ ./usrp_burn_mb_eeprom --key=master_clock_rate --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/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 <typename T> 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<boost::uint8_t *>(&master_clock_rate) //destination
+ );
+ if (master_clock_rate > 1e6 and master_clock_rate < 1e9){
+ mb_eeprom["master_clock_rate"] = boost::lexical_cast<std::string>(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<double>(mb_eeprom["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(
+ 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<double>(_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<double>());
return;