From ae9e89d76b2eb86a29995f04aaab1aa59ee93f04 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Sun, 16 Oct 2011 10:43:48 -0700
Subject: usrp: added get_tx/rx_rates

---
 host/lib/usrp/b100/b100_impl.cpp        |  4 ++++
 host/lib/usrp/cores/rx_dsp_core_200.cpp | 21 ++++++++++++++++-----
 host/lib/usrp/cores/rx_dsp_core_200.hpp |  2 ++
 host/lib/usrp/cores/tx_dsp_core_200.cpp | 21 ++++++++++++++++-----
 host/lib/usrp/cores/tx_dsp_core_200.hpp |  2 ++
 host/lib/usrp/e100/e100_impl.cpp        |  4 ++++
 host/lib/usrp/multi_usrp.cpp            |  8 ++++++++
 host/lib/usrp/usrp1/io_impl.cpp         | 27 ++++++++++++++++++++++-----
 host/lib/usrp/usrp1/usrp1_impl.cpp      |  8 ++++++--
 host/lib/usrp/usrp1/usrp1_impl.hpp      |  2 ++
 host/lib/usrp/usrp2/usrp2_impl.cpp      |  4 ++++
 11 files changed, 86 insertions(+), 17 deletions(-)

(limited to 'host/lib/usrp')

diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp
index d1928735b..bb91d415d 100644
--- a/host/lib/usrp/b100/b100_impl.cpp
+++ b/host/lib/usrp/b100/b100_impl.cpp
@@ -296,6 +296,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
         _tree->access<double>(mb_path / "tick_rate")
             .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1));
         fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);
+        _tree->create<meta_range_t>(rx_dsp_path / "rate/range")
+            .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno]));
         _tree->create<double>(rx_dsp_path / "rate/value")
             .set(1e6) //some default
             .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1))
@@ -317,6 +319,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
     _tx_dsp->set_link_rate(B100_LINK_RATE_BPS);
     _tree->access<double>(mb_path / "tick_rate")
         .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1));
+    _tree->create<meta_range_t>(mb_path / "tx_dsps/0/rate/range")
+        .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp));
     _tree->create<double>(mb_path / "tx_dsps/0/rate/value")
         .set(1e6) //some default
         .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1))
diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp
index b121bc849..6d306d507 100644
--- a/host/lib/usrp/cores/rx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp
@@ -134,12 +134,23 @@ public:
         _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc)
     }
 
+    uhd::meta_range_t get_host_rates(void){
+        meta_range_t range;
+        for (int rate = 512; rate > 256; rate -= 4){
+            range.push_back(range_t(_tick_rate/rate));
+        }
+        for (int rate = 256; rate > 128; rate -= 2){
+            range.push_back(range_t(_tick_rate/rate));
+        }
+        for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){
+            range.push_back(range_t(_tick_rate/rate));
+        }
+        return range;
+    }
+
     double set_host_rate(const double rate){
-        size_t decim_rate = uhd::clip<size_t>(
-            boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512
-        );
-        if (decim_rate > 128) decim_rate &= ~0x1; //CIC up to 128, have to use 1 HB
-        if (decim_rate > 256) decim_rate &= ~0x3; //CIC up to 128, have to use 2 HB
+        const size_t decim_rate = this->get_host_rates().clip(
+            boost::math::iround(_tick_rate/rate), true);
         size_t decim = decim_rate;
 
         //determine which half-band filters are activated
diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp
index ddd6f2abf..89b8c1f51 100644
--- a/host/lib/usrp/cores/rx_dsp_core_200.hpp
+++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp
@@ -48,6 +48,8 @@ public:
 
     virtual double set_host_rate(const double rate) = 0;
 
+    virtual uhd::meta_range_t get_host_rates(void) = 0;
+
     virtual double get_scaling_adjustment(void) = 0;
 
     virtual uhd::meta_range_t get_freq_range(void) = 0;
diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp
index f37b53527..1d571ea7c 100644
--- a/host/lib/usrp/cores/tx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp
@@ -74,12 +74,23 @@ public:
         _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc)
     }
 
+    uhd::meta_range_t get_host_rates(void){
+        meta_range_t range;
+        for (int rate = 512; rate > 256; rate -= 4){
+            range.push_back(range_t(_tick_rate/rate));
+        }
+        for (int rate = 256; rate > 128; rate -= 2){
+            range.push_back(range_t(_tick_rate/rate));
+        }
+        for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){
+            range.push_back(range_t(_tick_rate/rate));
+        }
+        return range;
+    }
+
     double set_host_rate(const double rate){
-        size_t interp_rate = uhd::clip<size_t>(
-            boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512
-        );
-        if (interp_rate > 128) interp_rate &= ~0x1; //CIC up to 128, have to use 1 HB
-        if (interp_rate > 256) interp_rate &= ~0x3; //CIC up to 128, have to use 2 HB
+        const size_t interp_rate = this->get_host_rates().clip(
+            boost::math::iround(_tick_rate/rate), true);
         size_t interp = interp_rate;
 
         //determine which half-band filters are activated
diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp
index 65f822558..e6be63557 100644
--- a/host/lib/usrp/cores/tx_dsp_core_200.hpp
+++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp
@@ -40,6 +40,8 @@ public:
 
     virtual double set_host_rate(const double rate) = 0;
 
+    virtual uhd::meta_range_t get_host_rates(void) = 0;
+
     virtual uhd::meta_range_t get_freq_range(void) = 0;
 
     virtual double set_freq(const double freq) = 0;
diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp
index deb52b2d7..6cb404000 100644
--- a/host/lib/usrp/e100/e100_impl.cpp
+++ b/host/lib/usrp/e100/e100_impl.cpp
@@ -270,6 +270,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){
         _tree->access<double>(mb_path / "tick_rate")
             .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1));
         fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);
+        _tree->create<meta_range_t>(rx_dsp_path / "rate/range")
+            .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno]));
         _tree->create<double>(rx_dsp_path / "rate/value")
             .set(1e6) //some default
             .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1))
@@ -291,6 +293,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){
     _tx_dsp->set_link_rate(E100_TX_LINK_RATE_BPS);
     _tree->access<double>(mb_path / "tick_rate")
         .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1));
+    _tree->create<meta_range_t>(mb_path / "tx_dsps/0/rate/range")
+        .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp));
     _tree->create<double>(mb_path / "tx_dsps/0/rate/value")
         .set(1e6) //some default
         .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1))
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index ab841487f..97c5ea630 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -477,6 +477,10 @@ public:
         return _tree->access<double>(rx_dsp_root(chan) / "rate" / "value").get();
     }
 
+    meta_range_t get_rx_rates(size_t chan){
+        return _tree->access<meta_range_t>(rx_dsp_root(chan) / "rate" / "range").get();
+    }
+
     tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){
         tune_result_t r = tune_xx_subdev_and_dsp(RX_SIGN, _tree->subtree(rx_dsp_root(chan)), _tree->subtree(rx_rf_fe_root(chan)), tune_request);
         do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX");
@@ -587,6 +591,10 @@ public:
         return _tree->access<double>(tx_dsp_root(chan) / "rate" / "value").get();
     }
 
+    meta_range_t get_tx_rates(size_t chan){
+        return _tree->access<meta_range_t>(tx_dsp_root(chan) / "rate" / "range").get();
+    }
+
     tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){
         tune_result_t r = tune_xx_subdev_and_dsp(TX_SIGN, _tree->subtree(tx_dsp_root(chan)), _tree->subtree(tx_rf_fe_root(chan)), tune_request);
         do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX");
diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp
index 12950d385..31c834109 100644
--- a/host/lib/usrp/usrp1/io_impl.cpp
+++ b/host/lib/usrp/usrp1/io_impl.cpp
@@ -442,7 +442,6 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){
     this->restore_tx(s);
 }
 
-
 void usrp1_impl::update_tick_rate(const double rate){
     //updating this variable should:
     //update dboard iface -> it has a reference
@@ -450,11 +449,29 @@ void usrp1_impl::update_tick_rate(const double rate){
     _master_clock_rate = rate;
 }
 
+uhd::meta_range_t usrp1_impl::get_rx_dsp_host_rates(void){
+    meta_range_t range;
+    const size_t div = this->has_rx_halfband()? 2 : 1;
+    for (int rate = 256; rate >= 4; rate -= div){
+        range.push_back(range_t(_master_clock_rate/rate));
+    }
+    return range;
+}
+
+uhd::meta_range_t usrp1_impl::get_tx_dsp_host_rates(void){
+    meta_range_t range;
+    const size_t div = this->has_tx_halfband()? 2 : 1;
+    for (int rate = 256; rate >= 8; rate -= div){
+        range.push_back(range_t(_master_clock_rate/rate));
+    }
+    return range;
+}
+
 double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){
 
     const size_t div = this->has_rx_halfband()? 2 : 1;
-    const size_t rate = uhd::clip<size_t>(
-        boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1);
+    const size_t rate = this->get_rx_dsp_host_rates().clip(
+        boost::math::iround(_master_clock_rate / samp_rate), true);
 
     if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) <<
         "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n"
@@ -482,8 +499,8 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){
 double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){
 
     const size_t div = this->has_tx_halfband()? 2 : 1;
-    const size_t rate = uhd::clip<size_t>(
-        boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1);
+    const size_t rate = this->get_tx_dsp_host_rates().clip(
+        boost::math::iround(_master_clock_rate / samp_rate), true);
 
     if (dspno == 0){ //only care if dsp0 is set since its homogeneous
         bool s = this->disable_tx();
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 5788c536f..1a61f8136 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -283,8 +283,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){
     _tree->create<int>(mb_path / "rx_dsps"); //dummy in case we have none
     for (size_t dspno = 0; dspno < get_num_ddcs(); dspno++){
         fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);
+        _tree->create<meta_range_t>(rx_dsp_path / "rate/range")
+            .publish(boost::bind(&usrp1_impl::get_rx_dsp_host_rates, this));
         _tree->create<double>(rx_dsp_path / "rate/value")
-            .set(1e6)
+            .set(1e6) //some default rate
             .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, dspno, _1));
         _tree->create<double>(rx_dsp_path / "freq/value")
             .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1));
@@ -304,8 +306,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){
     _tree->create<int>(mb_path / "tx_dsps"); //dummy in case we have none
     for (size_t dspno = 0; dspno < get_num_ducs(); dspno++){
         fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno);
+        _tree->create<meta_range_t>(tx_dsp_path / "rate/range")
+            .publish(boost::bind(&usrp1_impl::get_tx_dsp_host_rates, this));
         _tree->create<double>(tx_dsp_path / "rate/value")
-            .set(1e6)
+            .set(1e6) //some default rate
             .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1));
         _tree->create<double>(tx_dsp_path / "freq/value")
             .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1));
diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp
index 6f427c31e..ec313daf6 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.hpp
@@ -98,6 +98,8 @@ private:
     void update_tick_rate(const double rate);
     uhd::meta_range_t get_rx_dsp_freq_range(void);
     uhd::meta_range_t get_tx_dsp_freq_range(void);
+    uhd::meta_range_t get_rx_dsp_host_rates(void);
+    uhd::meta_range_t get_tx_dsp_host_rates(void);
 
     static uhd::usrp::dboard_iface::sptr make_dboard_iface(
         usrp1_iface::sptr,
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 2d89ddaf4..24178d10c 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -480,6 +480,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
             _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering
             _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected
             fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);
+            _tree->create<meta_range_t>(rx_dsp_path / "rate/range")
+                .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _mbc[mb].rx_dsps[dspno]));
             _tree->create<double>(rx_dsp_path / "rate/value")
                 .set(1e6) //some default
                 .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], _1))
@@ -501,6 +503,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
         _mbc[mb].tx_dsp->set_link_rate(USRP2_LINK_RATE_BPS);
         _tree->access<double>(mb_path / "tick_rate")
             .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1));
+        _tree->create<meta_range_t>(mb_path / "tx_dsps/0/rate/range")
+            .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _mbc[mb].tx_dsp));
         _tree->create<double>(mb_path / "tx_dsps/0/rate/value")
             .set(1e6) //some default
             .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1))
-- 
cgit v1.2.3