diff options
| -rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 149 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 3 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 81 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 35 | 
4 files changed, 131 insertions, 137 deletions
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index c83565875..ef9b5064c 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -28,12 +28,79 @@  using namespace uhd;  using namespace uhd::usrp; -static const size_t default_decim = 16; -static const size_t default_interp = 16; -  /*********************************************************************** - * DDC Helper Methods + * DSP impl and methods   **********************************************************************/ +struct usrp2_mboard_impl::dsp_impl{ +    uhd::dict<size_t, size_t> ddc_decim; +    uhd::dict<size_t, double> ddc_freq; +    uhd::dict<size_t, size_t> duc_interp; +    uhd::dict<size_t, double> duc_freq; +    std::vector<size_t> decim_and_interp_rates; +    uhd::dict<size_t, bool> continuous_streaming; +}; + +void usrp2_mboard_impl::dsp_init(size_t recv_samps_per_packet){ +    //create new dsp impl +    _dsp_impl = UHD_PIMPL_MAKE(dsp_impl, ()); + +    //load the allowed decim/interp rates +    //range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) +    for (size_t i = 4; i <= 128; i+=1){ +        _dsp_impl->decim_and_interp_rates.push_back(i); +    } +    for (size_t i = 130; i <= 256; i+=2){ +        _dsp_impl->decim_and_interp_rates.push_back(i); +    } +    for (size_t i = 260; i <= 512; i+=4){ +        _dsp_impl->decim_and_interp_rates.push_back(i); +    } + +    //bind and initialize the rx dsps +    for (size_t i = 0; i < NUM_RX_DSPS; i++){ +        _rx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2, i), +            boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2, i) +        ); + +        //initial config and update +        ddc_set(DSP_PROP_FREQ_SHIFT, double(0), i); +        ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i); + +        //setup the rx control registers +        _iface->poke32(_iface->regs.rx_ctrl[i].clear_overrun, 1); //reset +        _iface->poke32(_iface->regs.rx_ctrl[i].nsamps_per_pkt, recv_samps_per_packet); +        _iface->poke32(_iface->regs.rx_ctrl[i].nchannels, 1); +        _iface->poke32(_iface->regs.rx_ctrl[i].vrt_header, 0 +            | (0x1 << 28) //if data with stream id +            | (0x1 << 26) //has trailer +            | (0x3 << 22) //integer time other +            | (0x1 << 20) //fractional time sample count +        ); +        _iface->poke32(_iface->regs.rx_ctrl[i].vrt_stream_id, usrp2_impl::RECV_SID); +        _iface->poke32(_iface->regs.rx_ctrl[i].vrt_trailer, 0); +        _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq())); +    } + +    //bind and initialize the tx dsps +    for (size_t i = 0; i < NUM_TX_DSPS; i++){ +        _tx_dsp_proxies[str(boost::format("DSP%d")%i)] = wax_obj_proxy::make( +            boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2, i), +            boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2, i) +        ); + +        //initial config and update +        duc_set(DSP_PROP_FREQ_SHIFT, double(0), i); +        duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/16), i); + +        //init the tx control registers +        _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset +        _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0);    //1 channel +        _iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID); +        _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); +    } +} +  template <typename rate_type>  static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_type> &rates){      unsigned closest_match = rates.front(); @@ -44,27 +111,28 @@ static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_typ      return closest_match;  } -void usrp2_mboard_impl::init_ddc_config(void){ -    //create the ddc in the rx dsp dict -    _rx_dsp_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2), -        boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2) -    ); +void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd, size_t which_dsp){ +    _dsp_impl->continuous_streaming[which_dsp] = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS; +    _iface->poke32(_iface->regs.rx_ctrl[which_dsp].stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd)); +    _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_secs,  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); +    _iface->poke32(_iface->regs.rx_ctrl[which_dsp].time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); +} -    //initial config and update -    ddc_set(DSP_PROP_FREQ_SHIFT, double(0)); -    ddc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_decim)); +void usrp2_mboard_impl::handle_overflow(size_t which_dsp){ +    if (_dsp_impl->continuous_streaming[which_dsp]){ //re-issue the stream command if already continuous +        this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS, which_dsp); +    }  }  /***********************************************************************   * DDC Properties   **********************************************************************/ -void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME: -        val = _iface->get_cname() + " ddc0"; +        val = str(boost::format("%s ddc%d") % _iface->get_cname() % which_dsp);          return;      case DSP_PROP_OTHERS: @@ -72,7 +140,7 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _ddc_freq; +        val = _dsp_impl->ddc_freq[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -80,41 +148,41 @@ void usrp2_mboard_impl::ddc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_HOST_RATE: -        val = get_master_clock_freq()/_ddc_decim; +        val = get_master_clock_freq()/_dsp_impl->ddc_decim[which_dsp];          return;      default: UHD_THROW_PROP_GET_ERROR();      }  } -void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){ +void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_STREAM_CMD: -        issue_ddc_stream_cmd(val.as<stream_cmd_t>()); +        issue_ddc_stream_cmd(val.as<stream_cmd_t>(), which_dsp);          return;      case DSP_PROP_FREQ_SHIFT:{              double new_freq = val.as<double>(); -            _iface->poke32(_iface->regs.dsp_rx[0].freq, +            _iface->poke32(_iface->regs.dsp_rx[which_dsp].freq,                  dsp_type1::calc_cordic_word_and_update(new_freq, get_master_clock_freq())              ); -            _ddc_freq = new_freq; //shadow +            _dsp_impl->ddc_freq[which_dsp] = new_freq; //shadow          }          return;      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); +            _dsp_impl->ddc_decim[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates);              //set the decimation -            _iface->poke32(_iface->regs.dsp_rx[0].decim_rate, dsp_type1::calc_cic_filter_word(_ddc_decim)); +            _iface->poke32(_iface->regs.dsp_rx[which_dsp].decim_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->ddc_decim[which_dsp]));              //set the scaling              static const boost::int16_t default_rx_scale_iq = 1024; -            _iface->poke32(_iface->regs.dsp_rx[0].scale_iq, +            _iface->poke32(_iface->regs.dsp_rx[which_dsp].scale_iq,                  dsp_type1::calc_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq)              );          } @@ -125,29 +193,14 @@ void usrp2_mboard_impl::ddc_set(const wax::obj &key_, const wax::obj &val){  }  /*********************************************************************** - * DUC Helper Methods - **********************************************************************/ -void usrp2_mboard_impl::init_duc_config(void){ -    //create the duc in the tx dsp dict -    _tx_dsp_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2), -        boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2) -    ); - -    //initial config and update -    duc_set(DSP_PROP_FREQ_SHIFT, double(0)); -    duc_set(DSP_PROP_HOST_RATE, double(get_master_clock_freq()/default_interp)); -} - -/***********************************************************************   * DUC Properties   **********************************************************************/ -void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME: -        val = _iface->get_cname() + " duc0"; +        val = str(boost::format("%s duc%d") % _iface->get_cname() % which_dsp);          return;      case DSP_PROP_OTHERS: @@ -155,7 +208,7 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_FREQ_SHIFT: -        val = _duc_freq; +        val = _dsp_impl->duc_freq[which_dsp];          return;      case DSP_PROP_CODEC_RATE: @@ -163,14 +216,14 @@ void usrp2_mboard_impl::duc_get(const wax::obj &key_, wax::obj &val){          return;      case DSP_PROP_HOST_RATE: -        val = get_master_clock_freq()/_duc_interp; +        val = get_master_clock_freq()/_dsp_impl->duc_interp[which_dsp];          return;      default: UHD_THROW_PROP_GET_ERROR();      }  } -void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){ +void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val, size_t which_dsp){      named_prop_t key = named_prop_t::extract(key_);      switch(key.as<dsp_prop_t>()){ @@ -192,19 +245,19 @@ void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){              _iface->poke32(_iface->regs.dsp_tx_freq,                  dsp_type1::calc_cordic_word_and_update(new_freq, codec_rate)              ); -            _duc_freq = new_freq + dac_shift; //shadow +            _dsp_impl->duc_freq[which_dsp] = new_freq + dac_shift; //shadow          }          return;      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); +            _dsp_impl->duc_interp[which_dsp] = pick_closest_rate(extact_rate, _dsp_impl->decim_and_interp_rates);              //set the interpolation -            _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_duc_interp)); +            _iface->poke32(_iface->regs.dsp_tx_interp_rate, dsp_type1::calc_cic_filter_word(_dsp_impl->duc_interp[which_dsp]));              //set the scaling -            _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_duc_interp)); +            _iface->poke32(_iface->regs.dsp_tx_scale_iq, dsp_type1::calc_iq_scale_word(_dsp_impl->duc_interp[which_dsp]));          }          return; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index acd520b0b..816f1859a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -464,7 +464,8 @@ size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{  static void handle_overflow(std::vector<usrp2_mboard_impl::sptr> &mboards, size_t chan){      std::cerr << "O" << std::flush; -    mboards.at(chan/mboards.size())->handle_overflow(); +    //TODO this is wrong way to determine the index... +    mboards.at(chan/mboards.size())->handle_overflow(chan%mboards.size());  }  size_t usrp2_impl::recv( diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index a3de8673e..d95ad4a7a 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -56,40 +56,8 @@ usrp2_mboard_impl::usrp2_mboard_impl(      //if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl; -    //TODO move to dsp impl... -    //load the allowed decim/interp rates -    //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) -    _allowed_decim_and_interp_rates.clear(); -    for (size_t i = 4; i <= 128; i+=1){ -        _allowed_decim_and_interp_rates.push_back(i); -    } -    for (size_t i = 130; i <= 256; i+=2){ -        _allowed_decim_and_interp_rates.push_back(i); -    } -    for (size_t i = 260; i <= 512; i+=4){ -        _allowed_decim_and_interp_rates.push_back(i); -    } - -    //setup the vrt rx registers -    //TODO loop for 0, 1, in NUM_RX_DSPS -    _iface->poke32(_iface->regs.rx_ctrl[0].clear_overrun, 1); //reset -    _iface->poke32(_iface->regs.rx_ctrl[0].nsamps_per_pkt, recv_samps_per_packet); -    _iface->poke32(_iface->regs.rx_ctrl[0].nchannels, 1); -    _iface->poke32(_iface->regs.rx_ctrl[0].vrt_header, 0 -        | (0x1 << 28) //if data with stream id -        | (0x1 << 26) //has trailer -        | (0x3 << 22) //integer time other -        | (0x1 << 20) //fractional time sample count -    ); -    _iface->poke32(_iface->regs.rx_ctrl[0].vrt_stream_id, usrp2_impl::RECV_SID); -    _iface->poke32(_iface->regs.rx_ctrl[0].vrt_trailer, 0); -    _iface->poke32(_iface->regs.time64_tps, size_t(get_master_clock_freq())); - -    //init the tx control registers -    _iface->poke32(_iface->regs.tx_ctrl_clear_state, 1); //reset -    _iface->poke32(_iface->regs.tx_ctrl_num_chan, 0);    //1 channel -    _iface->poke32(_iface->regs.tx_ctrl_report_sid, usrp2_impl::ASYNC_SID); -    _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); +    //init the dsp stuff (before setting update packets) +    dsp_init(recv_samps_per_packet);      //setting the cycles per update (disabled by default)      const double ups_per_sec = device_args.cast<double>("ups_per_sec", 0.0); @@ -105,12 +73,6 @@ usrp2_mboard_impl::usrp2_mboard_impl(          _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up);      } -    //init the ddc -    init_ddc_config(); - -    //init the duc -    init_duc_config(); -      //initialize the clock configuration      if (device_args.has_key("mimo_mode")){          if (device_args["mimo_mode"] == "master"){ @@ -144,12 +106,14 @@ usrp2_mboard_impl::usrp2_mboard_impl(      (*this)[MBOARD_PROP_TX_SUBDEV_SPEC] = subdev_spec_t();      //This is a hack/fix for the lingering packet problem. +    /*      stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);      stream_cmd.num_samps = 1;      this->issue_ddc_stream_cmd(stream_cmd);      data_transport->get_recv_buff().get(); //recv with timeout for lingering      data_transport->get_recv_buff().get(); //recv with timeout for expected      _iface->poke32(_iface->regs.rx_ctrl[0].clear_overrun, 1); //resets sequence +    */  }  usrp2_mboard_impl::~usrp2_mboard_impl(void){ @@ -250,19 +214,6 @@ void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){      _iface->poke32(_iface->regs.time64_secs, boost::uint32_t(time_spec.get_full_secs()));  } -void usrp2_mboard_impl::handle_overflow(void){ -    if (_continuous_streaming){ //re-issue the stream command if already continuous -        this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); -    } -} - -void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ -    _continuous_streaming = stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS; -    _iface->poke32(_iface->regs.rx_ctrl[0].stream_cmd, dsp_type1::calc_stream_cmd_word(stream_cmd)); -    _iface->poke32(_iface->regs.rx_ctrl[0].time_secs,  boost::uint32_t(stream_cmd.time_spec.get_full_secs())); -    _iface->poke32(_iface->regs.rx_ctrl[0].time_ticks, stream_cmd.time_spec.get_tick_count(get_master_clock_freq())); -} -  /***********************************************************************   * MBoard Get Properties   **********************************************************************/ @@ -299,21 +250,19 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_RX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _rx_dsp_proxy->get_link(); +        val = _rx_dsp_proxies[key.name]->get_link();          return;      case MBOARD_PROP_RX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _rx_dsp_proxies.keys();          return;      case MBOARD_PROP_TX_DSP: -        UHD_ASSERT_THROW(key.name == ""); -        val = _tx_dsp_proxy->get_link(); +        val = _tx_dsp_proxies[key.name]->get_link();          return;      case MBOARD_PROP_TX_DSP_NAMES: -        val = prop_names_t(1, ""); +        val = _tx_dsp_proxies.keys();          return;      case MBOARD_PROP_CLOCK_CONFIG: @@ -380,15 +329,13 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){          _rx_subdev_spec = val.as<subdev_spec_t>();          verify_rx_subdev_spec(_rx_subdev_spec, this->get_link());          //sanity check -        UHD_ASSERT_THROW(_rx_subdev_spec.size() <= 2); +        UHD_ASSERT_THROW(_rx_subdev_spec.size() <= NUM_RX_DSPS);          //set the mux -        if (_rx_subdev_spec.size() >= 1) _iface->poke32(_iface->regs.dsp_rx[0].mux, dsp_type1::calc_rx_mux_word( -            _dboard_manager->get_rx_subdev(_rx_subdev_spec[0].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() -        )); -        //TODO -        //if (_rx_subdev_spec.size() >= 2) _iface->poke32(_iface->regs.dsp1_rx_mux, dsp_type1::calc_rx_mux_word( -        //    _dboard_manager->get_rx_subdev(_rx_subdev_spec[1].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() -        //)); +        for (size_t i = 0; i < _rx_subdev_spec.size(); i++){ +            if (_rx_subdev_spec.size() >= 1) _iface->poke32(_iface->regs.dsp_rx[i].mux, dsp_type1::calc_rx_mux_word( +                _dboard_manager->get_rx_subdev(_rx_subdev_spec[i].sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() +            )); +        }          return;      case MBOARD_PROP_TX_SUBDEV_SPEC: diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 9a406bc87..cb049f876 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -80,6 +80,9 @@ class usrp2_mboard_impl : public wax::obj{  public:      typedef boost::shared_ptr<usrp2_mboard_impl> sptr; +    static const size_t NUM_RX_DSPS = 2; +    static const size_t NUM_TX_DSPS = 1; +      //structors      usrp2_mboard_impl(          size_t index, @@ -95,11 +98,10 @@ public:          return _clock_ctrl->get_master_clock_rate();      } -    void handle_overflow(void); +    void handle_overflow(size_t);  private:      size_t _index; -    bool _continuous_streaming;      bool _mimo_clocking_mode_is_master;      //interfaces @@ -147,27 +149,20 @@ private:      wax_obj_proxy::sptr _tx_dboard_proxy;      uhd::usrp::dboard_eeprom_t _tx_db_eeprom; -    //methods and shadows for the ddc dsp -    std::vector<size_t> _allowed_decim_and_interp_rates; -    size_t _ddc_decim; -    double _ddc_freq; -    void init_ddc_config(void); -    void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd); - -    //methods and shadows for the duc dsp -    size_t _duc_interp; -    double _duc_freq; -    void init_duc_config(void); +    //methods and shadows for the dsps +    UHD_PIMPL_DECL(dsp_impl) _dsp_impl; +    void dsp_init(size_t recv_samps_per_packet); +    void issue_ddc_stream_cmd(const uhd::stream_cmd_t &, size_t);      //properties interface for ddc -    void ddc_get(const wax::obj &, wax::obj &); -    void ddc_set(const wax::obj &, const wax::obj &); -    wax_obj_proxy::sptr _rx_dsp_proxy; +    void ddc_get(const wax::obj &, wax::obj &, size_t); +    void ddc_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<std::string, wax_obj_proxy::sptr> _rx_dsp_proxies;      //properties interface for duc -    void duc_get(const wax::obj &, wax::obj &); -    void duc_set(const wax::obj &, const wax::obj &); -    wax_obj_proxy::sptr _tx_dsp_proxy; +    void duc_get(const wax::obj &, wax::obj &, size_t); +    void duc_set(const wax::obj &, const wax::obj &, size_t); +    uhd::dict<std::string, wax_obj_proxy::sptr> _tx_dsp_proxies;  }; @@ -181,8 +176,6 @@ public:      static const size_t sram_bytes = size_t(1 << 20);      static const boost::uint32_t RECV_SID = 1;      static const boost::uint32_t ASYNC_SID = 2; -    static const size_t NUM_RX_DSPS = 2; -    static const size_t NUM_TX_DSPS = 1;      /*!       * Create a new usrp2 impl base.  | 
