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. |