summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-01-27 13:56:41 +0000
committerJosh Blum <josh@joshknows.com>2011-01-27 13:56:41 +0000
commit38185eb6f18e77245d358860872336d9998e1c07 (patch)
tree2471c9ef09c148c28cdddb3c7d71f4fd0c76c121
parentc8eed953d74186049ba94432334771724d1a8070 (diff)
downloaduhd-38185eb6f18e77245d358860872336d9998e1c07.tar.gz
uhd-38185eb6f18e77245d358860872336d9998e1c07.tar.bz2
uhd-38185eb6f18e77245d358860872336d9998e1c07.zip
usrp-e100: tweak for clock control register calculation, works better
-rw-r--r--host/lib/usrp/usrp_e100/clock_ctrl.cpp63
1 files changed, 33 insertions, 30 deletions
diff --git a/host/lib/usrp/usrp_e100/clock_ctrl.cpp b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
index 36ab1a8be..e29fe18ce 100644
--- a/host/lib/usrp/usrp_e100/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp_e100/clock_ctrl.cpp
@@ -116,43 +116,46 @@ static clock_settings_type get_clock_settings(double rate){
const size_t X = i*ref_rate/gcd;
const size_t Y = i*out_rate/gcd;
- //determine chan_div, vco_div, and r_div
- //and fill in that order of preference
- cs.chan_divider = greatest_divisor<size_t>(X, 32);
- cs.vco_divider = greatest_divisor<size_t>(X/cs.chan_divider, 6);
- cs.r_counter = X/cs.chan_divider/cs.vco_divider;
-
- //avoid a vco divider of 1 (if possible)
- if (cs.vco_divider == 1){
- cs.vco_divider = least_divisor<size_t>(cs.chan_divider, 2);
- cs.chan_divider /= cs.vco_divider;
- }
-
//determine A and B (P is fixed)
cs.b_counter = Y/cs.prescaler;
cs.a_counter = Y - cs.b_counter*cs.prescaler;
- if (CLOCK_SETTINGS_DEBUG){
- std::cout << "X " << X << std::endl;
- std::cout << "Y " << Y << std::endl;
- std::cout << cs.to_pp_string() << std::endl;
- }
+ static const double vco_bound_pad = 100e6;
+ for ( //calculate an r divider that fits into the bounds of the vco
+ cs.r_counter = size_t(cs.get_n_counter()*cs.get_ref_rate()/(1800e6 - vco_bound_pad));
+ cs.r_counter <= size_t(cs.get_n_counter()*cs.get_ref_rate()/(1400e6 + vco_bound_pad))
+ and cs.r_counter > 0; cs.r_counter++
+ ){
+
+ //determine chan_div and vco_div
+ //and fill in that order of preference
+ cs.chan_divider = greatest_divisor<size_t>(X/cs.r_counter, 32);
+ cs.vco_divider = greatest_divisor<size_t>(X/cs.chan_divider/cs.r_counter, 6);
+
+ //avoid a vco divider of 1 (if possible)
+ if (cs.vco_divider == 1){
+ cs.vco_divider = least_divisor<size_t>(cs.chan_divider, 2);
+ cs.chan_divider /= cs.vco_divider;
+ }
- //filter limits on the counters
- if (cs.vco_divider == 1) continue;
- if (cs.r_counter >= (1<<14)) continue;
- if (cs.b_counter == 2) continue;
- if (cs.b_counter == 1 and cs.a_counter != 0) continue;
- if (cs.b_counter >= (1<<13)) continue;
- if (cs.a_counter >= (1<<6)) continue;
+ if (CLOCK_SETTINGS_DEBUG){
+ std::cout << "gcd " << gcd << std::endl;
+ std::cout << "X " << X << std::endl;
+ std::cout << "Y " << Y << std::endl;
+ std::cout << cs.to_pp_string() << std::endl;
+ }
- //check the bounds on the vco
- static const double vco_bound_pad = 100e6;
- if (cs.get_vco_rate() > (1800e6 - vco_bound_pad)) continue;
- if (cs.get_vco_rate() < (1400e6 + vco_bound_pad)) continue;
+ //filter limits on the counters
+ if (cs.vco_divider == 1) continue;
+ if (cs.r_counter >= (1<<14)) continue;
+ if (cs.b_counter == 2) continue;
+ if (cs.b_counter == 1 and cs.a_counter != 0) continue;
+ if (cs.b_counter >= (1<<13)) continue;
+ if (cs.a_counter >= (1<<6)) continue;
- std::cout << "USRP-E100 clock control:" << std::endl << cs.to_pp_string() << std::endl;
- return cs;
+ std::cout << "USRP-E100 clock control: " << i << std::endl << cs.to_pp_string() << std::endl;
+ return cs;
+ }
}
throw std::runtime_error(str(boost::format(