aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard
diff options
context:
space:
mode:
authorPhilip Balister <philip@opensdr.com>2010-10-20 20:00:09 -0400
committerPhilip Balister <philip@opensdr.com>2010-10-20 20:00:09 -0400
commit635440c5990e7a27fdb38f694123258633e85427 (patch)
tree603ff2312dd612ea7759432f51ffb7a6c7db3448 /host/lib/usrp/dboard
parent6b203950d9583ab882628311402e26cf40838aa0 (diff)
parente0c48ba5cc1033cd330e2ce73ceb03740923e954 (diff)
downloaduhd-635440c5990e7a27fdb38f694123258633e85427.tar.gz
uhd-635440c5990e7a27fdb38f694123258633e85427.tar.bz2
uhd-635440c5990e7a27fdb38f694123258633e85427.zip
Merge branch 'master' of ettus.sourcerepo.com:ettus/uhdpriv into usrp_e_mmap_b2
Diffstat (limited to 'host/lib/usrp/dboard')
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp14
-rw-r--r--host/lib/usrp/dboard/db_dbsrx.cpp47
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp14
-rw-r--r--host/lib/usrp/dboard/db_tvrx.cpp124
-rw-r--r--host/lib/usrp/dboard/db_unknown.cpp14
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp14
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp161
7 files changed, 305 insertions, 83 deletions
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index 4b0d8bf27..41f6f8002 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -149,6 +149,10 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
val = sd_name_to_conn[get_subdev_name()];
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -178,6 +182,9 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_FREQ:
return; // it wont do you much good, but you can set it
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -241,6 +248,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
val = sd_name_to_conn[get_subdev_name()];
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -270,6 +281,9 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_FREQ:
return; // it wont do you much good, but you can set it
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp
index 81434f054..939a79e58 100644
--- a/host/lib/usrp/dboard/db_dbsrx.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx.cpp
@@ -69,7 +69,7 @@ public:
private:
double _lo_freq;
- float _bandwidth;
+ double _bandwidth;
uhd::dict<std::string, float> _gains;
max2118_write_regs_t _max2118_write_regs;
max2118_read_regs_t _max2118_read_regs;
@@ -79,7 +79,7 @@ private:
void set_lo_freq(double target_freq);
void set_gain(float gain, const std::string &name);
- void set_bandwidth(float bandwidth);
+ void set_bandwidth(double bandwidth);
void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){
start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5));
@@ -239,7 +239,6 @@ void dbsrx::set_lo_freq(double target_freq){
double actual_freq=0.0, pfd_freq=0.0, ref_clock=0.0;
int R=0, N=0, r=0, m=0;
bool update_filter_settings = false;
-
//choose refclock
std::vector<double> clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX);
BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){
@@ -251,7 +250,7 @@ void dbsrx::set_lo_freq(double target_freq){
if(dbsrx_debug) std::cerr << boost::format(
"DBSRX: trying ref_clock %f and m_divider %d"
- ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % m << std::endl;
+ ) % (ref_clock) % m << std::endl;
if (m >= 32) continue;
@@ -277,15 +276,17 @@ void dbsrx::set_lo_freq(double target_freq){
}
}
- //Assert because we failed to find a suitable combination of ref_clock, R and N
- UHD_ASSERT_THROW(ref_clock/(1 << m) < 1e6 or ref_clock/(1 << m) > 2.5e6);
- UHD_ASSERT_THROW((pfd_freq < dbsrx_pfd_freq_range.min) or (pfd_freq > dbsrx_pfd_freq_range.max));
- UHD_ASSERT_THROW((N < 256) or (N > 32768));
done_loop:
+ //Assert because we failed to find a suitable combination of ref_clock, R and N
+ UHD_ASSERT_THROW(ref_clock <= 27.0e6 and ref_clock >= 0.0);
+ UHD_ASSERT_THROW(ref_clock/m >= 1e6 and ref_clock/m <= 2.5e6);
+ UHD_ASSERT_THROW((pfd_freq >= dbsrx_pfd_freq_range.min) and (pfd_freq <= dbsrx_pfd_freq_range.max));
+ UHD_ASSERT_THROW((N >= 256) and (N <= 32768));
+
if(dbsrx_debug) std::cerr << boost::format(
- "DBSRX: choose ref_clock %f and m_divider %d"
- ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % m << std::endl;
+ "DBSRX: choose ref_clock (current: %f, new: %f) and m_divider %d"
+ ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % ref_clock % m << std::endl;
//if ref_clock or m divider changed, we need to update the filter settings
if (ref_clock != this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX) or m != _max2118_write_regs.m_divider) update_filter_settings = true;
@@ -349,7 +350,7 @@ void dbsrx::set_lo_freq(double target_freq){
"DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n"
) % int(_max2118_write_regs.osc_band))
);
- UHD_ASSERT_THROW(_max2118_read_regs.adc == 0);
+ UHD_ASSERT_THROW(_max2118_read_regs.adc != 0); //just to cause a throw
}
if (_max2118_write_regs.osc_band <= 0) break;
_max2118_write_regs.osc_band -= 1;
@@ -363,7 +364,7 @@ void dbsrx::set_lo_freq(double target_freq){
"DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n"
) % int(_max2118_write_regs.osc_band))
);
- UHD_ASSERT_THROW(_max2118_read_regs.adc == 0);
+ UHD_ASSERT_THROW(_max2118_read_regs.adc != 7); //just to cause a throw
}
if (_max2118_write_regs.osc_band >= 7) break;
_max2118_write_regs.osc_band += 1;
@@ -401,6 +402,7 @@ void dbsrx::set_lo_freq(double target_freq){
<< boost::format(" Ref Freq=%fMHz\n") % (ref_clock/1e6)
<< boost::format(" Target Freq=%fMHz\n") % (target_freq/1e6)
<< boost::format(" Actual Freq=%fMHz\n") % (_lo_freq/1e6)
+ << boost::format(" VCO Freq=%fMHz\n") % (vco_freq/1e6)
<< std::endl;
if (update_filter_settings) set_bandwidth(_bandwidth);
@@ -480,9 +482,9 @@ void dbsrx::set_gain(float gain, const std::string &name){
/***********************************************************************
* Bandwidth Handling
**********************************************************************/
-void dbsrx::set_bandwidth(float bandwidth){
+void dbsrx::set_bandwidth(double bandwidth){
//clip the input
- bandwidth = std::clip<float>(bandwidth, 4e6, 33e6);
+ bandwidth = std::clip<double>(bandwidth, 4e6, 33e6);
double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX);
@@ -492,7 +494,7 @@ void dbsrx::set_bandwidth(float bandwidth){
_max2118_write_regs.f_dac = std::clip<int>(int((((bandwidth*_max2118_write_regs.m_divider)/ref_clock) - 4)/0.145),0,127);
//determine actual bandwidth
- _bandwidth = float((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac));
+ _bandwidth = double((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac));
if (dbsrx_debug) std::cerr << boost::format(
"DBSRX Filter Bandwidth: %f MHz, m: %d, f_dac: %d\n"
@@ -551,6 +553,10 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -559,12 +565,6 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){
val = this->get_locked();
return;
-/*
- case SUBDEV_PROP_RSSI:
- val = this->get_rssi();
- return;
-*/
-
case SUBDEV_PROP_BANDWIDTH:
val = _bandwidth;
return;
@@ -587,8 +587,11 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){
this->set_gain(val.as<float>(), key.name);
return;
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
case SUBDEV_PROP_BANDWIDTH:
- this->set_bandwidth(val.as<float>());
+ this->set_bandwidth(val.as<double>());
return;
default: UHD_THROW_PROP_SET_ERROR();
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index c3ab96e59..cfc34381e 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -444,6 +444,10 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_QI;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -474,6 +478,9 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
this->set_rx_ant(val.as<std::string>());
return;
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -524,6 +531,10 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = true;
return;
@@ -554,6 +565,9 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
this->set_tx_ant(val.as<std::string>());
return;
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp
index 41c52fbf5..10be8d1c3 100644
--- a/host/lib/usrp/dboard/db_tvrx.cpp
+++ b/host/lib/usrp/dboard/db_tvrx.cpp
@@ -58,7 +58,7 @@ static const bool tvrx_debug = false;
static const freq_range_t tvrx_freq_range(50e6, 860e6);
-static const prop_names_t tvrx_antennas = list_of(""); //only got one
+static const prop_names_t tvrx_antennas = list_of("RX");
static const uhd::dict<std::string, freq_range_t> tvrx_freq_ranges = map_list_of
("VHFLO", freq_range_t(50e6, 158e6))
@@ -66,25 +66,25 @@ static const uhd::dict<std::string, freq_range_t> tvrx_freq_ranges = map_list_of
("UHF" , freq_range_t(454e6, 860e6))
;
-static const boost::array<float, 17> vhflo_gains_db =
+static const boost::array<double, 17> vhflo_gains_db =
{{-6.00000, -6.00000, -6.00000, -4.00000, 0.00000,
5.00000, 10.00000, 17.40000, 26.30000, 36.00000,
43.00000, 48.00000, 49.50000, 50.10000, 50.30000,
50.30000, 50.30000}};
-
-static const boost::array<float, 17> vhfhi_gains_db =
- {{13.3000, -13.3000, -13.3000, -1.0000, 7.7000,
+
+static const boost::array<double, 17> vhfhi_gains_db =
+ {{-13.3000, -13.3000, -13.3000, -1.0000, 7.7000,
11.0000, 14.7000, 19.3000, 26.1000, 36.0000,
42.7000, 46.0000, 47.0000, 47.8000, 48.2000,
48.2000, 48.2000}};
-
-static const boost::array<float, 17> uhf_gains_db =
+
+static const boost::array<double, 17> uhf_gains_db =
{{-8.0000, -8.0000, -7.0000, 4.0000, 10.2000,
14.5000, 17.5000, 20.0000, 24.5000, 30.8000,
37.0000, 39.8000, 40.7000, 41.6000, 42.6000,
43.2000, 43.8000}};
-
-static const boost::array<float, 17> tvrx_if_gains_db =
+
+static const boost::array<double, 17> tvrx_if_gains_db =
{{-1.50000, -1.50000, -1.50000, -1.00000, 0.20000,
2.10000, 4.30000, 6.40000, 9.00000, 12.00000,
14.80000, 18.20000, 26.10000, 32.50000, 32.50000,
@@ -96,32 +96,32 @@ static const boost::array<float, 17> tvrx_if_gains_db =
//need dang near as many coefficients as to just map it like this and interp.
//these numbers are culled from the 4937DI5 datasheet and are probably totally inaccurate
//but if it's better than the old linear fit i'm happy
-static const uhd::dict<std::string, boost::array<float, 17> > tvrx_rf_gains_db = map_list_of
+static const uhd::dict<std::string, boost::array<double, 17> > tvrx_rf_gains_db = map_list_of
("VHFLO", vhflo_gains_db)
("VHFHI", vhfhi_gains_db)
("UHF" , uhf_gains_db)
;
//sample voltages for the above points
-static const boost::array<float, 17> tvrx_gains_volts =
+static const boost::array<double, 17> tvrx_gains_volts =
{{0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0}};
static uhd::dict<std::string, gain_range_t> get_tvrx_gain_ranges(void) {
- float rfmax = 0.0, rfmin = FLT_MAX;
+ double rfmax = 0.0, rfmin = FLT_MAX;
BOOST_FOREACH(const std::string range, tvrx_rf_gains_db.keys()) {
- float my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic
- float my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong
+ double my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic
+ double my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong
if(my_max > rfmax) rfmax = my_max;
if(my_min < rfmin) rfmin = my_min;
}
-
- float ifmin = tvrx_if_gains_db.front();
- float ifmax = tvrx_if_gains_db.back();
-
+
+ double ifmin = tvrx_if_gains_db.front();
+ double ifmax = tvrx_if_gains_db.back();
+
return map_list_of
- ("RF", gain_range_t(rfmin, rfmax, (rfmax-rfmin)/4096.0))
- ("IF", gain_range_t(ifmin, ifmax, (ifmax-ifmin)/4096.0))
- ;
+ ("RF", gain_range_t(float(rfmin), float(rfmax), float((rfmax-rfmin)/4096.0)))
+ ("IF", gain_range_t(float(ifmin), float(ifmax), float((ifmax-ifmin)/4096.0)))
+ ;
}
static const double opamp_gain = 1.22; //onboard DAC opamp gain
@@ -136,7 +136,7 @@ class tvrx : public rx_dboard_base{
public:
tvrx(ctor_args_t args);
~tvrx(void);
-
+
void rx_get(const wax::obj &key, wax::obj &val);
void rx_set(const wax::obj &key, const wax::obj &val);
@@ -198,11 +198,11 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){
}
//send initial register settings if necessary
-
+
//set default freq
_lo_freq = tvrx_freq_range.min + tvrx_if_freq; //init _lo_freq to a sane default
set_freq(tvrx_freq_range.min);
-
+
//set default gains
BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){
set_gain(get_tvrx_gain_ranges()[name].min, name);
@@ -238,33 +238,33 @@ static std::string get_band(double freq) {
* \return a voltage to feed the TVRX analog gain
*/
-static float gain_interp(float gain, boost::array<float, 17> db_vector, boost::array<float, 17> volts_vector) {
- float volts;
- gain = std::clip<float>(gain, db_vector.front(), db_vector.back()); //let's not get carried away here
-
+static double gain_interp(double gain, boost::array<double, 17> db_vector, boost::array<double, 17> volts_vector) {
+ double volts;
+ gain = std::clip<double>(gain, db_vector.front(), db_vector.back()); //let's not get carried away here
+
boost::uint8_t gain_step = 0;
//find which bin we're in
for(size_t i = 0; i < db_vector.size()-1; i++) {
if(gain >= db_vector[i] && gain <= db_vector[i+1]) gain_step = i;
}
-
+
//find the current slope for linear interpolation
- float slope = (volts_vector[gain_step + 1] - volts_vector[gain_step])
+ double slope = (volts_vector[gain_step + 1] - volts_vector[gain_step])
/ (db_vector[gain_step + 1] - db_vector[gain_step]);
-
+
//the problem here is that for gains approaching the maximum, the voltage slope becomes infinite
//i.e., a small change in gain requires an infinite change in voltage
//to cope, we limit the slope
-
- if(slope == std::numeric_limits<float>::infinity())
+
+ if(slope == std::numeric_limits<double>::infinity())
return volts_vector[gain_step];
//use the volts per dB slope to find the final interpolated voltage
volts = volts_vector[gain_step] + (slope * (gain - db_vector[gain_step]));
-
+
if(tvrx_debug)
std::cout << "Gain interp: gain: " << gain << ", gain_step: " << int(gain_step) << ", slope: " << slope << ", volts: " << volts << std::endl;
-
+
return volts;
}
@@ -283,17 +283,17 @@ static float rf_gain_to_voltage(float gain, double lo_freq){
std::string band = get_band(lo_freq + tvrx_if_freq);
//this is the voltage at the TVRX gain input
- float gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts);
+ double gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts);
//this is the voltage at the USRP DAC output
- float dac_volts = gain_volts / opamp_gain;
-
- dac_volts = std::clip<float>(dac_volts, 0.0, 3.3);
+ double dac_volts = gain_volts / opamp_gain;
+
+ dac_volts = std::clip<double>(dac_volts, 0.0, 3.3);
if (tvrx_debug) std::cerr << boost::format(
"tvrx RF AGC gain: %f dB, dac_volts: %f V"
) % gain % dac_volts << std::endl;
- return dac_volts;
+ return float(dac_volts);
}
/*!
@@ -306,17 +306,17 @@ static float rf_gain_to_voltage(float gain, double lo_freq){
static float if_gain_to_voltage(float gain){
//clip the input
gain = std::clip<float>(gain, get_tvrx_gain_ranges()["IF"].min, get_tvrx_gain_ranges()["IF"].max);
-
- float gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts);
- float dac_volts = gain_volts / opamp_gain;
-
- dac_volts = std::clip<float>(dac_volts, 0.0, 3.3);
+
+ double gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts);
+ double dac_volts = gain_volts / opamp_gain;
+
+ dac_volts = std::clip<double>(dac_volts, 0.0, 3.3);
if (tvrx_debug) std::cerr << boost::format(
"tvrx IF AGC gain: %f dB, dac_volts: %f V"
) % gain % dac_volts << std::endl;
- return dac_volts;
+ return float(dac_volts);
}
void tvrx::set_gain(float gain, const std::string &name){
@@ -337,27 +337,27 @@ void tvrx::set_gain(float gain, const std::string &name){
*/
void tvrx::set_freq(double freq) {
- freq = std::clip<float>(freq, tvrx_freq_range.min, tvrx_freq_range.max);
+ freq = std::clip<double>(freq, tvrx_freq_range.min, tvrx_freq_range.max);
std::string prev_band = get_band(_lo_freq - tvrx_if_freq);
std::string new_band = get_band(freq);
-
+
double target_lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing
double f_ref = reference_freq / double(reference_divider); //your tuning step size
-
+
int divisor = int((target_lo_freq + (f_ref * 4.0)) / (f_ref * 8)); //the divisor we'll use
double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get
-
+
if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH();
-
+
//now we update the registers
_tuner_4937di5_regs.db1 = (divisor >> 8) & 0xff;
_tuner_4937di5_regs.db2 = divisor & 0xff;
-
+
if(new_band == "VHFLO") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFLO;
else if(new_band == "VHFHI") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFHI;
else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF;
else UHD_THROW_INVALID_CODE_PATH();
-
+
_tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_OFF;
update_regs();
@@ -365,10 +365,10 @@ void tvrx::set_freq(double freq) {
//we do this because the gains are different for different band settings
//not FAR off, but we do this to be consistent
if(prev_band != new_band) set_gain(_gains["RF"], "RF");
-
- if(tvrx_debug)
+
+ if(tvrx_debug)
std::cout << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl;
-
+
_lo_freq = actual_lo_freq; //for rx props
}
@@ -422,7 +422,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_FREQ:
- /*
+ /*
* so here we have to do some magic. because the TVRX uses a relatively high IF,
* we have to watch the sample rate to see if the IF will be aliased
* or if it will fall within Nyquist.
@@ -436,7 +436,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_ANTENNA:
- val = std::string("");
+ val = tvrx_antennas.front(); //there's only one
return;
case SUBDEV_PROP_ANTENNA_NAMES:
@@ -447,6 +447,10 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -467,10 +471,14 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_GAIN:
this->set_gain(val.as<float>(), key.name);
return;
+
case SUBDEV_PROP_FREQ:
this->set_freq(val.as<double>());
return;
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp
index f6f4f4a61..ec7ab440b 100644
--- a/host/lib/usrp/dboard/db_unknown.cpp
+++ b/host/lib/usrp/dboard/db_unknown.cpp
@@ -122,6 +122,10 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -151,6 +155,9 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_FREQ:
return; // it wont do you much good, but you can set it
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -211,6 +218,10 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -240,6 +251,9 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_FREQ:
return; // it wont do you much good, but you can set it
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index e473ce41e..907268aac 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -513,6 +513,10 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -543,6 +547,9 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
this->set_rx_ant(val.as<std::string>());
return;
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -597,6 +604,10 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -627,6 +638,9 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
this->set_tx_ant(val.as<std::string>());
return;
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index 798ff74a3..fb1367113 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -51,6 +51,7 @@
#include <uhd/utils/static.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/warning.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/types/dict.hpp>
#include <uhd/usrp/subdev_props.hpp>
@@ -72,6 +73,7 @@ using namespace boost::assign;
static const bool xcvr2450_debug = false;
static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9);
+static const freq_range_t xcvr_freq_band_seperation(2.5e9, 4.9e9);
static const prop_names_t xcvr_antennas = list_of("J1")("J2");
@@ -100,6 +102,7 @@ public:
private:
double _lo_freq;
+ double _rx_bandwidth, _tx_bandwidth;
uhd::dict<std::string, float> _tx_gains, _rx_gains;
std::string _tx_ant, _rx_ant;
int _ad9515div;
@@ -110,6 +113,8 @@ private:
void set_rx_ant(const std::string &ant);
void set_tx_gain(float gain, const std::string &name);
void set_rx_gain(float gain, const std::string &name);
+ void set_rx_bandwidth(double bandwidth);
+ void set_tx_bandwidth(double bandwidth);
void update_atr(void);
void spi_reset(void);
@@ -176,6 +181,9 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){
spi_reset(); //prepare the spi
+ _rx_bandwidth = 9.5e6;
+ _tx_bandwidth = 12.0e6;
+
//setup the misc max2829 registers
_max2829_regs.mimo_select = max2829_regs_t::MIMO_SELECT_MIMO;
_max2829_regs.band_sel_mimo = max2829_regs_t::BAND_SEL_MIMO_MIMO;
@@ -183,7 +191,7 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){
_max2829_regs.rssi_high_bw = max2829_regs_t::RSSI_HIGH_BW_6MHZ;
_max2829_regs.tx_lpf_coarse_adj = max2829_regs_t::TX_LPF_COARSE_ADJ_12MHZ;
_max2829_regs.rx_lpf_coarse_adj = max2829_regs_t::RX_LPF_COARSE_ADJ_9_5MHZ;
- _max2829_regs.rx_lpf_fine_adj = max2829_regs_t::RX_LPF_FINE_ADJ_95;
+ _max2829_regs.rx_lpf_fine_adj = max2829_regs_t::RX_LPF_FINE_ADJ_100;
_max2829_regs.rx_vga_gain_spi = max2829_regs_t::RX_VGA_GAIN_SPI_SPI;
_max2829_regs.rssi_output_range = max2829_regs_t::RSSI_OUTPUT_RANGE_HIGH;
_max2829_regs.rssi_op_mode = max2829_regs_t::RSSI_OP_MODE_ENABLED;
@@ -244,15 +252,24 @@ void xcvr2450::update_atr(void){
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP_RXIO | RX_DIS_RXIO);
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP_RXIO | RX_ENB_RXIO);
this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP_RXIO | RX_DIS_RXIO);
- this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP_RXIO | RX_ENB_RXIO);
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP_RXIO | RX_DIS_RXIO);
}
/***********************************************************************
* Tuning
**********************************************************************/
void xcvr2450::set_lo_freq(double target_freq){
+ //clip for highband and lowband
+ if((target_freq > xcvr_freq_band_seperation.min) and (target_freq < xcvr_freq_band_seperation.max)){
+ if(target_freq - xcvr_freq_band_seperation.min < xcvr_freq_band_seperation.max - target_freq){
+ target_freq = xcvr_freq_band_seperation.min;
+ }else{
+ target_freq = xcvr_freq_band_seperation.max;
+ }
+ }
+
+ //clip for max and min
target_freq = std::clip(target_freq, xcvr_freq_range.min, xcvr_freq_range.max);
- //TODO: clip for highband and lowband
//variables used in the calculation below
double scaler = xcvr2450::is_highband(target_freq)? (4.0/5.0) : (4.0/3.0);
@@ -434,6 +451,114 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){
_rx_gains[name] = gain;
}
+
+/***********************************************************************
+ * Bandwidth Handling
+ **********************************************************************/
+static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(double &bandwidth){
+ int reg = std::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3);
+
+ switch(reg){
+ case 1: // bandwidth < 15MHz
+ bandwidth = 12e6;
+ return max2829_regs_t::TX_LPF_COARSE_ADJ_12MHZ;
+ case 2: // 15MHz < bandwidth < 21MHz
+ bandwidth = 18e6;
+ return max2829_regs_t::TX_LPF_COARSE_ADJ_18MHZ;
+ case 3: // bandwidth > 21MHz
+ bandwidth = 24e6;
+ return max2829_regs_t::TX_LPF_COARSE_ADJ_24MHZ;
+ }
+ UHD_THROW_INVALID_CODE_PATH();
+}
+
+static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(double &bandwidth, double requested_bandwidth){
+ int reg = std::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22);
+
+ switch(reg){
+ case 18: // requested_bandwidth < 92.5%
+ bandwidth = 0.9 * bandwidth;
+ return max2829_regs_t::RX_LPF_FINE_ADJ_90;
+ case 19: // 92.5% < requested_bandwidth < 97.5%
+ bandwidth = 0.95 * bandwidth;
+ return max2829_regs_t::RX_LPF_FINE_ADJ_95;
+ case 20: // 97.5% < requested_bandwidth < 102.5%
+ bandwidth = 1.0 * bandwidth;
+ return max2829_regs_t::RX_LPF_FINE_ADJ_100;
+ case 21: // 102.5% < requested_bandwidth < 107.5%
+ bandwidth = 1.05 * bandwidth;
+ return max2829_regs_t::RX_LPF_FINE_ADJ_105;
+ case 22: // 107.5% < requested_bandwidth
+ bandwidth = 1.1 * bandwidth;
+ return max2829_regs_t::RX_LPF_FINE_ADJ_110;
+ }
+ UHD_THROW_INVALID_CODE_PATH();
+}
+
+static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double &bandwidth){
+ int reg = std::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11);
+
+ switch(reg){
+ case 0: // bandwidth < 7.5MHz
+ case 1: // 7.5MHz < bandwidth < 8.5MHz
+ bandwidth = 7.5e6;
+ return max2829_regs_t::RX_LPF_COARSE_ADJ_7_5MHZ;
+ case 2: // 8.5MHz < bandwidth < 9.5MHz
+ case 3: // 9.5MHz < bandwidth < 10.5MHz
+ case 4: // 10.5MHz < bandwidth < 11.5MHz
+ bandwidth = 9.5e6;
+ return max2829_regs_t::RX_LPF_COARSE_ADJ_9_5MHZ;
+ case 5: // 11.5MHz < bandwidth < 12.5MHz
+ case 6: // 12.5MHz < bandwidth < 13.5MHz
+ case 7: // 13.5MHz < bandwidth < 14.5MHz
+ case 8: // 14.5MHz < bandwidth < 15.5MHz
+ bandwidth = 14e6;
+ return max2829_regs_t::RX_LPF_COARSE_ADJ_14MHZ;
+ case 9: // 15.5MHz < bandwidth < 16.5MHz
+ case 10: // 16.5MHz < bandwidth < 17.5MHz
+ case 11: // 17.5MHz < bandwidth
+ bandwidth = 18e6;
+ return max2829_regs_t::RX_LPF_COARSE_ADJ_18MHZ;
+ }
+ UHD_THROW_INVALID_CODE_PATH();
+}
+
+void xcvr2450::set_rx_bandwidth(double bandwidth){
+ double requested_bandwidth = bandwidth;
+
+ //compute coarse low pass cutoff frequency setting
+ _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth);
+
+ //compute fine low pass cutoff frequency setting
+ _max2829_regs.rx_lpf_fine_adj = bandwidth_to_rx_lpf_fine_reg(bandwidth, requested_bandwidth);
+
+ //shadow bandwidth setting
+ _rx_bandwidth = bandwidth;
+
+ //update register
+ send_reg(0x7);
+
+ if (xcvr2450_debug) std::cerr << boost::format(
+ "XCVR2450 RX Bandwidth (lp_fc): %f Hz, coarse reg: %d, fine reg: %d"
+ ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl;
+}
+
+void xcvr2450::set_tx_bandwidth(double bandwidth){
+ //compute coarse low pass cutoff frequency setting
+ _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth);
+
+ //shadow bandwidth setting
+ _tx_bandwidth = bandwidth;
+
+ //update register
+ send_reg(0x7);
+
+ if (xcvr2450_debug) std::cerr << boost::format(
+ "XCVR2450 TX Bandwidth (lp_fc): %f Hz, coarse reg: %d"
+ ) % _tx_bandwidth % (int(_max2829_regs.tx_lpf_coarse_adj)) << std::endl;
+}
+
+
/***********************************************************************
* RX Get and Set
**********************************************************************/
@@ -484,6 +609,10 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_IQ;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -496,6 +625,10 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
val = this->get_rssi();
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = _rx_bandwidth;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -518,6 +651,13 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){
this->set_rx_ant(val.as<std::string>());
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ this->set_rx_bandwidth(val.as<double>());
+ return;
+
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -572,6 +712,10 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
val = SUBDEV_CONN_COMPLEX_QI;
return;
+ case SUBDEV_PROP_ENABLED:
+ val = true; //always enabled
+ return;
+
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
@@ -580,6 +724,10 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
val = this->get_locked();
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = _tx_bandwidth;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -598,10 +746,17 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){
this->set_tx_gain(val.as<float>(), key.name);
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ this->set_tx_bandwidth(val.as<double>());
+ return;
+
case SUBDEV_PROP_ANTENNA:
this->set_tx_ant(val.as<std::string>());
return;
+ case SUBDEV_PROP_ENABLED:
+ return; //always enabled
+
default: UHD_THROW_PROP_SET_ERROR();
}
}