From e4561a18cd4bbcf8a20799704c42bfb4c2543dc2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 14:41:57 -0700 Subject: usrp1: did work for stream interface on usrp1 --- host/lib/usrp/usrp1/usrp1_impl.hpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 68ce31a54..7776ea8d6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -55,21 +55,8 @@ public: ~usrp1_impl(void); //the io interface - size_t send(const send_buffs_type &, - size_t, - const uhd::tx_metadata_t &, - const uhd::io_type_t &, - send_mode_t, double); - - size_t recv(const recv_buffs_type &, - size_t, uhd::rx_metadata_t &, - const uhd::io_type_t &, - recv_mode_t, double); - - size_t get_max_send_samps_per_packet(void) const; - - size_t get_max_recv_samps_per_packet(void) const; - + uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); + uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: @@ -94,6 +81,10 @@ private: double _master_clock_rate; //clock rate shadow + //weak pointers to streamers for update purposes + boost::weak_ptr _rx_streamer; + boost::weak_ptr _tx_streamer; + void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &); void set_db_eeprom(const std::string &, const std::string &, const uhd::usrp::dboard_eeprom_t &); double update_rx_codec_gain(const std::string &, const double); //sets A and B at once @@ -101,6 +92,7 @@ private: void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); double update_rx_samp_rate(const double); double update_tx_samp_rate(const double); + void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); @@ -119,8 +111,7 @@ private: void tx_stream_on_off(bool); void handle_overrun(size_t); - //otw types - uhd::otw_type_t _rx_otw_type, _tx_otw_type; + //channel mapping shadows uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; //capabilities -- cgit v1.2.3 From fac15db5d77c5196badb4a06f2f5fec34eb57337 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 09:25:54 -0700 Subject: uhd: renamed some of the stream types and functions --- host/examples/benchmark_rate.cpp | 8 +- host/examples/latency_test.cpp | 6 +- host/examples/rx_ascii_art_dft.cpp | 4 +- host/examples/rx_multi_samples.cpp | 4 +- host/examples/rx_samples_to_file.cpp | 4 +- host/examples/rx_samples_to_udp.cpp | 4 +- host/examples/rx_timed_samples.cpp | 4 +- host/examples/test_messages.cpp | 6 +- host/examples/tx_bursts.cpp | 4 +- host/examples/tx_samples_from_file.cpp | 4 +- host/examples/tx_timed_samples.cpp | 4 +- host/examples/tx_waveforms.cpp | 4 +- host/include/uhd/CMakeLists.txt | 2 +- host/include/uhd/device.hpp | 6 +- host/include/uhd/device_deprecated.ipp | 16 +- host/include/uhd/stream.hpp | 189 +++++++++++++++++++++++ host/include/uhd/streamer.hpp | 189 ----------------------- host/include/uhd/usrp/multi_usrp.hpp | 8 +- host/lib/transport/super_recv_packet_handler.hpp | 2 +- host/lib/transport/super_send_packet_handler.hpp | 2 +- host/lib/usrp/usrp1/io_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 +- host/lib/usrp/usrp2/io_impl.cpp | 4 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 4 +- 24 files changed, 243 insertions(+), 243 deletions(-) create mode 100644 host/include/uhd/stream.hpp delete mode 100644 host/include/uhd/streamer.hpp (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp index 7862bd44b..fce184514 100644 --- a/host/examples/benchmark_rate.cpp +++ b/host/examples/benchmark_rate.cpp @@ -44,8 +44,8 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //print pre-test summary std::cout << boost::format( @@ -98,8 +98,8 @@ void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //print pre-test summary std::cout << boost::format( diff --git a/host/examples/latency_test.cpp b/host/examples/latency_test.cpp index b995b0433..518d2383a 100644 --- a/host/examples/latency_test.cpp +++ b/host/examples/latency_test.cpp @@ -84,9 +84,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::vector > buffer(nsamps); //create RX and TX streamers - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //initialize result counts int time_error = 0; diff --git a/host/examples/rx_ascii_art_dft.cpp b/host/examples/rx_ascii_art_dft.cpp index 14b83fb65..2e5bbba9d 100644 --- a/host/examples/rx_ascii_art_dft.cpp +++ b/host/examples/rx_ascii_art_dft.cpp @@ -148,8 +148,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //allocate recv buffer and metatdata uhd::rx_metadata_t md; diff --git a/host/examples/rx_multi_samples.cpp b/host/examples/rx_multi_samples.cpp index 56aed60af..7561f1285 100644 --- a/host/examples/rx_multi_samples.cpp +++ b/host/examples/rx_multi_samples.cpp @@ -113,10 +113,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a receive streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) - uhd::streamer_args stream_args("fc32"); //complex floats + uhd::stream_args_t stream_args("fc32"); //complex floats for (size_t chan = 0; chan < usrp->get_rx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming std::cout << std::endl; diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 58bd158a5..605439748 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -39,8 +39,8 @@ template void recv_to_file( size_t samps_per_buff ){ //create a receive streamer - uhd::streamer_args stream_args(cpu_format); - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args(cpu_format); + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); uhd::rx_metadata_t md; std::vector buff(samps_per_buff); diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp index 3db436ad5..cf7fd493a 100644 --- a/host/examples/rx_samples_to_udp.cpp +++ b/host/examples/rx_samples_to_udp.cpp @@ -131,8 +131,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 6389375d9..0851593cd 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -71,8 +71,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming std::cout << std::endl; diff --git a/host/examples/test_messages.cpp b/host/examples/test_messages.cpp index 668f25ef3..f24a172d1 100644 --- a/host/examples/test_messages.cpp +++ b/host/examples/test_messages.cpp @@ -302,9 +302,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //create RX and TX streamers - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //------------------------------------------------------------------ // begin messages test diff --git a/host/examples/tx_bursts.cpp b/host/examples/tx_bursts.cpp index 98853ce20..f5ae18a9f 100644 --- a/host/examples/tx_bursts.cpp +++ b/host/examples/tx_bursts.cpp @@ -94,8 +94,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate buffer with data to send const size_t spb = tx_stream->get_max_num_samps(); diff --git a/host/examples/tx_samples_from_file.cpp b/host/examples/tx_samples_from_file.cpp index 09939183b..964c6cea8 100644 --- a/host/examples/tx_samples_from_file.cpp +++ b/host/examples/tx_samples_from_file.cpp @@ -34,8 +34,8 @@ template void send_from_file( size_t samps_per_buff ){ //create a transmit streamer - uhd::streamer_args stream_args(cpu_format); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args(cpu_format); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); uhd::tx_metadata_t md; md.start_of_burst = false; diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 3daf1974a..3b8cc75d4 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -74,8 +74,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate buffer with data to send std::vector > buff(tx_stream->get_max_num_samps(), std::complex(ampl, ampl)); diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 9aa3ec71f..1eb6c2f1e 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -204,10 +204,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a transmit streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) - uhd::streamer_args stream_args("fc32"); + uhd::stream_args_t stream_args("fc32"); for (size_t chan = 0; chan < usrp->get_tx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate a buffer which we re-use for each channel std::vector > buff(spb); diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 6b277654d..2b0c6ec14 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -30,7 +30,7 @@ INSTALL(FILES exception.hpp property_tree.ipp property_tree.hpp - streamer.hpp + stream.hpp version.hpp wax.hpp DESTINATION ${INCLUDE_DIR}/uhd diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index c96139858..89c6332da 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_DEVICE_HPP #include -#include +#include #include #include #include @@ -77,10 +77,10 @@ public: static sptr make(const device_addr_t &hint, size_t which = 0); //! Make a new receive streamer from the streamer arguments - virtual rx_streamer::sptr get_rx_streamer(const streamer_args &args) = 0; + virtual rx_streamer::sptr get_rx_stream(const stream_args_t &args) = 0; //! Make a new transmit streamer from the streamer arguments - virtual tx_streamer::sptr get_tx_streamer(const streamer_args &args) = 0; + virtual tx_streamer::sptr get_tx_stream(const stream_args_t &args) = 0; /*! * Receive and asynchronous message from the device. diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp index 7afaaca2d..8e61c389f 100644 --- a/host/include/uhd/device_deprecated.ipp +++ b/host/include/uhd/device_deprecated.ipp @@ -80,12 +80,12 @@ size_t send( if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size() or _send_tid != io_type.tid){ _send_tid = io_type.tid; _tx_streamer.reset(); //cleanup possible old one - streamer_args args; + stream_args_t args; args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; for (size_t ch = 0; ch < buffs.size(); ch++) args.channels.push_back(ch); //linear mapping - _tx_streamer = get_tx_streamer(args); + _tx_streamer = get_tx_stream(args); } const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_send_samps_per_packet()) : @@ -135,12 +135,12 @@ size_t recv( if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size() or _recv_tid != io_type.tid){ _recv_tid = io_type.tid; _rx_streamer.reset(); //cleanup possible old one - streamer_args args; + stream_args_t args; args.cpu_format = (_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; for (size_t ch = 0; ch < buffs.size(); ch++) args.channels.push_back(ch); //linear mapping - _rx_streamer = get_rx_streamer(args); + _rx_streamer = get_rx_stream(args); } const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_recv_samps_per_packet()) : @@ -154,10 +154,10 @@ size_t recv( */ size_t get_max_send_samps_per_packet(void){ if (_tx_streamer.get() == NULL){ - streamer_args args; + stream_args_t args; args.cpu_format = "fc32"; args.otw_format = "sc16"; - _tx_streamer = get_tx_streamer(args); + _tx_streamer = get_tx_stream(args); _send_tid = io_type_t::COMPLEX_FLOAT32; } return _tx_streamer->get_max_num_samps(); @@ -169,10 +169,10 @@ size_t get_max_send_samps_per_packet(void){ */ size_t get_max_recv_samps_per_packet(void){ if (_rx_streamer.get() == NULL){ - streamer_args args; + stream_args_t args; args.cpu_format = "fc32"; args.otw_format = "sc16"; - _rx_streamer = get_rx_streamer(args); + _rx_streamer = get_rx_stream(args); _recv_tid = io_type_t::COMPLEX_FLOAT32; } return _rx_streamer->get_max_num_samps(); diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp new file mode 100644 index 000000000..583dfd1e4 --- /dev/null +++ b/host/include/uhd/stream.hpp @@ -0,0 +1,189 @@ +// +// Copyright 2011 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_UHD_STREAM_HPP +#define INCLUDED_UHD_STREAM_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ + +/*! + * A struct of parameters to construct a streamer. + * + * Note: + * Not all combinations of CPU and OTW format have conversion support. + * You may however write and register your own conversion routines. + */ +struct UHD_API stream_args_t{ + + //! Convenience constructor for streamer args + stream_args_t( + const std::string &cpu = "fc32", + const std::string &otw = "sc16" + ){ + cpu_format = cpu; + otw_format = otw; + } + + /*! + * The CPU format is a string that describes the format of host memory. + * Common CPU formats are: + * - fc32 - complex + * - fc64 - complex + * - sc16 - complex + * - sc8 - complex + * - f32 - float + * - f64 - double + * - s16 - int16_t + * - s8 - int8_t + */ + std::string cpu_format; + + /*! + * The OTW format is a string that describes the format over-the-wire. + * Common OTW format are: + * - sc16 - Q16 I16 + * - sc8 - Q8_1 I8_1 Q8_0 I8_0 + * - s16 - R16_1 R16_0 + * - s8 - R8_3 R8_2 R8_1 R8_0 + */ + std::string otw_format; + + /*! + * The args parameter is currently unused. Leave it blank. + * The intention is that a user with a custom DSP design + * may want to pass args and do something special with it. + */ + std::string args; + + /*! + * The channels is a list of channel numbers. + * Leave this blank to default to channel 0. + * Set channels for a multi-channel application. + * Channel mapping depends on the front-end selection. + */ + std::vector channels; +}; + +/*! + * The RX streamer is the host interface to receiving samples. + * It represents the layer between the samples on the host + * and samples inside the device's receive DSP processing. + */ +class UHD_API rx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of recv buffers + typedef ref_vector buffs_type; + + /*! + * Receive buffers containing samples described by the metadata. + * + * Receive handles fragmentation as follows: + * If the buffer has insufficient space to hold all samples + * that were received in a single packet over-the-wire, + * then the buffer will be completely filled and the implementation + * will hold a pointer into the remaining portion of the packet. + * Subsequent calls will load from the remainder of the packet, + * and will flag the metadata to show that this is a fragment. + * The next call to receive, after the remainder becomes exahausted, + * will perform an over-the-wire receive as usual. + * See the rx metadata fragment flags and offset fields for details. + * + * This is a blocking call and will not return until the number + * of samples returned have been written into each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of writable memory to fill with samples + * \param nsamps_per_buff the size of each buffer in number of samples + * \param metadata data to fill describing the buffer + * \param timeout the timeout in seconds to wait for a packet + * \return the number of samples received or 0 on error + */ + virtual size_t recv( + const buffs_type &buffs, + const size_t nsamps_per_buff, + rx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +/*! + * The TX streamer is the host interface to transmitting samples. + * It represents the layer between the samples on the host + * and samples inside the device's transmit DSP processing. + */ +class UHD_API tx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of send buffers + typedef ref_vector buffs_type; + + /*! + * Send buffers containing samples described by the metadata. + * + * Send handles fragmentation as follows: + * If the buffer has more items than the maximum per packet, + * the send method will fragment the samples across several packets. + * Send will respect the burst flags when fragmenting to ensure + * that start of burst can only be set on the first fragment and + * that end of burst can only be set on the final fragment. + * + * This is a blocking call and will not return until the number + * of samples returned have been read out of each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of read-only memory containing samples + * \param nsamps_per_buff the number of samples to send, per buffer + * \param metadata data describing the buffer's contents + * \param timeout the timeout in seconds to wait on a packet + * \return the number of samples sent + */ + virtual size_t send( + const buffs_type &buffs, + const size_t nsamps_per_buff, + const tx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_STREAM_HPP */ diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp deleted file mode 100644 index c9c6fef89..000000000 --- a/host/include/uhd/streamer.hpp +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright 2011 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_UHD_STREAMER_HPP -#define INCLUDED_UHD_STREAMER_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace uhd{ - -/*! - * A struct of parameters to construct a streamer. - * - * Note: - * Not all combinations of CPU and OTW format have conversion support. - * You may however write and register your own conversion routines. - */ -struct UHD_API streamer_args{ - - //! Convenience constructor for streamer args - streamer_args( - const std::string &cpu = "fc32", - const std::string &otw = "sc16" - ){ - cpu_format = cpu; - otw_format = otw; - } - - /*! - * The CPU format is a string that describes the format of host memory. - * Common CPU formats are: - * - fc32 - complex - * - fc64 - complex - * - sc16 - complex - * - sc8 - complex - * - f32 - float - * - f64 - double - * - s16 - int16_t - * - s8 - int8_t - */ - std::string cpu_format; - - /*! - * The OTW format is a string that describes the format over-the-wire. - * Common OTW format are: - * - sc16 - Q16 I16 - * - sc8 - Q8_1 I8_1 Q8_0 I8_0 - * - s16 - R16_1 R16_0 - * - s8 - R8_3 R8_2 R8_1 R8_0 - */ - std::string otw_format; - - /*! - * The args parameter is currently unused. Leave it blank. - * The intention is that a user with a custom DSP design - * may want to pass args and do something special with it. - */ - std::string args; - - /*! - * The channels is a list of channel numbers. - * Leave this blank to default to channel 0. - * Set channels for a multi-channel application. - * Channel mapping depends on the front-end selection. - */ - std::vector channels; -}; - -/*! - * The RX streamer is the host interface to receiving samples. - * It represents the layer between the samples on the host - * and samples inside the device's receive DSP processing. - */ -class UHD_API rx_streamer : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - //! Get the number of channels associated with this streamer - virtual size_t get_num_channels(void) const = 0; - - //! Get the max number of samples per buffer per packet - virtual size_t get_max_num_samps(void) const = 0; - - //! Typedef for a pointer to a single, or a collection of recv buffers - typedef ref_vector buffs_type; - - /*! - * Receive buffers containing samples described by the metadata. - * - * Receive handles fragmentation as follows: - * If the buffer has insufficient space to hold all samples - * that were received in a single packet over-the-wire, - * then the buffer will be completely filled and the implementation - * will hold a pointer into the remaining portion of the packet. - * Subsequent calls will load from the remainder of the packet, - * and will flag the metadata to show that this is a fragment. - * The next call to receive, after the remainder becomes exahausted, - * will perform an over-the-wire receive as usual. - * See the rx metadata fragment flags and offset fields for details. - * - * This is a blocking call and will not return until the number - * of samples returned have been written into each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * \param buffs a vector of writable memory to fill with samples - * \param nsamps_per_buff the size of each buffer in number of samples - * \param metadata data to fill describing the buffer - * \param timeout the timeout in seconds to wait for a packet - * \return the number of samples received or 0 on error - */ - virtual size_t recv( - const buffs_type &buffs, - const size_t nsamps_per_buff, - rx_metadata_t &metadata, - double timeout = 0.1 - ) = 0; -}; - -/*! - * The TX streamer is the host interface to transmitting samples. - * It represents the layer between the samples on the host - * and samples inside the device's transmit DSP processing. - */ -class UHD_API tx_streamer : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - //! Get the number of channels associated with this streamer - virtual size_t get_num_channels(void) const = 0; - - //! Get the max number of samples per buffer per packet - virtual size_t get_max_num_samps(void) const = 0; - - //! Typedef for a pointer to a single, or a collection of send buffers - typedef ref_vector buffs_type; - - /*! - * Send buffers containing samples described by the metadata. - * - * Send handles fragmentation as follows: - * If the buffer has more items than the maximum per packet, - * the send method will fragment the samples across several packets. - * Send will respect the burst flags when fragmenting to ensure - * that start of burst can only be set on the first fragment and - * that end of burst can only be set on the final fragment. - * - * This is a blocking call and will not return until the number - * of samples returned have been read out of each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * \param buffs a vector of read-only memory containing samples - * \param nsamps_per_buff the number of samples to send, per buffer - * \param metadata data describing the buffer's contents - * \param timeout the timeout in seconds to wait on a packet - * \return the number of samples sent - */ - virtual size_t send( - const buffs_type &buffs, - const size_t nsamps_per_buff, - const tx_metadata_t &metadata, - double timeout = 0.1 - ) = 0; -}; - -} //namespace uhd - -#endif /* INCLUDED_UHD_STREAMER_HPP */ diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 303af7ef9..72386204f 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -109,13 +109,13 @@ public: virtual device::sptr get_device(void) = 0; //! Convenience method to get a RX streamer - rx_streamer::sptr get_rx_streamer(const streamer_args &args){ - return this->get_device()->get_rx_streamer(args); + rx_streamer::sptr get_rx_stream(const stream_args_t &args){ + return this->get_device()->get_rx_stream(args); } //! Convenience method to get a TX streamer - tx_streamer::sptr get_tx_streamer(const streamer_args &args){ - return this->get_device()->get_tx_streamer(args); + tx_streamer::sptr get_tx_stream(const stream_args_t &args){ + return this->get_device()->get_tx_stream(args); } /******************************************************************* diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index f4dbc5531..de7b4b34c 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 079fea11e..42bac5e21 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 7d4fe2ec7..22c2db6ae 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -527,7 +527,7 @@ bool usrp1_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ +rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -567,7 +567,7 @@ rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp1_impl::get_tx_streamer(const uhd::streamer_args &args){ +tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 7776ea8d6..c777307ee 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -55,8 +55,8 @@ public: ~usrp1_impl(void); //the io interface - uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); - uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f271d480a..d37be403b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -366,7 +366,7 @@ bool usrp2_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ +rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -426,7 +426,7 @@ rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp2_impl::get_tx_streamer(const uhd::streamer_args &args){ +tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index a67c704c8..31a390af7 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -72,8 +72,8 @@ public: ~usrp2_impl(void); //the io interface - uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); - uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: -- cgit v1.2.3 From 4c4f0810ef06be18e989b6933ff236ff97c13dd0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 18:41:59 -0700 Subject: usrp1: type conversions and 8-bit work --- host/lib/convert/convert_common.hpp | 12 ++-- host/lib/convert/gen_convert_general.py | 102 ++++++++++++++++++++++++++------ host/lib/usrp/usrp1/io_impl.cpp | 69 ++++++++++++++------- host/lib/usrp/usrp1/usrp1_calc_mux.hpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 +- 6 files changed, 143 insertions(+), 52 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 8c8cc88b0..612fa312b 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -86,19 +86,19 @@ static UHD_INLINE sc16_t item32_to_sc16(item32_t item, double){ /*********************************************************************** * Convert complex float buffer to items32 (no swap) **********************************************************************/ -static UHD_INLINE item32_t fc32_to_item32(fc32_t num, float scale_factor){ - boost::uint16_t real = boost::int16_t(num.real()*scale_factor); - boost::uint16_t imag = boost::int16_t(num.imag()*scale_factor); +static UHD_INLINE item32_t fc32_to_item32(fc32_t num, double scale_factor){ + boost::uint16_t real = boost::int16_t(num.real()*float(scale_factor)); + boost::uint16_t imag = boost::int16_t(num.imag()*float(scale_factor)); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** * Convert items32 buffer to complex float **********************************************************************/ -static UHD_INLINE fc32_t item32_to_fc32(item32_t item, float scale_factor){ +static UHD_INLINE fc32_t item32_to_fc32(item32_t item, double scale_factor){ return fc32_t( - float(boost::int16_t(item >> 16)*scale_factor), - float(boost::int16_t(item >> 0)*scale_factor) + float(boost::int16_t(item >> 16)*float(scale_factor)), + float(boost::int16_t(item >> 0)*float(scale_factor)) ); } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 0d68a4dd3..a5c4d4cb7 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -28,13 +28,13 @@ TMPL_HEADER = """ using namespace uhd::convert; """ -TMPL_CONV_TO_FROM_ITEM32_1 = """ +TMPL_CONV_GEN2_COMPLEX = """ DECLARE_CONVERTER($(cpu_type), 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ const $(cpu_type)_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], float(scale_factor))); + output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], scale_factor)); } } @@ -43,33 +43,83 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), float(scale_factor)); + output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), scale_factor); } } """ -TMPL_CONV_TO_FROM_ITEM32_X = """ -DECLARE_CONVERTER($(cpu_type), $(width), sc16_item32_$(end), 1, PRIORITY_GENERAL){ + +TMPL_CONV_USRP1_COMPLEX = """ +DECLARE_CONVERTER($(cpu_type), $(width), sc16_item16_usrp1, 1, PRIORITY_GENERAL){ #for $w in range($width) const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); #end for - item32_t *output = reinterpret_cast(outputs[0]); + boost::uint16_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output[j++] = $(to_wire)($(cpu_type)_to_item32(input$(w)[i], float(scale_factor))); + output[j++] = $(to_wire)(boost::int16_t(input$(w)[i].real()$(do_scale))); + output[j++] = $(to_wire)(boost::int16_t(input$(w)[i].imag()$(do_scale))); #end for } } -DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), $(width), PRIORITY_GENERAL){ - const item32_t *input = reinterpret_cast(inputs[0]); +DECLARE_CONVERTER(sc16_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ + const boost::uint16_t *input = reinterpret_cast(inputs[0]); #for $w in range($width) $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]); #end for + if (scale_factor == 0){} //avoids unused warning + for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output$(w)[i] = item32_to_$(cpu_type)($(to_host)(input[j++]), float(scale_factor)); + output$(w)[i] = $(cpu_type)_t( + boost::int16_t($(to_host)(input[j+0]))$(do_scale), + boost::int16_t($(to_host)(input[j+1]))$(do_scale) + ); + j += 2; + #end for + } +} + +DECLARE_CONVERTER($(cpu_type), $(width), sc8_item16_usrp1, 1, PRIORITY_GENERAL){ + #for $w in range($width) + const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); + #end for + boost::uint16_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0, j = 0; i < nsamps; i++){ + #for $w in range($width) + { + const boost::uint8_t real = boost::int8_t(input$(w)[i].real()$(do_scale)); + const boost::uint8_t imag = boost::int8_t(input$(w)[i].imag()$(do_scale)); + output[j++] = $(to_wire)((boost::uint16_t(imag) << 8) | real); + } + #end for + } +} + +DECLARE_CONVERTER(sc8_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ + const boost::uint16_t *input = reinterpret_cast(inputs[0]); + #for $w in range($width) + $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]); + #end for + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0, j = 0; i < nsamps; i++){ + #for $w in range($width) + { + const boost::uint16_t num = $(to_host)(input[j++]); + output$(w)[i] = $(cpu_type)_t( + boost::int8_t(num)$(do_scale), + boost::int8_t(num >> 8)$(do_scale) + ); + } #end for } } @@ -83,14 +133,28 @@ if __name__ == '__main__': import sys, os file = os.path.basename(__file__) output = parse_tmpl(TMPL_HEADER, file=file) - for width in 1, 2, 3, 4: - for end, to_host, to_wire in ( - ('be', 'uhd::ntohx', 'uhd::htonx'), - ('le', 'uhd::wtohx', 'uhd::htowx'), + + #generate complex converters for all gen2 platforms + for end, to_host, to_wire in ( + ('be', 'uhd::ntohx', 'uhd::htonx'), + ('le', 'uhd::wtohx', 'uhd::htowx'), + ): + for cpu_type in 'fc64', 'fc32', 'sc16': + output += parse_tmpl( + TMPL_CONV_GEN2_COMPLEX, + end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type + ) + + #generate complex converters for usrp1 format + for width in 1, 2, 4: + for cpu_type, do_scale in ( + ('fc64', '*scale_factor'), + ('fc32', '*float(scale_factor)'), + ('sc16', ''), ): - for cpu_type in 'fc64', 'fc32', 'sc16': - output += parse_tmpl( - TMPL_CONV_TO_FROM_ITEM32_1 if width == 1 else TMPL_CONV_TO_FROM_ITEM32_X, - width=width, end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type - ) + output += parse_tmpl( + TMPL_CONV_USRP1_COMPLEX, + width=width, to_host='uhd::wtohx', to_wire='uhd::htowx', + cpu_type=cpu_type, do_scale=do_scale + ) open(sys.argv[1], 'w').write(output) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 03263ed26..7f20a8608 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -438,41 +438,45 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } -double usrp1_impl::update_rx_samp_rate(const double samp_rate){ +double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 + boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 16e6)), 256 ); - bool s = this->disable_rx(); - _iface->poke32(FR_DECIM_RATE, rate/2 - 1); - this->restore_rx(s); + if (dspno == 0){ //only care if dsp0 is set since its homogeneous + bool s = this->disable_rx(); + _iface->poke32(FR_DECIM_RATE, rate/2 - 1); + this->restore_rx(s); - //update the streamer if created - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_rx_streamer.lock()); - if (my_streamer.get() != NULL){ - my_streamer->set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } } return _master_clock_rate / rate; } -double usrp1_impl::update_tx_samp_rate(const double samp_rate){ +double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 ); - bool s = this->disable_tx(); - _iface->poke32(FR_INTERP_RATE, rate/2 - 1); - this->restore_tx(s); + if (dspno == 0){ //only care if dsp0 is set since its homogeneous + bool s = this->disable_tx(); + _iface->poke32(FR_INTERP_RATE, rate/2 - 1); + this->restore_tx(s); - //update the streamer if created - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_tx_streamer.lock()); - if (my_streamer.get() != NULL){ - my_streamer->set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } } return _master_clock_rate / rate; @@ -528,6 +532,25 @@ bool usrp1_impl::recv_async_msg( * Receive streamer **********************************************************************/ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ + if (args.otw_format == "sc16"){ + _iface->poke32(FR_RX_FORMAT, 0 + | (0 << bmFR_RX_FORMAT_SHIFT_SHIFT) + | (16 << bmFR_RX_FORMAT_WIDTH_SHIFT) + | bmFR_RX_FORMAT_WANT_Q + ); + } + else if (args.otw_format == "sc8"){ + _iface->poke32(FR_RX_FORMAT, 0 + | (8 << bmFR_RX_FORMAT_SHIFT_SHIFT) + | (8 << bmFR_RX_FORMAT_WIDTH_SHIFT) + | bmFR_RX_FORMAT_WANT_Q + | bmFR_RX_FORMAT_BYPASS_HB //needed for 16Msps + ); + } + else{ + throw uhd::value_error("USRP1 RX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -548,7 +571,7 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_le"; + id.input_markup = args.otw_format + "_item16_usrp1"; id.num_inputs = 1; id.output_markup = args.cpu_format; id.num_outputs = channels.size(); @@ -568,6 +591,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ * Transmit streamer **********************************************************************/ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ + if (args.otw_format != "sc16"){ + throw uhd::value_error("USRP1 TX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -591,7 +618,7 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ uhd::convert::id_type id; id.input_markup = args.cpu_format; id.num_inputs = channels.size(); - id.output_markup = args.otw_format + "_item32_le"; + id.output_markup = args.otw_format + "_item16_usrp1"; id.num_outputs = 1; id.args = args.args; my_streamer->set_converter(id); diff --git a/host/lib/usrp/usrp1/usrp1_calc_mux.hpp b/host/lib/usrp/usrp1/usrp1_calc_mux.hpp index 31c190db0..d86a7a809 100644 --- a/host/lib/usrp/usrp1/usrp1_calc_mux.hpp +++ b/host/lib/usrp/usrp1/usrp1_calc_mux.hpp @@ -37,7 +37,7 @@ typedef std::pair mapping_pair_t; * to account for the reversal in the type conversion routines. **********************************************************************/ static int calc_rx_mux_pair(int adc_for_i, int adc_for_q){ - return (adc_for_i << 2) | (adc_for_q << 0); //shift reversal here + return (adc_for_i << 0) | (adc_for_q << 2); } /*! @@ -98,7 +98,7 @@ static boost::uint32_t calc_rx_mux(const std::vector &mapping){ * to account for the reversal in the type conversion routines. **********************************************************************/ static int calc_tx_mux_pair(int chn_for_i, int chn_for_q){ - return (chn_for_i << 4) | (chn_for_q << 0); //shift reversal here + return (chn_for_i << 0) | (chn_for_q << 4); } /*! diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index d169c4823..93a301c02 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -282,7 +282,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") .set(1e6) - .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, _1)); + .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/range") @@ -303,7 +303,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); _tree->create(tx_dsp_path / "rate/value") .set(1e6) - .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, _1)); + .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/range") //magic scalar comes from codec control: diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index c777307ee..cfdcbbcc1 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -90,8 +90,8 @@ private: double update_rx_codec_gain(const std::string &, const double); //sets A and B at once void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); - double update_rx_samp_rate(const double); - double update_tx_samp_rate(const double); + double update_rx_samp_rate(size_t dspno, const double); + double update_tx_samp_rate(size_t dspno, const double); void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); -- cgit v1.2.3 From 5538048873f140f3ac2bbab12dc5b0729f68f1a5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 12:12:25 -0700 Subject: usrp1: support variable clock rate through API --- host/docs/usrp1.rst | 6 ++++++ host/lib/usrp/usrp1/dboard_iface.cpp | 26 +++++++++++++------------- host/lib/usrp/usrp1/io_impl.cpp | 9 +++++++++ host/lib/usrp/usrp1/usrp1_impl.cpp | 36 ++++++++++++++++++++++++++++-------- host/lib/usrp/usrp1/usrp1_impl.hpp | 5 ++++- 5 files changed, 60 insertions(+), 22 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index 8b274a2b3..597b5b17f 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -84,3 +84,9 @@ Run the following commands to record the setting into the EEPROM: cd /share/uhd/utils ./usrp_burn_mb_eeprom --args= --key=mcr --val= + +The user may override the clock rate specified in the EEPROM by using a device address: +Example: +:: + + uhd_usrp_probe --args="mcr=52e6" diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 449ec64fe..34bbe1893 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -39,7 +39,7 @@ public: usrp1_dboard_iface(usrp1_iface::sptr iface, usrp1_codec_ctrl::sptr codec, usrp1_impl::dboard_slot_t dboard_slot, - const double master_clock_rate, + const double &master_clock_rate, const dboard_id_t &rx_dboard_id ): _dboard_slot(dboard_slot), @@ -49,10 +49,8 @@ public: _iface = iface; _codec = codec; - //init the clock rate shadows - this->set_clock_rate(UNIT_RX, this->get_clock_rates(UNIT_RX).front()); - this->set_clock_rate(UNIT_TX, this->get_clock_rates(UNIT_TX).front()); - + _dbsrx_classic_div = 1; + //yes this is evil but it's necessary for TVRX to work on USRP1 if(_rx_dboard_id == tvrx_id) _codec->bypass_adc_buffers(false); //else _codec->bypass_adc_buffers(false); //don't think this is necessary @@ -103,9 +101,9 @@ public: private: usrp1_iface::sptr _iface; usrp1_codec_ctrl::sptr _codec; - uhd::dict _clock_rates; + unsigned _dbsrx_classic_div; const usrp1_impl::dboard_slot_t _dboard_slot; - const double _master_clock_rate; + const double &_master_clock_rate; const dboard_id_t _rx_dboard_id; }; @@ -115,7 +113,7 @@ private: dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface, usrp1_codec_ctrl::sptr codec, usrp1_impl::dboard_slot_t dboard_slot, - const double master_clock_rate, + const double &master_clock_rate, const dboard_id_t &rx_dboard_id ){ return dboard_iface::sptr(new usrp1_dboard_iface( @@ -137,17 +135,16 @@ static const dboard_id_t dbsrx_classic_id(0x0002); void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate) { assert_has(this->get_clock_rates(unit), rate, "dboard clock rate"); - _clock_rates[unit] = rate; if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ - size_t divider = size_t(_master_clock_rate/rate); + _dbsrx_classic_div = size_t(_master_clock_rate/rate); switch(_dboard_slot){ case usrp1_impl::DBOARD_SLOT_A: - _iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80); + _iface->poke32(FR_RX_A_REFCLK, (_dbsrx_classic_div & 0x7f) | 0x80); break; case usrp1_impl::DBOARD_SLOT_B: - _iface->poke32(FR_RX_B_REFCLK, (divider & 0x7f) | 0x80); + _iface->poke32(FR_RX_B_REFCLK, (_dbsrx_classic_div & 0x7f) | 0x80); break; } } @@ -168,7 +165,10 @@ std::vector usrp1_dboard_iface::get_clock_rates(unit_t unit) double usrp1_dboard_iface::get_clock_rate(unit_t unit) { - return _clock_rates[unit]; + if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ + return _master_clock_rate/_dbsrx_classic_div; + } + return _master_clock_rate; } void usrp1_dboard_iface::set_clock_enabled(unit_t, bool) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index a0fdfc6bf..f46f4741b 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -441,6 +441,14 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } + +void usrp1_impl::update_tick_rate(const double rate){ + //updating this variable should: + //update dboard iface -> it has a reference + //update dsp freq bounds -> publisher + _master_clock_rate = rate; +} + double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; @@ -495,6 +503,7 @@ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ void usrp1_impl::update_rates(void){ const fs_path mb_path = "/mboards/0"; + this->update_tick_rate(_master_clock_rate); BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").update(); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index db652b033..5788c536f 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -225,14 +225,25 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // create clock control objects //////////////////////////////////////////////////////////////////// _master_clock_rate = 64e6; - try{ - if (not mb_eeprom["mcr"].empty()) + if (device_addr.has_key("mcr")){ + try{ + _master_clock_rate = boost::lexical_cast(device_addr["mcr"]); + } + catch(const std::exception &e){ + UHD_MSG(error) << "Error parsing FPGA clock rate from device address: " << e.what() << std::endl; + } + } + else if (not mb_eeprom["mcr"].empty()){ + try{ _master_clock_rate = boost::lexical_cast(mb_eeprom["mcr"]); - }catch(const std::exception &e){ - UHD_MSG(error) << "Error parsing FPGA clock rate from EEPROM: " << e.what() << std::endl; + } + catch(const std::exception &e){ + UHD_MSG(error) << "Error parsing FPGA clock rate from EEPROM: " << e.what() << std::endl; + } } UHD_MSG(status) << boost::format("Using FPGA clock rate of %fMHz...") % (_master_clock_rate/1e6) << std::endl; - _tree->create(mb_path / "tick_rate").set(_master_clock_rate); + _tree->create(mb_path / "tick_rate") + .subscribe(boost::bind(&usrp1_impl::update_tick_rate, this, _1)); //////////////////////////////////////////////////////////////////// // create codec control objects @@ -278,7 +289,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/range") - .set(meta_range_t(-_master_clock_rate/2, +_master_clock_rate/2)); + .publish(boost::bind(&usrp1_impl::get_rx_dsp_freq_range, this)); _tree->create(rx_dsp_path / "stream_cmd"); if (dspno == 0){ //only subscribe the callback for dspno 0 since it will stream all dsps @@ -298,8 +309,8 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); - _tree->create(tx_dsp_path / "freq/range") //magic scalar comes from codec control: - .set(meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875)); + _tree->create(tx_dsp_path / "freq/range") + .publish(boost::bind(&usrp1_impl::get_tx_dsp_freq_range, this)); } //////////////////////////////////////////////////////////////////// @@ -443,3 +454,12 @@ double usrp1_impl::update_rx_codec_gain(const std::string &db, const double gain _dbc[db].codec->set_rx_pga_gain(gain, 'B'); return _dbc[db].codec->get_rx_pga_gain('A'); } + +uhd::meta_range_t usrp1_impl::get_rx_dsp_freq_range(void){ + return meta_range_t(-_master_clock_rate/2, +_master_clock_rate/2); +} + +uhd::meta_range_t usrp1_impl::get_tx_dsp_freq_range(void){ + //magic scalar comes from codec control: + return meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875); +} diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index cfdcbbcc1..6f427c31e 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -95,12 +95,15 @@ private: void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); + void update_tick_rate(const double rate); + uhd::meta_range_t get_rx_dsp_freq_range(void); + uhd::meta_range_t get_tx_dsp_freq_range(void); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, usrp1_codec_ctrl::sptr, dboard_slot_t, - const double, + const double &, const uhd::usrp::dboard_id_t & ); -- cgit v1.2.3 From ae9e89d76b2eb86a29995f04aaab1aa59ee93f04 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 16 Oct 2011 10:43:48 -0700 Subject: usrp: added get_tx/rx_rates --- host/include/uhd/usrp/multi_usrp.hpp | 16 ++++++++++++++++ host/lib/usrp/b100/b100_impl.cpp | 4 ++++ host/lib/usrp/cores/rx_dsp_core_200.cpp | 21 ++++++++++++++++----- host/lib/usrp/cores/rx_dsp_core_200.hpp | 2 ++ host/lib/usrp/cores/tx_dsp_core_200.cpp | 21 ++++++++++++++++----- host/lib/usrp/cores/tx_dsp_core_200.hpp | 2 ++ host/lib/usrp/e100/e100_impl.cpp | 4 ++++ host/lib/usrp/multi_usrp.cpp | 8 ++++++++ host/lib/usrp/usrp1/io_impl.cpp | 27 ++++++++++++++++++++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 8 ++++++-- host/lib/usrp/usrp1/usrp1_impl.hpp | 2 ++ host/lib/usrp/usrp2/usrp2_impl.cpp | 4 ++++ 12 files changed, 102 insertions(+), 17 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index ee7bf8424..baa47b39e 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -18,7 +18,9 @@ #ifndef INCLUDED_UHD_USRP_MULTI_USRP_HPP #define INCLUDED_UHD_USRP_MULTI_USRP_HPP +//define API capabilities for compile time detection of new features #define UHD_USRP_MULTI_USRP_REF_SOURCES_API +#define UHD_USRP_MULTI_USRP_GET_RATES_API #include #include @@ -367,6 +369,13 @@ public: */ virtual double get_rx_rate(size_t chan = 0) = 0; + /*! + * Get a range of possible RX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_rx_rates(size_t chan = 0) = 0; + /*! * Set the RX center frequency. * \param tune_request tune request instructions @@ -567,6 +576,13 @@ public: */ virtual double get_tx_rate(size_t chan = 0) = 0; + /*! + * Get a range of possible TX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_tx_rates(size_t chan = 0) = 0; + /*! * Set the TX center frequency. * \param tune_request tune request instructions diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index d1928735b..bb91d415d 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -296,6 +296,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1)); fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) @@ -317,6 +319,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tx_dsp->set_link_rate(B100_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index b121bc849..6d306d507 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -134,12 +134,23 @@ public: _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } + uhd::meta_range_t get_host_rates(void){ + meta_range_t range; + for (int rate = 512; rate > 256; rate -= 4){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 256; rate > 128; rate -= 2){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){ + range.push_back(range_t(_tick_rate/rate)); + } + return range; + } + double set_host_rate(const double rate){ - size_t decim_rate = uhd::clip( - boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512 - ); - if (decim_rate > 128) decim_rate &= ~0x1; //CIC up to 128, have to use 1 HB - if (decim_rate > 256) decim_rate &= ~0x3; //CIC up to 128, have to use 2 HB + const size_t decim_rate = this->get_host_rates().clip( + boost::math::iround(_tick_rate/rate), true); size_t decim = decim_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp index ddd6f2abf..89b8c1f51 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp @@ -48,6 +48,8 @@ public: virtual double set_host_rate(const double rate) = 0; + 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; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index f37b53527..1d571ea7c 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -74,12 +74,23 @@ public: _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } + uhd::meta_range_t get_host_rates(void){ + meta_range_t range; + for (int rate = 512; rate > 256; rate -= 4){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 256; rate > 128; rate -= 2){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){ + range.push_back(range_t(_tick_rate/rate)); + } + return range; + } + double set_host_rate(const double rate){ - size_t interp_rate = uhd::clip( - boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512 - ); - if (interp_rate > 128) interp_rate &= ~0x1; //CIC up to 128, have to use 1 HB - if (interp_rate > 256) interp_rate &= ~0x3; //CIC up to 128, have to use 2 HB + const size_t interp_rate = this->get_host_rates().clip( + boost::math::iround(_tick_rate/rate), true); size_t interp = interp_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp index 65f822558..e6be63557 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp @@ -40,6 +40,8 @@ public: virtual double set_host_rate(const double rate) = 0; + virtual uhd::meta_range_t get_host_rates(void) = 0; + virtual uhd::meta_range_t get_freq_range(void) = 0; virtual double set_freq(const double freq) = 0; diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index deb52b2d7..6cb404000 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -270,6 +270,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1)); fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) @@ -291,6 +293,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tx_dsp->set_link_rate(E100_TX_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index ab841487f..97c5ea630 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -477,6 +477,10 @@ public: return _tree->access(rx_dsp_root(chan) / "rate" / "value").get(); } + meta_range_t get_rx_rates(size_t chan){ + return _tree->access(rx_dsp_root(chan) / "rate" / "range").get(); + } + tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ tune_result_t r = tune_xx_subdev_and_dsp(RX_SIGN, _tree->subtree(rx_dsp_root(chan)), _tree->subtree(rx_rf_fe_root(chan)), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); @@ -587,6 +591,10 @@ public: return _tree->access(tx_dsp_root(chan) / "rate" / "value").get(); } + meta_range_t get_tx_rates(size_t chan){ + return _tree->access(tx_dsp_root(chan) / "rate" / "range").get(); + } + tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ tune_result_t r = tune_xx_subdev_and_dsp(TX_SIGN, _tree->subtree(tx_dsp_root(chan)), _tree->subtree(tx_rf_fe_root(chan)), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 12950d385..31c834109 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -442,7 +442,6 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } - void usrp1_impl::update_tick_rate(const double rate){ //updating this variable should: //update dboard iface -> it has a reference @@ -450,11 +449,29 @@ void usrp1_impl::update_tick_rate(const double rate){ _master_clock_rate = rate; } +uhd::meta_range_t usrp1_impl::get_rx_dsp_host_rates(void){ + meta_range_t range; + const size_t div = this->has_rx_halfband()? 2 : 1; + for (int rate = 256; rate >= 4; rate -= div){ + range.push_back(range_t(_master_clock_rate/rate)); + } + return range; +} + +uhd::meta_range_t usrp1_impl::get_tx_dsp_host_rates(void){ + meta_range_t range; + const size_t div = this->has_tx_halfband()? 2 : 1; + for (int rate = 256; rate >= 8; rate -= div){ + range.push_back(range_t(_master_clock_rate/rate)); + } + return range; +} + double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; - const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1); + const size_t rate = this->get_rx_dsp_host_rates().clip( + boost::math::iround(_master_clock_rate / samp_rate), true); if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) << "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n" @@ -482,8 +499,8 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_tx_halfband()? 2 : 1; - const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1); + const size_t rate = this->get_tx_dsp_host_rates().clip( + boost::math::iround(_master_clock_rate / samp_rate), true); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_tx(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 5788c536f..1a61f8136 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -283,8 +283,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "rx_dsps"); //dummy in case we have none for (size_t dspno = 0; dspno < get_num_ddcs(); dspno++){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&usrp1_impl::get_rx_dsp_host_rates, this)); _tree->create(rx_dsp_path / "rate/value") - .set(1e6) + .set(1e6) //some default rate .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); @@ -304,8 +306,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_dsps"); //dummy in case we have none for (size_t dspno = 0; dspno < get_num_ducs(); dspno++){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); + _tree->create(tx_dsp_path / "rate/range") + .publish(boost::bind(&usrp1_impl::get_tx_dsp_host_rates, this)); _tree->create(tx_dsp_path / "rate/value") - .set(1e6) + .set(1e6) //some default rate .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 6f427c31e..ec313daf6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -98,6 +98,8 @@ private: void update_tick_rate(const double rate); uhd::meta_range_t get_rx_dsp_freq_range(void); uhd::meta_range_t get_tx_dsp_freq_range(void); + uhd::meta_range_t get_rx_dsp_host_rates(void); + uhd::meta_range_t get_tx_dsp_host_rates(void); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2d89ddaf4..24178d10c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -480,6 +480,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _mbc[mb].rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], _1)) @@ -501,6 +503,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].tx_dsp->set_link_rate(USRP2_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _mbc[mb].tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1)) -- cgit v1.2.3 From f11d64579a7c1421cc2b0f04c85f0c0e82b6a74e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 Oct 2011 16:38:45 -0700 Subject: usrp1: implement rx dc offset control hooks --- host/lib/usrp/usrp1/usrp1_impl.cpp | 41 +++++++++++++++++++++++++++++++------- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 ++++ 2 files changed, 38 insertions(+), 7 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 1a61f8136..fcc4f36ae 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include using namespace uhd; @@ -187,13 +188,6 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // Normal mode with no loopback or Rx counting _iface->poke32(FR_MODE, 0x00000000); _iface->poke32(FR_DEBUG_EN, 0x00000000); - _iface->poke32(FR_DC_OFFSET_CL_EN, 0x0000000f); - - // Reset offset correction registers - _iface->poke32(FR_ADC_OFFSET_0, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_1, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_2, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_3, 0x00000000); UHD_LOG << "USRP1 Capabilities" << std::endl @@ -277,6 +271,15 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&usrp1_impl::update_tx_subdev_spec, this, _1)); + BOOST_FOREACH(const std::string &db, _dbc.keys()){ + _tree->create >(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&usrp1_impl::set_rx_dc_offset, this, db, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&usrp1_impl::set_enb_rx_dc_offset, this, db, _1)) + .set(true); + } + //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// @@ -467,3 +470,27 @@ uhd::meta_range_t usrp1_impl::get_tx_dsp_freq_range(void){ //magic scalar comes from codec control: return meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875); } + +void usrp1_impl::set_enb_rx_dc_offset(const std::string &db, const bool enb){ + const size_t shift = (db == "A")? 0 : 2; + _rx_dc_offset_shadow &= ~(0x3 << shift); //clear bits + _rx_dc_offset_shadow &= ((enb)? 0x3 : 0x0) << shift; + _iface->poke32(FR_DC_OFFSET_CL_EN, _rx_dc_offset_shadow & 0xf); +} + +std::complex usrp1_impl::set_rx_dc_offset(const std::string &db, const std::complex &offset){ + const boost::int32_t i_off = boost::math::iround(offset.real() * (1ul << 31)); + const boost::int32_t q_off = boost::math::iround(offset.imag() * (1ul << 31)); + + if (db == "A"){ + _iface->poke32(FR_ADC_OFFSET_0, i_off); + _iface->poke32(FR_ADC_OFFSET_1, q_off); + } + + if (db == "B"){ + _iface->poke32(FR_ADC_OFFSET_2, i_off); + _iface->poke32(FR_ADC_OFFSET_3, q_off); + } + + return std::complex(double(i_off) * (1ul << 31), double(q_off) * (1ul << 31)); +} diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index ec313daf6..99bb01c76 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #ifndef INCLUDED_USRP1_IMPL_HPP #define INCLUDED_USRP1_IMPL_HPP @@ -100,6 +101,9 @@ private: uhd::meta_range_t get_tx_dsp_freq_range(void); uhd::meta_range_t get_rx_dsp_host_rates(void); uhd::meta_range_t get_tx_dsp_host_rates(void); + size_t _rx_dc_offset_shadow; + void set_enb_rx_dc_offset(const std::string &db, const bool); + std::complex set_rx_dc_offset(const std::string &db, const std::complex &); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, -- cgit v1.2.3