From 9cb9e7d52255d3e14e57867eee76b555f705954c Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Fri, 13 Aug 2010 16:20:41 -0700 Subject: usrp1: Add usrp1 implementation --- host/lib/usrp/usrp1/io_impl.cpp | 229 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 host/lib/usrp/usrp1/io_impl.cpp (limited to 'host/lib/usrp/usrp1/io_impl.cpp') diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp new file mode 100644 index 000000000..3f3e74b80 --- /dev/null +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -0,0 +1,229 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "../../transport/vrt_packet_handler.hpp" +#include "usrp_commands.h" +#include "usrp1_impl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +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; +}; + +/*********************************************************************** + * IO Implementation Details + **********************************************************************/ +struct usrp1_impl::io_impl { + io_impl(zero_copy_if::sptr zc_if); + ~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; + usrp1_send_state send_state; + + zero_copy_if::sptr data_transport; + unsigned int count; +}; + +usrp1_impl::io_impl::io_impl(zero_copy_if::sptr zc_if) + : packet_handler_recv_state(1), data_transport(zc_if), count(0) +{ + /* NOP */ +} + +usrp1_impl::io_impl::~io_impl(void) +{ + /* NOP */ +} + +void usrp1_impl::io_init(void) +{ + _rx_otw_type.width = 16; + _rx_otw_type.shift = 0; + _rx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + + _tx_otw_type.width = 16; + _tx_otw_type.shift = 0; + _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; + + _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); +} + +/*********************************************************************** + * Data Send + **********************************************************************/ +size_t usrp1_impl::send(const std::vector &buffs, + size_t num_samps, + const tx_metadata_t &, + const io_type_t &io_type, + send_mode_t) +{ + UHD_ASSERT_THROW(buffs.size() == 1); + + 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(buffs[0]); + + boost::uint8_t *otw_mem = _io_impl->send_state.send_buff->cast(); + + // 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; + } + } + + return total_samps_sent; +} + +/*********************************************************************** + * Data Recv + **********************************************************************/ +void _recv_helper(vrt_packet_handler::recv_state &state) +{ + size_t num_packet_words32 = + state.managed_buffs[0]->size() / sizeof(boost::uint32_t); + + const boost::uint32_t *data = + state.managed_buffs[0]->cast(); + + state.copy_buffs[0] = reinterpret_cast(data); + size_t num_payload_bytes = num_packet_words32 * sizeof(boost::uint32_t); + state.size_of_copy_buffs = num_payload_bytes; +} + +size_t usrp1_impl::recv(const std::vector &buffs, + size_t num_samps, + rx_metadata_t &, + const io_type_t &io_type, + 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(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; + } + } + return sent_samps; +} -- cgit v1.2.3 From dafbb2c047fc0878288a67ec161c7c2735e1dcb8 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Thu, 19 Aug 2010 17:44:07 -0700 Subject: usrp1: Make underrun/overrun checking rate dependent Calculate a polling interval based on the sample rate and size. --- host/lib/usrp/usrp1/io_impl.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'host/lib/usrp/usrp1/io_impl.cpp') diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 3f3e74b80..71b2c4fc5 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,6 +33,8 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; +static const float poll_interval = 0.1; //100ms + /* * The FX2 firmware bursts data to the FPGA in 512 byte chunks so * maintain send state to make sure that happens. @@ -57,11 +59,15 @@ struct usrp1_impl::io_impl { usrp1_send_state send_state; zero_copy_if::sptr data_transport; - unsigned int count; + + //overun-underrun values + unsigned int tx_underrun_count; + unsigned int rx_overrun_count; }; usrp1_impl::io_impl::io_impl(zero_copy_if::sptr zc_if) - : packet_handler_recv_state(1), data_transport(zc_if), count(0) + : packet_handler_recv_state(1), data_transport(zc_if), + tx_underrun_count(0), rx_overrun_count(0) { /* NOP */ } @@ -133,9 +139,10 @@ size_t usrp1_impl::send(const std::vector &buffs, } total_samps_sent += copy_samps; + _io_impl->tx_underrun_count += copy_samps * _tx_otw_type.get_sample_size(); //check for underruns - if (!(_io_impl->count++ % 1000)) { + if (!(_io_impl->tx_underrun_count > _tx_dsp_freq * poll_interval * _tx_otw_type.get_sample_size())) { unsigned char underrun; int ret = _ctrl_transport->usrp_control_read(VRQ_GET_STATUS, 0, @@ -145,6 +152,8 @@ size_t usrp1_impl::send(const std::vector &buffs, std::cerr << "error: underrun check failed" << std::endl; if (underrun) std::cerr << "U" << std::endl; + + _io_impl->tx_underrun_count = 0; } } @@ -208,22 +217,25 @@ size_t usrp1_impl::recv(const std::vector &buffs, _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; + _io_impl->rx_overrun_count += nsamps_to_copy; sent_samps += nsamps_to_copy; - //check for overruns - if (!(_io_impl->count++ % 10000)) { + //check for overruns + if (_io_impl->rx_overrun_count > (8e6 * poll_interval)) { unsigned char overrun; - int ret = _ctrl_transport->usrp_control_read( - VRQ_GET_STATUS, - 0, - GS_RX_OVERRUN, - &overrun, sizeof(char)); + 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; + + _io_impl->rx_overrun_count = 0; } } + return sent_samps; } -- cgit v1.2.3 From 4021779856d6b971fa8add5f617528158bf727a2 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Mon, 23 Aug 2010 15:13:44 -0700 Subject: usrp1: Refactor I/O implementation --- host/lib/usrp/usrp1/dsp_impl.cpp | 4 + host/lib/usrp/usrp1/io_impl.cpp | 337 +++++++++++++++++++++++-------------- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 + 3 files changed, 215 insertions(+), 130 deletions(-) (limited to 'host/lib/usrp/usrp1/io_impl.cpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index ce0c12e4b..ddd1e811b 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -95,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; @@ -175,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 71b2c4fc5..33a04ffe6 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -35,41 +35,53 @@ namespace asio = boost::asio; static const float poll_interval = 0.1; //100ms -/* - * 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_written; size_t bytes_free; + size_t underrun_poll_samp_count; +}; + +struct usrp1_recv_state { + uhd::transport::managed_recv_buffer::sptr recv_buff; + size_t bytes_read; + size_t bytes_avail; + size_t overrun_poll_samp_count; }; /*********************************************************************** * 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; - - //overun-underrun values - unsigned int tx_underrun_count; - unsigned int rx_overrun_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), - tx_underrun_count(0), rx_overrun_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) @@ -87,12 +99,94 @@ 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_free = send_state.send_buff->size(); + 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(buff); + + boost::uint8_t *otw_mem = send_state.send_buff->cast(); + + 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.bytes_free -= 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 &buffs, size_t num_samps, const tx_metadata_t &, @@ -104,57 +198,21 @@ size_t usrp1_impl::send(const std::vector &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(buffs[0]); - - boost::uint8_t *otw_mem = _io_impl->send_state.send_buff->cast(); - - // 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; - _io_impl->tx_underrun_count += copy_samps * _tx_otw_type.get_sample_size(); - - //check for underruns - if (!(_io_impl->tx_underrun_count > _tx_dsp_freq * poll_interval * _tx_otw_type.get_sample_size())) { - 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; - - _io_impl->tx_underrun_count = 0; - } + 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; @@ -163,17 +221,72 @@ size_t usrp1_impl::send(const std::vector &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) +{ + if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail == 0)) { + + recv_state.recv_buff = zc_if->get_recv_buff(); + if (recv_state.recv_buff == NULL) + return false; + + recv_state.bytes_read = 0; + recv_state.bytes_avail = recv_state.recv_buff->size(); + } + + 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(); + + boost::uint8_t *io_mem = reinterpret_cast(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.bytes_avail -= 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) { - size_t num_packet_words32 = - state.managed_buffs[0]->size() / sizeof(boost::uint32_t); + unsigned char overrun = 0; + + bool ready_to_poll = recv_state.overrun_poll_samp_count > poll_interval; - const boost::uint32_t *data = - state.managed_buffs[0]->cast(); + 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; + } - state.copy_buffs[0] = reinterpret_cast(data); - size_t num_payload_bytes = num_packet_words32 * sizeof(boost::uint32_t); - state.size_of_copy_buffs = num_payload_bytes; + return (bool) overrun; } size_t usrp1_impl::recv(const std::vector &buffs, @@ -183,59 +296,23 @@ size_t usrp1_impl::recv(const std::vector &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(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; - _io_impl->rx_overrun_count += nsamps_to_copy; - - sent_samps += nsamps_to_copy; - - //check for overruns - if (_io_impl->rx_overrun_count > (8e6 * poll_interval)) { - 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; - - _io_impl->rx_overrun_count = 0; - } + 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/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index f57f9a09a..5934d1779 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -124,6 +124,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; -- cgit v1.2.3 From 9449d05773c0e3d328ff721ef01b1d0dd50aa372 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Tue, 24 Aug 2010 16:04:24 -0700 Subject: usrp1: Cleanup unnecessary state variables --- host/lib/usrp/usrp1/io_impl.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'host/lib/usrp/usrp1/io_impl.cpp') diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 33a04ffe6..a0efa14d1 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -38,15 +38,29 @@ static const float poll_interval = 0.1; //100ms struct usrp1_send_state { uhd::transport::managed_send_buffer::sptr send_buff; size_t bytes_written; - size_t bytes_free; 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 bytes_avail; size_t overrun_poll_samp_count; + + size_t bytes_avail() + { + if (recv_buff != NULL) + return recv_buff->size() - bytes_read; + else + return 0; + } }; /*********************************************************************** @@ -113,7 +127,6 @@ bool usrp1_impl::io_impl::get_send_buffer(zero_copy_if::sptr zc_if) if (send_state.send_buff == NULL) return false; - send_state.bytes_free = send_state.send_buff->size(); send_state.bytes_written = 0; } @@ -126,9 +139,9 @@ size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff, const io_type_t io_type, otw_type_t otw_type) { - UHD_ASSERT_THROW(send_state.bytes_free % otw_type.get_sample_size() == 0); + 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 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 = @@ -143,7 +156,6 @@ size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff, copy_samps); send_state.bytes_written += copy_samps * otw_type.get_sample_size(); - send_state.bytes_free -= copy_samps * otw_type.get_sample_size(); send_state.underrun_poll_samp_count += copy_samps; return copy_samps; @@ -154,7 +166,7 @@ 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) { + 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; @@ -223,14 +235,13 @@ size_t usrp1_impl::send(const std::vector &buffs, **********************************************************************/ bool usrp1_impl::io_impl::get_recv_buffer(zero_copy_if::sptr zc_if) { - if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail == 0)) { + if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail() == 0)) { recv_state.recv_buff = zc_if->get_recv_buff(); if (recv_state.recv_buff == NULL) return false; recv_state.bytes_read = 0; - recv_state.bytes_avail = recv_state.recv_buff->size(); } return true; @@ -242,9 +253,9 @@ size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff, const io_type_t io_type, otw_type_t otw_type) { - UHD_ASSERT_THROW(recv_state.bytes_avail % otw_type.get_sample_size() == 0); + 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 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 = @@ -259,7 +270,6 @@ size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff, copy_samps); recv_state.bytes_read += copy_samps * otw_type.get_sample_size(); - recv_state.bytes_avail -= copy_samps * otw_type.get_sample_size(); recv_state.overrun_poll_samp_count += copy_samps; return copy_samps; -- cgit v1.2.3 From df6e52627540124e35e114522a897ff1409dc3a7 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Tue, 24 Aug 2010 16:06:11 -0700 Subject: usrp1: Remove unused overrun/underrun poll variable The polling inverval for overrun and underrun checking is rate dependent and calculated in the dsp code whenever the interpolation or decimation is changed. --- host/lib/usrp/usrp1/io_impl.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'host/lib/usrp/usrp1/io_impl.cpp') diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index a0efa14d1..5e206b3d5 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,8 +33,6 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; -static const float poll_interval = 0.1; //100ms - struct usrp1_send_state { uhd::transport::managed_send_buffer::sptr send_buff; size_t bytes_written; -- cgit v1.2.3 From 7d7479ad0569337910f01b77df9bd8e3d385f8a5 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Fri, 27 Aug 2010 22:40:21 -0700 Subject: usrp1: Don't flush the stream buffer after every overrun/underrun --- host/lib/usrp/usrp1/io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/usrp1/io_impl.cpp') diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 5e206b3d5..920c47b30 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -189,7 +189,7 @@ bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if, if (ret < 0) std::cerr << "USRP: underrun check failed" << std::endl; if (underrun) - std::cerr << "U" << std::endl; + std::cerr << "Uu"; send_state.underrun_poll_samp_count = 0; } @@ -289,7 +289,7 @@ bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if, if (ret < 0) std::cerr << "USRP: overrrun check failed" << std::endl; if (overrun) - std::cerr << "O" << std::endl; + std::cerr << "Oo"; recv_state.overrun_poll_samp_count = 0; } -- cgit v1.2.3 From c9cd9b605897078daed77c8b7f9c538cb77bd4bc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 31 Aug 2010 12:19:17 -0700 Subject: usrp1: flush for flow error messages --- host/lib/usrp/usrp1/io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/usrp1/io_impl.cpp') diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 920c47b30..92e8bc20a 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -189,7 +189,7 @@ bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if, if (ret < 0) std::cerr << "USRP: underrun check failed" << std::endl; if (underrun) - std::cerr << "Uu"; + std::cerr << "U" << std::flush; send_state.underrun_poll_samp_count = 0; } @@ -289,7 +289,7 @@ bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if, if (ret < 0) std::cerr << "USRP: overrrun check failed" << std::endl; if (overrun) - std::cerr << "Oo"; + std::cerr << "O" << std::flush; recv_state.overrun_poll_samp_count = 0; } -- cgit v1.2.3