diff options
author | Thomas Tsou <ttsou@vt.edu> | 2010-08-26 12:33:06 -0700 |
---|---|---|
committer | Thomas Tsou <ttsou@vt.edu> | 2010-08-26 12:33:06 -0700 |
commit | 4434e8233fadc4eec81d345a6c4e63922d8c01ab (patch) | |
tree | 392a85fc9f11f230eeb0cc8d0a17fdaa819b74bd /host/lib/usrp/usrp1 | |
parent | 2f3269f359043290fcaa7659e90292919306a8bc (diff) | |
parent | fe7df530e69834e974108d2c3e682f38b8a75524 (diff) | |
download | uhd-4434e8233fadc4eec81d345a6c4e63922d8c01ab.tar.gz uhd-4434e8233fadc4eec81d345a6c4e63922d8c01ab.tar.bz2 uhd-4434e8233fadc4eec81d345a6c4e63922d8c01ab.zip |
Merge branch 'usrp1_next' into usrp1
Diffstat (limited to 'host/lib/usrp/usrp1')
-rw-r--r-- | host/lib/usrp/usrp1/clock_ctrl.cpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/codec_ctrl.cpp | 174 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/codec_ctrl.hpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/dsp_impl.cpp | 30 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/io_impl.cpp | 341 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/mboard_impl.cpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/usrp1_iface.cpp | 12 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/usrp1_impl.cpp | 45 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/usrp1_impl.hpp | 4 |
9 files changed, 354 insertions, 268 deletions
diff --git a/host/lib/usrp/usrp1/clock_ctrl.cpp b/host/lib/usrp/usrp1/clock_ctrl.cpp index c83ad4c68..54f7b0b98 100644 --- a/host/lib/usrp/usrp1/clock_ctrl.cpp +++ b/host/lib/usrp/usrp1/clock_ctrl.cpp @@ -64,7 +64,7 @@ public: rates.push_back(master_clock_rate / div); return rates; #else - return std::vector<double>(1, 64e6); + return std::vector<double>(1, master_clock_rate); #endif } diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 01617de94..6751b9b7e 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -17,6 +17,7 @@ #include "codec_ctrl.hpp" #include "usrp_commands.h" +#include "clock_ctrl.hpp" #include "ad9862_regs.hpp" #include <uhd/types/dict.hpp> #include <uhd/utils/assert.hpp> @@ -43,7 +44,9 @@ const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1); class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl { public: //structors - usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave); + usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + int spi_slave); ~usrp1_codec_ctrl_impl(void); //aux adc and dac control @@ -51,7 +54,7 @@ public: void write_aux_dac(aux_dac_t which, float volts); //duc control - bool set_duc_freq(double freq); + void set_duc_freq(double freq); //pga gain control void set_tx_pga_gain(float); @@ -61,25 +64,26 @@ public: private: usrp1_iface::sptr _iface; + usrp1_clock_ctrl::sptr _clock_ctrl; int _spi_slave; ad9862_regs_t _ad9862_regs; aux_adc_t _last_aux_adc_a, _last_aux_adc_b; void send_reg(boost::uint8_t addr); void recv_reg(boost::uint8_t addr); - //FIXME: poison - double _tx_freq[4]; - unsigned int compute_freq_control_word_9862 (double master_freq, - double target_freq, - double *actual_freq); + double coarse_tune(double codec_rate, double freq); + double fine_tune(double codec_rate, double freq); }; /*********************************************************************** * Codec Control Structors **********************************************************************/ -usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + int spi_slave) { _iface = iface; + _clock_ctrl = clock; _spi_slave = spi_slave; //soft reset @@ -96,15 +100,15 @@ usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_sl _ad9862_regs.byp_buffer_b = 1; _ad9862_regs.buffer_a_pd = 1; _ad9862_regs.buffer_b_pd = 1; - _ad9862_regs.rx_pga_a = 0;//0x1f; //TODO bring under api control - _ad9862_regs.rx_pga_b = 0;//0x1f; //TODO bring under api control + _ad9862_regs.rx_pga_a = 0; + _ad9862_regs.rx_pga_b = 0; _ad9862_regs.rx_twos_comp = 1; _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS; //setup tx side of codec _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH; _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED; - _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control + _ad9862_regs.tx_pga_gain = 199; _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS; _ad9862_regs.interp = ad9862_regs_t::INTERP_4; _ad9862_regs.tx_twos_comp = 1; @@ -152,8 +156,8 @@ usrp1_codec_ctrl_impl::~usrp1_codec_ctrl_impl(void) **********************************************************************/ void usrp1_codec_ctrl_impl::set_tx_pga_gain(float gain) { - int gain_word = int(63*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); - _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 63); + int gain_word = int(255*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min)); + _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 255); this->send_reg(16); } @@ -324,118 +328,102 @@ void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr) /*********************************************************************** * DUC tuning **********************************************************************/ -unsigned int usrp1_codec_ctrl_impl::compute_freq_control_word_9862( - double master_freq, double target_freq, double *actual_freq) +double usrp1_codec_ctrl_impl::coarse_tune(double codec_rate, double freq) { - double sign = 1.0; - - if (target_freq < 0) - sign = -1.0; - - int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0)); - *actual_freq = v * master_freq / pow (2.0, 24.0) * sign; - - std::cout << boost::format( - "compute_freq_control_word_9862: target = %g actual = %g delta = %g v = %8d\n" - ) % target_freq % *actual_freq % (*actual_freq - target_freq) % v; - - return (unsigned int) v; -} + double coarse_freq; -bool usrp1_codec_ctrl_impl::set_duc_freq(double freq) -{ - int channel = 0; - float dac_rate = 128e6; - - double coarse; - - std::cout << "duc_freq: " << freq << std::endl; - - // First coarse frequency - double coarse_freq_1 = dac_rate / 8; - // Second coarse frequency - double coarse_freq_2 = dac_rate / 4; - // Midpoint of [0 , freq1] range + double coarse_freq_1 = codec_rate / 8; + double coarse_freq_2 = codec_rate / 4; double coarse_limit_1 = coarse_freq_1 / 2; - // Midpoint of [freq1 , freq2] range double coarse_limit_2 = (coarse_freq_1 + coarse_freq_2) / 2; - // Highest meaningful frequency - double high_limit = (double) 44e6 / 128e6 * dac_rate; + double max_freq = coarse_freq_2 + .09375 * codec_rate; - if (freq < -high_limit) { // too low + if (freq < -max_freq) { return false; } - else if (freq < -coarse_limit_2) { // For 64MHz: [-44, -24) + else if (freq < -coarse_limit_2) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; - coarse = -coarse_freq_2; + coarse_freq = -coarse_freq_2; } - else if (freq < -coarse_limit_1) { // For 64MHz: [-24, -8) + else if (freq < -coarse_limit_1) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; - coarse = -coarse_freq_1; + coarse_freq = -coarse_freq_1; } - else if (freq < coarse_limit_1) { // For 64MHz: [-8, 8) + else if (freq < coarse_limit_1) { _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; - coarse = 0; + coarse_freq = 0; } - else if (freq < coarse_limit_2) { // For 64MHz: [8, 24) + else if (freq < coarse_limit_2) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; - coarse = coarse_freq_1; + coarse_freq = coarse_freq_1; } - else if (freq <= high_limit) { // For 64MHz: [24, 44] + else if (freq <= max_freq) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; - coarse = coarse_freq_2; + coarse_freq = coarse_freq_2; } - else { // too high - return false; + else { + return 0; } - - double fine = freq - coarse; - - // Compute fine tuning word... - // This assumes we're running the 4x on-chip interpolator. - // (This is required to use the fine modulator.) - - unsigned int v = compute_freq_control_word_9862 (dac_rate / 4, fine, - &_tx_freq[channel]); - - _tx_freq[channel] += coarse; // adjust actual - - boost::uint8_t high; - boost::uint8_t mid; - boost::uint8_t low; - - high = (v >> 16) & 0xff; - mid = (v >> 8) & 0xff; - low = (v >> 0) & 0xff; - - // write the fine tuning word - _ad9862_regs.ftw_23_16 = high; - _ad9862_regs.ftw_15_8 = mid; - _ad9862_regs.ftw_7_0 = low; - - _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; - - if (fine < 0) + + return coarse_freq; +} + +double usrp1_codec_ctrl_impl::fine_tune(double codec_rate, double target_freq) +{ + static const double scale_factor = std::pow(2.0, 24); + + boost::uint32_t freq_word = boost::uint32_t( + boost::math::round(abs((target_freq / codec_rate) * scale_factor))); + + double actual_freq = freq_word * codec_rate / scale_factor; + + if (target_freq < 0) { _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_NEG_SHIFT; - else + actual_freq = -actual_freq; + } + else { _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_POS_SHIFT; - + } + + _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; + _ad9862_regs.ftw_23_16 = (freq_word >> 16) & 0xff; + _ad9862_regs.ftw_15_8 = (freq_word >> 8) & 0xff; + _ad9862_regs.ftw_7_0 = (freq_word >> 0) & 0xff; + + return actual_freq; +} + +void usrp1_codec_ctrl_impl::set_duc_freq(double freq) +{ + double codec_rate = _clock_ctrl->get_master_clock_freq() * 2; + double coarse_freq = coarse_tune(codec_rate, freq); + double fine_freq = fine_tune(codec_rate / 4, freq - coarse_freq); + + if (codec_debug) { + std::cout << "ad9862 tuning result:" << std::endl; + std::cout << " requested: " << freq << std::endl; + std::cout << " actual: " << coarse_freq + fine_freq << std::endl; + std::cout << " coarse freq: " << coarse_freq << std::endl; + std::cout << " fine freq: " << fine_freq << std::endl; + std::cout << " codec rate: " << codec_rate << std::endl; + } + this->send_reg(20); this->send_reg(21); this->send_reg(22); this->send_reg(23); - - return true; } /*********************************************************************** * Codec Control Make **********************************************************************/ -usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + int spi_slave) { - return sptr(new usrp1_codec_ctrl_impl(iface, spi_slave)); + return sptr(new usrp1_codec_ctrl_impl(iface, clock, spi_slave)); } diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 6440f97d1..259d10ef4 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -19,6 +19,7 @@ #define INCLUDED_USRP1_CODEC_CTRL_HPP #include "usrp1_iface.hpp" +#include "clock_ctrl.hpp" #include <uhd/types/ranges.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> @@ -41,7 +42,9 @@ public: * \param spi_slave which spi device * \return the clock control object */ - static sptr make(usrp1_iface::sptr iface, int spi_slave); + static sptr make(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, int spi_slave + ); //! aux adc identifier constants enum aux_adc_t{ @@ -87,7 +90,8 @@ public: //! Get the RX PGA gain ('A' or 'B') virtual float get_rx_pga_gain(char which) = 0; - virtual bool set_duc_freq(double freq) = 0; + //! Set the TX modulator frequency + virtual void set_duc_freq(double freq) = 0; }; #endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 0db3cb473..ddd1e811b 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -73,31 +73,13 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) /*********************************************************************** * RX DDC Set **********************************************************************/ -unsigned int compute_freq_word(double master, double target) -{ - static const int NBITS = 14; - int v = (int) rint (target / master * pow(2.0, 32.0)); - - if (0) - v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS - - double actual_freq = v * master / pow(2.0, 32.0); - - if (0) std::cerr << boost::format( - "compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n" - ) % target % actual_freq % (actual_freq - target); - - return (unsigned int) v; -} - void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as<dsp_prop_t>()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as<double>(); - boost::uint32_t hw_freq_word = compute_freq_word( - _clock_ctrl->get_master_clock_freq(), new_freq); - _iface->poke32(FR_RX_FREQ_0, hw_freq_word); + _iface->poke32(FR_RX_FREQ_0, + -dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_master_clock_freq())); _tx_dsp_freq = new_freq; return; } @@ -113,6 +95,8 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) } _rx_dsp_decim = rate; + _rx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() / rate; + _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1); } return; @@ -173,15 +157,15 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as<dsp_prop_t>()) { + // TODO: Set both codec frequencies until we have duality properties case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as<double>(); _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); + _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq); _tx_dsp_freq = new_freq; return; } - //TODO freq prop secondary: DBOARD_SLOT_B codec... - case DSP_PROP_HOST_RATE: { unsigned int rate = _clock_ctrl->get_master_clock_freq() * 2 / val.as<double>(); @@ -193,6 +177,8 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) } _tx_dsp_interp = rate; + _tx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate; + _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1); return; } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 3f3e74b80..5e206b3d5 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,37 +33,67 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -/* - * The FX2 firmware bursts data to the FPGA in 512 byte chunks so - * maintain send state to make sure that happens. - */ struct usrp1_send_state { uhd::transport::managed_send_buffer::sptr send_buff; - size_t bytes_used; - size_t bytes_free; + size_t bytes_written; + size_t underrun_poll_samp_count; + + size_t bytes_free() + { + if (send_buff != NULL) + return send_buff->size() - bytes_written; + else + return 0; + } +}; + +struct usrp1_recv_state { + uhd::transport::managed_recv_buffer::sptr recv_buff; + size_t bytes_read; + size_t overrun_poll_samp_count; + + size_t bytes_avail() + { + if (recv_buff != NULL) + return recv_buff->size() - bytes_read; + else + return 0; + } }; /*********************************************************************** * IO Implementation Details **********************************************************************/ struct usrp1_impl::io_impl { - io_impl(zero_copy_if::sptr zc_if); + io_impl(); ~io_impl(void); - bool get_recv_buff(managed_recv_buffer::sptr buff); - - //state management for the vrt packet handler code - vrt_packet_handler::recv_state packet_handler_recv_state; + //state handling for buffer management + usrp1_recv_state recv_state; usrp1_send_state send_state; - zero_copy_if::sptr data_transport; - unsigned int count; + //send transport management + bool get_send_buffer(zero_copy_if::sptr zc_if); + size_t copy_convert_send_samps(const void *buff, size_t num_samps, + size_t sample_offset, const io_type_t io_type, + otw_type_t otw_type); + bool conditional_buff_commit(bool force); + bool check_underrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, bool force); + + //recv transport management + bool get_recv_buffer(zero_copy_if::sptr zc_if); + size_t copy_convert_recv_samps(void *buff, size_t num_samps, + size_t sample_offset, const io_type_t io_type, + otw_type_t otw_type); + bool check_overrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, bool force); }; -usrp1_impl::io_impl::io_impl(zero_copy_if::sptr zc_if) - : packet_handler_recv_state(1), data_transport(zc_if), count(0) +usrp1_impl::io_impl::io_impl() { - /* NOP */ + send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); + recv_state.recv_buff = uhd::transport::managed_recv_buffer::sptr(); } usrp1_impl::io_impl::~io_impl(void) @@ -81,12 +111,92 @@ void usrp1_impl::io_init(void) _tx_otw_type.shift = 0; _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); + _io_impl = UHD_PIMPL_MAKE(io_impl, ()); } /*********************************************************************** * Data Send **********************************************************************/ +bool usrp1_impl::io_impl::get_send_buffer(zero_copy_if::sptr zc_if) +{ + if (send_state.send_buff == NULL) { + + send_state.send_buff = zc_if->get_send_buff(); + if (send_state.send_buff == NULL) + return false; + + send_state.bytes_written = 0; + } + + return true; +} + +size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff, + size_t num_samps, + size_t sample_offset, + const io_type_t io_type, + otw_type_t otw_type) +{ + UHD_ASSERT_THROW(send_state.bytes_free() % otw_type.get_sample_size() == 0); + + size_t samps_free = send_state.bytes_free() / otw_type.get_sample_size(); + size_t copy_samps = std::min(num_samps - sample_offset, samps_free); + + const boost::uint8_t *io_mem = + reinterpret_cast<const boost::uint8_t *>(buff); + + boost::uint8_t *otw_mem = send_state.send_buff->cast<boost::uint8_t *>(); + + convert_io_type_to_otw_type(io_mem + sample_offset * io_type.size, + io_type, + otw_mem + send_state.bytes_written, + otw_type, + copy_samps); + + send_state.bytes_written += copy_samps * otw_type.get_sample_size(); + send_state.underrun_poll_samp_count += copy_samps; + + return copy_samps; +} + +bool usrp1_impl::io_impl::conditional_buff_commit(bool force) +{ + if (send_state.bytes_written % 512) + return false; + + if (force || send_state.bytes_free() == 0) { + send_state.send_buff->commit(send_state.bytes_written); + send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); + return true; + } + + return false; +} + +bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, + bool force) +{ + unsigned char underrun = 0; + + bool ready_to_poll = send_state.underrun_poll_samp_count > poll_interval; + + if (force || ready_to_poll) { + int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, + 0, + GS_TX_UNDERRUN, + &underrun, sizeof(char)); + if (ret < 0) + std::cerr << "USRP: underrun check failed" << std::endl; + if (underrun) + std::cerr << "U" << std::endl; + + send_state.underrun_poll_samp_count = 0; + } + + return (bool) underrun; +} + size_t usrp1_impl::send(const std::vector<const void *> &buffs, size_t num_samps, const tx_metadata_t &, @@ -98,54 +208,21 @@ size_t usrp1_impl::send(const std::vector<const void *> &buffs, size_t total_samps_sent = 0; while (total_samps_sent < num_samps) { - - if (_io_impl->send_state.send_buff == NULL) { - _io_impl->send_state.send_buff = _data_transport->get_send_buff(); - if (_io_impl->send_state.send_buff == NULL) { - return 0; - } - _io_impl->send_state.bytes_used = 0; - _io_impl->send_state.bytes_free = _io_impl->send_state.send_buff->size(); - } - - size_t copy_samps = - std::min(num_samps - total_samps_sent, _io_impl->send_state.bytes_free / _tx_otw_type.get_sample_size()); - - const boost::uint8_t *io_mem = - reinterpret_cast<const boost::uint8_t *>(buffs[0]); - - boost::uint8_t *otw_mem = _io_impl->send_state.send_buff->cast<boost::uint8_t *>(); - - // Type conversion and copy - convert_io_type_to_otw_type( - io_mem + total_samps_sent * io_type.size, - io_type, - otw_mem + _io_impl->send_state.bytes_used, - _tx_otw_type, - copy_samps); - - _io_impl->send_state.bytes_used += copy_samps * _tx_otw_type.get_sample_size(); - _io_impl->send_state.bytes_free -= copy_samps * _tx_otw_type.get_sample_size(); - - if (_io_impl->send_state.bytes_free == 0) { - _io_impl->send_state.send_buff->commit(_io_impl->send_state.bytes_used); - _io_impl->send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); - } - - total_samps_sent += copy_samps; - - //check for underruns - if (!(_io_impl->count++ % 1000)) { - unsigned char underrun; - int ret = _ctrl_transport->usrp_control_read(VRQ_GET_STATUS, - 0, - GS_TX_UNDERRUN, - &underrun, sizeof(char)); - if (ret < 0) - std::cerr << "error: underrun check failed" << std::endl; - if (underrun) - std::cerr << "U" << std::endl; - } + if (!_io_impl->get_send_buffer(_data_transport)) + return 0; + + total_samps_sent += _io_impl->copy_convert_send_samps(buffs[0], + num_samps, + total_samps_sent, + io_type, + _tx_otw_type); + if (total_samps_sent == num_samps) + _io_impl->conditional_buff_commit(true); + else + _io_impl->conditional_buff_commit(false); + + _io_impl->check_underrun(_ctrl_transport, + _tx_samps_per_poll_interval, false); } return total_samps_sent; @@ -154,17 +231,70 @@ size_t usrp1_impl::send(const std::vector<const void *> &buffs, /*********************************************************************** * Data Recv **********************************************************************/ -void _recv_helper(vrt_packet_handler::recv_state &state) +bool usrp1_impl::io_impl::get_recv_buffer(zero_copy_if::sptr zc_if) { - size_t num_packet_words32 = - state.managed_buffs[0]->size() / sizeof(boost::uint32_t); + if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail() == 0)) { - const boost::uint32_t *data = - state.managed_buffs[0]->cast<const boost::uint32_t *>(); + recv_state.recv_buff = zc_if->get_recv_buff(); + if (recv_state.recv_buff == NULL) + return false; + + recv_state.bytes_read = 0; + } - state.copy_buffs[0] = reinterpret_cast<const boost::uint8_t *>(data); - size_t num_payload_bytes = num_packet_words32 * sizeof(boost::uint32_t); - state.size_of_copy_buffs = num_payload_bytes; + return true; +} + +size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff, + size_t num_samps, + size_t sample_offset, + const io_type_t io_type, + otw_type_t otw_type) +{ + UHD_ASSERT_THROW(recv_state.bytes_avail() % otw_type.get_sample_size() == 0); + + size_t samps_avail = recv_state.bytes_avail() / otw_type.get_sample_size(); + size_t copy_samps = std::min(num_samps - sample_offset, samps_avail); + + const boost::uint8_t *otw_mem = + recv_state.recv_buff->cast<const boost::uint8_t *>(); + + boost::uint8_t *io_mem = reinterpret_cast<boost::uint8_t *>(buff); + + convert_otw_type_to_io_type(otw_mem + recv_state.bytes_read, + otw_type, + io_mem + sample_offset * io_type.size, + io_type, + copy_samps); + + recv_state.bytes_read += copy_samps * otw_type.get_sample_size(); + recv_state.overrun_poll_samp_count += copy_samps; + + return copy_samps; +} + +bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, + bool force) +{ + unsigned char overrun = 0; + + bool ready_to_poll = recv_state.overrun_poll_samp_count > poll_interval; + + if (force || ready_to_poll) { + int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, + 0, + GS_RX_OVERRUN, + &overrun, sizeof(char)); + if (ret < 0) + std::cerr << "USRP: overrrun check failed" << std::endl; + if (overrun) + std::cerr << "O" << std::endl; + + recv_state.overrun_poll_samp_count = 0; + } + + return (bool) overrun; } size_t usrp1_impl::recv(const std::vector<void *> &buffs, @@ -174,56 +304,23 @@ size_t usrp1_impl::recv(const std::vector<void *> &buffs, recv_mode_t, size_t) { - UHD_ASSERT_THROW(_io_impl->packet_handler_recv_state.width == 1); UHD_ASSERT_THROW(buffs.size() == 1); - size_t sent_samps = 0; - size_t nsamps_to_copy = 0;; - - while (sent_samps < num_samps) { - if (_io_impl->packet_handler_recv_state.size_of_copy_buffs == 0) { - _io_impl->packet_handler_recv_state.fragment_offset_in_samps = 0; - _io_impl->packet_handler_recv_state.managed_buffs[0] = - _io_impl->data_transport->get_recv_buff(); - - //timeout or something bad returns zero - if (!_io_impl->packet_handler_recv_state.managed_buffs[0].get()) - return 0; - - _recv_helper(_io_impl->packet_handler_recv_state); - } - - size_t bytes_per_item = _rx_otw_type.get_sample_size(); - size_t nsamps_available = - _io_impl->packet_handler_recv_state.size_of_copy_buffs / bytes_per_item; - nsamps_to_copy = std::min(num_samps, nsamps_available); - size_t bytes_to_copy = nsamps_to_copy * bytes_per_item; - - convert_otw_type_to_io_type( - _io_impl->packet_handler_recv_state.copy_buffs[0], - _rx_otw_type, - reinterpret_cast<boost::uint8_t *>(buffs[0]) + sent_samps * io_type.size, - io_type, - nsamps_to_copy); - - _io_impl->packet_handler_recv_state.copy_buffs[0] += bytes_to_copy; - _io_impl->packet_handler_recv_state.size_of_copy_buffs -= bytes_to_copy; - - sent_samps += nsamps_to_copy; - - //check for overruns - if (!(_io_impl->count++ % 10000)) { - unsigned char overrun; - int ret = _ctrl_transport->usrp_control_read( - VRQ_GET_STATUS, - 0, - GS_RX_OVERRUN, - &overrun, sizeof(char)); - if (ret < 0) - std::cerr << "error: overrun check failed" << std::endl; - if (overrun) - std::cerr << "O" << std::endl; - } + size_t total_samps_recv = 0; + + while (total_samps_recv < num_samps) { + + if (!_io_impl->get_recv_buffer(_data_transport)) + return 0; + + total_samps_recv += _io_impl->copy_convert_recv_samps(buffs[0], + num_samps, + total_samps_recv, + io_type, + _rx_otw_type); + _io_impl->check_overrun(_ctrl_transport, + _rx_samps_per_poll_interval, false); } - return sent_samps; + + return total_samps_recv; } diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index c3343f1f8..74ec514ff 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -114,7 +114,7 @@ static boost::uint32_t calc_tx_mux( //calculate the channel flags int channel_flags = 0, chan = 0; BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){ - wax::obj dboard = mboard[named_prop_t(MBOARD_PROP_RX_DBOARD, pair.db_name)]; + wax::obj dboard = mboard[named_prop_t(MBOARD_PROP_TX_DBOARD, pair.db_name)]; wax::obj subdev = dboard[named_prop_t(DBOARD_PROP_SUBDEV, pair.sd_name)]; subdev_conn_t conn = subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>(); @@ -298,7 +298,7 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) case MBOARD_PROP_RX_SUBDEV_SPEC: _rx_subdev_spec = val.as<subdev_spec_t>(); - verify_rx_subdev_spec(_rx_subdev_spec, this->get_link()); + verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link()); //sanity check UHD_ASSERT_THROW(_rx_subdev_spec.size() <= 2); //set the mux and set the number of rx channels @@ -307,7 +307,7 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) case MBOARD_PROP_TX_SUBDEV_SPEC: _tx_subdev_spec = val.as<subdev_spec_t>(); - verify_tx_subdev_spec(_tx_subdev_spec, this->get_link()); + verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link()); //sanity check UHD_ASSERT_THROW(_tx_subdev_spec.size() <= 2); //set the mux and set the number of tx channels diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index b175ba21f..9d326d6bd 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -53,7 +53,8 @@ public: if (iface_debug) { std::cout.fill('0'); - std::cout << "poke32(" << std::dec << addr << ", 0x"; + std::cout << "poke32("; + std::cout << std::dec << std::setw(2) << addr << ", 0x"; std::cout << std::hex << std::setw(8) << value << ")" << std::endl; } @@ -129,11 +130,7 @@ public: { UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes); - byte_vector_t out_bytes; - byte_vector_t::iterator it = out_bytes.begin(); - unsigned char buff[max_i2c_data_bytes]; - int ret = _ctrl_transport->usrp_control_read(VRQ_I2C_READ, addr & 0xff, 0, @@ -142,9 +139,10 @@ public: if ((ret < 0) || (unsigned)ret < (num_bytes)) { std::cerr << "USRP: failed i2c read: " << ret << std::endl; - return out_bytes; + return byte_vector_t(num_bytes, 0xff); } + byte_vector_t out_bytes; for (size_t i = 0; i < num_bytes; i++) out_bytes.push_back(buff[i]); @@ -168,7 +166,7 @@ public: size_t num_bits, bool readback) { - UHD_ASSERT_THROW((num_bits < 32) && !(num_bits % 8)); + UHD_ASSERT_THROW((num_bits <= 32) && !(num_bits % 8)); size_t num_bytes = num_bits / 8; // Byteswap on num_bytes diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 33a069bc6..a15d0a244 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -55,13 +55,15 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl; //see what we got on the USB bus - usb_descriptors_t usb_descriptors; - usb_descriptors = usb_control::get_device_list(); + std::vector<usb_device_handle::sptr> device_list = + usb_device_handle::get_device_list(); //find the usrps and load firmware - BOOST_FOREACH(usb_descriptor_t desc, usb_descriptors) { - if (desc.vendor_id == 0xfffe && desc.product_id == 0x0002) { - usb_control::sptr ctrl_transport = usb_control::make(desc); + BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + if (handle->get_vendor_id() == 0xfffe && + handle->get_product_id() == 0x0002) { + + usb_control::sptr ctrl_transport = usb_control::make(handle); usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_firmware(usrp1_fw_image); } @@ -71,13 +73,15 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) boost::this_thread::sleep(boost::posix_time::milliseconds(500)); //get descriptors again with serial number - usb_descriptors = usb_control::get_device_list(); + device_list = usb_device_handle::get_device_list(); + + BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + if (handle->get_vendor_id() == 0xfffe && + handle->get_product_id() == 0x0002) { - BOOST_FOREACH(usb_descriptor_t desc, usb_descriptors) { - if (desc.vendor_id == 0xfffe && desc.product_id == 0x0002) { device_addr_t new_addr; new_addr["type"] = "usrp1"; - new_addr["serial"] = desc.serial; + new_addr["serial"] = handle->get_serial(); usrp1_addrs.push_back(new_addr); } } @@ -97,22 +101,23 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) std::cout << "USRP1 FPGA image: " << usrp1_fpga_image << std::endl; //try to match the given device address with something on the USB bus - usb_descriptors_t usb_descriptors; - usb_descriptors = usb_control::get_device_list(); + std::vector<usb_device_handle::sptr> device_list = + usb_device_handle::get_device_list(); //create data and control transports usb_zero_copy::sptr data_transport; usrp_ctrl::sptr usrp_ctrl; - BOOST_FOREACH(usb_descriptor_t desc, usb_descriptors) { - if (desc.serial == device_addr["serial"] - && desc.vendor_id == 0xfffe && desc.product_id == 0x0002) { + BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + if (handle->get_vendor_id() == 0xfffe && + handle->get_product_id() == 0x0002 && + handle->get_serial() == device_addr["serial"]) { - usb_control::sptr ctrl_transport = usb_control::make(desc); + 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(desc, // identifier + data_transport = usb_zero_copy::make(handle, // identifier 6, // IN endpoint 2, // OUT endpoint 2 * (1 << 20), // buffer size @@ -142,8 +147,12 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, _clock_ctrl = usrp1_clock_ctrl::make(_iface); //create codec interface - _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_A); - _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_B); + _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make( + _iface, _clock_ctrl, SPI_ENABLE_CODEC_A + ); + _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make( + _iface, _clock_ctrl, SPI_ENABLE_CODEC_B + ); //initialize the codecs codec_init(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index cbd3d5315..4b4ac51dd 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -120,6 +120,10 @@ private: void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); void handle_overrun(size_t); + //underrun and overrun poll intervals + size_t _rx_samps_per_poll_interval; + size_t _tx_samps_per_poll_interval; + //otw types uhd::otw_type_t _rx_otw_type; uhd::otw_type_t _tx_otw_type; |