diff options
| -rw-r--r-- | host/docs/coding.rst | 7 | ||||
| -rw-r--r-- | host/docs/images.rst | 3 | ||||
| -rw-r--r-- | host/examples/tx_waveforms.cpp | 89 | ||||
| -rw-r--r-- | host/include/uhd/utils/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/include/uhd/utils/images.hpp | 38 | ||||
| -rw-r--r-- | host/lib/utils/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/lib/utils/images.cpp | 40 | ||||
| -rw-r--r-- | host/lib/utils/paths.cpp | 14 | 
8 files changed, 146 insertions, 47 deletions
| diff --git a/host/docs/coding.rst b/host/docs/coding.rst index 84f9abf3e..23f350b0f 100644 --- a/host/docs/coding.rst +++ b/host/docs/coding.rst @@ -64,7 +64,12 @@ Integrating custom hardware  ------------------------------------------------------------------------  Creators of custom hardware can create drivers that use the UHD API.  These drivers can be built as dynamically loadable modules that the UHD will load at runtime. -For a module to be loaded at runtime, it must be found in the UHD_MODULE_PATH environment variable. + +For a module to be loaded at runtime, it must be: + +* found in the UHD_MODULE_PATH environment variable, +* installed into the <prefix>/share/uhd/modules directory, +* or installed into /usr/share/uhd/modules directory (unix only).  ^^^^^^^^^^^^^^^^^^^^^^^^^^^  Custom motherboard diff --git a/host/docs/images.rst b/host/docs/images.rst index ff5c5404e..612a00aa5 100644 --- a/host/docs/images.rst +++ b/host/docs/images.rst @@ -58,8 +58,7 @@ Where <prefix> was set by the CMAKE_INSTALL_PREFIX at configure-time.  **Option 2:**  Unpack the archive anywhere and set the UHD_IMAGE_PATH environment variable. -The UHD_IMAGE_PATH may contain a list of directories to search for image files, -or paths to specific image files. +The UHD_IMAGE_PATH may contain a list of directories to search for image files.  ------------------------------------------------------------------------  Building images diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index e9cf210bb..9886000b1 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -20,19 +20,41 @@  #include <uhd/usrp/simple_usrp.hpp>  #include <boost/program_options.hpp>  #include <boost/thread/thread_time.hpp> //system time +#include <boost/math/special_functions/round.hpp>  #include <boost/format.hpp> +#include <boost/function.hpp>  #include <iostream>  #include <complex>  #include <cmath>  namespace po = boost::program_options; +/*********************************************************************** + * Waveform generators + **********************************************************************/ +float gen_const(float){ +    return 1; +} + +float gen_square(float x){ +    return float((std::fmod(x, 1) < float(0.5))? 0 : 1); +} + +float gen_ramp(float x){ +    return std::fmod(x, 1)*2 - 1; +} + +float gen_sine(float x){ +    static const float two_pi = 2*std::acos(float(-1)); +    return std::sin(x*two_pi); +} +  int UHD_SAFE_MAIN(int argc, char *argv[]){      uhd::set_thread_priority_safe();      //variables to be set by po      std::string args, wave_type; -    size_t total_duration, amspb; +    size_t total_duration, spb;      double rate, freq, wave_freq;      float ampl, gain; @@ -42,7 +64,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){          ("help", "help message")          ("args", po::value<std::string>(&args)->default_value(""), "simple uhd device address args")          ("duration", po::value<size_t>(&total_duration)->default_value(3), "number of seconds to transmit") -        ("amspb", po::value<size_t>(&amspb)->default_value(10000), "approximate mimimum samples per buffer") +        ("spb", po::value<size_t>(&spb)->default_value(10000), "samples per buffer")          ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of outgoing samples")          ("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")          ("ampl", po::value<float>(&l)->default_value(float(0.3)), "amplitude of the waveform") @@ -88,33 +110,24 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      }      //error when the waveform is not possible to generate -    if (std::abs(wave_freq)/sdev->get_tx_rate() < 0.5/amspb){ -        throw std::runtime_error("wave freq/tx rate too small"); -    }      if (std::abs(wave_freq) > sdev->get_tx_rate()/2){          throw std::runtime_error("wave freq out of Nyquist zone");      } -    //fill a buffer with one period worth of samples -    std::vector<float> period(size_t(sdev->get_tx_rate()/std::abs(wave_freq))); -    std::cout << boost::format("Samples per waveform period: %d") % period.size() << std::endl; -    for (size_t n = 0; n < period.size(); n++){ -        if      (wave_type == "CONST")  period[n] = ampl; -        else if (wave_type == "SQUARE") period[n] = (n > period.size()/2)? ampl : 0; -        else if (wave_type == "RAMP")   period[n] = float((n/double(period.size()-1)) * 2*ampl - ampl); -        else if (wave_type == "SINE")   period[n] = ampl*float(std::sin(2*M_PI*n/double(period.size()))); -        else throw std::runtime_error("unknown waveform type: " + wave_type); -    } - -    //allocate data to send (fill with several periods worth of IQ samples) -    const size_t periods_per_buff = std::max<size_t>(1, amspb/period.size()); -    std::vector<std::complex<float> > buff(period.size()*periods_per_buff); -    std::cout << boost::format("Samples per send buffer: %d") % buff.size() << std::endl; -    const size_t i_ahead = (wave_freq > 0)? period.size()/4 : 0; -    const size_t q_ahead = (wave_freq < 0)? period.size()/4 : 0; -    for (size_t n = 0; n < buff.size(); n++) buff[n] = std::complex<float>( -        period[(n+i_ahead)%period.size()], period[(n+q_ahead)%period.size()] //I,Q -    ); +    //store the generator function for the selected waveform +    boost::function<float(float)> wave_gen; +    if      (wave_type == "CONST")  wave_gen = &gen_const; +    else if (wave_type == "SQUARE") wave_gen = &gen_square; +    else if (wave_type == "RAMP")   wave_gen = &gen_ramp; +    else if (wave_type == "SINE")   wave_gen = &gen_sine; +    else throw std::runtime_error("unknown waveform type: " + wave_type); + +    //allocate the buffer and precalculate values +    std::vector<std::complex<float> > buff(spb); +    const float cps = float(wave_freq/sdev->get_tx_rate()); +    const float i_off = (wave_freq > 0)? float(0.25) : 0; +    const float q_off = (wave_freq < 0)? float(0.25) : 0; +    float theta = 0;      //setup the metadata flags      uhd::tx_metadata_t md; @@ -123,11 +136,27 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      //send the data in multiple packets      boost::system_time end_time(boost::get_system_time() + boost::posix_time::seconds(total_duration)); -    while(end_time > boost::get_system_time()) dev->send( -        &buff.front(), buff.size(), md, -        uhd::io_type_t::COMPLEX_FLOAT32, -        uhd::device::SEND_MODE_FULL_BUFF -    ); +    while(end_time > boost::get_system_time()){ + +        //fill the buffer with the waveform +        for (size_t n = 0; n < buff.size(); n++){ +            buff[n] = std::complex<float>( +                ampl*wave_gen(i_off + theta), +                ampl*wave_gen(q_off + theta) +            ); +            theta += cps; +        } + +        //bring the theta back into range [0, 1) +        theta = std::fmod(theta, 1); + +        //send the entire contents of the buffer +        dev->send( +            &buff.front(), buff.size(), md, +            uhd::io_type_t::COMPLEX_FLOAT32, +            uhd::device::SEND_MODE_FULL_BUFF +        ); +    }      //send a mini EOB packet      md.start_of_burst = false; diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index ef8e64ce0..b39b6083c 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -23,6 +23,7 @@ INSTALL(FILES      byteswap.ipp      exception.hpp      gain_group.hpp +    images.hpp      pimpl.hpp      props.hpp      safe_main.hpp diff --git a/host/include/uhd/utils/images.hpp b/host/include/uhd/utils/images.hpp new file mode 100644 index 000000000..8b5a1eedd --- /dev/null +++ b/host/include/uhd/utils/images.hpp @@ -0,0 +1,38 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_IMAGES_HPP +#define INCLUDED_UHD_UTILS_IMAGES_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + +    /*! +     * Search for an image in the system image paths: +     * Search compiled-in paths and environment variable paths +     * for a specific image file with the provided file name. +     * \param image_name the name of the file +     * \return the full system path to the file +     * \throw exception if the image was not found +     */ +    UHD_API std::string find_image_path(const std::string &image_name); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_IMAGES_HPP */ diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index 68945545a..32b679d49 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -79,6 +79,7 @@ ENDIF(HAVE_DLFCN_H)  LIBUHD_APPEND_SOURCES(      ${CMAKE_SOURCE_DIR}/lib/utils/assert.cpp      ${CMAKE_SOURCE_DIR}/lib/utils/gain_group.cpp +    ${CMAKE_SOURCE_DIR}/lib/utils/images.cpp      ${CMAKE_SOURCE_DIR}/lib/utils/load_modules.cpp      ${CMAKE_SOURCE_DIR}/lib/utils/paths.cpp      ${CMAKE_SOURCE_DIR}/lib/utils/props.cpp diff --git a/host/lib/utils/images.cpp b/host/lib/utils/images.cpp new file mode 100644 index 000000000..395e542c1 --- /dev/null +++ b/host/lib/utils/images.cpp @@ -0,0 +1,40 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/utils/images.hpp> +#include <boost/foreach.hpp> +#include <boost/filesystem.hpp> +#include <stdexcept> +#include <vector> + +namespace fs = boost::filesystem; + +std::vector<fs::path> get_image_paths(void); //defined in paths.cpp + +/*********************************************************************** + * Find a image in the image paths + **********************************************************************/ +std::string uhd::find_image_path(const std::string &image_name){ +    if (fs::exists(image_name)){ +        return fs::system_complete(image_name).file_string(); +    } +    BOOST_FOREACH(const fs::path &path, get_image_paths()){ +        fs::path image_path = path / image_name; +        if (fs::exists(image_path)) return image_path.file_string(); +    } +    throw std::runtime_error("Could not find path for image: " + image_name); +} diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 6ad12d3cc..9e9525caf 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -85,17 +85,3 @@ std::vector<fs::path> get_module_paths(void){          paths.push_back(fs::path(INSTALLER_PKG_DATA_DIR) / "modules");      return paths;  } - -/*********************************************************************** - * Find a image in the image paths - **********************************************************************/ -std::string find_image_path(const std::string &image_name){ -    if (fs::exists(image_name)){ -        return fs::system_complete(image_name).file_string(); -    } -    BOOST_FOREACH(const fs::path &path, get_image_paths()){ -        fs::path image_path = path / image_name; -        if (fs::exists(image_path)) return image_path.file_string(); -    } -    throw std::runtime_error("Could not find path for image: " + image_name); -} | 
