summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/examples/rx_timed_samples.cpp2
-rw-r--r--host/include/uhd/usrp/dsp_props.hpp23
-rw-r--r--host/include/uhd/usrp/mboard_props.hpp3
-rw-r--r--host/include/uhd/usrp/simple_usrp.hpp2
-rw-r--r--host/include/uhd/usrp/subdev_props.hpp2
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp8
-rw-r--r--host/lib/usrp/simple_usrp.cpp46
-rw-r--r--host/lib/usrp/tune_helper.cpp13
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp250
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp62
10 files changed, 168 insertions, 243 deletions
diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp
index 1292d9b27..7b06981b2 100644
--- a/host/examples/rx_timed_samples.cpp
+++ b/host/examples/rx_timed_samples.cpp
@@ -57,7 +57,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << boost::format("Using Device: %s") % sdev->get_name() << std::endl;
//set properties on the device
- double rx_rate = sdev->get_rx_rates()[4]; //pick some rate
+ double rx_rate = 100e6/16; //FIXME get this from somewhere
std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl;
sdev->set_rx_rate(rx_rate);
std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
diff --git a/host/include/uhd/usrp/dsp_props.hpp b/host/include/uhd/usrp/dsp_props.hpp
index 60c0df942..75d8c0a60 100644
--- a/host/include/uhd/usrp/dsp_props.hpp
+++ b/host/include/uhd/usrp/dsp_props.hpp
@@ -24,15 +24,24 @@ namespace uhd{ namespace usrp{
/*!
* Possible device dsp properties:
- * A dsp can have a wide range of possible properties.
- * A ddc would have a properties "decim", "freq", "taps"...
- * Other properties could be gains, complex scalars, enables...
- * For this reason the only required properties of a dsp is a name
- * and a property to get list of other possible properties.
+ * A dsp is a black box fpga component found between
+ * the over-the-wire data and the codec pins.
+ *
+ * The host rate can be modified to control resampling.
+ * Resampling can take the form of decimation, interpolation,
+ * or more complex fractional resampling techniques.
+ * As usual, read back the host rate after setting it
+ * to get the actual rate that was set (implementation dependent).
+ *
+ * A dsp can also shift the digital stream in frequency.
+ * Set the shift property and read it back to get actual shift.
*/
enum dsp_prop_t{
- DSP_PROP_NAME = 'n', //ro, std::string
- DSP_PROP_OTHERS = 'o' //ro, prop_names_t
+ DSP_PROP_NAME = 'n', //ro, std::string
+ DSP_PROP_OTHERS = 'o', //ro, prop_names_t
+ DSP_PROP_FREQ_SHIFT = 'f', //rw, double Hz
+ DSP_PROP_CODEC_RATE = 'c', //ro, double Sps
+ DSP_PROP_HOST_RATE = 'h' //rw, double Sps
};
}} //namespace
diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp
index cfc1f412e..55c11b822 100644
--- a/host/include/uhd/usrp/mboard_props.hpp
+++ b/host/include/uhd/usrp/mboard_props.hpp
@@ -42,7 +42,8 @@ namespace uhd{ namespace usrp{
MBOARD_PROP_TX_DBOARD_NAMES = 'V', //ro, prop_names_t
MBOARD_PROP_CLOCK_CONFIG = 'C', //rw, clock_config_t
MBOARD_PROP_TIME_NOW = 't', //wo, time_spec_t
- MBOARD_PROP_TIME_NEXT_PPS = 'T' //wo, time_spec_t
+ MBOARD_PROP_TIME_NEXT_PPS = 'T', //wo, time_spec_t
+ MBOARD_PROP_STREAM_CMD = 's' //wo, stream_cmd_t
};
}} //namespace
diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp
index 2d6ad2a0f..6f74a406b 100644
--- a/host/include/uhd/usrp/simple_usrp.hpp
+++ b/host/include/uhd/usrp/simple_usrp.hpp
@@ -59,7 +59,6 @@ public:
******************************************************************/
virtual void set_rx_rate(double rate) = 0;
virtual double get_rx_rate(void) = 0;
- virtual std::vector<double> get_rx_rates(void) = 0;
virtual tune_result_t set_rx_freq(double freq) = 0;
virtual freq_range_t get_rx_freq_range(void) = 0;
@@ -77,7 +76,6 @@ public:
******************************************************************/
virtual void set_tx_rate(double rate) = 0;
virtual double get_tx_rate(void) = 0;
- virtual std::vector<double> get_tx_rates(void) = 0;
virtual tune_result_t set_tx_freq(double freq) = 0;
virtual freq_range_t get_tx_freq_range(void) = 0;
diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp
index 92d18340b..d35793c6b 100644
--- a/host/include/uhd/usrp/subdev_props.hpp
+++ b/host/include/uhd/usrp/subdev_props.hpp
@@ -39,7 +39,7 @@ namespace uhd{ namespace usrp{
SUBDEV_PROP_QUADRATURE = 'q', //ro, bool
SUBDEV_PROP_IQ_SWAPPED = 'i', //ro, bool
SUBDEV_PROP_SPECTRUM_INVERTED = 's', //ro, bool
- SUBDEV_PROP_LO_INTERFERES = 'l' //ro, bool
+ SUBDEV_PROP_USE_LO_OFFSET = 'l' //ro, bool
//SUBDEV_PROP_RSSI, //ro, float //----> not on all boards, use named prop
//SUBDEV_PROP_BANDWIDTH //rw, double //----> not on all boards, use named prop
};
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index be4e646ed..930646f76 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -150,7 +150,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
case SUBDEV_PROP_IQ_SWAPPED:
case SUBDEV_PROP_SPECTRUM_INVERTED:
- case SUBDEV_PROP_LO_INTERFERES:
+ case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
}
@@ -186,7 +186,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_QUADRATURE:
case SUBDEV_PROP_IQ_SWAPPED:
case SUBDEV_PROP_SPECTRUM_INVERTED:
- case SUBDEV_PROP_LO_INTERFERES:
+ case SUBDEV_PROP_USE_LO_OFFSET:
throw std::runtime_error(str(boost::format(
"Error: trying to set read-only property on %s subdev"
) % dboard_id::to_string(get_rx_id())));
@@ -258,7 +258,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
case SUBDEV_PROP_IQ_SWAPPED:
case SUBDEV_PROP_SPECTRUM_INVERTED:
- case SUBDEV_PROP_LO_INTERFERES:
+ case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
return;
}
@@ -294,7 +294,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_QUADRATURE:
case SUBDEV_PROP_IQ_SWAPPED:
case SUBDEV_PROP_SPECTRUM_INVERTED:
- case SUBDEV_PROP_LO_INTERFERES:
+ case SUBDEV_PROP_USE_LO_OFFSET:
throw std::runtime_error(str(boost::format(
"Error: trying to set read-only property on %s subdev"
) % dboard_id::to_string(get_tx_id())));
diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp
index a0551a630..bd8bac00f 100644
--- a/host/lib/usrp/simple_usrp.cpp
+++ b/host/lib/usrp/simple_usrp.cpp
@@ -22,6 +22,7 @@
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/usrp/device_props.hpp>
#include <uhd/usrp/dboard_props.hpp>
+#include <uhd/usrp/dsp_props.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <stdexcept>
@@ -30,17 +31,6 @@ using namespace uhd;
using namespace uhd::usrp;
/***********************************************************************
- * Helper Functions
- **********************************************************************/
-static std::vector<double> get_xx_rates(wax::obj decerps, wax::obj rate){
- std::vector<double> rates;
- BOOST_FOREACH(size_t decerp, decerps.as<std::vector<size_t> >()){
- rates.push_back(rate.as<double>()/decerp);
- }
- return rates;
-}
-
-/***********************************************************************
* Simple Device Implementation
**********************************************************************/
class simple_usrp_impl : public simple_usrp{
@@ -48,8 +38,8 @@ public:
simple_usrp_impl(const device_addr_t &addr){
_dev = device::make(addr);
_mboard = (*_dev)[DEVICE_PROP_MBOARD];
- _rx_ddc = _mboard[named_prop_t(MBOARD_PROP_RX_DSP, "ddc0")];
- _tx_duc = _mboard[named_prop_t(MBOARD_PROP_TX_DSP, "duc0")];
+ _rx_dsp = _mboard[named_prop_t(MBOARD_PROP_RX_DSP, "ddc0")]; //FIX string crap
+ _tx_dsp = _mboard[named_prop_t(MBOARD_PROP_TX_DSP, "duc0")]; //FIX string crap
//extract rx subdevice
wax::obj rx_dboard = _mboard[MBOARD_PROP_RX_DBOARD];
@@ -86,7 +76,7 @@ public:
}
void issue_stream_cmd(const stream_cmd_t &stream_cmd){
- _rx_ddc[std::string("stream_cmd")] = stream_cmd;
+ _mboard[MBOARD_PROP_STREAM_CMD] = stream_cmd;
}
void set_clock_config(const clock_config_t &clock_config){
@@ -101,21 +91,15 @@ public:
* RX methods
******************************************************************/
void set_rx_rate(double rate){
- double samp_rate = _rx_ddc[std::string("if_rate")].as<double>();
- assert_has(get_rx_rates(), rate, "simple device rx rate");
- _rx_ddc[std::string("decim")] = size_t(samp_rate/rate);
+ _rx_dsp[DSP_PROP_HOST_RATE] = rate;
}
double get_rx_rate(void){
- return _rx_ddc[std::string("bb_rate")].as<double>();
- }
-
- std::vector<double> get_rx_rates(void){
- return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("if_rate")]);
+ return _rx_dsp[DSP_PROP_HOST_RATE].as<double>();
}
tune_result_t set_rx_freq(double target_freq){
- return tune_rx_subdev_and_ddc(_rx_subdev, _rx_ddc, target_freq);
+ return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq);
}
freq_range_t get_rx_freq_range(void){
@@ -150,21 +134,15 @@ public:
* TX methods
******************************************************************/
void set_tx_rate(double rate){
- double samp_rate = _tx_duc[std::string("if_rate")].as<double>();
- assert_has(get_tx_rates(), rate, "simple device tx rate");
- _tx_duc[std::string("interp")] = size_t(samp_rate/rate);
+ _tx_dsp[DSP_PROP_HOST_RATE] = rate;
}
double get_tx_rate(void){
- return _tx_duc[std::string("bb_rate")].as<double>();
- }
-
- std::vector<double> get_tx_rates(void){
- return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("if_rate")]);
+ return _tx_dsp[DSP_PROP_HOST_RATE].as<double>();
}
tune_result_t set_tx_freq(double target_freq){
- return tune_tx_subdev_and_duc(_tx_subdev, _tx_duc, target_freq);
+ return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq);
}
freq_range_t get_tx_freq_range(void){
@@ -198,8 +176,8 @@ public:
private:
device::sptr _dev;
wax::obj _mboard;
- wax::obj _rx_ddc;
- wax::obj _tx_duc;
+ wax::obj _rx_dsp;
+ wax::obj _tx_dsp;
wax::obj _rx_subdev;
wax::obj _tx_subdev;
};
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index 79a6aff7b..2fb15064c 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -18,6 +18,7 @@
#include <uhd/usrp/tune_helper.hpp>
#include <uhd/utils/algorithm.hpp>
#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/usrp/dsp_props.hpp>
#include <cmath>
using namespace uhd;
@@ -34,8 +35,8 @@ static tune_result_t tune_xx_subdev_and_dxc(
wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>();
- wax::obj dxc_freq_proxy = dxc[std::string("freq")];
- double dxc_sample_rate = dxc[std::string("if_rate")].as<double>();
+ wax::obj dxc_freq_proxy = dxc[DSP_PROP_FREQ_SHIFT];
+ double dxc_sample_rate = dxc[DSP_PROP_CODEC_RATE].as<double>();
// Ask the d'board to tune as closely as it can to target_freq+lo_offset
double target_inter_freq = target_freq + lo_offset;
@@ -96,8 +97,8 @@ tune_result_t uhd::usrp::tune_rx_subdev_and_ddc(
){
double lo_offset = 0.0;
//if the local oscillator will be in the passband, use an offset
- if (subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
- lo_offset = 2.0*ddc[std::string("bb_rate")].as<double>();
+ if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
+ lo_offset = 2.0*ddc[DSP_PROP_HOST_RATE].as<double>();
}
return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset);
}
@@ -119,8 +120,8 @@ tune_result_t uhd::usrp::tune_tx_subdev_and_duc(
){
double lo_offset = 0.0;
//if the local oscillator will be in the passband, use an offset
- if (subdev[SUBDEV_PROP_LO_INTERFERES].as<bool>()){
- lo_offset = 2.0*duc[std::string("bb_rate")].as<double>();
+ if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
+ lo_offset = 2.0*duc[DSP_PROP_HOST_RATE].as<double>();
}
return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset);
}
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 1fe7b7f25..559ea38d8 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -54,6 +54,16 @@ static boost::uint32_t calculate_iq_scale_word(boost::int16_t i, boost::int16_t
return (boost::uint16_t(i) << 16) | (boost::uint16_t(q) << 0);
}
+template <class rate_t> static rate_t
+pick_closest_rate(double exact_rate, const std::vector<rate_t> &rates){
+ rate_t closest_match = rates.at(0);
+ BOOST_FOREACH(rate_t possible_rate, rates){
+ if(std::abs(exact_rate - possible_rate) < std::abs(exact_rate - closest_match))
+ closest_match = possible_rate;
+ }
+ return closest_match;
+}
+
void usrp2_impl::init_ddc_config(void){
//create the ddc in the rx dsp dict
_rx_dsps["ddc0"] = wax_obj_proxy::make(
@@ -81,128 +91,57 @@ void usrp2_impl::update_ddc_config(void){
);
}
-void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO);
- out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0;
- out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs);
- out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.ticks);
-
- //set these to defaults, then change in the switch statement
- out_data.data.stream_cmd.continuous = 0;
- out_data.data.stream_cmd.chain = 0;
- out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps);
-
- //setup chain, num samps, and continuous below
- switch(stream_cmd.stream_mode){
- case stream_cmd_t::STREAM_MODE_START_CONTINUOUS:
- out_data.data.stream_cmd.continuous = 1;
- break;
-
- case stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS:
- out_data.data.stream_cmd.num_samps = htonl(0);
- break;
-
- case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE:
- //all set by defaults above
- break;
-
- case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE:
- out_data.data.stream_cmd.chain = 1;
- break;
- }
-
- //send and recv
- usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
- ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE);
-}
-
/***********************************************************************
* DDC Properties
**********************************************************************/
void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
- //handle the case where the key is an expected dsp property
- if (key.type() == typeid(dsp_prop_t)){
- switch(key.as<dsp_prop_t>()){
- case DSP_PROP_NAME:
- val = std::string("usrp2 ddc0");
- return;
-
- case DSP_PROP_OTHERS:{
- prop_names_t others = boost::assign::list_of
- ("if_rate")
- ("bb_rate")
- ("decim")
- ("decims")
- ("freq")
- ("stream_cmd")
- ;
- val = others;
- }
- return;
- }
- }
-
- //handle string-based properties specific to this dsp
- std::string key_name = key.as<std::string>();
- if (key_name == "if_rate"){
- val = get_master_clock_freq();
+ switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_NAME:
+ val = std::string("usrp2 ddc0");
return;
- }
- else if (key_name == "bb_rate"){
- val = get_master_clock_freq()/_ddc_decim;
+
+ case DSP_PROP_OTHERS:
+ val = prop_names_t(); //empty
return;
- }
- else if (key_name == "decim"){
- val = _ddc_decim;
+
+ case DSP_PROP_FREQ_SHIFT:
+ val = _ddc_freq;
return;
- }
- else if (key_name == "decims"){
- val = _allowed_decim_and_interp_rates;
+
+ case DSP_PROP_CODEC_RATE:
+ val = get_master_clock_freq();
return;
- }
- else if (key_name == "freq"){
- val = _ddc_freq;
+
+ case DSP_PROP_HOST_RATE:
+ val = get_master_clock_freq()/_ddc_decim;
return;
}
-
- throw std::invalid_argument(str(
- boost::format("error getting: unknown key with name %s") % key_name
- ));
}
void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){
- //handle string-based properties specific to this dsp
- std::string key_name = key.as<std::string>();
- if (key_name == "decim"){
- size_t new_decim = val.as<size_t>();
- assert_has(
- _allowed_decim_and_interp_rates,
- new_decim, "usrp2 decimation"
- );
- _ddc_decim = new_decim; //shadow
- update_ddc_config();
- return;
- }
- else if (key_name == "freq"){
- double new_freq = val.as<double>();
- ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
- ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
- _ddc_freq = new_freq; //shadow
- this->poke32(FR_DSP_RX_FREQ,
- calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq())
- );
+ switch(key.as<dsp_prop_t>()){
+
+ case DSP_PROP_FREQ_SHIFT:{
+ double new_freq = val.as<double>();
+ ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
+ ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
+ _ddc_freq = new_freq; //shadow
+ this->poke32(FR_DSP_RX_FREQ,
+ calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq())
+ );
+ }
return;
- }
- else if (key_name == "stream_cmd"){
- issue_ddc_stream_cmd(val.as<stream_cmd_t>());
+
+ case DSP_PROP_HOST_RATE:{
+ double extact_rate = get_master_clock_freq()/val.as<double>();
+ _ddc_decim = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates);
+ update_ddc_config();
+ }
return;
- }
- throw std::invalid_argument(str(
- boost::format("error setting: unknown key with name %s") % key_name
- ));
+ default:
+ throw std::runtime_error("Error: trying to set read-only property on usrp2 ddc0");
+ }
}
/***********************************************************************
@@ -241,80 +180,51 @@ void usrp2_impl::update_duc_config(void){
* DUC Properties
**********************************************************************/
void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
- //handle the case where the key is an expected dsp property
- if (key.type() == typeid(dsp_prop_t)){
- switch(key.as<dsp_prop_t>()){
- case DSP_PROP_NAME:
- val = std::string("usrp2 duc0");
- return;
-
- case DSP_PROP_OTHERS:{
- prop_names_t others = boost::assign::list_of
- ("if_rate")
- ("bb_rate")
- ("interp")
- ("interps")
- ("freq")
- ;
- val = others;
- }
- return;
- }
- }
-
- //handle string-based properties specific to this dsp
- std::string key_name = key.as<std::string>();
- if (key_name == "if_rate"){
- val = get_master_clock_freq();
+ switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_NAME:
+ val = std::string("usrp2 duc0");
return;
- }
- else if (key_name == "bb_rate"){
- val = get_master_clock_freq()/_duc_interp;
+
+ case DSP_PROP_OTHERS:
+ val = prop_names_t(); //empty
return;
- }
- else if (key_name == "interp"){
- val = _duc_interp;
+
+ case DSP_PROP_FREQ_SHIFT:
+ val = _duc_freq;
return;
- }
- else if (key_name == "interps"){
- val = _allowed_decim_and_interp_rates;
+
+ case DSP_PROP_CODEC_RATE:
+ val = get_master_clock_freq();
return;
- }
- else if (key_name == "freq"){
- val = _duc_freq;
+
+ case DSP_PROP_HOST_RATE:
+ val = get_master_clock_freq()/_duc_interp;
return;
}
-
- throw std::invalid_argument(str(
- boost::format("error getting: unknown key with name %s") % key_name
- ));
}
void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){
- //handle string-based properties specific to this dsp
- std::string key_name = key.as<std::string>();
- if (key_name == "interp"){
- size_t new_interp = val.as<size_t>();
- assert_has(
- _allowed_decim_and_interp_rates,
- new_interp, "usrp2 interpolation"
- );
- _duc_interp = new_interp; //shadow
- update_duc_config();
+ switch(key.as<dsp_prop_t>()){
+
+ case DSP_PROP_FREQ_SHIFT:{
+ double new_freq = val.as<double>();
+ ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
+ ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
+ _duc_freq = new_freq; //shadow
+ this->poke32(FR_DSP_TX_FREQ,
+ calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq())
+ );
+ }
return;
- }
- else if (key_name == "freq"){
- double new_freq = val.as<double>();
- ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
- ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
- _duc_freq = new_freq; //shadow
- this->poke32(FR_DSP_TX_FREQ,
- calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq())
- );
+
+ case DSP_PROP_HOST_RATE:{
+ double extact_rate = get_master_clock_freq()/val.as<double>();
+ _duc_interp = pick_closest_rate(extact_rate, _allowed_decim_and_interp_rates);
+ update_duc_config();
+ }
return;
- }
- throw std::invalid_argument(str(
- boost::format("error setting: unknown key with name %s") % key_name
- ));
+ default:
+ throw std::runtime_error("Error: trying to set read-only property on usrp2 duc0");
+ }
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index ceb2ec98f..0891f9dc8 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -82,6 +82,43 @@ void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){
this->poke32(FR_TIME64_IMM, imm_flags);
}
+void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO);
+ out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0;
+ out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs);
+ out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.ticks);
+
+ //set these to defaults, then change in the switch statement
+ out_data.data.stream_cmd.continuous = 0;
+ out_data.data.stream_cmd.chain = 0;
+ out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps);
+
+ //setup chain, num samps, and continuous below
+ switch(stream_cmd.stream_mode){
+ case stream_cmd_t::STREAM_MODE_START_CONTINUOUS:
+ out_data.data.stream_cmd.continuous = 1;
+ break;
+
+ case stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS:
+ out_data.data.stream_cmd.num_samps = htonl(0);
+ break;
+
+ case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE:
+ //all set by defaults above
+ break;
+
+ case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE:
+ out_data.data.stream_cmd.chain = 1;
+ break;
+ }
+
+ //send and recv
+ usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE);
+}
+
/***********************************************************************
* MBoard Get Properties
**********************************************************************/
@@ -179,8 +216,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
val = _clock_config;
return;
- case MBOARD_PROP_TIME_NOW:
- case MBOARD_PROP_TIME_NEXT_PPS:
+ default:
throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard");
}
@@ -226,27 +262,19 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
update_clock_config();
return;
- case MBOARD_PROP_TIME_NOW:{
+ case MBOARD_PROP_TIME_NOW:
set_time_spec(val.as<time_spec_t>(), true);
return;
- }
- case MBOARD_PROP_TIME_NEXT_PPS:{
+ case MBOARD_PROP_TIME_NEXT_PPS:
set_time_spec(val.as<time_spec_t>(), false);
return;
- }
- case MBOARD_PROP_NAME:
- case MBOARD_PROP_OTHERS:
- case MBOARD_PROP_CLOCK_RATE:
- case MBOARD_PROP_RX_DSP:
- case MBOARD_PROP_RX_DSP_NAMES:
- case MBOARD_PROP_TX_DSP:
- case MBOARD_PROP_TX_DSP_NAMES:
- case MBOARD_PROP_RX_DBOARD:
- case MBOARD_PROP_RX_DBOARD_NAMES:
- case MBOARD_PROP_TX_DBOARD:
- case MBOARD_PROP_TX_DBOARD_NAMES:
+ case MBOARD_PROP_STREAM_CMD:
+ issue_ddc_stream_cmd(val.as<stream_cmd_t>());
+ return;
+
+ default:
throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard");
}