From 8f25550d1a8ac634ee3873ae90a86d1e07dd5482 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 28 Jan 2012 12:21:01 -0800 Subject: dsp rework: implemented new scalefactor in rx dsp core --- host/lib/usrp/e100/io_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 441e32a8d..97f4db6f1 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -278,7 +278,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 0x400)); + const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 1)); //calculate packet size static const size_t hdr_size = 0 -- cgit v1.2.3 From aa95e53a91fa52b61b6796fcfc811251b20dcb73 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 28 Jan 2012 16:08:17 -0800 Subject: dsp rework: work on scaling and args parsing on RX and TX dsp This simplified some copy pasta in the io_impl.cpp files, and adds a place for sc8 tx mode in the tx dsp core code. --- host/lib/usrp/b100/io_impl.cpp | 13 ++++------- host/lib/usrp/cores/rx_dsp_core_200.cpp | 12 ++++++----- host/lib/usrp/cores/rx_dsp_core_200.hpp | 3 ++- host/lib/usrp/cores/tx_dsp_core_200.cpp | 38 ++++++++++++++++++++++++++++++--- host/lib/usrp/cores/tx_dsp_core_200.hpp | 6 ++++-- host/lib/usrp/e100/io_impl.cpp | 13 ++++------- host/lib/usrp/usrp2/io_impl.cpp | 13 ++++------- 7 files changed, 60 insertions(+), 38 deletions(-) (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index c98f71754..6e9e017aa 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -154,6 +154,8 @@ void b100_impl::update_tx_samp_rate(const size_t dspno, const double rate){ if (my_streamer.get() == NULL) return; my_streamer->set_samp_rate(rate); + const double adj = _tx_dsp->get_scaling_adjustment(); + my_streamer->set_scale_factor(adj); } void b100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ @@ -202,7 +204,6 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 1)); //calculate packet size static const size_t hdr_size = 0 @@ -233,8 +234,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ const size_t dsp = args.channels[chan_i]; _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this - if (not args.args.has_key("noclear")) _rx_dsps[dsp]->clear(); - _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); + _rx_dsps[dsp]->setup(args); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 ), true /*flush*/); @@ -260,10 +260,6 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - if (args.otw_format != "sc16"){ - throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); - } - //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -291,8 +287,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ const size_t dsp = args.channels[chan_i]; UHD_ASSERT_THROW(dsp == 0); //always 0 - if (not args.args.has_key("noclear")) _tx_dsp->clear(); - if (args.args.has_key("underflow_policy")) _tx_dsp->set_underflow_policy(args.args["underflow_policy"]); + _tx_dsp->setup(args); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &zero_copy_if::get_send_buff, _data_transport, _1 )); diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index cbc732c9c..b2bf934bc 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -224,17 +224,19 @@ public: if (_continuous_streaming) issue_stream_command(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); } - void set_format(const std::string &format, const unsigned scale){ + void setup(const uhd::stream_args_t &stream_args){ + if (not stream_args.args.has_key("noclear")) this->clear(); + unsigned format_word = 0; - if (format == "sc16"){ + if (stream_args.otw_format == "sc16"){ format_word = 0; _extra_scaling = 1.0; } - else if (format == "sc8"){ + else if (stream_args.otw_format == "sc8"){ format_word = (1 << 0); - _extra_scaling = scale; + _extra_scaling = stream_args.args.cast("scalar", 1.0); } - else throw uhd::value_error("USRP RX cannot handle requested wire format: " + format); + else throw uhd::value_error("USRP RX cannot handle requested wire format: " + stream_args.otw_format); this->update_scalar(); diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp index 58be51eee..b01f751e9 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp @@ -19,6 +19,7 @@ #define INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP #include +#include #include #include #include @@ -60,7 +61,7 @@ public: virtual void handle_overflow(void) = 0; - virtual void set_format(const std::string &format, const unsigned scale) = 0; + virtual void setup(const uhd::stream_args_t &stream_args) = 0; }; #endif /* INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP */ diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index f4c303d05..2c5b86bfc 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -58,6 +58,11 @@ public: ): _iface(iface), _dsp_base(dsp_base), _ctrl_base(ctrl_base), _sid(sid) { + //init to something so update method has reasonable defaults + _scaling_adjustment = 1.0; + _extra_scaling = 1.0; + _fxpt_scalar_correction = 1.0; + //init the tx control registers this->clear(); this->set_underflow_policy("next_packet"); @@ -121,13 +126,24 @@ public: // Calculate CIC interpolation (i.e., without halfband interpolators) // Calculate closest multiplier constant to reverse gain absent scale multipliers - double rate_cubed = std::pow(double(interp & 0xff), 3); - const boost::int32_t scale = boost::math::iround((4096*std::pow(2, ceil_log2(rate_cubed)))/(1.65*rate_cubed)); - _iface->poke32(REG_DSP_TX_SCALE_IQ, scale); + const double rate_pow = std::pow(double(interp & 0xff), 3); + _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.65*rate_pow); + this->update_scalar(); return _tick_rate/interp_rate; } + void update_scalar(void){ + const double target_scalar = (1 << 17)*_scaling_adjustment/_extra_scaling; + const boost::int32_t actual_scalar = boost::math::iround(target_scalar); + _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small + _iface->poke32(REG_DSP_TX_SCALE_IQ, actual_scalar); + } + + double get_scaling_adjustment(void){ + return _fxpt_scalar_correction*_extra_scaling*32767.; + } + double set_freq(const double freq_){ //correct for outside of rate (wrap around) double freq = std::fmod(freq_, _tick_rate); @@ -156,10 +172,26 @@ public: _iface->poke32(REG_TX_CTRL_PACKETS_PER_UP, (packets_per_up == 0)? 0 : (FLAG_TX_CTRL_UP_ENB | packets_per_up)); } + void setup(const uhd::stream_args_t &stream_args){ + if (not stream_args.args.has_key("noclear")) this->clear(); + + if (stream_args.otw_format == "sc16"){ + _extra_scaling = 1.0; + } + else throw uhd::value_error("USRP TX cannot handle requested wire format: " + stream_args.otw_format); + + this->update_scalar(); + + if (stream_args.args.has_key("underflow_policy")){ + this->set_underflow_policy(stream_args.args["underflow_policy"]); + } + } + private: wb_iface::sptr _iface; const size_t _dsp_base, _ctrl_base; double _tick_rate, _link_rate; + double _scaling_adjustment, _extra_scaling, _fxpt_scalar_correction; const boost::uint32_t _sid; }; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp index 4b39a5b07..0e1cfb6bc 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp @@ -19,6 +19,7 @@ #define INCLUDED_LIBUHD_USRP_TX_DSP_CORE_200_HPP #include +#include #include #include #include @@ -44,14 +45,15 @@ public: virtual uhd::meta_range_t get_host_rates(void) = 0; + virtual double get_scaling_adjustment(void) = 0; + virtual uhd::meta_range_t get_freq_range(void) = 0; virtual double set_freq(const double freq) = 0; virtual void set_updates(const size_t cycles_per_up, const size_t packets_per_up) = 0; - virtual void set_underflow_policy(const std::string &policy) = 0; - + virtual void setup(const uhd::stream_args_t &stream_args) = 0; }; #endif /* INCLUDED_LIBUHD_USRP_TX_DSP_CORE_200_HPP */ diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 97f4db6f1..89a4ed00b 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -217,6 +217,8 @@ void e100_impl::update_tx_samp_rate(const size_t dspno, const double rate){ if (my_streamer.get() == NULL) return; my_streamer->set_samp_rate(rate); + const double adj = _tx_dsp->get_scaling_adjustment(); + my_streamer->set_scale_factor(adj); } void e100_impl::update_rates(void){ @@ -278,7 +280,6 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 1)); //calculate packet size static const size_t hdr_size = 0 @@ -309,8 +310,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ const size_t dsp = args.channels[chan_i]; _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this - if (not args.args.has_key("noclear")) _rx_dsps[dsp]->clear(); - _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); + _rx_dsps[dsp]->setup(args); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 ), true /*flush*/); @@ -336,10 +336,6 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - if (args.otw_format != "sc16"){ - throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); - } - //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -367,8 +363,7 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ const size_t dsp = args.channels[chan_i]; UHD_ASSERT_THROW(dsp == 0); //always 0 - if (not args.args.has_key("noclear")) _tx_dsp->clear(); - if (args.args.has_key("underflow_policy")) _tx_dsp->set_underflow_policy(args.args["underflow_policy"]); + _tx_dsp->setup(args); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &zero_copy_if::get_send_buff, _data_transport, _1 )); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 5f5369f7d..58a5df2a5 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -307,6 +307,8 @@ void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, co if (my_streamer.get() == NULL) return; my_streamer->set_samp_rate(rate); + const double adj = _mbc[mb].tx_dsp->get_scaling_adjustment(); + my_streamer->set_scale_factor(adj); } void usrp2_impl::update_rates(void){ @@ -380,7 +382,6 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 1)); //calculate packet size static const size_t hdr_size = 0 @@ -416,8 +417,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ if (chan < num_chan_so_far){ const size_t dsp = chan + _mbc[mb].rx_chan_occ - num_chan_so_far; _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this - if (not args.args.has_key("noclear")) _mbc[mb].rx_dsps[dsp]->clear(); - _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); + _mbc[mb].rx_dsps[dsp]->setup(args); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 ), true /*flush*/); @@ -447,10 +447,6 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - if (args.otw_format != "sc16"){ - throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); - } - //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -485,10 +481,9 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ if (chan < num_chan_so_far){ const size_t dsp = chan + _mbc[mb].tx_chan_occ - num_chan_so_far; if (not args.args.has_key("noclear")){ - _mbc[mb].tx_dsp->clear(); _io_impl->fc_mons[abs]->clear(); } - if (args.args.has_key("underflow_policy")) _mbc[mb].tx_dsp->set_underflow_policy(args.args["underflow_policy"]); + _mbc[mb].tx_dsp->setup(args); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, _1 )); -- cgit v1.2.3 From d46c176af34b728fd43b3dd46485b38623a7335e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 30 Jan 2012 22:23:38 -0800 Subject: dsp rework: tx trailer, scaling work (peak) --- host/include/uhd/stream.hpp | 9 +++-- host/lib/convert/convert_common.hpp | 48 ++++++++++++++++++++++++ host/lib/convert/convert_with_tables.cpp | 21 ++++------- host/lib/convert/gen_convert_general.py | 16 ++++++++ host/lib/transport/gen_vrt_if_packet.py | 0 host/lib/transport/super_send_packet_handler.hpp | 2 +- host/lib/usrp/b100/io_impl.cpp | 1 + host/lib/usrp/cores/rx_dsp_core_200.cpp | 17 +++++---- host/lib/usrp/cores/tx_dsp_core_200.cpp | 25 +++++++++--- host/lib/usrp/e100/io_impl.cpp | 1 + host/lib/usrp/usrp2/io_impl.cpp | 1 + 11 files changed, 110 insertions(+), 31 deletions(-) mode change 100755 => 100644 host/lib/transport/gen_vrt_if_packet.py (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp index 0c9282545..cec2eee79 100644 --- a/host/include/uhd/stream.hpp +++ b/host/include/uhd/stream.hpp @@ -79,10 +79,11 @@ struct UHD_API stream_args_t{ * The args parameter is used to pass arbitrary key/value pairs. * Possible keys used by args (depends on implementation): * - * - scalar: an integer scaling factor used with the sc8 wire format. - * Use scalar=1 to harvest the lower 8-bits. - * Use scalar=256 to harvest the upper 8-bits. - * Any scalar in-between is also a possibility. + * - peak: specifies a fractional sample level to calculate scaling with the sc8 wire format. + * When using sc8 samples over the wire, the device must scale samples + * (both on the host and in the device) to satisfy the dynamic range needs. + * The peak value specifies a fraction of the maximum sample level (1.0 = 100%). + * Set peak to max_sample_level/full_scale_level to ensure optimum dynamic range. * * - underflow_policy: how the TX DSP should recover from underflow. * Possible options are "next_burst" or "next_packet". diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 699d6301b..aab59de4b 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -190,4 +190,52 @@ static UHD_INLINE void item32_sc8_to_fc64(item32_t item, fc64_t &out0, fc64_t &o ); } +/*********************************************************************** + * Convert complex char to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t sc8_to_item32_sc8(sc8_t in0, sc8_t in1, double){ + return + (item32_t(boost::uint8_t(in0.real())) << 8) | + (item32_t(boost::uint8_t(in0.imag())) << 0) | + (item32_t(boost::uint8_t(in1.real())) << 24) | + (item32_t(boost::uint8_t(in1.imag())) << 16) + ; +} + +/*********************************************************************** + * Convert complex short to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t sc16_to_item32_sc8(sc16_t in0, sc16_t in1, double){ + return + (item32_t(boost::uint8_t(in0.real())) << 8) | + (item32_t(boost::uint8_t(in0.imag())) << 0) | + (item32_t(boost::uint8_t(in1.real())) << 24) | + (item32_t(boost::uint8_t(in1.imag())) << 16) + ; +} + +/*********************************************************************** + * Convert complex float to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t fc32_to_item32_sc8(fc32_t in0, fc32_t in1, double scale_factor){ + return + (item32_t(boost::uint8_t(in0.real()*float(scale_factor))) << 8) | + (item32_t(boost::uint8_t(in0.imag()*float(scale_factor))) << 0) | + (item32_t(boost::uint8_t(in1.real()*float(scale_factor))) << 24) | + (item32_t(boost::uint8_t(in1.imag()*float(scale_factor))) << 16) + ; +} + +/*********************************************************************** + * Convert complex double to items32 sc8 buffer + **********************************************************************/ +static UHD_INLINE item32_t fc64_to_item32_sc8(fc64_t in0, fc64_t in1, double scale_factor){ + return + (item32_t(boost::uint8_t(in0.real()*(scale_factor))) << 8) | + (item32_t(boost::uint8_t(in0.imag()*(scale_factor))) << 0) | + (item32_t(boost::uint8_t(in1.real()*(scale_factor))) << 24) | + (item32_t(boost::uint8_t(in1.imag()*(scale_factor))) << 16) + ; +} + #endif /* INCLUDED_LIBUHD_CONVERT_COMMON_HPP */ diff --git a/host/lib/convert/convert_with_tables.cpp b/host/lib/convert/convert_with_tables.cpp index c033a2959..2379739a7 100644 --- a/host/lib/convert/convert_with_tables.cpp +++ b/host/lib/convert/convert_with_tables.cpp @@ -68,24 +68,19 @@ class convert_sc8_item32_1_to_fcxx_1 : public converter{ public: convert_sc8_item32_1_to_fcxx_1(void): _table(sc16_table_len){} - void set_scalar(const double scalar){ - - //special case, this is converts sc8 to sc16, - //use the scale-factor but no normalization + //special case for sc16 type, 32767 undoes float normalization + static type conv(const boost::int8_t &num, const double scalar){ if (sizeof(type) == sizeof(s16_t)){ - for (size_t i = 0; i < sc16_table_len; i++){ - const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff)); - const type real = type(boost::math::iround(boost::int8_t(val >> 8)*scalar*32767)); - const type imag = type(boost::math::iround(boost::int8_t(val >> 0)*scalar*32767)); - _table[i] = std::complex(real, imag); - } - return; + return type(boost::math::iround(num*scalar*32767)); } + return type(num*scalar); + } + void set_scalar(const double scalar){ for (size_t i = 0; i < sc16_table_len; i++){ const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff)); - const type real = type(boost::int8_t(val >> 8)*scalar); - const type imag = type(boost::int8_t(val >> 0)*scalar); + const type real = conv(boost::int8_t(val >> 8), scalar); + const type imag = conv(boost::int8_t(val >> 0), scalar); _table[i] = std::complex(real, imag); } } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index b8d64aa4b..a6ae3f810 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -92,6 +92,22 @@ DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ item32_sc8_to_$(cpu_type)(item_n, output[num_samps-1], dummy, scale_factor); } } + +DECLARE_CONVERTER($(cpu_type), 1, sc8_item32_$(end), 1, PRIORITY_GENERAL){ + const $(cpu_type)_t *input = reinterpret_cast(inputs[0]); + item32_t *output = reinterpret_cast(outputs[0]); + + const size_t num_pairs = nsamps/2; + for (size_t i = 0, j = 0; i < num_pairs; i++, j+=2){ + const item32_t item = $(cpu_type)_to_item32_sc8(input[j], input[j+1], scale_factor); + output[i] = $(to_wire)(item); + } + + if (nsamps != num_pairs*2){ + const item32_t item = $(cpu_type)_to_item32_sc8(input[nsamps-1], 0, scale_factor); + output[num_pairs] = $(to_wire)(item); + } +} """ TMPL_CONV_USRP1_COMPLEX = """ diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py old mode 100755 new mode 100644 diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 5ed8e0143..57304a7d4 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -134,7 +134,7 @@ public: vrt::if_packet_info_t if_packet_info; if_packet_info.has_sid = false; if_packet_info.has_cid = false; - if_packet_info.has_tlr = false; + if_packet_info.has_tlr = true; if_packet_info.has_tsi = metadata.has_time_spec; if_packet_info.has_tsf = metadata.has_time_spec; if_packet_info.tsi = boost::uint32_t(metadata.time_spec.get_full_secs()); diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 6e9e017aa..9474268ef 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -263,6 +263,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; static const size_t bpp = 2048 - hdr_size; diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index b2bf934bc..7b35daa42 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -63,8 +63,7 @@ public: { //init to something so update method has reasonable defaults _scaling_adjustment = 1.0; - _extra_scaling = 1.0; - _fxpt_scalar_correction = 1.0; + _dsp_extra_scaling = 1.0; //This is a hack/fix for the lingering packet problem. //The caller should also flush the recv transports @@ -187,14 +186,14 @@ public: } void update_scalar(void){ - const double target_scalar = (1 << 16)*_scaling_adjustment/_extra_scaling; + const double target_scalar = (1 << 16)*_scaling_adjustment/_dsp_extra_scaling; const boost::int32_t actual_scalar = boost::math::iround(target_scalar); _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small _iface->poke32(REG_DSP_RX_SCALE_IQ, actual_scalar); } double get_scaling_adjustment(void){ - return _fxpt_scalar_correction*_extra_scaling/32767.; + return _fxpt_scalar_correction*_host_extra_scaling/32767.; } double set_freq(const double freq_){ @@ -230,11 +229,15 @@ public: unsigned format_word = 0; if (stream_args.otw_format == "sc16"){ format_word = 0; - _extra_scaling = 1.0; + _dsp_extra_scaling = 1.0; + _host_extra_scaling = 1.0; } else if (stream_args.otw_format == "sc8"){ format_word = (1 << 0); - _extra_scaling = stream_args.args.cast("scalar", 1.0); + double peak = stream_args.args.cast("peak", 1.0); + peak = std::max(peak, 1.0/256); + _host_extra_scaling = peak*256; + _dsp_extra_scaling = peak*256; } else throw uhd::value_error("USRP RX cannot handle requested wire format: " + stream_args.otw_format); @@ -248,7 +251,7 @@ private: const size_t _dsp_base, _ctrl_base; double _tick_rate, _link_rate; bool _continuous_streaming; - double _scaling_adjustment, _extra_scaling, _fxpt_scalar_correction; + double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction; const boost::uint32_t _sid; }; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index 2c5b86bfc..15358e184 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -18,6 +18,7 @@ #include "tx_dsp_core_200.hpp" #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #define REG_TX_CTRL_POLICY _ctrl_base + 12 #define REG_TX_CTRL_CYCLES_PER_UP _ctrl_base + 16 #define REG_TX_CTRL_PACKETS_PER_UP _ctrl_base + 20 +#define REG_TX_CTRL_FORMAT _ctrl_base + 24 #define FLAG_TX_CTRL_POLICY_WAIT (0x1 << 0) #define FLAG_TX_CTRL_POLICY_NEXT_PACKET (0x1 << 1) @@ -60,8 +62,7 @@ public: { //init to something so update method has reasonable defaults _scaling_adjustment = 1.0; - _extra_scaling = 1.0; - _fxpt_scalar_correction = 1.0; + _dsp_extra_scaling = 1.0; //init the tx control registers this->clear(); @@ -134,14 +135,14 @@ public: } void update_scalar(void){ - const double target_scalar = (1 << 17)*_scaling_adjustment/_extra_scaling; + const double target_scalar = (1 << 17)*_scaling_adjustment/_dsp_extra_scaling; const boost::int32_t actual_scalar = boost::math::iround(target_scalar); _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small _iface->poke32(REG_DSP_TX_SCALE_IQ, actual_scalar); } double get_scaling_adjustment(void){ - return _fxpt_scalar_correction*_extra_scaling*32767.; + return _fxpt_scalar_correction*_host_extra_scaling*32767.; } double set_freq(const double freq_){ @@ -175,13 +176,25 @@ public: void setup(const uhd::stream_args_t &stream_args){ if (not stream_args.args.has_key("noclear")) this->clear(); + unsigned format_word = 0; if (stream_args.otw_format == "sc16"){ - _extra_scaling = 1.0; + format_word = 0; + _dsp_extra_scaling = 1.0; + _host_extra_scaling = 1.0; + } + else if (stream_args.otw_format == "sc8"){ + format_word = (1 << 0); + double peak = stream_args.args.cast("peak", 1.0); + peak = std::max(peak, 1.0/256); + _host_extra_scaling = 1.0/peak/256; + _dsp_extra_scaling = 1.0/peak; } else throw uhd::value_error("USRP TX cannot handle requested wire format: " + stream_args.otw_format); this->update_scalar(); + _iface->poke32(REG_TX_CTRL_FORMAT, format_word); + if (stream_args.args.has_key("underflow_policy")){ this->set_underflow_policy(stream_args.args["underflow_policy"]); } @@ -191,7 +204,7 @@ private: wb_iface::sptr _iface; const size_t _dsp_base, _ctrl_base; double _tick_rate, _link_rate; - double _scaling_adjustment, _extra_scaling, _fxpt_scalar_correction; + double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction; const boost::uint32_t _sid; }; diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 89a4ed00b..53f783a3f 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -339,6 +339,7 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 58a5df2a5..6dcec6f1f 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -450,6 +450,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + vrt_send_header_offset_words32*sizeof(boost::uint32_t) - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; -- cgit v1.2.3 From d27125b9ab86e0d44db1317707aff7e9f9f8f32f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 1 Feb 2012 09:48:28 -0800 Subject: dsp rework: account for no sid used in tx vita pkt --- host/lib/usrp/b100/io_impl.cpp | 1 + host/lib/usrp/e100/io_impl.cpp | 1 + host/lib/usrp/usrp2/io_impl.cpp | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 9474268ef..da3abada8 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -264,6 +264,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; static const size_t bpp = 2048 - hdr_size; diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 53f783a3f..2b64e7f17 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -340,6 +340,7 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 6dcec6f1f..9b6c1c2f0 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -449,10 +449,11 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ //calculate packet size static const size_t hdr_size = 0 + + vrt_send_header_offset_words32*sizeof(boost::uint32_t) + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - + vrt_send_header_offset_words32*sizeof(boost::uint32_t) - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used ; const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size; const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); -- cgit v1.2.3 From b7ff81c9a8316bb0310d9291afe722c48b441f29 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 2 Feb 2012 15:15:54 -0800 Subject: dsp rework: work on usb wrapper for smaller packets, large luts --- host/lib/transport/libusb1_zero_copy.cpp | 17 +++-- host/lib/transport/usb_zero_copy_wrapper.cpp | 100 +++++++++++++-------------- host/lib/usrp/b100/b100_impl.cpp | 5 +- host/lib/usrp/b100/b100_impl.hpp | 3 +- host/lib/usrp/b100/b100_regs.hpp | 17 ++++- host/lib/usrp/b100/io_impl.cpp | 10 +-- host/lib/usrp/e100/e100_impl.cpp | 2 +- host/lib/usrp/e100/e100_impl.hpp | 2 +- host/lib/usrp/e100/e100_regs.hpp | 17 ++++- host/lib/usrp/e100/io_impl.cpp | 2 +- host/lib/usrp/usrp1/io_impl.cpp | 2 +- host/lib/usrp/usrp2/io_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 +- host/lib/usrp/usrp2/usrp2_regs.hpp | 2 +- 15 files changed, 105 insertions(+), 80 deletions(-) (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 28d6cdd5b..3e67264cd 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -80,13 +80,14 @@ UHD_INLINE bool wait_for_completion(libusb_context *ctx, const double timeout, b **********************************************************************/ class libusb_zero_copy_mrb : public managed_recv_buffer{ public: - libusb_zero_copy_mrb(libusb_transfer *lut): + libusb_zero_copy_mrb(libusb_transfer *lut, const size_t frame_size): _ctx(libusb::session::get_global_session()->get_context()), - _lut(lut), _expired(false) { /* NOP */ } + _lut(lut), _expired(false), _frame_size(frame_size) { /* NOP */ } void release(void){ if (_expired) return; completed = false; + _lut->length = _frame_size; //always reset length UHD_ASSERT_THROW(libusb_submit_transfer(_lut) == 0); _expired = true; } @@ -109,6 +110,7 @@ private: libusb_context *_ctx; libusb_transfer *_lut; bool _expired; + const size_t _frame_size; }; /*********************************************************************** @@ -118,9 +120,9 @@ private: **********************************************************************/ class libusb_zero_copy_msb : public managed_send_buffer{ public: - libusb_zero_copy_msb(libusb_transfer *lut): + libusb_zero_copy_msb(libusb_transfer *lut, const size_t frame_size): _ctx(libusb::session::get_global_session()->get_context()), - _lut(lut), _expired(false) { /* NOP */ } + _lut(lut), _expired(false), _frame_size(frame_size) { /* NOP */ } void commit(size_t len){ if (_expired) return; @@ -144,11 +146,12 @@ public: private: void *get_buff(void) const{return _lut->buffer;} - size_t get_size(void) const{return _lut->length;} + size_t get_size(void) const{return _frame_size;} libusb_context *_ctx; libusb_transfer *_lut; bool _expired; + const size_t _frame_size; }; /*********************************************************************** @@ -184,7 +187,7 @@ public: libusb_transfer *lut = libusb_alloc_transfer(0); UHD_ASSERT_THROW(lut != NULL); - _mrb_pool.push_back(boost::shared_ptr(new libusb_zero_copy_mrb(lut))); + _mrb_pool.push_back(boost::shared_ptr(new libusb_zero_copy_mrb(lut, this->get_recv_frame_size()))); libusb_fill_bulk_transfer( lut, // transfer @@ -207,7 +210,7 @@ public: libusb_transfer *lut = libusb_alloc_transfer(0); UHD_ASSERT_THROW(lut != NULL); - _msb_pool.push_back(boost::shared_ptr(new libusb_zero_copy_msb(lut))); + _msb_pool.push_back(boost::shared_ptr(new libusb_zero_copy_msb(lut, this->get_send_frame_size()))); libusb_fill_bulk_transfer( lut, // transfer diff --git a/host/lib/transport/usb_zero_copy_wrapper.cpp b/host/lib/transport/usb_zero_copy_wrapper.cpp index 74f07f956..07105cad3 100644 --- a/host/lib/transport/usb_zero_copy_wrapper.cpp +++ b/host/lib/transport/usb_zero_copy_wrapper.cpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -18,17 +18,13 @@ #include #include #include +#include +#include #include #include #include using namespace uhd::transport; -bool debug = true; - -static inline size_t next_boundary(size_t length, size_t boundary){ - //pad to the boundary, assumes boundary is a power of 2 - return (length + (boundary-1)) & ~(boundary-1); -} /*********************************************************************** * USB zero copy wrapper - managed receive buffer @@ -45,7 +41,7 @@ public: _mrb.reset(); } - sptr get_new(managed_recv_buffer::sptr mrb, const void *mem, size_t len){ + UHD_INLINE sptr get_new(managed_recv_buffer::sptr mrb, const void *mem, size_t len){ _mrb = mrb; _mem = mem; _len = len; @@ -67,28 +63,46 @@ private: **********************************************************************/ class usb_zero_copy_wrapper_msb : public managed_send_buffer{ public: - usb_zero_copy_wrapper_msb(bounded_buffer &queue, size_t boundary): - _queue(queue), _boundary(boundary){/*NOP*/} + usb_zero_copy_wrapper_msb(const usb_zero_copy::sptr internal, const size_t fragmentation_size): + _internal(internal), _fragmentation_size(fragmentation_size){/*NOP*/} void commit(size_t len){ - if (_msb.get() == NULL) return; - _msb->commit(len); - _queue.push_with_haste(this); - _msb.reset(); + if (len == 0) return; + + //get a reference to the VITA header before incrementing + const boost::uint32_t vita_header = reinterpret_cast(_mem_buffer_tip)[0]; + + _bytes_in_buffer += len; + _mem_buffer_tip += len; + + //extract VITA end of packet flag, we must force flush under eof conditions + const bool eop = (uhd::wtohx(vita_header) & (0x1 << 24)) != 0; + const bool full = _bytes_in_buffer >= (_last_send_buff->size() - _fragmentation_size); + if (eop or full){ + _last_send_buff->commit(_bytes_in_buffer); + _last_send_buff.reset(); + } } - sptr get_new(managed_send_buffer::sptr msb){ - _msb = msb; + UHD_INLINE sptr get_new(const double timeout){ + if (not _last_send_buff){ + _last_send_buff = _internal->get_send_buff(timeout); + if (not _last_send_buff) return sptr(); + _mem_buffer_tip = _last_send_buff->cast(); + _bytes_in_buffer = 0; + } return make_managed_buffer(this); } private: - void *get_buff(void) const{return _msb->cast();} - size_t get_size(void) const{return _msb->size();} - - bounded_buffer &_queue; - size_t _boundary; - managed_send_buffer::sptr _msb; + void *get_buff(void) const{return reinterpret_cast(_mem_buffer_tip);} + size_t get_size(void) const{return _fragmentation_size;} + + usb_zero_copy::sptr _internal; + const size_t _fragmentation_size; + managed_send_buffer::sptr _last_send_buff; + size_t _bytes_in_buffer; + char *_mem_buffer_tip; }; /*********************************************************************** @@ -96,23 +110,15 @@ private: **********************************************************************/ class usb_zero_copy_wrapper : public usb_zero_copy{ public: - usb_zero_copy_wrapper( - sptr usb_zc, size_t usb_frame_boundary - ): + usb_zero_copy_wrapper(sptr usb_zc, const size_t frame_boundary): _internal_zc(usb_zc), - _usb_frame_boundary(usb_frame_boundary), _available_recv_buffs(this->get_num_recv_frames()), - _available_send_buffs(this->get_num_send_frames()), _mrb_pool(this->get_num_recv_frames(), usb_zero_copy_wrapper_mrb(_available_recv_buffs)), - _msb_pool(this->get_num_send_frames(), usb_zero_copy_wrapper_msb(_available_send_buffs, usb_frame_boundary)) + _the_only_msb(usb_zero_copy_wrapper_msb(usb_zc, frame_boundary)) { BOOST_FOREACH(usb_zero_copy_wrapper_mrb &mrb, _mrb_pool){ _available_recv_buffs.push_with_haste(&mrb); } - - BOOST_FOREACH(usb_zero_copy_wrapper_msb &msb, _msb_pool){ - _available_send_buffs.push_with_haste(&msb); - } } managed_recv_buffer::sptr get_recv_buff(double timeout){ @@ -128,18 +134,17 @@ public: //extract this packet's memory address and length in bytes const char *mem = _last_recv_buff->cast() + _last_recv_offset; const boost::uint32_t *mem32 = reinterpret_cast(mem); - size_t len = (mem32[0] & 0xffff)*sizeof(boost::uint32_t); //length in bytes (from VRT header) - + const size_t len = (uhd::wtohx(mem32[0]) & 0xffff)*sizeof(boost::uint32_t); //length in bytes (from VRT header) + managed_recv_buffer::sptr recv_buff; //the buffer to be returned to the user - recv_buff = wmrb->get_new(_last_recv_buff, mem, len); - _last_recv_offset = next_boundary(_last_recv_offset + len, 4); - + _last_recv_offset += len; + //check if this receive buffer has been exhausted if (_last_recv_offset >= _last_recv_buff->size()) { _last_recv_buff.reset(); } - + return recv_buff; } @@ -156,16 +161,7 @@ public: } managed_send_buffer::sptr get_send_buff(double timeout){ - managed_send_buffer::sptr send_buff = _internal_zc->get_send_buff(timeout); - - //attempt to get a wrapper for a managed send buffer - usb_zero_copy_wrapper_msb *wmsb = NULL; - if (send_buff.get() and _available_send_buffs.pop_with_haste(wmsb)){ - return wmsb->get_new(send_buff); - } - - //otherwise return a null sptr for failure - return managed_send_buffer::sptr(); + return _the_only_msb.get_new(timeout); } size_t get_num_send_frames(void) const{ @@ -178,15 +174,13 @@ public: private: sptr _internal_zc; - size_t _usb_frame_boundary; bounded_buffer _available_recv_buffs; - bounded_buffer _available_send_buffs; std::vector _mrb_pool; - std::vector _msb_pool; - + usb_zero_copy_wrapper_msb _the_only_msb; + //buffer to store partially-received VRT packets in buffer_pool::sptr _fragment_mem; - + //state for last recv buffer to create multiple managed buffers managed_recv_buffer::sptr _last_recv_buff; size_t _last_recv_offset; diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 87aee9568..455efa2fe 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2012 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 @@ -229,7 +229,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ 2, 6, // IN interface, endpoint 1, 2, // OUT interface, endpoint data_xport_args // param hints - ) + ), + B100_MAX_PKT_BYTE_LIMIT ); //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 433f45aef..49a3139f0 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -52,6 +52,7 @@ static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x09; static const boost::uint32_t B100_RX_SID_BASE = 2; static const boost::uint32_t B100_TX_ASYNC_SID = 1; static const double B100_DEFAULT_TICK_RATE = 64e6; +static const size_t B100_MAX_PKT_BYTE_LIMIT = 2048; //! Make a b100 dboard interface uhd::usrp::dboard_iface::sptr make_b100_dboard_iface( diff --git a/host/lib/usrp/b100/b100_regs.hpp b/host/lib/usrp/b100/b100_regs.hpp index b625e65a5..b87a0ad73 100644 --- a/host/lib/usrp/b100/b100_regs.hpp +++ b/host/lib/usrp/b100/b100_regs.hpp @@ -1,4 +1,19 @@ - +// +// Copyright 2010-2012 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 . +// //////////////////////////////////////////////////////////////// // diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 7c07c6349..b1a44d70e 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -211,7 +211,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - const size_t bpp = 2048 - hdr_size; //limited by FPGA pkt buffer size + const size_t bpp = B100_MAX_PKT_BYTE_LIMIT - hdr_size; const size_t bpi = convert::get_bytes_per_item(args.otw_format); const size_t spp = unsigned(args.args.cast("spp", bpp/bpi)); @@ -260,10 +260,6 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - if (args.otw_format == "sc8"){ - throw uhd::value_error("USRP TX requested wire format not implemented in FPGA: " + args.otw_format); - } - //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -271,7 +267,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; + static const size_t bpp = B100_MAX_PKT_BYTE_LIMIT - hdr_size; const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); //make the new streamer given the samples per packet diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index cd6143a16..8ab6ab533 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp index e641aeea9..1d36cb2ac 100644 --- a/host/lib/usrp/e100/e100_impl.hpp +++ b/host/lib/usrp/e100/e100_impl.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 diff --git a/host/lib/usrp/e100/e100_regs.hpp b/host/lib/usrp/e100/e100_regs.hpp index 265086540..eee27b5b3 100644 --- a/host/lib/usrp/e100/e100_regs.hpp +++ b/host/lib/usrp/e100/e100_regs.hpp @@ -1,4 +1,19 @@ - +// +// Copyright 2010-2012 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 . +// //////////////////////////////////////////////////////////////// // diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 2b64e7f17..4d530585b 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index e9d9b65c2..f3cad188a 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 9b6c1c2f0..f19f49e28 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 206016972..7101e040a 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index c060f75b5..882a61f80 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 8f714cbbc..5d39e527d 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 -- cgit v1.2.3 From c6e63c9d2af2c0b2e168aa6fdd63fe7b214927de Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 4 Feb 2012 16:38:15 -0800 Subject: b100/e100: unify rx/tx fifo clears into one --- host/lib/usrp/b100/b100_regs.hpp | 6 ++---- host/lib/usrp/b100/io_impl.cpp | 5 ++--- host/lib/usrp/e100/e100_regs.hpp | 6 ++---- host/lib/usrp/e100/io_impl.cpp | 5 ++--- 4 files changed, 8 insertions(+), 14 deletions(-) (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/lib/usrp/b100/b100_regs.hpp b/host/lib/usrp/b100/b100_regs.hpp index cc94d0a2a..77b643372 100644 --- a/host/lib/usrp/b100/b100_regs.hpp +++ b/host/lib/usrp/b100/b100_regs.hpp @@ -103,8 +103,7 @@ #define B100_SR_TX_FRONT 54 // 5 regs (+0 to +4) #define B100_SR_REG_TEST32 60 // 1 reg -#define B100_SR_CLEAR_RX_FIFO 61 // 1 reg -#define B100_SR_CLEAR_TX_FIFO 62 // 1 reg +#define B100_SR_CLEAR_FIFO 61 // 1 reg #define B100_SR_GLOBAL_RESET 63 // 1 reg #define B100_SR_USER_REGS 64 // 2 regs @@ -117,8 +116,7 @@ ///////////////////////////////////////////////// // Magic reset regs //////////////////////////////////////////////// -#define B100_REG_CLEAR_RX B100_REG_SR_ADDR(B100_SR_CLEAR_RX_FIFO) -#define B100_REG_CLEAR_TX B100_REG_SR_ADDR(B100_SR_CLEAR_RX_FIFO) +#define B100_REG_CLEAR_FIFO B100_REG_SR_ADDR(B100_SR_CLEAR_FIFO) #define B100_REG_GLOBAL_RESET B100_REG_SR_ADDR(B100_SR_GLOBAL_RESET) #endif diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index db5af0dc5..ac7c860d2 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -54,9 +54,8 @@ struct b100_impl::io_impl{ **********************************************************************/ void b100_impl::io_init(void){ - //clear state machines - _fpga_ctrl->poke32(B100_REG_CLEAR_RX, 0); - _fpga_ctrl->poke32(B100_REG_CLEAR_TX, 0); + //clear fifo state machines + _fpga_ctrl->poke32(B100_REG_CLEAR_FIFO, 0); //allocate streamer weak ptrs containers _rx_streamers.resize(_rx_dsps.size()); diff --git a/host/lib/usrp/e100/e100_regs.hpp b/host/lib/usrp/e100/e100_regs.hpp index eee27b5b3..0ec5f4de3 100644 --- a/host/lib/usrp/e100/e100_regs.hpp +++ b/host/lib/usrp/e100/e100_regs.hpp @@ -116,8 +116,7 @@ #define UE_SR_TX_FRONT 54 // 5 regs (+0 to +4) #define UE_SR_REG_TEST32 60 // 1 reg -#define UE_SR_CLEAR_RX_FIFO 61 // 1 reg -#define UE_SR_CLEAR_TX_FIFO 62 // 1 reg +#define UE_SR_CLEAR_FIFO 61 // 1 reg #define UE_SR_GLOBAL_RESET 63 // 1 reg #define UE_SR_USER_REGS 64 // 2 regs @@ -131,8 +130,7 @@ ///////////////////////////////////////////////// // Magic reset regs //////////////////////////////////////////////// -#define E100_REG_CLEAR_RX E100_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO) -#define E100_REG_CLEAR_TX E100_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO) +#define E100_REG_CLEAR_FIFO E100_REG_SR_ADDR(UE_SR_CLEAR_FIFO) #define E100_REG_GLOBAL_RESET E100_REG_SR_ADDR(UE_SR_GLOBAL_RESET) #endif diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 4d530585b..8c7f5e742 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -164,9 +164,8 @@ void e100_impl::io_init(void){ _io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), E100_RX_SID_BASE); _io_impl->iface = _fpga_ctrl; - //clear state machines - _fpga_ctrl->poke32(E100_REG_CLEAR_RX, 0); - _fpga_ctrl->poke32(E100_REG_CLEAR_TX, 0); + //clear fifo state machines + _fpga_ctrl->poke32(E100_REG_CLEAR_FIFO, 0); //allocate streamer weak ptrs containers _rx_streamers.resize(_rx_dsps.size()); -- cgit v1.2.3 From 5eec31fab45649b529428cda756d04bcdaeb3134 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 6 Feb 2012 16:40:42 -0800 Subject: dsp rework: implement 64 bit ticks, no seconds --- host/include/uhd/types/time_spec.hpp | 20 ++++++++++++-- host/lib/transport/super_recv_packet_handler.hpp | 8 +++--- host/lib/transport/super_send_packet_handler.hpp | 12 ++++----- host/lib/types/time_spec.cpp | 29 ++++++++++---------- host/lib/usrp/b100/b100_impl.cpp | 8 +++--- host/lib/usrp/b100/b100_regs.hpp | 8 +++--- host/lib/usrp/b100/io_impl.cpp | 8 +++--- host/lib/usrp/cores/rx_dsp_core_200.cpp | 10 +++---- host/lib/usrp/cores/time64_core_200.cpp | 34 +++++++++++++----------- host/lib/usrp/cores/time64_core_200.hpp | 4 +-- host/lib/usrp/e100/e100_impl.cpp | 8 +++--- host/lib/usrp/e100/e100_regs.hpp | 8 +++--- host/lib/usrp/e100/io_impl.cpp | 8 +++--- host/lib/usrp/usrp2/io_impl.cpp | 8 +++--- host/lib/usrp/usrp2/usrp2_iface.cpp | 4 +-- host/lib/usrp/usrp2/usrp2_impl.cpp | 8 +++--- host/lib/usrp/usrp2/usrp2_regs.hpp | 8 +++--- host/tests/sph_recv_test.cpp | 24 ++++++++--------- host/tests/sph_send_test.cpp | 6 +---- host/tests/time_spec_test.cpp | 6 ++--- 20 files changed, 120 insertions(+), 109 deletions(-) (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/include/uhd/types/time_spec.hpp b/host/include/uhd/types/time_spec.hpp index 02de20ea1..cf8588c5b 100644 --- a/host/include/uhd/types/time_spec.hpp +++ b/host/include/uhd/types/time_spec.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -60,7 +60,7 @@ namespace uhd{ time_spec_t(time_t full_secs, double frac_secs = 0); /*! - * Create a time_spec_t from whole and fractional seconds. + * Create a time_spec_t from whole seconds and fractional ticks. * Translation from clock-domain specific units. * \param full_secs the whole/integer seconds count * \param tick_count the fractional seconds tick count @@ -68,6 +68,14 @@ namespace uhd{ */ time_spec_t(time_t full_secs, long tick_count, double tick_rate); + /*! + * Create a time_spec_t from a 64-bit tick count. + * Translation from clock-domain specific units. + * \param ticks an integer count of ticks + * \param tick_rate the number of ticks per second + */ + static time_spec_t from_ticks(long long ticks, double tick_rate); + /*! * Convert the fractional seconds to clock ticks. * Translation into clock-domain specific units. @@ -76,6 +84,14 @@ namespace uhd{ */ long get_tick_count(double tick_rate) const; + /*! + * Convert the time spec into a 64-bit tick count. + * Translation into clock-domain specific units. + * \param tick_rate the number of ticks per second + * \return an integer number of ticks + */ + long long to_ticks(const double tick_rate) const; + /*! * Get the time as a real-valued seconds count. * Note: If this time_spec_t represents an absolute time, diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index a5876c8bf..939e7aeb3 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -283,7 +283,7 @@ private: info.ifpi.num_packet_words32 = num_packet_words32 - _header_offset_words32; info.vrt_hdr = buff->cast() + _header_offset_words32; _vrt_unpacker(info.vrt_hdr, info.ifpi); - info.time = time_spec_t(time_t(info.ifpi.tsi), size_t(info.ifpi.tsf), _tick_rate); //assumes has_tsi and has_tsf are true + info.time = time_spec_t::from_ticks(info.ifpi.tsf, _tick_rate); //assumes has_tsf is true info.copy_buff = reinterpret_cast(info.vrt_hdr + info.ifpi.num_header_words32); //-------------------------------------------------------------- @@ -436,7 +436,7 @@ private: alignment_check(index, curr_info); std::swap(curr_info, next_info); //save progress from curr -> next curr_info.metadata.has_time_spec = prev_info.metadata.has_time_spec; - curr_info.metadata.time_spec = prev_info.metadata.time_spec + time_spec_t(0, + curr_info.metadata.time_spec = prev_info.metadata.time_spec + time_spec_t::from_ticks( prev_info[index].ifpi.num_payload_words32*sizeof(boost::uint32_t)/_bytes_per_otw_item, _samp_rate); curr_info.metadata.more_fragments = false; curr_info.metadata.fragment_offset = 0; @@ -508,7 +508,7 @@ private: metadata = info.metadata; //interpolate the time spec (useful when this is a fragment) - metadata.time_spec += time_spec_t(0, info.fragment_offset_in_samps, _samp_rate); + metadata.time_spec += time_spec_t::from_ticks(info.fragment_offset_in_samps, _samp_rate); //extract the number of samples available to copy const size_t nsamps_available = info.data_bytes_to_copy/_bytes_per_otw_item; diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 57304a7d4..3d68507ed 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -135,10 +135,9 @@ public: if_packet_info.has_sid = false; if_packet_info.has_cid = false; if_packet_info.has_tlr = true; - if_packet_info.has_tsi = metadata.has_time_spec; + if_packet_info.has_tsi = false; if_packet_info.has_tsf = metadata.has_time_spec; - if_packet_info.tsi = boost::uint32_t(metadata.time_spec.get_full_secs()); - if_packet_info.tsf = boost::uint64_t(metadata.time_spec.get_tick_count(_tick_rate)); + if_packet_info.tsf = metadata.time_spec.to_ticks(_tick_rate); if_packet_info.sob = metadata.start_of_burst; if_packet_info.eob = metadata.end_of_burst; @@ -174,9 +173,8 @@ public: if (num_samps_sent == 0) return total_num_samps_sent; //setup metadata for the next fragment - const time_spec_t time_spec = metadata.time_spec + time_spec_t(0, total_num_samps_sent, _samp_rate); - if_packet_info.tsi = boost::uint32_t(time_spec.get_full_secs()); - if_packet_info.tsf = boost::uint64_t(time_spec.get_tick_count(_tick_rate)); + const time_spec_t time_spec = metadata.time_spec + time_spec_t::from_ticks(total_num_samps_sent, _samp_rate); + if_packet_info.tsf = time_spec.to_ticks(_tick_rate); if_packet_info.sob = false; } diff --git a/host/lib/types/time_spec.cpp b/host/lib/types/time_spec.cpp index 8e540c14c..176ee8079 100644 --- a/host/lib/types/time_spec.cpp +++ b/host/lib/types/time_spec.cpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -16,6 +16,7 @@ // #include +#include //imaxdiv, intmax_t using namespace uhd; @@ -23,18 +24,6 @@ using namespace uhd; * Time spec system time **********************************************************************/ -/*! - * Creates a time spec from system counts: - * TODO make part of API as a static factory function - * The counts type is 64 bits and will overflow the ticks type of long. - * Therefore, divmod the counts into seconds + sub-second counts first. - */ -#include //imaxdiv, intmax_t -static UHD_INLINE time_spec_t time_spec_t_from_counts(intmax_t counts, intmax_t freq){ - imaxdiv_t divres = imaxdiv(counts, freq); - return time_spec_t(time_t(divres.quot), double(divres.rem)/freq); -} - #ifdef HAVE_CLOCK_GETTIME #include time_spec_t time_spec_t::get_system_time(void){ @@ -49,7 +38,7 @@ time_spec_t time_spec_t::get_system_time(void){ time_spec_t time_spec_t::get_system_time(void){ mach_timebase_info_data_t info; mach_timebase_info(&info); intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom; - return time_spec_t_from_counts(nanosecs, intmax_t(1e9)); + return time_spec_t::from_ticks(nanosecs, intmax_t(1e9)); } #endif /* HAVE_MACH_ABSOLUTE_TIME */ @@ -60,7 +49,7 @@ time_spec_t time_spec_t::get_system_time(void){ LARGE_INTEGER counts, freq; QueryPerformanceCounter(&counts); QueryPerformanceFrequency(&freq); - return time_spec_t_from_counts(counts.QuadPart, freq.QuadPart); + return time_spec_t::from_ticks(counts.QuadPart, freq.QuadPart); } #endif /* HAVE_QUERY_PERFORMANCE_COUNTER */ @@ -104,6 +93,11 @@ time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate){ time_spec_init(full_secs, frac_secs); } +time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){ + const imaxdiv_t divres = imaxdiv(ticks, tick_rate); + return time_spec_t(time_t(divres.quot), double(divres.rem)/tick_rate); +} + /*********************************************************************** * Time spec accessors **********************************************************************/ @@ -111,6 +105,11 @@ long time_spec_t::get_tick_count(double tick_rate) const{ return long(this->get_frac_secs()*tick_rate + 0.5); } +long long time_spec_t::to_ticks(double tick_rate) const{ + return (long long)(this->get_frac_secs()*tick_rate + 0.5) + \ + (long long)((this->get_full_secs()) * (long long)(tick_rate)); +} + double time_spec_t::get_real_secs(void) const{ return this->_full_secs + this->_frac_secs; } diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 08a2cdeec..ce0b9453b 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -364,10 +364,10 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ // create time control objects //////////////////////////////////////////////////////////////////// time64_core_200::readback_bases_type time64_rb_bases; - time64_rb_bases.rb_secs_now = B100_REG_RB_TIME_NOW_SECS; - time64_rb_bases.rb_ticks_now = B100_REG_RB_TIME_NOW_TICKS; - time64_rb_bases.rb_secs_pps = B100_REG_RB_TIME_PPS_SECS; - time64_rb_bases.rb_ticks_pps = B100_REG_RB_TIME_PPS_TICKS; + time64_rb_bases.rb_hi_now = B100_REG_RB_TIME_NOW_HI; + time64_rb_bases.rb_lo_now = B100_REG_RB_TIME_NOW_LO; + time64_rb_bases.rb_hi_pps = B100_REG_RB_TIME_PPS_HI; + time64_rb_bases.rb_lo_pps = B100_REG_RB_TIME_PPS_LO; _time64 = time64_core_200::make( _fpga_ctrl, B100_REG_SR_ADDR(B100_SR_TIME64), time64_rb_bases ); diff --git a/host/lib/usrp/b100/b100_regs.hpp b/host/lib/usrp/b100/b100_regs.hpp index 77b643372..987a09f03 100644 --- a/host/lib/usrp/b100/b100_regs.hpp +++ b/host/lib/usrp/b100/b100_regs.hpp @@ -76,10 +76,10 @@ #define B100_REG_RB_MUX_32_BASE B100_REG_SLAVE(7) -#define B100_REG_RB_TIME_NOW_SECS B100_REG_RB_MUX_32_BASE + 0 -#define B100_REG_RB_TIME_NOW_TICKS B100_REG_RB_MUX_32_BASE + 4 -#define B100_REG_RB_TIME_PPS_SECS B100_REG_RB_MUX_32_BASE + 8 -#define B100_REG_RB_TIME_PPS_TICKS B100_REG_RB_MUX_32_BASE + 12 +#define B100_REG_RB_TIME_NOW_HI B100_REG_RB_MUX_32_BASE + 0 +#define B100_REG_RB_TIME_NOW_LO B100_REG_RB_MUX_32_BASE + 4 +#define B100_REG_RB_TIME_PPS_HI B100_REG_RB_MUX_32_BASE + 8 +#define B100_REG_RB_TIME_PPS_LO B100_REG_RB_MUX_32_BASE + 12 #define B100_REG_RB_MISC_TEST32 B100_REG_RB_MUX_32_BASE + 16 #define B100_REG_RB_COMPAT B100_REG_RB_MUX_32_BASE + 24 #define B100_REG_RB_GPIO B100_REG_RB_MUX_32_BASE + 28 diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index ac7c860d2..bd60e75cf 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -84,10 +84,8 @@ void b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){ //fill in the async metadata async_metadata_t metadata; metadata.channel = 0; - metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; - metadata.time_spec = time_spec_t( - time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), _clock_ctrl->get_fpga_clock_rate() - ); + metadata.has_time_spec = if_packet_info.has_tsf; + metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, _clock_ctrl->get_fpga_clock_rate()); metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info)); _io_impl->async_msg_fifo.push_with_pop_on_full(metadata); if (metadata.event_code & @@ -206,6 +204,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used ; const size_t bpp = B100_MAX_PKT_BYTE_LIMIT - hdr_size; const size_t bpi = convert::get_bytes_per_item(args.otw_format); @@ -262,6 +261,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used ; static const size_t bpp = B100_MAX_PKT_BYTE_LIMIT - hdr_size; const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index d9ca84e0f..ea0384dbe 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -36,8 +36,8 @@ #define FLAG_DSP_RX_MUX_REAL_MODE (1 << 1) #define REG_RX_CTRL_STREAM_CMD _ctrl_base + 0 -#define REG_RX_CTRL_TIME_SECS _ctrl_base + 4 -#define REG_RX_CTRL_TIME_TICKS _ctrl_base + 8 +#define REG_RX_CTRL_TIME_HI _ctrl_base + 4 +#define REG_RX_CTRL_TIME_LO _ctrl_base + 8 #define REG_RX_CTRL_CLEAR _ctrl_base + 12 #define REG_RX_CTRL_VRT_HDR _ctrl_base + 16 #define REG_RX_CTRL_VRT_SID _ctrl_base + 20 @@ -83,7 +83,6 @@ public: _iface->poke32(REG_RX_CTRL_VRT_HDR, 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(REG_RX_CTRL_VRT_SID, _sid); @@ -122,8 +121,9 @@ public: //issue the stream command _iface->poke32(REG_RX_CTRL_STREAM_CMD, cmd_word); - _iface->poke32(REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); - _iface->poke32(REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_tick_rate)); //latches the command + const boost::uint64_t ticks = stream_cmd.time_spec.to_ticks(_tick_rate); + _iface->poke32(REG_RX_CTRL_TIME_HI, boost::uint32_t(ticks >> 32)); + _iface->poke32(REG_RX_CTRL_TIME_LO, boost::uint32_t(ticks >> 0)); //latches the command } void set_mux(const std::string &mode, const bool fe_swapped){ diff --git a/host/lib/usrp/cores/time64_core_200.cpp b/host/lib/usrp/cores/time64_core_200.cpp index 23d1bdea2..e460d1106 100644 --- a/host/lib/usrp/cores/time64_core_200.cpp +++ b/host/lib/usrp/cores/time64_core_200.cpp @@ -20,11 +20,10 @@ #include #include -#define REG_TIME64_SECS _base + 0 -#define REG_TIME64_TICKS _base + 4 +#define REG_TIME64_TICKS_HI _base + 0 +#define REG_TIME64_TICKS_LO _base + 4 #define REG_TIME64_FLAGS _base + 8 #define REG_TIME64_IMM _base + 12 -#define REG_TIME64_TPS _base + 16 #define REG_TIME64_MIMO_SYNC _base + 20 //lower byte is delay cycles //pps flags (see above) @@ -59,39 +58,42 @@ public: void set_tick_rate(const double rate){ _tick_rate = rate; - _iface->poke32(REG_TIME64_TPS, boost::math::iround(rate)); } uhd::time_spec_t get_time_now(void){ for (size_t i = 0; i < 3; i++){ //special algorithm because we cant read 64 bits synchronously - const boost::uint32_t secs = _iface->peek32(_readback_bases.rb_secs_now); - const boost::uint32_t ticks = _iface->peek32(_readback_bases.rb_ticks_now); - if (secs != _iface->peek32(_readback_bases.rb_secs_now)) continue; - return time_spec_t(secs, ticks, _tick_rate); + const boost::uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_now); + const boost::uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_now); + if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_now)) continue; + const boost::uint64_t ticks = (boost::uint64_t(ticks_hi) << 32) | ticks_lo; + return time_spec_t::from_ticks(ticks, _tick_rate); } throw uhd::runtime_error("time64_core_200: get time now timeout"); } uhd::time_spec_t get_time_last_pps(void){ for (size_t i = 0; i < 3; i++){ //special algorithm because we cant read 64 bits synchronously - const boost::uint32_t secs = _iface->peek32(_readback_bases.rb_secs_pps); - const boost::uint32_t ticks = _iface->peek32(_readback_bases.rb_ticks_pps); - if (secs != _iface->peek32(_readback_bases.rb_secs_pps)) continue; - return time_spec_t(secs, ticks, _tick_rate); + const boost::uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_pps); + const boost::uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_pps); + if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_pps)) continue; + const boost::uint64_t ticks = (boost::uint64_t(ticks_hi) << 32) | ticks_lo; + return time_spec_t::from_ticks(ticks, _tick_rate); } throw uhd::runtime_error("time64_core_200: get time last pps timeout"); } void set_time_now(const uhd::time_spec_t &time){ - _iface->poke32(REG_TIME64_TICKS, time.get_tick_count(_tick_rate)); + const boost::uint64_t ticks = time.to_ticks(_tick_rate); + _iface->poke32(REG_TIME64_TICKS_LO, boost::uint32_t(ticks >> 0)); _iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NOW); - _iface->poke32(REG_TIME64_SECS, boost::uint32_t(time.get_full_secs())); //latches all 3 + _iface->poke32(REG_TIME64_TICKS_HI, boost::uint32_t(ticks >> 32)); //latches all 3 } void set_time_next_pps(const uhd::time_spec_t &time){ - _iface->poke32(REG_TIME64_TICKS, time.get_tick_count(_tick_rate)); + const boost::uint64_t ticks = time.to_ticks(_tick_rate); + _iface->poke32(REG_TIME64_TICKS_LO, boost::uint32_t(ticks >> 0)); _iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NEXT_PPS); - _iface->poke32(REG_TIME64_SECS, boost::uint32_t(time.get_full_secs())); //latches all 3 + _iface->poke32(REG_TIME64_TICKS_HI, boost::uint32_t(ticks >> 32)); //latches all 3 } void set_time_source(const std::string &source){ diff --git a/host/lib/usrp/cores/time64_core_200.hpp b/host/lib/usrp/cores/time64_core_200.hpp index ebd51a02f..7571573a5 100644 --- a/host/lib/usrp/cores/time64_core_200.hpp +++ b/host/lib/usrp/cores/time64_core_200.hpp @@ -31,8 +31,8 @@ public: typedef boost::shared_ptr sptr; struct readback_bases_type{ - size_t rb_secs_now, rb_ticks_now; - size_t rb_secs_pps, rb_ticks_pps; + size_t rb_hi_now, rb_lo_now; + size_t rb_hi_pps, rb_lo_pps; }; //! makes a new time64 core from iface and slave base diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 8ab6ab533..a01ce4a7b 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -326,10 +326,10 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ // create time control objects //////////////////////////////////////////////////////////////////// time64_core_200::readback_bases_type time64_rb_bases; - time64_rb_bases.rb_secs_now = E100_REG_RB_TIME_NOW_SECS; - time64_rb_bases.rb_ticks_now = E100_REG_RB_TIME_NOW_TICKS; - time64_rb_bases.rb_secs_pps = E100_REG_RB_TIME_PPS_SECS; - time64_rb_bases.rb_ticks_pps = E100_REG_RB_TIME_PPS_TICKS; + time64_rb_bases.rb_hi_now = E100_REG_RB_TIME_NOW_HI; + time64_rb_bases.rb_lo_now = E100_REG_RB_TIME_NOW_LO; + time64_rb_bases.rb_hi_pps = E100_REG_RB_TIME_PPS_HI; + time64_rb_bases.rb_lo_pps = E100_REG_RB_TIME_PPS_LO; _time64 = time64_core_200::make( _fpga_ctrl, E100_REG_SR_ADDR(UE_SR_TIME64), time64_rb_bases ); diff --git a/host/lib/usrp/e100/e100_regs.hpp b/host/lib/usrp/e100/e100_regs.hpp index 0ec5f4de3..75be2cfbe 100644 --- a/host/lib/usrp/e100/e100_regs.hpp +++ b/host/lib/usrp/e100/e100_regs.hpp @@ -86,10 +86,10 @@ #define E100_REG_RB_MUX_32_BASE E100_REG_SLAVE(7) -#define E100_REG_RB_TIME_NOW_SECS E100_REG_RB_MUX_32_BASE + 0 -#define E100_REG_RB_TIME_NOW_TICKS E100_REG_RB_MUX_32_BASE + 4 -#define E100_REG_RB_TIME_PPS_SECS E100_REG_RB_MUX_32_BASE + 8 -#define E100_REG_RB_TIME_PPS_TICKS E100_REG_RB_MUX_32_BASE + 12 +#define E100_REG_RB_TIME_NOW_HI E100_REG_RB_MUX_32_BASE + 0 +#define E100_REG_RB_TIME_NOW_LO E100_REG_RB_MUX_32_BASE + 4 +#define E100_REG_RB_TIME_PPS_HI E100_REG_RB_MUX_32_BASE + 8 +#define E100_REG_RB_TIME_PPS_LO E100_REG_RB_MUX_32_BASE + 12 #define E100_REG_RB_MISC_TEST32 E100_REG_RB_MUX_32_BASE + 16 #define E100_REG_RB_ERR_STATUS E100_REG_RB_MUX_32_BASE + 20 #define E100_REG_RB_COMPAT E100_REG_RB_MUX_32_BASE + 24 diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 8c7f5e742..f8e15f3fd 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -124,10 +124,8 @@ void e100_impl::io_impl::handle_irq(void){ //fill in the async metadata async_metadata_t metadata; metadata.channel = 0; - metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; - metadata.time_spec = time_spec_t( - time_t(if_packet_info.tsi), long(if_packet_info.tsf), tick_rate - ); + metadata.has_time_spec = if_packet_info.has_tsf; + metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, tick_rate); metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(data.buf, if_packet_info)); //push the message onto the queue @@ -285,6 +283,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used ; const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size; const size_t bpi = convert::get_bytes_per_item(args.otw_format); @@ -341,6 +340,7 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used ; static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f19f49e28..f0c159f16 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -202,10 +202,8 @@ void usrp2_impl::io_impl::recv_pirate_loop( //fill in the async metadata async_metadata_t metadata; metadata.channel = index; - metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; - metadata.time_spec = time_spec_t( - time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), tick_rate - ); + metadata.has_time_spec = if_packet_info.has_tsf; + metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, tick_rate); metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info)); //catch the flow control packets and react @@ -388,6 +386,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used + - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used ; const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size; const size_t bpi = convert::get_bytes_per_item(args.otw_format); @@ -454,6 +453,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used + - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used ; const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size; const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 4830c10d9..f3d474a2d 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -126,7 +126,7 @@ public: bool is_device_locked(void){ boost::uint32_t lock_secs = this->get_reg(U2_FW_REG_LOCK_TIME); boost::uint32_t lock_gpid = this->get_reg(U2_FW_REG_LOCK_GPID); - boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_SECS_RB_IMM); + boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_LO_RB_IMM)/100e6; //if the difference is larger, assume not locked anymore if (curr_secs - lock_secs >= 3) return false; @@ -137,7 +137,7 @@ public: void lock_task(void){ //re-lock in task - boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_SECS_RB_IMM); + boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_LO_RB_IMM)/100e6; this->get_reg(U2_FW_REG_LOCK_TIME, curr_secs); //sleep for a bit boost::this_thread::sleep(boost::posix_time::milliseconds(1500)); diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 7101e040a..2077ab009 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -546,10 +546,10 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ // create time control objects //////////////////////////////////////////////////////////////// time64_core_200::readback_bases_type time64_rb_bases; - time64_rb_bases.rb_secs_now = U2_REG_TIME64_SECS_RB_IMM; - time64_rb_bases.rb_ticks_now = U2_REG_TIME64_TICKS_RB_IMM; - time64_rb_bases.rb_secs_pps = U2_REG_TIME64_SECS_RB_PPS; - time64_rb_bases.rb_ticks_pps = U2_REG_TIME64_TICKS_RB_PPS; + time64_rb_bases.rb_hi_now = U2_REG_TIME64_HI_RB_IMM; + time64_rb_bases.rb_lo_now = U2_REG_TIME64_LO_RB_IMM; + time64_rb_bases.rb_hi_pps = U2_REG_TIME64_HI_RB_PPS; + time64_rb_bases.rb_lo_pps = U2_REG_TIME64_LO_RB_PPS; _mbc[mb].time64 = time64_core_200::make( _mbc[mb].iface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles ); diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 5d39e527d..e14798ecb 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -97,11 +97,11 @@ //////////////////////////////////////////////// #define U2_REG_STATUS READBACK_BASE + 4*8 #define U2_REG_GPIO_RB READBACK_BASE + 4*9 -#define U2_REG_TIME64_SECS_RB_IMM READBACK_BASE + 4*10 -#define U2_REG_TIME64_TICKS_RB_IMM READBACK_BASE + 4*11 +#define U2_REG_TIME64_HI_RB_IMM READBACK_BASE + 4*10 +#define U2_REG_TIME64_LO_RB_IMM READBACK_BASE + 4*11 #define U2_REG_COMPAT_NUM_RB READBACK_BASE + 4*12 #define U2_REG_IRQ_RB READBACK_BASE + 4*13 -#define U2_REG_TIME64_SECS_RB_PPS READBACK_BASE + 4*14 -#define U2_REG_TIME64_TICKS_RB_PPS READBACK_BASE + 4*15 +#define U2_REG_TIME64_HI_RB_PPS READBACK_BASE + 4*14 +#define U2_REG_TIME64_LO_RB_PPS READBACK_BASE + 4*15 #endif /* INCLUDED_USRP2_REGS_HPP */ diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp index 85d06aa0d..9b45d7016 100644 --- a/host/tests/sph_recv_test.cpp +++ b/host/tests/sph_recv_test.cpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10); num_accum_samps += num_samps_ret; } @@ -232,14 +232,14 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); num_accum_samps += 10 + i%10; } else{ BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10); num_accum_samps += num_samps_ret; } @@ -323,7 +323,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10); num_accum_samps += num_samps_ret; if (i == NUM_PKTS_TO_TEST/2){ @@ -332,7 +332,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ ); std::cout << "metadata.error_code " << metadata.error_code << std::endl; BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(overflow_handler.num_overflow, size_t(1)); } } @@ -414,7 +414,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10); num_accum_samps += num_samps_ret; } @@ -500,14 +500,14 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); num_accum_samps += 10 + i%10; } else{ BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10); num_accum_samps += num_samps_ret; } @@ -593,7 +593,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10); num_accum_samps += num_samps_ret; if (i == NUM_PKTS_TO_TEST/2){ @@ -677,7 +677,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, 10); num_accum_samps += num_samps_ret; @@ -690,7 +690,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ BOOST_CHECK(not metadata.more_fragments); BOOST_CHECK_EQUAL(metadata.fragment_offset, 10); BOOST_CHECK(metadata.has_time_spec); - BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE)); + BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, i%10); num_accum_samps += num_samps_ret; } diff --git a/host/tests/sph_send_test.cpp b/host/tests/sph_send_test.cpp index 25a3f97ee..c31399d12 100644 --- a/host/tests/sph_send_test.cpp +++ b/host/tests/sph_send_test.cpp @@ -1,5 +1,5 @@ // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -136,9 +136,7 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ std::cout << "data check " << i << std::endl; dummy_send_xport.pop_front_packet(ifpi); BOOST_CHECK_EQUAL(ifpi.num_payload_words32, 10+i%10); - BOOST_CHECK(ifpi.has_tsi); BOOST_CHECK(ifpi.has_tsf); - BOOST_CHECK_EQUAL(ifpi.tsi, 0); BOOST_CHECK_EQUAL(ifpi.tsf, num_accum_samps*TICK_RATE/SAMP_RATE); BOOST_CHECK_EQUAL(ifpi.sob, i == 0); BOOST_CHECK_EQUAL(ifpi.eob, i == NUM_PKTS_TO_TEST-1); @@ -191,9 +189,7 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_full_buffer_mode){ std::cout << "data check " << i << std::endl; dummy_send_xport.pop_front_packet(ifpi); BOOST_CHECK_EQUAL(ifpi.num_payload_words32, 20); - BOOST_CHECK(ifpi.has_tsi); BOOST_CHECK(ifpi.has_tsf); - BOOST_CHECK_EQUAL(ifpi.tsi, 0); BOOST_CHECK_EQUAL(ifpi.tsf, num_accum_samps*TICK_RATE/SAMP_RATE); BOOST_CHECK_EQUAL(ifpi.sob, i == 0); BOOST_CHECK_EQUAL(ifpi.eob, i == NUM_PKTS_TO_TEST-1); diff --git a/host/tests/time_spec_test.cpp b/host/tests/time_spec_test.cpp index 467da5c18..102b7cda3 100644 --- a/host/tests/time_spec_test.cpp +++ b/host/tests/time_spec_test.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -54,11 +54,11 @@ BOOST_AUTO_TEST_CASE(test_time_spec_parts){ BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_full_secs(), 1); BOOST_CHECK_CLOSE(uhd::time_spec_t(1.1).get_frac_secs(), 0.1, 0.001); - BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).get_tick_count(100), 10); + BOOST_CHECK_EQUAL(uhd::time_spec_t(1.1).to_ticks(100), 110); BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_full_secs(), -2); BOOST_CHECK_CLOSE(uhd::time_spec_t(-1.1).get_frac_secs(), 0.9, 0.001); - BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).get_tick_count(100), 90); + BOOST_CHECK_EQUAL(uhd::time_spec_t(-1.1).to_ticks(100), -110); } BOOST_AUTO_TEST_CASE(test_time_spec_get_system_time){ -- cgit v1.2.3 From 115100034071b3b58de1fce7c795995f6ee615a1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 9 Feb 2012 17:59:48 -0800 Subject: uhd: various tweaks for compiler warns and valgrind --- host/examples/test_messages.cpp | 3 ++- host/lib/types/time_spec.cpp | 14 +++++++++----- host/lib/usrp/b100/io_impl.cpp | 2 +- host/lib/usrp/cores/rx_dsp_core_200.cpp | 2 +- host/lib/usrp/e100/io_impl.cpp | 2 +- host/lib/usrp/usrp1/soft_time_ctrl.cpp | 4 ++-- host/lib/usrp/usrp2/io_impl.cpp | 3 ++- host/lib/usrp/usrp2/usrp2_iface.cpp | 13 ++++++++----- host/tests/convert_test.cpp | 4 ++-- 9 files changed, 28 insertions(+), 19 deletions(-) (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/examples/test_messages.cpp b/host/examples/test_messages.cpp index f24a172d1..afb092092 100644 --- a/host/examples/test_messages.cpp +++ b/host/examples/test_messages.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -326,7 +327,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //run the tests, pick at random - std::srand(uhd::time_spec_t::get_system_time().get_full_secs()); + std::srand((unsigned int) time(NULL)); for (size_t n = 0; n < ntests; n++){ std::string key = tests.keys()[std::rand() % tests.size()]; bool pass = tests[key](usrp, rx_stream, tx_stream); diff --git a/host/lib/types/time_spec.cpp b/host/lib/types/time_spec.cpp index 176ee8079..0c3a3dbea 100644 --- a/host/lib/types/time_spec.cpp +++ b/host/lib/types/time_spec.cpp @@ -38,7 +38,7 @@ time_spec_t time_spec_t::get_system_time(void){ time_spec_t time_spec_t::get_system_time(void){ mach_timebase_info_data_t info; mach_timebase_info(&info); intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom; - return time_spec_t::from_ticks(nanosecs, intmax_t(1e9)); + return time_spec_t::from_ticks(nanosecs, 1e9); } #endif /* HAVE_MACH_ABSOLUTE_TIME */ @@ -80,6 +80,10 @@ time_spec_t time_spec_t::get_system_time(void){ } \ } +UHD_INLINE long long fast_llround(const double x){ + return (long long)(x + 0.5); // assumption of non-negativity +} + time_spec_t::time_spec_t(double secs){ time_spec_init(0, secs); } @@ -94,7 +98,7 @@ time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate){ } time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){ - const imaxdiv_t divres = imaxdiv(ticks, tick_rate); + const imaxdiv_t divres = imaxdiv(ticks, fast_llround(tick_rate)); return time_spec_t(time_t(divres.quot), double(divres.rem)/tick_rate); } @@ -102,12 +106,12 @@ time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){ * Time spec accessors **********************************************************************/ long time_spec_t::get_tick_count(double tick_rate) const{ - return long(this->get_frac_secs()*tick_rate + 0.5); + return long(fast_llround(this->get_frac_secs()*tick_rate)); } long long time_spec_t::to_ticks(double tick_rate) const{ - return (long long)(this->get_frac_secs()*tick_rate + 0.5) + \ - (long long)((this->get_full_secs()) * (long long)(tick_rate)); + return fast_llround(this->get_frac_secs()*tick_rate) + \ + (this->get_full_secs() * fast_llround(tick_rate)); } double time_spec_t::get_real_secs(void) const{ diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index bd60e75cf..d7effcac1 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -41,7 +41,7 @@ using namespace uhd::transport; **********************************************************************/ struct b100_impl::io_impl{ io_impl(void): - async_msg_fifo(100/*messages deep*/) + async_msg_fifo(1000/*messages deep*/) { /* NOP */ } zero_copy_if::sptr data_transport; diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index ea0384dbe..cebf92f6a 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -121,7 +121,7 @@ public: //issue the stream command _iface->poke32(REG_RX_CTRL_STREAM_CMD, cmd_word); - const boost::uint64_t ticks = stream_cmd.time_spec.to_ticks(_tick_rate); + const boost::uint64_t ticks = (stream_cmd.stream_now)? 0 : stream_cmd.time_spec.to_ticks(_tick_rate); _iface->poke32(REG_RX_CTRL_TIME_HI, boost::uint32_t(ticks >> 32)); _iface->poke32(REG_RX_CTRL_TIME_LO, boost::uint32_t(ticks >> 0)); //latches the command } diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index f8e15f3fd..b090e45c7 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -50,7 +50,7 @@ using namespace uhd::transport; **********************************************************************/ struct e100_impl::io_impl{ io_impl(void): - false_alarm(0), async_msg_fifo(100/*messages deep*/) + false_alarm(0), async_msg_fifo(1000/*messages deep*/) { /* NOP */ } double tick_rate; //set by update tick rate method diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp index b8af8af06..90b3a92da 100644 --- a/host/lib/usrp/usrp1/soft_time_ctrl.cpp +++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp @@ -39,8 +39,8 @@ public: _nsamps_remaining(0), _stream_mode(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS), _cmd_queue(2), - _async_msg_queue(100), - _inline_msg_queue(100), + _async_msg_queue(1000), + _inline_msg_queue(1000), _stream_on_off(stream_on_off) { //synchronously spawn a new thread diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f0c159f16..221b747cb 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -135,7 +135,8 @@ private: struct usrp2_impl::io_impl{ io_impl(void): - async_msg_fifo(100/*messages deep*/) + async_msg_fifo(1000/*messages deep*/), + tick_rate(1 /*non-zero default*/) { /* NOP */ } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index f3d474a2d..eeba6756e 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -87,7 +87,7 @@ public: //Obtain the firmware's compat number. //Save the response compat number for communication. //TODO can choose to reject certain older compat numbers - usrp2_ctrl_data_t ctrl_data; + usrp2_ctrl_data_t ctrl_data = usrp2_ctrl_data_t(); ctrl_data.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO); ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0); if (ntohl(ctrl_data.id) != USRP2_CTRL_ID_WAZZUP_DUDE) @@ -126,10 +126,9 @@ public: bool is_device_locked(void){ boost::uint32_t lock_secs = this->get_reg(U2_FW_REG_LOCK_TIME); boost::uint32_t lock_gpid = this->get_reg(U2_FW_REG_LOCK_GPID); - boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_LO_RB_IMM)/100e6; //if the difference is larger, assume not locked anymore - if (curr_secs - lock_secs >= 3) return false; + if (this->get_curr_secs() - lock_secs >= 3) return false; //otherwise only lock if the device hash is different that ours return lock_gpid != boost::uint32_t(get_gpid()); @@ -137,12 +136,16 @@ public: void lock_task(void){ //re-lock in task - boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_LO_RB_IMM)/100e6; - this->get_reg(U2_FW_REG_LOCK_TIME, curr_secs); + this->get_reg(U2_FW_REG_LOCK_TIME, this->get_curr_secs()); //sleep for a bit boost::this_thread::sleep(boost::posix_time::milliseconds(1500)); } + boost::uint32_t get_curr_secs(void){ + //may not be the right tick rate, but this is ok for locking purposes + return boost::uint32_t(this->peek32(U2_REG_TIME64_LO_RB_IMM)/100e6); + } + /*********************************************************************** * Peek and Poke **********************************************************************/ diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp index d82014d3f..6b0ae53a9 100644 --- a/host/tests/convert_test.cpp +++ b/host/tests/convert_test.cpp @@ -124,8 +124,8 @@ static void test_convert_types_for_floats( //fill the input samples std::vector input(nsamps), output(nsamps); BOOST_FOREACH(data_type &in, input) in = data_type( - ((std::rand()/value_type(RAND_MAX/2)) - 1)*extra_scale, - ((std::rand()/value_type(RAND_MAX/2)) - 1)*extra_scale + ((std::rand()/value_type(RAND_MAX/2)) - 1)*float(extra_scale), + ((std::rand()/value_type(RAND_MAX/2)) - 1)*float(extra_scale) ); //run the loopback and test -- cgit v1.2.3 From 3060006b35859c8766e00d3b234b51a19aa8595f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 14 Feb 2012 18:26:03 -0800 Subject: uhd: added async md user payload and common utils --- host/include/uhd/types/metadata.hpp | 15 ++++-- host/lib/usrp/b100/io_impl.cpp | 26 +++++----- host/lib/usrp/common/async_packet_handler.hpp | 71 +++++++++++++++++++++++++++ host/lib/usrp/e100/io_impl.cpp | 18 ++----- host/lib/usrp/usrp2/io_impl.cpp | 18 ++----- 5 files changed, 100 insertions(+), 48 deletions(-) create mode 100644 host/lib/usrp/common/async_packet_handler.hpp (limited to 'host/lib/usrp/e100/io_impl.cpp') diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 269c77c7c..788999900 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2012 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 @@ -20,6 +20,7 @@ #include #include +#include namespace uhd{ @@ -140,13 +141,21 @@ namespace uhd{ EVENT_CODE_UNDERFLOW = 0x2, //! Packet loss between host and device. EVENT_CODE_SEQ_ERROR = 0x4, - //! Packet had time that was late (or too early). + //! Packet had time that was late. EVENT_CODE_TIME_ERROR = 0x8, //! Underflow occurred inside a packet. EVENT_CODE_UNDERFLOW_IN_PACKET = 0x10, //! Packet loss within a burst. - EVENT_CODE_SEQ_ERROR_IN_BURST = 0x20 + EVENT_CODE_SEQ_ERROR_IN_BURST = 0x20, + //! Some kind of custom user payload + EVENT_CODE_USER_PAYLOAD = 0x40 } event_code; + + /*! + * A special payload populated by custom FPGA fabric. + */ + boost::uint32_t user_payload[4]; + }; } //namespace uhd diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 6f8d3fb52..674380cca 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -17,6 +17,7 @@ #include "recv_packet_demuxer.hpp" #include "validate_subdev_spec.hpp" +#include "async_packet_handler.hpp" #include "../../transport/super_recv_packet_handler.hpp" #include "../../transport/super_send_packet_handler.hpp" #include "usrp_commands.h" @@ -47,6 +48,7 @@ struct b100_impl::io_impl{ zero_copy_if::sptr data_transport; bounded_buffer async_msg_fifo; recv_packet_demuxer::sptr demuxer; + double tick_rate; }; /*********************************************************************** @@ -81,24 +83,16 @@ void b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){ } if (if_packet_info.sid == B100_TX_ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ + //fill in the async metadata async_metadata_t metadata; - metadata.channel = 0; - metadata.has_time_spec = if_packet_info.has_tsf; - metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, _clock_ctrl->get_fpga_clock_rate()); - metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info)); + load_metadata_from_buff(uhd::wtohx, metadata, if_packet_info, vrt_hdr, _io_impl->tick_rate); + + //push the message onto the queue _io_impl->async_msg_fifo.push_with_pop_on_full(metadata); - if (metadata.event_code & - ( async_metadata_t::EVENT_CODE_UNDERFLOW - | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) - ) UHD_MSG(fastpath) << "U"; - else if (metadata.event_code & - ( async_metadata_t::EVENT_CODE_SEQ_ERROR - | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) - ) UHD_MSG(fastpath) << "S"; - else if (metadata.event_code & - async_metadata_t::EVENT_CODE_TIME_ERROR - ) UHD_MSG(fastpath) << "L"; + + //print some fastpath messages + standard_async_msg_prints(metadata); } else UHD_MSG(error) << "Unknown async packet" << std::endl; } @@ -117,6 +111,8 @@ void b100_impl::update_rates(void){ } void b100_impl::update_tick_rate(const double rate){ + _io_impl->tick_rate = rate; + //update the tick rate on all existing streamers -> thread safe for (size_t i = 0; i < _rx_streamers.size(); i++){ boost::shared_ptr my_streamer = diff --git a/host/lib/usrp/common/async_packet_handler.hpp b/host/lib/usrp/common/async_packet_handler.hpp new file mode 100644 index 000000000..fef03483f --- /dev/null +++ b/host/lib/usrp/common/async_packet_handler.hpp @@ -0,0 +1,71 @@ +// +// Copyright 2012 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 . +// + +#ifndef INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP +#define INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP + +#include +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ + + template + void load_metadata_from_buff( + const to_host_type &to_host, + async_metadata_t &metadata, + const transport::vrt::if_packet_info_t &if_packet_info, + const boost::uint32_t *vrt_hdr, + const double tick_rate, + const size_t channel = 0 + ){ + const boost::uint32_t *payload = vrt_hdr + if_packet_info.num_header_words32; + + //load into metadata + metadata.channel = channel; + metadata.has_time_spec = if_packet_info.has_tsf; + metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, tick_rate); + metadata.event_code = async_metadata_t::event_code_t(to_host(payload[0]) & 0xff); + + //load user payload + for (size_t i = 1; i < if_packet_info.num_payload_words32; i++){ + if (i-1 == 4) break; //limit of 4 words32 + metadata.user_payload[i-1] = to_host(payload[i]); + } + } + + UHD_INLINE void standard_async_msg_prints(const async_metadata_t &metadata) + { + if (metadata.event_code & + ( async_metadata_t::EVENT_CODE_UNDERFLOW + | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) + ) UHD_MSG(fastpath) << "U"; + else if (metadata.event_code & + ( async_metadata_t::EVENT_CODE_SEQ_ERROR + | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) + ) UHD_MSG(fastpath) << "S"; + else if (metadata.event_code & + async_metadata_t::EVENT_CODE_TIME_ERROR + ) UHD_MSG(fastpath) << "L"; + } + + +}} //namespace uhd::usrp + +#endif /* INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP */ diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index b090e45c7..e9608125f 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -17,6 +17,7 @@ #include "recv_packet_demuxer.hpp" #include "validate_subdev_spec.hpp" +#include "async_packet_handler.hpp" #include "../../transport/super_recv_packet_handler.hpp" #include "../../transport/super_send_packet_handler.hpp" #include //ioctl structures and constants @@ -123,26 +124,13 @@ void e100_impl::io_impl::handle_irq(void){ //fill in the async metadata async_metadata_t metadata; - metadata.channel = 0; - metadata.has_time_spec = if_packet_info.has_tsf; - metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, tick_rate); - metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(data.buf, if_packet_info)); + load_metadata_from_buff(uhd::wtohx, metadata, if_packet_info, data.buf, tick_rate); //push the message onto the queue async_msg_fifo.push_with_pop_on_full(metadata); //print some fastpath messages - if (metadata.event_code & - ( async_metadata_t::EVENT_CODE_UNDERFLOW - | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) - ) UHD_MSG(fastpath) << "U"; - else if (metadata.event_code & - ( async_metadata_t::EVENT_CODE_SEQ_ERROR - | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) - ) UHD_MSG(fastpath) << "S"; - else if (metadata.event_code & - async_metadata_t::EVENT_CODE_TIME_ERROR - ) UHD_MSG(fastpath) << "L"; + standard_async_msg_prints(metadata); } //prepare for the next round diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 221b747cb..d32ffb62c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -16,6 +16,7 @@ // #include "validate_subdev_spec.hpp" +#include "async_packet_handler.hpp" #include "../../transport/super_recv_packet_handler.hpp" #include "../../transport/super_send_packet_handler.hpp" #include "usrp2_impl.hpp" @@ -202,10 +203,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( //fill in the async metadata async_metadata_t metadata; - metadata.channel = index; - metadata.has_time_spec = if_packet_info.has_tsf; - metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, tick_rate); - metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info)); + load_metadata_from_buff(uhd::ntohx, metadata, if_packet_info, vrt_hdr, tick_rate, index); //catch the flow control packets and react if (metadata.event_code == 0){ @@ -216,17 +214,7 @@ void usrp2_impl::io_impl::recv_pirate_loop( //else UHD_MSG(often) << "metadata.event_code " << metadata.event_code << std::endl; async_msg_fifo.push_with_pop_on_full(metadata); - if (metadata.event_code & - ( async_metadata_t::EVENT_CODE_UNDERFLOW - | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) - ) UHD_MSG(fastpath) << "U"; - else if (metadata.event_code & - ( async_metadata_t::EVENT_CODE_SEQ_ERROR - | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) - ) UHD_MSG(fastpath) << "S"; - else if (metadata.event_code & - async_metadata_t::EVENT_CODE_TIME_ERROR - ) UHD_MSG(fastpath) << "L"; + standard_async_msg_prints(metadata); } else{ //TODO unknown received packet, may want to print error... -- cgit v1.2.3