summaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
authorNick Foster <nick@nerdnetworks.org>2010-10-08 16:58:45 -0700
committerNick Foster <nick@nerdnetworks.org>2010-10-08 16:58:45 -0700
commit3df994e1c784d7037e869610f1417fe64e0e89a8 (patch)
tree03183a0bff1b128d70d90aee5f9e6c641b9cf999 /host/lib/usrp
parent4a6990c5d3019ca6881464f135a315e3ec022b93 (diff)
parent58e1ca09772408d5d18ee219146fe57d2045c496 (diff)
downloaduhd-3df994e1c784d7037e869610f1417fe64e0e89a8.tar.gz
uhd-3df994e1c784d7037e869610f1417fe64e0e89a8.tar.bz2
uhd-3df994e1c784d7037e869610f1417fe64e0e89a8.zip
Merge branch 'master' of ettus.sourcerepo.com:ettus/uhdpriv into usrp2p
Conflicts: host/lib/usrp/usrp2/io_impl.cpp host/lib/usrp/usrp2/mboard_impl.cpp
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp14
-rw-r--r--host/lib/usrp/dboard/db_dbsrx.cpp7
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp14
-rw-r--r--host/lib/usrp/dboard/db_tvrx.cpp118
-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.cpp14
-rw-r--r--host/lib/usrp/dboard_manager.cpp12
-rw-r--r--host/lib/usrp/misc_utils.cpp17
-rw-r--r--host/lib/usrp/single_usrp.cpp18
-rw-r--r--host/lib/usrp/subdev_spec.cpp4
-rw-r--r--host/lib/usrp/usrp1/io_impl.cpp202
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp52
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.hpp17
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp60
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp8
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp40
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp72
18 files changed, 381 insertions, 316 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..23cafea53 100644
--- a/host/lib/usrp/dboard/db_dbsrx.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx.cpp
@@ -551,6 +551,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;
@@ -587,6 +591,9 @@ 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>());
return;
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..b1fc2ea76 100644
--- a/host/lib/usrp/dboard/db_tvrx.cpp
+++ b/host/lib/usrp/dboard/db_tvrx.cpp
@@ -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 =
+
+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.
@@ -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..0ee133f3d 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -484,6 +484,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;
@@ -518,6 +522,9 @@ void xcvr2450::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();
}
}
@@ -572,6 +579,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;
@@ -602,6 +613,9 @@ void xcvr2450::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_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index 181f843a0..78daa1b4d 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -86,7 +86,7 @@ std::string dboard_id_t::to_pp_string(void) const{
}
/***********************************************************************
- * internal helper classe
+ * internal helper classes
**********************************************************************/
/*!
* A special wax proxy object that forwards calls to a subdev.
@@ -330,4 +330,14 @@ void dboard_manager_impl::set_nice_dboard_if(void){
_iface->set_pin_ctrl(unit, 0x0000); //all gpio
_iface->set_clock_enabled(unit, false); //clock off
}
+
+ //disable all rx subdevices
+ BOOST_FOREACH(const std::string &sd_name, this->get_rx_subdev_names()){
+ this->get_rx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false;
+ }
+
+ //disable all tx subdevices
+ BOOST_FOREACH(const std::string &sd_name, this->get_tx_subdev_names()){
+ this->get_tx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false;
+ }
}
diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp
index 5cfcdc8d3..05308baba 100644
--- a/host/lib/usrp/misc_utils.cpp
+++ b/host/lib/usrp/misc_utils.cpp
@@ -17,6 +17,7 @@
#include <uhd/usrp/misc_utils.hpp>
#include <uhd/utils/assert.hpp>
+#include <uhd/utils/algorithm.hpp>
#include <uhd/utils/gain_group.hpp>
#include <uhd/usrp/dboard_id.hpp>
#include <uhd/usrp/subdev_props.hpp>
@@ -186,6 +187,22 @@ static void verify_xx_subdev_spec(
"Validate %s subdev spec failed: %s\n %s"
) % xx_type % subdev_spec.to_string() % e.what()));
}
+
+ //now use the subdev spec to enable the subdevices in use and vice-versa
+ BOOST_FOREACH(const std::string &db_name, mboard[dboard_names_prop].as<prop_names_t>()){
+ wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)];
+ BOOST_FOREACH(const std::string &sd_name, dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>()){
+ try{
+ bool enable = std::has(subdev_spec, subdev_spec_pair_t(db_name, sd_name));
+ dboard[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)][SUBDEV_PROP_ENABLED] = enable;
+ }
+ catch(const std::exception &e){
+ throw std::runtime_error(str(boost::format(
+ "Cannot set enabled property on subdevice %s:%s\n %s"
+ ) % db_name % sd_name % e.what()));
+ }
+ }
+ }
}
void usrp::verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){
diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp
index bb4af44b8..08dc3bb1d 100644
--- a/host/lib/usrp/single_usrp.cpp
+++ b/host/lib/usrp/single_usrp.cpp
@@ -54,6 +54,9 @@ public:
return _dev;
}
+ /*******************************************************************
+ * Mboard methods
+ ******************************************************************/
std::string get_pp_string(void){
std::string buff = str(boost::format(
"Single USRP:\n"
@@ -101,9 +104,10 @@ public:
return buff;
}
- /*******************************************************************
- * Misc
- ******************************************************************/
+ std::string get_mboard_name(void){
+ return _mboard()[MBOARD_PROP_NAME].as<std::string>();
+ }
+
time_spec_t get_time_now(void){
return _mboard()[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
}
@@ -135,6 +139,10 @@ public:
return _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>();
}
+ std::string get_rx_subdev_name(size_t chan){
+ return _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>();
+ }
+
void set_rx_rate(double rate){
_rx_dsp()[DSP_PROP_HOST_RATE] = rate;
}
@@ -206,6 +214,10 @@ public:
return _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>();
}
+ std::string get_tx_subdev_name(size_t chan){
+ return _tx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>();
+ }
+
void set_tx_rate(double rate){
_tx_dsp()[DSP_PROP_HOST_RATE] = rate;
}
diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp
index 7a3e72867..95d2cbb12 100644
--- a/host/lib/usrp/subdev_spec.cpp
+++ b/host/lib/usrp/subdev_spec.cpp
@@ -34,6 +34,10 @@ subdev_spec_pair_t::subdev_spec_pair_t(
/* NOP */
}
+bool usrp::operator==(const subdev_spec_pair_t &lhs, const subdev_spec_pair_t &rhs){
+ return (lhs.db_name == rhs.db_name) and (lhs.sd_name == rhs.sd_name);
+}
+
subdev_spec_t::subdev_spec_t(const std::string &markup){
BOOST_FOREACH(const std::string &pair, std::split_string(markup)){
if (pair == "") continue;
diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp
index aee760a83..6728d9b15 100644
--- a/host/lib/usrp/usrp1/io_impl.cpp
+++ b/host/lib/usrp/usrp1/io_impl.cpp
@@ -33,33 +33,26 @@ using namespace uhd::usrp;
using namespace uhd::transport;
namespace asio = boost::asio;
+static const size_t alignment_padding = 512;
+
/***********************************************************************
- * Pseudo send buffer implementation
+ * Helper struct to associate an offset with a buffer
**********************************************************************/
-class pseudo_managed_send_buffer : public managed_send_buffer{
+class offset_send_buffer{
public:
+ typedef boost::shared_ptr<offset_send_buffer> sptr;
- pseudo_managed_send_buffer(
- const boost::asio::mutable_buffer &buff,
- const boost::function<ssize_t(size_t)> &commit
- ):
- _buff(buff),
- _commit(commit)
- {
- /* NOP */
+ static sptr make(managed_send_buffer::sptr buff, size_t offset = 0){
+ return sptr(new offset_send_buffer(buff, offset));
}
- ssize_t commit(size_t num_bytes){
- return _commit(num_bytes);
- }
+ //member variables
+ managed_send_buffer::sptr buff;
+ size_t offset; /* in bytes */
private:
- const boost::asio::mutable_buffer &get(void) const{
- return _buff;
- }
-
- const boost::asio::mutable_buffer _buff;
- const boost::function<ssize_t(size_t)> _commit;
+ offset_send_buffer(managed_send_buffer::sptr buff, size_t offset):
+ buff(buff), offset(offset){/* NOP */}
};
/***********************************************************************
@@ -70,8 +63,8 @@ struct usrp1_impl::io_impl{
data_transport(data_transport),
underflow_poll_samp_count(0),
overflow_poll_samp_count(0),
- send_buff(data_transport->get_send_buff()),
- num_bytes_committed(0)
+ curr_buff_committed(true),
+ curr_buff(offset_send_buffer::make(data_transport->get_send_buff()))
{
/* NOP */
}
@@ -91,100 +84,91 @@ struct usrp1_impl::io_impl{
size_t overflow_poll_samp_count;
//wrapper around the actual send buffer interface
- //all of this to ensure only full buffers are committed
- managed_send_buffer::sptr send_buff;
- size_t num_bytes_committed;
- boost::uint8_t pseudo_buff[BYTES_PER_PACKET];
- ssize_t phony_commit_pseudo_buff(size_t num_bytes);
- ssize_t phony_commit_send_buff(size_t num_bytes);
- ssize_t commit_send_buff(void);
+ //all of this to ensure only aligned lengths are committed
+ //NOTE: you must commit before getting a new buffer
+ //since the vrt packet handler obeys this, we are ok
+ bool curr_buff_committed;
+ offset_send_buffer::sptr curr_buff;
+ void commit_send_buff(offset_send_buffer::sptr, offset_send_buffer::sptr, size_t);
void flush_send_buff(void);
- bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &);
-
- //helpers to get at the send buffer + offset
- inline void *get_send_mem_ptr(void){
- return send_buff->cast<boost::uint8_t *>() + num_bytes_committed;
- }
- inline size_t get_send_mem_size(void){
- return send_buff->size() - num_bytes_committed;
- }
+ bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &, double);
};
/*!
- * Accept a commit of num bytes to the pseudo buffer.
- * Memcpy the entire contents of pseudo buffer into send buffers.
- *
- * Under most conditions:
- * The first loop iteration will fill the remainder of the send buffer.
- * The second loop iteration will empty the pseudo buffer remainder.
+ * Perform an actual commit on the send buffer:
+ * Copy the remainder of alignment to the next buffer.
+ * Commit the current buffer at multiples of alignment.
*/
-ssize_t usrp1_impl::io_impl::phony_commit_pseudo_buff(size_t num_bytes){
- size_t bytes_to_copy = num_bytes, bytes_copied = 0;
- while(bytes_to_copy){
- size_t bytes_copied_here = std::min(bytes_to_copy, get_send_mem_size());
- std::memcpy(get_send_mem_ptr(), pseudo_buff + bytes_copied, bytes_copied_here);
- ssize_t ret = phony_commit_send_buff(bytes_copied_here);
- if (ret < 0) return ret;
- bytes_to_copy -= ret;
- bytes_copied += ret;
- }
- return bytes_copied;
-}
+void usrp1_impl::io_impl::commit_send_buff(
+ offset_send_buffer::sptr curr,
+ offset_send_buffer::sptr next,
+ size_t num_bytes
+){
+ //total number of bytes now in the current buffer
+ size_t bytes_in_curr_buffer = curr->offset + num_bytes;
+
+ //calculate how many to commit and remainder
+ size_t num_bytes_remaining = bytes_in_curr_buffer % alignment_padding;
+ size_t num_bytes_to_commit = bytes_in_curr_buffer - num_bytes_remaining;
+
+ //copy the remainder into the next buffer
+ std::memcpy(
+ next->buff->cast<char *>() + next->offset,
+ curr->buff->cast<char *>() + num_bytes_to_commit,
+ num_bytes_remaining
+ );
-/*!
- * Accept a commit of num bytes to the send buffer.
- * Conditionally commit the send buffer if full.
- */
-ssize_t usrp1_impl::io_impl::phony_commit_send_buff(size_t num_bytes){
- num_bytes_committed += num_bytes;
- if (num_bytes_committed != send_buff->size()) return num_bytes;
- ssize_t ret = commit_send_buff();
- return (ret < 0)? ret : num_bytes;
+ //update the offset into the next buffer
+ next->offset += num_bytes_remaining;
+
+ //commit the current buffer
+ curr->buff->commit(num_bytes_to_commit);
+ curr_buff_committed = true;
}
/*!
- * Flush the send buffer:
- * Zero-pad the send buffer to the nearest 512 byte boundary and commit.
+ * Flush the current buffer by padding out to alignment and committing.
*/
void usrp1_impl::io_impl::flush_send_buff(void){
- size_t bytes_to_pad = (-1*num_bytes_committed)%512;
- std::memset(get_send_mem_ptr(), 0, bytes_to_pad);
- num_bytes_committed += bytes_to_pad;
- commit_send_buff();
+ //calculate the number of bytes to alignment
+ size_t bytes_to_pad = (-1*curr_buff->offset)%alignment_padding;
+
+ //get the buffer, clear, and commit (really current buffer)
+ vrt_packet_handler::managed_send_buffs_t buffs(1);
+ if (this->get_send_buffs(buffs, 0.1)){
+ std::memset(buffs[0]->cast<void *>(), 0, bytes_to_pad);
+ buffs[0]->commit(bytes_to_pad);
+ }
}
/*!
- * Perform an actual commit on the send buffer:
- * Commit the contents of the send buffer and request a new buffer.
+ * Get a managed send buffer with the alignment padding:
+ * Always grab the next send buffer so we can timeout here.
*/
-ssize_t usrp1_impl::io_impl::commit_send_buff(void){
- ssize_t ret = send_buff->commit(num_bytes_committed);
- send_buff = data_transport->get_send_buff();
- num_bytes_committed = 0;
- return ret;
-}
-
bool usrp1_impl::io_impl::get_send_buffs(
- vrt_packet_handler::managed_send_buffs_t &buffs
+ vrt_packet_handler::managed_send_buffs_t &buffs, double timeout
){
- UHD_ASSERT_THROW(buffs.size() == 1);
+ UHD_ASSERT_THROW(curr_buff_committed and buffs.size() == 1);
+
+ //try to get a new managed buffer with timeout
+ offset_send_buffer::sptr next_buff(offset_send_buffer::make(data_transport->get_send_buff(timeout)));
+ if (not next_buff->buff.get()) return false; /* propagate timeout here */
+
+ //calculate the buffer pointer and size given the offset
+ //references to the buffers are held in the bound function
+ buffs[0] = managed_send_buffer::make_safe(
+ boost::asio::buffer(
+ curr_buff->buff->cast<char *>() + curr_buff->offset,
+ curr_buff->buff->size() - curr_buff->offset
+ ),
+ boost::bind(&usrp1_impl::io_impl::commit_send_buff, this, curr_buff, next_buff, _1)
+ );
- //not enough bytes free -> use the pseudo buffer
- if (get_send_mem_size() < BYTES_PER_PACKET){
- buffs[0] = managed_send_buffer::sptr(new pseudo_managed_send_buffer(
- boost::asio::buffer(pseudo_buff),
- boost::bind(&usrp1_impl::io_impl::phony_commit_pseudo_buff, this, _1)
- ));
- }
- //otherwise use the send buffer offset by the bytes written
- else{
- buffs[0] = managed_send_buffer::sptr(new pseudo_managed_send_buffer(
- boost::asio::buffer(get_send_mem_ptr(), get_send_mem_size()),
- boost::bind(&usrp1_impl::io_impl::phony_commit_send_buff, this, _1)
- ));
- }
+ //store the next buffer for the next call
+ curr_buff = next_buff;
+ curr_buff_committed = false;
- return buffs[0].get() != NULL;
+ return true;
}
/***********************************************************************
@@ -213,10 +197,17 @@ static void usrp1_bs_vrt_packer(
if_packet_info.num_packet_words32 = if_packet_info.num_payload_words32;
}
+size_t usrp1_impl::get_max_send_samps_per_packet(void) const {
+ return (_data_transport->get_send_frame_size() - alignment_padding)
+ / _tx_otw_type.get_sample_size()
+ / _tx_subdev_spec.size()
+ ;
+}
+
size_t usrp1_impl::send(
const std::vector<const void *> &buffs, size_t num_samps,
const tx_metadata_t &metadata, const io_type_t &io_type,
- send_mode_t send_mode
+ send_mode_t send_mode, double timeout
){
size_t num_samps_sent = vrt_packet_handler::send(
_io_impl->packet_handler_send_state, //last state of the send handler
@@ -225,7 +216,7 @@ size_t usrp1_impl::send(
io_type, _tx_otw_type, //input and output types to convert
_clock_ctrl->get_master_clock_freq(), //master clock tick rate
&usrp1_bs_vrt_packer,
- boost::bind(&usrp1_impl::io_impl::get_send_buffs, _io_impl.get(), _1),
+ boost::bind(&usrp1_impl::io_impl::get_send_buffs, _io_impl.get(), _1, timeout),
get_max_send_samps_per_packet(),
0, //vrt header offset
_tx_subdev_spec.size() //num channels
@@ -272,18 +263,25 @@ static void usrp1_bs_vrt_unpacker(
}
static bool get_recv_buffs(
- zero_copy_if::sptr zc_if, size_t timeout_ms,
+ zero_copy_if::sptr zc_if, double timeout,
vrt_packet_handler::managed_recv_buffs_t &buffs
){
UHD_ASSERT_THROW(buffs.size() == 1);
- buffs[0] = zc_if->get_recv_buff(timeout_ms);
+ buffs[0] = zc_if->get_recv_buff(timeout);
return buffs[0].get() != NULL;
}
+size_t usrp1_impl::get_max_recv_samps_per_packet(void) const {
+ return _data_transport->get_recv_frame_size()
+ / _rx_otw_type.get_sample_size()
+ / _rx_subdev_spec.size()
+ ;
+}
+
size_t usrp1_impl::recv(
const std::vector<void *> &buffs, size_t num_samps,
rx_metadata_t &metadata, const io_type_t &io_type,
- recv_mode_t recv_mode, size_t timeout_ms
+ recv_mode_t recv_mode, double timeout
){
size_t num_samps_recvd = vrt_packet_handler::recv(
_io_impl->packet_handler_recv_state, //last state of the recv handler
@@ -292,7 +290,7 @@ size_t usrp1_impl::recv(
io_type, _rx_otw_type, //input and output types to convert
_clock_ctrl->get_master_clock_freq(), //master clock tick rate
&usrp1_bs_vrt_unpacker,
- boost::bind(&get_recv_buffs, _data_transport, timeout_ms, _1),
+ boost::bind(&get_recv_buffs, _data_transport, timeout, _1),
&vrt_packet_handler::handle_overflow_nop,
0, //vrt header offset
_rx_subdev_spec.size() //num channels
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 156fc119f..276ca86f6 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -106,17 +106,8 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
/***********************************************************************
* Make
**********************************************************************/
-template<typename output_type> static output_type cast_from_dev_addr(
- const device_addr_t &device_addr,
- const std::string &key,
- output_type def_val
-){
- return (device_addr.has_key(key))?
- boost::lexical_cast<output_type>(device_addr[key]) : def_val;
-}
+static device::sptr usrp1_make(const device_addr_t &device_addr){
-static device::sptr usrp1_make(const device_addr_t &device_addr)
-{
//extract the FPGA path for the USRP1
std::string usrp1_fpga_image = find_image_path(
device_addr.has_key("fpga")? device_addr["fpga"] : "usrp1_fpga.rbf"
@@ -127,29 +118,26 @@ static device::sptr usrp1_make(const device_addr_t &device_addr)
std::vector<usb_device_handle::sptr> device_list =
usb_device_handle::get_device_list(USRP1_VENDOR_ID, USRP1_PRODUCT_ID);
- //create data and control transports
- usb_zero_copy::sptr data_transport;
- usrp_ctrl::sptr usrp_ctrl;
-
-
- BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
- if (handle->get_serial() == device_addr["serial"]) {
- usb_control::sptr ctrl_transport = usb_control::make(handle);
- usrp_ctrl = usrp_ctrl::make(ctrl_transport);
- usrp_ctrl->usrp_load_fpga(usrp1_fpga_image);
-
- data_transport = usb_zero_copy::make(
- handle, // identifier
- 6, // IN endpoint
- 2, // OUT endpoint
- size_t(cast_from_dev_addr<double>(device_addr, "recv_xfer_size", 0)),
- size_t(cast_from_dev_addr<double>(device_addr, "recv_num_xfers", 0)),
- size_t(cast_from_dev_addr<double>(device_addr, "send_xfer_size", 0)),
- size_t(cast_from_dev_addr<double>(device_addr, "send_num_xfers", 0))
- );
+ //locate the matching handle in the device list
+ usb_device_handle::sptr handle;
+ BOOST_FOREACH(usb_device_handle::sptr dev_handle, device_list) {
+ if (dev_handle->get_serial() == device_addr["serial"]){
+ handle = dev_handle;
break;
}
}
+ UHD_ASSERT_THROW(handle.get() != NULL); //better be found
+
+ //create control objects and a data transport
+ usb_control::sptr ctrl_transport = usb_control::make(handle);
+ usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport);
+ usrp_ctrl->usrp_load_fpga(usrp1_fpga_image);
+ usb_zero_copy::sptr data_transport = usb_zero_copy::make(
+ handle, // identifier
+ 6, // IN endpoint
+ 2, // OUT endpoint
+ device_addr // param hints
+ );
//create the usrp1 implementation guts
return device::sptr(new usrp1_impl(data_transport, usrp_ctrl));
@@ -209,9 +197,9 @@ usrp1_impl::~usrp1_impl(void){
/* NOP */
}
-bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, size_t timeout_ms){
+bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, double timeout){
//dummy fill-in for the recv_async_msg
- boost::this_thread::sleep(boost::posix_time::milliseconds(timeout_ms));
+ boost::this_thread::sleep(boost::posix_time::microseconds(long(timeout*1e6)));
return false;
}
diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp
index 20ae3c02a..ff4d40762 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.hpp
@@ -83,25 +83,18 @@ public:
size_t,
const uhd::tx_metadata_t &,
const uhd::io_type_t &,
- send_mode_t);
+ send_mode_t, double);
size_t recv(const std::vector<void *> &,
size_t, uhd::rx_metadata_t &,
const uhd::io_type_t &,
- recv_mode_t,
- size_t timeout);
+ recv_mode_t, double);
- static const size_t BYTES_PER_PACKET = 512*4; //under the transfer size
+ size_t get_max_send_samps_per_packet(void) const;
- size_t get_max_send_samps_per_packet(void) const {
- return BYTES_PER_PACKET/_tx_otw_type.get_sample_size()/_tx_subdev_spec.size();
- }
-
- size_t get_max_recv_samps_per_packet(void) const {
- return BYTES_PER_PACKET/_rx_otw_type.get_sample_size()/_rx_subdev_spec.size();
- }
+ size_t get_max_recv_samps_per_packet(void) const;
- bool recv_async_msg(uhd::async_metadata_t &, size_t);
+ bool recv_async_msg(uhd::async_metadata_t &, double);
private:
/*!
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 7d9a426a3..eba704059 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -33,7 +33,6 @@ using namespace uhd::transport;
namespace asio = boost::asio;
static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET;
-static const double RECV_TIMEOUT_MS = 100;
/***********************************************************************
* io impl details (internal to this file)
@@ -59,9 +58,9 @@ struct usrp2_impl::io_impl{
recv_pirate_crew.join_all();
}
- bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, size_t timeout_ms){
+ bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){
boost::this_thread::disable_interruption di; //disable because the wait can throw
- return recv_pirate_booty->pop_elems_with_timed_wait(buffs, boost::posix_time::milliseconds(timeout_ms));
+ return recv_pirate_booty->pop_elems_with_timed_wait(buffs, timeout);
}
//state management for the vrt packet handler code
@@ -91,7 +90,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(
size_t next_packet_seq = 0;
while(recv_pirate_crew_raiding){
- managed_recv_buffer::sptr buff = zc_if->get_recv_buff(RECV_TIMEOUT_MS);
+ managed_recv_buffer::sptr buff = zc_if->get_recv_buff();
if (not buff.get()) continue; //ignore timeout/error buffers
try{
@@ -151,8 +150,7 @@ void usrp2_impl::io_init(void){
std::memcpy(send_buff->cast<void*>(), &data, sizeof(data));
send_buff->commit(sizeof(data));
//drain the recv buffers (may have junk)
-
- while (data_transport->get_recv_buff(RECV_TIMEOUT_MS).get()){};
+ while (data_transport->get_recv_buff().get()){};
}
//the number of recv frames is the number for the first transport
@@ -170,22 +168,16 @@ void usrp2_impl::io_init(void){
_mboards.at(i), i
));
}
-
- std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl;
- std::cout << "TX samples per packet: " << get_max_send_samps_per_packet() << std::endl;
- std::cout << "Recv pirate num frames: " << num_frames << std::endl;
}
/***********************************************************************
* Async Data
**********************************************************************/
bool usrp2_impl::recv_async_msg(
- async_metadata_t &async_metadata, size_t timeout_ms
+ async_metadata_t &async_metadata, double timeout
){
boost::this_thread::disable_interruption di; //disable because the wait can throw
- return _io_impl->async_msg_fifo->pop_with_timed_wait(
- async_metadata, boost::posix_time::milliseconds(timeout_ms)
- );
+ return _io_impl->async_msg_fifo->pop_with_timed_wait(async_metadata, timeout);
}
/***********************************************************************
@@ -193,28 +185,40 @@ bool usrp2_impl::recv_async_msg(
**********************************************************************/
static bool get_send_buffs(
const std::vector<udp_zero_copy::sptr> &trans,
- vrt_packet_handler::managed_send_buffs_t &buffs
+ vrt_packet_handler::managed_send_buffs_t &buffs,
+ double timeout
){
UHD_ASSERT_THROW(trans.size() == buffs.size());
+ bool good = true;
for (size_t i = 0; i < buffs.size(); i++){
- buffs[i] = trans[i]->get_send_buff();
+ buffs[i] = trans[i]->get_send_buff(timeout);
+ good = good and (buffs[i].get() != NULL);
}
- return true;
+ return good;
+}
+
+size_t usrp2_impl::get_max_send_samps_per_packet(void) const{
+ static const size_t hdr_size = 0
+ + vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ - sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ ;
+ const size_t bpp = _data_transports.front()->get_send_frame_size() - hdr_size;
+ return bpp/_tx_otw_type.get_sample_size();
}
size_t usrp2_impl::send(
const std::vector<const void *> &buffs, size_t num_samps,
const tx_metadata_t &metadata, const io_type_t &io_type,
- send_mode_t send_mode
+ send_mode_t send_mode, double timeout
){
return vrt_packet_handler::send(
_io_impl->packet_handler_send_state, //last state of the send handler
buffs, num_samps, //buffer to fill
metadata, send_mode, //samples metadata
- io_type, _io_helper.get_tx_otw_type(), //input and output types to convert
+ io_type, _tx_otw_type, //input and output types to convert
_mboards.front()->get_master_clock_freq(), //master clock tick rate
uhd::transport::vrt::if_hdr_pack_be,
- boost::bind(&get_send_buffs, _data_transports, _1),
+ boost::bind(&get_send_buffs, _data_transports, _1, timeout),
get_max_send_samps_per_packet()
);
}
@@ -222,18 +226,28 @@ size_t usrp2_impl::send(
/***********************************************************************
* Receive Data
**********************************************************************/
+size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{
+ static const size_t hdr_size = 0
+ + vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
+ - sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ ;
+ const size_t bpp = _data_transports.front()->get_recv_frame_size() - hdr_size;
+ return bpp/_rx_otw_type.get_sample_size();
+}
+
size_t usrp2_impl::recv(
const std::vector<void *> &buffs, size_t num_samps,
rx_metadata_t &metadata, const io_type_t &io_type,
- recv_mode_t recv_mode, size_t timeout_ms
+ recv_mode_t recv_mode, double timeout
){
return vrt_packet_handler::recv(
_io_impl->packet_handler_recv_state, //last state of the recv handler
buffs, num_samps, //buffer to fill
metadata, recv_mode, //samples metadata
- io_type, _io_helper.get_rx_otw_type(), //input and output types to convert
+ io_type, _rx_otw_type, //input and output types to convert
_mboards.front()->get_master_clock_freq(), //master clock tick rate
uhd::transport::vrt::if_hdr_unpack_be,
- boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout_ms)
+ boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout)
);
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 8c5ef49ed..e0e0d726e 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -40,10 +40,10 @@ using namespace boost::posix_time;
usrp2_mboard_impl::usrp2_mboard_impl(
size_t index,
transport::udp_simple::sptr ctrl_transport,
- const usrp2_io_helper &io_helper
+ size_t recv_frame_size
):
_index(index),
- _io_helper(io_helper)
+ _recv_frame_size(recv_frame_size)
{
//make a new interface for usrp2 stuff
_iface = usrp2_iface::make(ctrl_transport);
@@ -83,7 +83,7 @@ usrp2_mboard_impl::usrp2_mboard_impl(
this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
//setup the vrt rx registers
- _iface->poke32(_iface->regs.rx_ctrl_nsamps_per_pkt, _io_helper.get_max_recv_samps_per_packet());
+ _iface->poke32(_iface->regs.rx_ctrl_nsamps_per_pkt, _recv_frame_size);
_iface->poke32(_iface->regs.rx_ctrl_nchannels, 1);
_iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset
_iface->poke32(_iface->regs.rx_ctrl_vrt_header, 0
@@ -196,7 +196,7 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){
void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
_iface->poke32(_iface->regs.rx_ctrl_stream_cmd, dsp_type1::calc_stream_cmd_word(
- stream_cmd, _io_helper.get_max_recv_samps_per_packet()
+ stream_cmd, _recv_frame_size
));
_iface->poke32(_iface->regs.rx_ctrl_time_secs, boost::uint32_t(stream_cmd.time_spec.get_full_secs()));
_iface->poke32(_iface->regs.rx_ctrl_time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq()));
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 568c87a22..a680708ad 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -124,26 +124,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){
/***********************************************************************
* Make
**********************************************************************/
-template <typename out_type, typename in_type>
-out_type lexical_cast(const in_type &in){
- try{
- return boost::lexical_cast<out_type>(in);
- }catch(...){
- throw std::runtime_error(str(boost::format(
- "failed to cast \"%s\" to type \"%s\""
- ) % boost::lexical_cast<std::string>(in) % typeid(out_type).name()));
- }
-}
-
static device::sptr usrp2_make(const device_addr_t &device_addr){
- //extract the receive and send buffer sizes
- size_t recv_buff_size = 0, send_buff_size= 0 ;
- if (device_addr.has_key("recv_buff_size")){
- recv_buff_size = size_t(lexical_cast<double>(device_addr["recv_buff_size"]));
- }
- if (device_addr.has_key("send_buff_size")){
- send_buff_size = size_t(lexical_cast<double>(device_addr["send_buff_size"]));
- }
//create a ctrl and data transport for each address
std::vector<udp_simple::sptr> ctrl_transports;
@@ -154,8 +135,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){
addr, num2str(USRP2_UDP_CTRL_PORT)
));
data_transports.push_back(udp_zero_copy::make(
- addr, num2str(USRP2_UDP_DATA_PORT),
- recv_buff_size, send_buff_size
+ addr, num2str(USRP2_UDP_DATA_PORT), device_addr
));
}
@@ -178,11 +158,23 @@ usrp2_impl::usrp2_impl(
):
_data_transports(data_transports)
{
+ //setup rx otw type
+ _rx_otw_type.width = 16;
+ _rx_otw_type.shift = 0;
+ _rx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
+
+ //setup tx otw type
+ _tx_otw_type.width = 16;
+ _tx_otw_type.shift = 0;
+ _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
+
+ //!!!!! set the otw type here before continuing, its used below
+
//create a new mboard handler for each control transport
for(size_t i = 0; i < ctrl_transports.size(); i++){
- _mboards.push_back(usrp2_mboard_impl::sptr(
- new usrp2_mboard_impl(i, ctrl_transports[i], _io_helper)
- ));
+ _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl(
+ i, ctrl_transports[i], this->get_max_recv_samps_per_packet()
+ )));
//use an empty name when there is only one mboard
std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : "";
_mboard_dict[name] = _mboards.back();
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index b37c61488..b81711e2b 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -73,54 +73,6 @@ private:
};
/*!
- * The io helper class encapculates the max packet sizes and otw types.
- * The otw types are read-only for now, this will be reimplemented
- * when it becomes possible to change the otw type in the usrp2.
- */
-class usrp2_io_helper{
-public:
- usrp2_io_helper(void){
- //setup rx otw type
- _rx_otw_type.width = 16;
- _rx_otw_type.shift = 0;
- _rx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
-
- //setup tx otw type
- _tx_otw_type.width = 16;
- _tx_otw_type.shift = 0;
- _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
- }
-
- inline size_t get_max_send_samps_per_packet(void) const{
- return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size();
- }
-
- inline size_t get_max_recv_samps_per_packet(void) const{
- return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size();
- }
-
- inline const uhd::otw_type_t &get_rx_otw_type(void) const{
- return _rx_otw_type;
- }
-
- inline const uhd::otw_type_t &get_tx_otw_type(void) const{
- return _tx_otw_type;
- }
-
-private:
- uhd::otw_type_t _rx_otw_type, _tx_otw_type;
- static const size_t _max_rx_bytes_per_packet = uhd::transport::udp_simple::mtu
- - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- - sizeof(uhd::transport::vrt::if_packet_info_t().tlr) //forced to have trailer
- + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used
- ;
- static const size_t _max_tx_bytes_per_packet = uhd::transport::udp_simple::mtu
- - uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- + sizeof(uhd::transport::vrt::if_packet_info_t().cid) //no class id ever used
- ;
-};
-
-/*!
* USRP2 mboard implementation guts:
* The implementation details are encapsulated here.
* Handles properties on the mboard, dboard, dsps...
@@ -130,7 +82,11 @@ public:
typedef boost::shared_ptr<usrp2_mboard_impl> sptr;
//structors
- usrp2_mboard_impl(size_t index, uhd::transport::udp_simple::sptr, const usrp2_io_helper &);
+ usrp2_mboard_impl(
+ size_t index,
+ uhd::transport::udp_simple::sptr,
+ size_t recv_frame_size
+ );
~usrp2_mboard_impl(void);
inline double get_master_clock_freq(void){
@@ -140,7 +96,7 @@ public:
private:
size_t _index;
int _rev_hi, _rev_lo;
- const usrp2_io_helper &_io_helper;
+ const size_t _recv_frame_size;
//properties for this mboard
void get(const wax::obj &, wax::obj &);
@@ -233,23 +189,19 @@ public:
~usrp2_impl(void);
//the io interface
- size_t get_max_send_samps_per_packet(void) const{
- return _io_helper.get_max_send_samps_per_packet();
- }
size_t send(
const std::vector<const void *> &, size_t,
const uhd::tx_metadata_t &, const uhd::io_type_t &,
- uhd::device::send_mode_t
+ uhd::device::send_mode_t, double
);
- size_t get_max_recv_samps_per_packet(void) const{
- return _io_helper.get_max_recv_samps_per_packet();
- }
size_t recv(
const std::vector<void *> &, size_t,
uhd::rx_metadata_t &, const uhd::io_type_t &,
- uhd::device::recv_mode_t, size_t
+ uhd::device::recv_mode_t, double
);
- bool recv_async_msg(uhd::async_metadata_t &, size_t);
+ size_t get_max_send_samps_per_packet(void) const;
+ size_t get_max_recv_samps_per_packet(void) const;
+ bool recv_async_msg(uhd::async_metadata_t &, double);
private:
//device properties interface
@@ -262,7 +214,7 @@ private:
//io impl methods and members
std::vector<uhd::transport::udp_zero_copy::sptr> _data_transports;
- const usrp2_io_helper _io_helper;
+ uhd::otw_type_t _rx_otw_type, _tx_otw_type;
UHD_PIMPL_DECL(io_impl) _io_impl;
void io_init(void);
};