diff options
32 files changed, 493 insertions, 293 deletions
diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 99c149d45..b81d32b2d 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -92,15 +92,10 @@ dbsm_t dsp_tx_sm;	// the state machine   * ================================================================   */ -typedef struct{ -    uint32_t control_word; -    uint32_t vrt_header[]; -} rx_dsp_buff_t; - -#define MK_RX_CTRL_WORD(num_words) (((num_words)*sizeof(uint32_t)) | (1 << 16)) +static const uint32_t rx_ctrl_word = 1 << 16;  // DSP Rx writes ethernet header words -#define DSP_RX_FIRST_LINE ((offsetof(rx_dsp_buff_t, vrt_header))/sizeof(uint32_t)) +#define DSP_RX_FIRST_LINE sizeof(rx_ctrl_word)/sizeof(uint32_t)  // receive from DSP  buf_cmd_args_t dsp_rx_recv_args = { @@ -423,22 +418,6 @@ static void setup_network(void){    sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD;		// zero UDP checksum  } -/* - * This is called when the DSP Rx chain has filled in a packet. - */ -bool  -fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)	// returns false -{ -  // insert the correct length into the control word and vrt header -  rx_dsp_buff_t *buff = (rx_dsp_buff_t*)buffer_ram(buf_this); -  size_t vrt_len = buffer_pool_status->last_line[buf_this]-DSP_RX_FIRST_LINE; -  buff->control_word = MK_RX_CTRL_WORD(vrt_len); -  buff->vrt_header[0] = (buff->vrt_header[0] & ~VRTH_PKT_SIZE_MASK) | (vrt_len & VRTH_PKT_SIZE_MASK); - -  return false;		// we didn't handle the packet -} - -  inline static void  buffer_irq_handler(unsigned irq)  { @@ -479,16 +458,15 @@ main(void)      dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,  	      &dsp_rx_recv_args, &dsp_rx_send_args, -	      fw_sets_seqno_inspector); - - -  // tell app_common that this dbsm could be sending to the ethernet -  ac_could_be_sending_to_eth = &dsp_rx_sm; +	      dbsm_nop_inspector);    sr_tx_ctrl->clear_state = 1;    bp_clear_buf(DSP_TX_BUF_0);    bp_clear_buf(DSP_TX_BUF_1); +  buffer_ram(DSP_RX_BUF_0)[0] = rx_ctrl_word; +  buffer_ram(DSP_RX_BUF_0)[1] = rx_ctrl_word; +    // kick off the state machine    dbsm_start(&dsp_tx_sm); diff --git a/firmware/microblaze/lib/dbsm.c b/firmware/microblaze/lib/dbsm.c index 9d66ec39c..d495860fd 100644 --- a/firmware/microblaze/lib/dbsm.c +++ b/firmware/microblaze/lib/dbsm.c @@ -160,10 +160,12 @@ dbsm_process_status(dbsm_t *sm, uint32_t status)      putchar('E');      // Most likely an ethernet Rx error.  We just restart the transfer.      if (status & (BPS_ERROR(sm->buf0))) -      dbsm_error_helper(sm, sm->buf0); +      //dbsm_error_helper(sm, sm->buf0); +      dbsm_process_helper(sm, sm->buf0); //forward errors      if (status & (BPS_ERROR(sm->buf0 ^ 1))) -      dbsm_error_helper(sm, sm->buf0 ^ 1); +      //dbsm_error_helper(sm, sm->buf0 ^ 1); +      dbsm_process_helper(sm, sm->buf0 ^ 1); //forward errors    }    if (status & BPS_DONE(sm->buf0)) diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 086e63a2f..8e28ddb34 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -77,7 +77,11 @@ ENDIF(MSVC)  ########################################################################  # Setup Boost  ######################################################################## -SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42") +IF(UNIX AND EXISTS "/usr/lib64") +    LIST(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix +ENDIF(UNIX AND EXISTS "/usr/lib64") + +SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42" "1.43.0" "1.43")  FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS      date_time      filesystem diff --git a/host/docs/build.rst b/host/docs/build.rst index 5944a6ebe..8f0d0db59 100644 --- a/host/docs/build.rst +++ b/host/docs/build.rst @@ -100,7 +100,6 @@ Generate Makefiles with cmake  **Notes:**  * For a custom prefix, use: cmake -DCMAKE_INSTALL_PREFIX=<prefix> ../ -* On some Fedora 64-bit systems, cmake has trouble finding boost, use: cmake -DBOOST_LIBRARYDIR=/usr/lib64 ../  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  Build and install diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp index a63337b38..752facb0d 100644 --- a/host/examples/benchmark_rx_rate.cpp +++ b/host/examples/benchmark_rx_rate.cpp @@ -62,13 +62,18 @@ static inline void test_device(              uhd::io_type_t::COMPLEX_FLOAT32,              uhd::device::RECV_MODE_ONE_PACKET          ); -        if (num_rx_samps == 0 and md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){ -            std::cerr << "Unexpected timeout on recv, exit test..." << std::endl; + +        //handle the error codes +        switch(md.error_code){ +        case uhd::rx_metadata_t::ERROR_CODE_NONE: +        case uhd::rx_metadata_t::ERROR_CODE_OVERRUN: +            break; + +        default: +            std::cerr << "Unexpected error on recv, exit test..." << std::endl;              return;          } -        if (num_rx_samps == 0 and md.error_code != uhd::rx_metadata_t::ERROR_CODE_OVERRUN){ -            std::cerr << "Unexpected error on recv, continuing..." << std::endl; -        } +          if (not md.has_time_spec){              std::cerr << "Metadata missing time spec, exit test..." << std::endl;              return; @@ -132,6 +137,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){      std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;      uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args);      std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; +    sdev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); //stop if left running      if (not vm.count("rate")){          sdev->set_rx_rate(500e3); //initial rate diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 95f805007..3b9acbb2c 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -92,20 +92,32 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){              uhd::io_type_t::COMPLEX_FLOAT32,              uhd::device::RECV_MODE_ONE_PACKET          ); -        if (num_rx_samps == 0 and num_acc_samps > 0){ + +        //handle the error codes +        switch(md.error_code){ +        case uhd::rx_metadata_t::ERROR_CODE_NONE: +            break; + +        case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: +            if (num_acc_samps == 0) continue;              std::cout << boost::format( -                "Got error code 0x%x before all samples received, possible packet loss, exiting loop..." +                "Got timeout before all samples received, possible packet loss, exiting loop..."              ) % md.error_code << std::endl; -            break; +            goto done_loop; + +        default: +            std::cout << boost::format( +                "Got error code 0x%x, exiting loop..." +            ) % md.error_code << std::endl; +            goto done_loop;          } -        if (num_rx_samps == 0) continue; //wait for packets with contents          if(verbose) std::cout << boost::format(              "Got packet: %u samples, %u full secs, %f frac secs"          ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl;          num_acc_samps += num_rx_samps; -    } +    } done_loop:      //finished      std::cout << std::endl << "Done!" << std::endl << std::endl; diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 2360174a4..dacd3a96b 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -101,4 +101,15 @@      #define UHD_DEPRECATED  #endif +// Platform defines for conditional parts of headers: +// Taken from boost/config/select_platform_config.hpp, +// however, we define macros, not strings for platforms. +#if defined(linux) || defined(__linux) || defined(__linux__) +    #define UHD_PLATFORM_LINUX +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +    #define UHD_PLATFORM_WIN32 +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +    #define UHD_PLATFORM_MACOS +#endif +  #endif /* INCLUDED_UHD_CONFIG_HPP */ diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp index c428a7692..9eebc161a 100644 --- a/host/include/uhd/types/tune_result.hpp +++ b/host/include/uhd/types/tune_result.hpp @@ -19,6 +19,7 @@  #define INCLUDED_UHD_TYPES_TUNE_RESULT_HPP  #include <uhd/config.hpp> +#include <string>  namespace uhd{ @@ -28,15 +29,18 @@ namespace uhd{       * the target and actual intermediate frequency.       * The struct hold the result of tuning the DSP as       * the target and actual digital converter frequency. -     * It also tell us weather or not the spectrum is inverted.       */      struct UHD_API tune_result_t{          double target_inter_freq;          double actual_inter_freq;          double target_dsp_freq;          double actual_dsp_freq; -        bool spectrum_inverted; -        tune_result_t(void); + +        /*! +         * Create a pretty print string for this tune result struct. +         * \return the printable string +         */ +        std::string to_pp_string(void) const;      };  } //namespace uhd diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index 68a42cad8..fd0f4596f 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -124,6 +124,7 @@ public:      virtual tune_result_t set_rx_freq(size_t chan, double freq) = 0;      virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0; +    virtual double get_rx_freq(size_t chan) = 0;      virtual freq_range_t get_rx_freq_range(size_t chan) = 0;      virtual void set_rx_gain(size_t chan, float gain) = 0; @@ -152,6 +153,7 @@ public:      virtual tune_result_t set_tx_freq(size_t chan, double freq) = 0;      virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0; +    virtual double get_tx_freq(size_t chan) = 0;      virtual freq_range_t get_tx_freq_range(size_t chan) = 0;      virtual void set_tx_gain(size_t chan, float gain) = 0; diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 1d9136f08..a100579ce 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -112,6 +112,7 @@ public:      virtual tune_result_t set_rx_freq(double freq) = 0;      virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0; +    virtual double get_rx_freq(void) = 0;      virtual freq_range_t get_rx_freq_range(void) = 0;      virtual void set_rx_gain(float gain) = 0; @@ -139,6 +140,7 @@ public:      virtual tune_result_t set_tx_freq(double freq) = 0;      virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0; +    virtual double get_tx_freq(void) = 0;      virtual freq_range_t get_tx_freq_range(void) = 0;      virtual void set_tx_gain(float gain) = 0; diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp index 1f8e91d68..f7bdcd161 100644 --- a/host/include/uhd/usrp/subdev_props.hpp +++ b/host/include/uhd/usrp/subdev_props.hpp @@ -23,6 +23,22 @@  namespace uhd{ namespace usrp{      /*! +     * Possible subdev connection types: +     * +     * A complex subdevice is physically connected to both channels, +     * which may be connected in one of two ways: IQ or QI (swapped). +     * +     * A real subdevice is only physically connected one channel, +     * either only the I channel or only the Q channel. +     */ +    enum subdev_conn_t{ +        SUBDEV_CONN_COMPLEX_IQ = 'C', +        SUBDEV_CONN_COMPLEX_QI = 'c', +        SUBDEV_CONN_REAL_I     = 'R', +        SUBDEV_CONN_REAL_Q     = 'r' +    }; + +    /*!       * Possible device subdev properties       */      enum subdev_prop_t{ @@ -36,9 +52,9 @@ namespace uhd{ namespace usrp{          SUBDEV_PROP_ANTENNA           = 'a', //rw, std::string          SUBDEV_PROP_ANTENNA_NAMES     = 'A', //ro, prop_names_t          SUBDEV_PROP_LO_LOCKED         = 'L', //ro, bool -        SUBDEV_PROP_QUADRATURE        = 'q', //ro, bool -        SUBDEV_PROP_IQ_SWAPPED        = 'i', //ro, bool -        SUBDEV_PROP_SPECTRUM_INVERTED = 's', //ro, bool +        SUBDEV_PROP_CONNECTION        = 'c', //ro, subdev_conn_t +        //SUBDEV_PROP_QUADRATURE        = 'q', //ro, bool +        //SUBDEV_PROP_IQ_SWAPPED        = 'i', //ro, bool          SUBDEV_PROP_USE_LO_OFFSET     = 'l', //ro, bool          SUBDEV_PROP_RSSI              = 'R', //ro, float          SUBDEV_PROP_BANDWIDTH         = 'B'  //rw, double diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp index f1e276d4f..df3907b3e 100644 --- a/host/include/uhd/usrp/tune_helper.hpp +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -24,55 +24,75 @@  namespace uhd{ namespace usrp{ -/*! - * Tune a rx chain to the desired frequency: - * The IF of the subdevice is set as close as possible to - * the given target frequency + the LO offset (when applicable). - * The ddc cordic is setup to bring the IF down to baseband. - * \param subdev the dboard subdevice object with properties - * \param ddc the ddc properties object (with "if_rate", "bb_rate", "freq") - * \param target_freq the desired center frequency - * \param lo_offset an offset for the subdevice IF from center - * \return a tune result struct - */ -UHD_API tune_result_t tune_rx_subdev_and_ddc( -    wax::obj subdev, wax::obj ddc, -    double target_freq, double lo_offset -); +    /*! +     * Tune a rx chain to the desired frequency: +     * The IF of the subdevice is set as close as possible to +     * the given target frequency + the LO offset (when applicable). +     * The ddc cordic is setup to bring the IF down to baseband. +     * \param subdev the dboard subdevice object with properties +     * \param ddc the mboard dsp object with properties +     * \param target_freq the desired center frequency +     * \param lo_offset an offset for the subdevice IF from center +     * \return a tune result struct +     */ +    UHD_API tune_result_t tune_rx_subdev_and_dsp( +        wax::obj subdev, wax::obj ddc, +        double target_freq, double lo_offset +    ); -/*! - * Tune a rx chain to the desired frequency: - * Same as the above, except the LO offset - * is calculated based on the subdevice and BW. - */ -UHD_API tune_result_t tune_rx_subdev_and_ddc( -    wax::obj subdev, wax::obj ddc, double target_freq -); +    /*! +     * Tune a rx chain to the desired frequency: +     * Same as the above, except the LO offset +     * is calculated based on the subdevice and BW. +     */ +    UHD_API tune_result_t tune_rx_subdev_and_dsp( +        wax::obj subdev, wax::obj ddc, double target_freq +    ); -/*! - * Tune a tx chain to the desired frequency: - * The IF of the subdevice is set as close as possible to - * the given target frequency + the LO offset (when applicable). - * The duc cordic is setup to bring the baseband up to IF. - * \param subdev the dboard subdevice object with properties - * \param duc the duc properties object (with "if_rate", "bb_rate", "freq") - * \param target_freq the desired center frequency - * \param lo_offset an offset for the subdevice IF from center - * \return a tune result struct - */ -UHD_API tune_result_t tune_tx_subdev_and_duc( -    wax::obj subdev, wax::obj duc, -    double target_freq, double lo_offset -); +    /*! +     * Calculate the overall frequency from the combination of dboard IF and DDC shift. +     * \param subdev the dboard subdevice object with properties +     * \param ddc the mboard dsp object with properties +     * \return the overall tune frequency of the system in Hz +     */ +    UHD_API double derive_freq_from_rx_subdev_and_dsp( +        wax::obj subdev, wax::obj ddc +    ); -/*! - * Tune a tx chain to the desired frequency: - * Same as the above, except the LO offset - * is calculated based on the subdevice and BW. - */ -UHD_API tune_result_t tune_tx_subdev_and_duc( -    wax::obj subdev, wax::obj duc, double target_freq -); +    /*! +     * Tune a tx chain to the desired frequency: +     * The IF of the subdevice is set as close as possible to +     * the given target frequency + the LO offset (when applicable). +     * The duc cordic is setup to bring the baseband up to IF. +     * \param subdev the dboard subdevice object with properties +     * \param duc the mboard dsp object with properties +     * \param target_freq the desired center frequency +     * \param lo_offset an offset for the subdevice IF from center +     * \return a tune result struct +     */ +    UHD_API tune_result_t tune_tx_subdev_and_dsp( +        wax::obj subdev, wax::obj duc, +        double target_freq, double lo_offset +    ); + +    /*! +     * Tune a tx chain to the desired frequency: +     * Same as the above, except the LO offset +     * is calculated based on the subdevice and BW. +     */ +    UHD_API tune_result_t tune_tx_subdev_and_dsp( +        wax::obj subdev, wax::obj duc, double target_freq +    ); + +    /*! +     * Calculate the overall frequency from the combination of dboard IF and DUC shift. +     * \param subdev the dboard subdevice object with properties +     * \param duc the mboard dsp object with properties +     * \return the overall tune frequency of the system in Hz +     */ +    UHD_API double derive_freq_from_tx_subdev_and_dsp( +        wax::obj subdev, wax::obj duc +    );  }} diff --git a/host/include/uhd/utils/byteswap.ipp b/host/include/uhd/utils/byteswap.ipp index 11c82a4ec..a070a7cf5 100644 --- a/host/include/uhd/utils/byteswap.ipp +++ b/host/include/uhd/utils/byteswap.ipp @@ -21,7 +21,7 @@  /***********************************************************************   * Platform-specific implementation details for byteswap below:   **********************************************************************/ -#ifdef BOOST_MSVC //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx +#if defined(UHD_PLATFORM_WIN32) //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx      #include <stdlib.h>      UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ @@ -50,7 +50,7 @@          return __builtin_bswap64(x);      } -#elif defined(__FreeBSD__) || defined(__MACOSX__) || defined(__APPLE__) +#elif defined(UHD_PLATFORM_MACOS)      #include <libkern/OSByteOrder.h>      UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ @@ -65,7 +65,7 @@          return OSSwapInt64(x);      } -#elif defined(linux) || defined(__linux) +#elif defined(UHD_PLATFORM_LINUX)      #include <byteswap.h>      UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py index 7438f5ff4..dbe026ba3 100755 --- a/host/lib/transport/gen_vrt_if_packet.py +++ b/host/lib/transport/gen_vrt_if_packet.py @@ -141,11 +141,17 @@ void vrt::if_hdr_unpack_$(suffix)(  ){      //extract vrt header      boost::uint32_t vrt_hdr_word = $(XE_MACRO)(packet_buff[0]); +    /*      size_t packet_words32 = vrt_hdr_word & 0xffff;      //failure case      if (if_packet_info.num_packet_words32 < packet_words32)          throw std::runtime_error("bad vrt header or packet fragment"); +    */ +    //Fix for short packets sent from the fpga: +    //  Use the num_packet_words32 passed in as input, +    //  and do not use the header bits which could be wrong. +    size_t packet_words32 = if_packet_info.num_packet_words32;      //extract fields from the header      if_packet_info.packet_type = if_packet_info_t::packet_type_t(vrt_hdr_word >> 29); diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 98451f188..bfbcf62d8 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -161,10 +161,13 @@ template<typename Opt> static void resize_buff_helper(          ) % name % MIN_SOCK_BUFF_SIZE << std::endl;      } +    //only enable on platforms that are happy with the large buffer resize +    #if defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)      //otherwise, ensure that the buffer is at least the minimum size      else if (udp_trans->get_buff_size<Opt>() < MIN_SOCK_BUFF_SIZE){          resize_buff_helper<Opt>(udp_trans, MIN_SOCK_BUFF_SIZE, name);      } +    #endif /*defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)*/  }  udp_zero_copy::sptr udp_zero_copy::make( diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 6623957ac..bd76cbb8f 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -146,6 +146,8 @@ namespace vrt_packet_handler{          const handle_overrun_t &handle_overrun,          size_t vrt_header_offset_words32      ){ +        metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE; +          //perform a receive if no rx data is waiting to be copied          if (state.size_of_copy_buffs == 0){              state.fragment_offset_in_samps = 0; @@ -171,7 +173,6 @@ namespace vrt_packet_handler{              metadata.has_time_spec = false;              metadata.start_of_burst = false;              metadata.end_of_burst = false; -            metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE;          }          //extract the number of samples available to copy @@ -323,7 +324,8 @@ namespace vrt_packet_handler{              );              //commit the samples to the zero-copy interface -            if (send_buffs[i]->commit(if_packet_info.num_packet_words32*sizeof(boost::uint32_t)) < ssize_t(num_samps)){ +            size_t num_bytes_total = (vrt_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t); +            if (send_buffs[i]->commit(num_bytes_total) < ssize_t(num_bytes_total)){                  std::cerr << "commit to send buffer returned less than commit size" << std::endl;              }          } diff --git a/host/lib/types.cpp b/host/lib/types.cpp index e0ce61058..fdc435fef 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -60,14 +60,17 @@ freq_range_t::freq_range_t(double min, double max):  /***********************************************************************   * tune result   **********************************************************************/ -tune_result_t::tune_result_t(void): -    target_inter_freq(0.0), -    actual_inter_freq(0.0), -    target_dsp_freq(0.0), -    actual_dsp_freq(0.0), -    spectrum_inverted(false) -{ -    /* NOP */ +std::string tune_result_t::to_pp_string(void) const{ +    return str(boost::format( +        "Tune Result:\n" +        "    Target Intermediate Freq: %f (MHz)\n" +        "    Actual Intermediate Freq: %f (MHz)\n" +        "    Target DSP Freq Shift:    %f (MHz)\n" +        "    Actual DSP Freq Shift:    %f (MHz)\n" +    ) +        % (target_inter_freq/1e6) % (actual_inter_freq/1e6) +        % (target_dsp_freq/1e6)   % (actual_dsp_freq/1e6) +    );  }  /*********************************************************************** diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 766deac78..9180828d8 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -16,6 +16,7 @@  //  #include <uhd/usrp/subdev_props.hpp> +#include <uhd/types/dict.hpp>  #include <uhd/types/ranges.hpp>  #include <uhd/utils/assert.hpp>  #include <uhd/utils/static.hpp> @@ -138,17 +139,14 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){          val = prop_names_t(1, ""); //vector of 1 empty string          return; -    case SUBDEV_PROP_QUADRATURE: -        val = (get_subdev_name() == "AB"); //only quadrature in ab mode -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; -        return; +    case SUBDEV_PROP_CONNECTION:{ +            static const uhd::dict<std::string, subdev_conn_t> name_to_conn = map_list_of +                ("A",  SUBDEV_CONN_REAL_I) +                ("B",  SUBDEV_CONN_REAL_Q) +                ("AB", SUBDEV_CONN_COMPLEX_IQ) +            ; +            val = name_to_conn[get_subdev_name()]; +        } return;      case SUBDEV_PROP_USE_LO_OFFSET:          val = false; @@ -237,16 +235,8 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){          val = prop_names_t(1, ""); //vector of 1 empty string          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_IQ;          return;      case SUBDEV_PROP_USE_LO_OFFSET: diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 2d6088983..914ca5e19 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -426,16 +426,8 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          val = rfx_rx_antennas;          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = true; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_QI;          return;      case SUBDEV_PROP_USE_LO_OFFSET: @@ -516,16 +508,8 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          val = rfx_tx_antennas;          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_IQ;          return;      case SUBDEV_PROP_USE_LO_OFFSET: diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index ced27e34d..9dd9b550b 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -119,16 +119,8 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){          val = prop_names_t(1, ""); //vector of 1 empty string          return; -    case SUBDEV_PROP_QUADRATURE: -        val = false; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_IQ;          return;      case SUBDEV_PROP_USE_LO_OFFSET: @@ -218,16 +210,8 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){          val = prop_names_t(1, ""); //vector of 1 empty string          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_IQ;          return;      case SUBDEV_PROP_USE_LO_OFFSET: diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 2b2822b6b..3038ce30b 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -86,7 +86,7 @@ using namespace boost::assign;   **********************************************************************/  static const bool wbx_debug = false; -static const freq_range_t wbx_freq_range(50e6, 2.22e9); +static const freq_range_t wbx_freq_range(68.75e6, 2.2e9);  static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); @@ -439,6 +439,7 @@ double wbx_xcvr::set_lo_freq(      regs.reference_divide_by_2 = T;      regs.reference_doubler = D;      regs.band_select_clock_div = BS; +    UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv));      regs.rf_divider_select = rfdivsel_to_enum[RFdiv];      //write the registers @@ -509,16 +510,8 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          val = wbx_rx_antennas;          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_IQ;          return;      case SUBDEV_PROP_USE_LO_OFFSET: @@ -603,16 +596,8 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          val = wbx_tx_antennas;          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_IQ;          return;      case SUBDEV_PROP_USE_LO_OFFSET: diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 5032b6f31..2c94bcd2d 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -481,16 +481,8 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){          val = xcvr_antennas;          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_IQ;          return;      case SUBDEV_PROP_USE_LO_OFFSET: @@ -579,16 +571,8 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){          val = xcvr_antennas;          return; -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = true; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; +    case SUBDEV_PROP_CONNECTION: +        val = SUBDEV_CONN_COMPLEX_QI;          return;      case SUBDEV_PROP_USE_LO_OFFSET: diff --git a/host/lib/usrp/dsp_utils.hpp b/host/lib/usrp/dsp_utils.hpp index 3fd5f1811..2f246c788 100644 --- a/host/lib/usrp/dsp_utils.hpp +++ b/host/lib/usrp/dsp_utils.hpp @@ -22,6 +22,7 @@  #include <uhd/types/dict.hpp>  #include <uhd/utils/assert.hpp>  #include <uhd/types/stream_cmd.hpp> +#include <uhd/usrp/subdev_props.hpp>  #include <boost/cstdint.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/tuple/tuple.hpp> @@ -37,37 +38,36 @@ namespace dsp_type1{      /*!       * Calculate the rx mux word from properties. -     * \param is_quadrature true if the subdev is complex -     * \param is_iq_swapped true if the i and q are reversed +     * \param subdev_conn the subdev connection type       * \param the 32-bit rx mux control word       */      static inline boost::uint32_t calc_rx_mux_word( -        bool is_quadrature, -        bool is_iq_swapped +        subdev_conn_t subdev_conn      ){ -        boost::uint32_t rx_mux = 0; -        if (is_quadrature){ -            rx_mux = (0x01 << 2) | (0x00 << 0); //Q=ADC1, I=ADC0 -        }else{ -            rx_mux = (0x11 << 2) | (0x00 << 0); //Q=ZERO, I=ADC0 +        switch(subdev_conn){ +        case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 2) | (0x0 << 0); //DDC0Q=ADC1, DDC0I=ADC0 +        case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 2) | (0x1 << 0); //DDC0Q=ADC0, DDC0I=ADC1 +        case SUBDEV_CONN_REAL_I:     return (0x3 << 2) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0 +        case SUBDEV_CONN_REAL_Q:     return (0x1 << 2) | (0x3 << 0); //DDC0Q=ADC1, DDC0I=ZERO +        default:                     UHD_THROW_INVALID_CODE_PATH();          } -        if (is_iq_swapped){ -            rx_mux = (rx_mux << 2) | (rx_mux >> 2); -        } -        return rx_mux;      }      /*!       * Calculate the tx mux word from properties. -     * \param is_iq_swapped true if the i and q are reversed +     * \param subdev_conn the subdev connection type       * \param the 32-bit tx mux control word       */ -    static inline boost::uint32_t calc_tx_mux_word(bool is_iq_swapped){ -        boost::uint32_t tx_mux = 0x10; -        if (is_iq_swapped){ -            tx_mux = (tx_mux << 4) | (tx_mux >> 4); +    static inline boost::uint32_t calc_tx_mux_word( +        subdev_conn_t subdev_conn +    ){ +        switch(subdev_conn){ +        case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC1=DUC0Q, DAC0=DUC0I +        case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC1=DUC0I, DAC0=DUC0Q +        case SUBDEV_CONN_REAL_I:     return (0xf << 4) | (0x0 << 0); //DAC1=ZERO,  DAC0=DUC0I +        case SUBDEV_CONN_REAL_Q:     return (0x0 << 4) | (0xf << 0); //DAC1=DUC0I, DAC0=ZERO +        default:                     UHD_THROW_INVALID_CODE_PATH();          } -        return tx_mux;      }      /*! @@ -82,16 +82,16 @@ namespace dsp_type1{          double &freq,          double codec_rate      ){ -        UHD_ASSERT_THROW(std::abs(freq) < codec_rate/2.0); +        UHD_ASSERT_THROW(freq >= -codec_rate/2.0 and freq < codec_rate/2.0);          static const double scale_factor = std::pow(2.0, 32); -        //calculate the freq register word -        boost::uint32_t freq_word = boost::math::iround((freq / codec_rate) * scale_factor); +        //calculate the freq register word (signed) +        boost::int32_t freq_word = boost::math::iround((freq / codec_rate) * scale_factor);          //update the actual frequency          freq = (double(freq_word) / scale_factor) * codec_rate; -        return freq_word; +        return boost::uint32_t(freq_word);      }      /*! diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index b40f98226..ec0f1dcc8 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -33,6 +33,11 @@  using namespace uhd;  using namespace uhd::usrp; +static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ +    double codec_rate = dsp[DSP_PROP_CODEC_RATE].as<double>(); +    return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} +  /***********************************************************************   * MIMO USRP Implementation   **********************************************************************/ @@ -180,15 +185,19 @@ public:      }      tune_result_t set_rx_freq(size_t chan, double target_freq){ -        return tune_rx_subdev_and_ddc(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq); +        return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq);      }      tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ -        return tune_rx_subdev_and_ddc(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq, lo_off); +        return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq, lo_off); +    } + +    double get_rx_freq(size_t chan){ +        return derive_freq_from_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan));      }      freq_range_t get_rx_freq_range(size_t chan){ -        return _rx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(); +        return add_dsp_shift(_rx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsps.at(chan));      }      void set_rx_gain(size_t chan, float gain){ @@ -243,15 +252,19 @@ public:      }      tune_result_t set_tx_freq(size_t chan, double target_freq){ -        return tune_tx_subdev_and_duc(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq); +        return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq);      }      tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ -        return tune_tx_subdev_and_duc(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq, lo_off); +        return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq, lo_off); +    } + +    double get_tx_freq(size_t chan){ +        return derive_freq_from_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan));      }      freq_range_t get_tx_freq_range(size_t chan){ -        return _tx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(); +        return add_dsp_shift(_tx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsps.at(chan));      }      void set_tx_gain(size_t chan, float gain){ diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index 56e82d7ee..5cb9511f4 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -30,6 +30,11 @@  using namespace uhd;  using namespace uhd::usrp; +static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ +    double codec_rate = dsp[DSP_PROP_CODEC_RATE].as<double>(); +    return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} +  /***********************************************************************   * Simple USRP Implementation   **********************************************************************/ @@ -118,15 +123,19 @@ public:      }      tune_result_t set_rx_freq(double target_freq){ -        return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq); +        return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq);      }      tune_result_t set_rx_freq(double target_freq, double lo_off){ -        return tune_rx_subdev_and_ddc(_rx_subdev, _rx_dsp, target_freq, lo_off); +        return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq, lo_off); +    } + +    double get_rx_freq(void){ +        return derive_freq_from_rx_subdev_and_dsp(_rx_subdev, _rx_dsp);      }      freq_range_t get_rx_freq_range(void){ -        return _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(); +        return add_dsp_shift(_rx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp);      }      void set_rx_gain(float gain){ @@ -173,15 +182,19 @@ public:      }      tune_result_t set_tx_freq(double target_freq){ -        return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq); +        return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq);      }      tune_result_t set_tx_freq(double target_freq, double lo_off){ -        return tune_tx_subdev_and_duc(_tx_subdev, _tx_dsp, target_freq, lo_off); +        return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq, lo_off); +    } + +    double get_tx_freq(void){ +        return derive_freq_from_tx_subdev_and_dsp(_tx_subdev, _tx_dsp);      }      freq_range_t get_tx_freq_range(void){ -        return _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(); +        return add_dsp_shift(_tx_subdev[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp);      }      void set_tx_gain(float gain){ diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index 082c39f6d..c5cce3ecf 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -19,22 +19,21 @@  #include <uhd/utils/algorithm.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dsp_props.hpp> +#include <uhd/usrp/dboard_iface.hpp> //unit_t  #include <cmath>  using namespace uhd;  using namespace uhd::usrp;  /*********************************************************************** - * Tune Helper Function + * Tune Helper Functions   **********************************************************************/  static tune_result_t tune_xx_subdev_and_dxc( -    bool is_tx, +    dboard_iface::unit_t unit,      wax::obj subdev, wax::obj dxc,      double target_freq, double lo_offset  ){      wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; -    bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>(); -    bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>();      wax::obj dxc_freq_proxy = dxc[DSP_PROP_FREQ_SHIFT];      double dxc_sample_rate = dxc[DSP_PROP_CODEC_RATE].as<double>(); @@ -43,55 +42,52 @@ static tune_result_t tune_xx_subdev_and_dxc(      subdev_freq_proxy = target_inter_freq;      double actual_inter_freq = subdev_freq_proxy.as<double>(); -    // Calculate the DDC setting that will downconvert the baseband from the -    // daughterboard to our target frequency. -    double delta_freq = target_freq - actual_inter_freq; -    int delta_sign = std::signum(delta_freq); -    delta_freq *= delta_sign; -    delta_freq = std::fmod(delta_freq, dxc_sample_rate); -    bool inverted = delta_freq > dxc_sample_rate/2.0; -    double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq); -    target_dxc_freq *= delta_sign; - -    // If the spectrum is inverted, and the daughterboard doesn't do -    // quadrature downconversion, we can fix the inversion by flipping the -    // sign of the dxc_freq...  (This only happens using the basic_rx board) -    if (subdev_spectrum_inverted){ -        inverted = not inverted; -    } -    if (inverted and not subdev_quadrature){ -        target_dxc_freq *= -1.0; -        inverted = not inverted; -    } -    // down conversion versus up conversion, fight! -    // your mother is ugly and your going down... -    target_dxc_freq *= (is_tx)? -1.0 : +1.0; +    //perform the correction correction for dxc rates outside of nyquist +    double delta_freq = std::fmod(target_freq - actual_inter_freq, dxc_sample_rate); +    bool outside_of_nyquist = std::abs(delta_freq) > dxc_sample_rate/2.0; +    double target_dxc_freq = (outside_of_nyquist)? +        std::signum(delta_freq)*dxc_sample_rate - delta_freq : -delta_freq; + +    //invert the sign on the dxc freq given the following conditions +    if (unit == dboard_iface::UNIT_TX) target_dxc_freq *= -1.0;      dxc_freq_proxy = target_dxc_freq;      double actual_dxc_freq = dxc_freq_proxy.as<double>(); -    //return some kind of tune result tuple/struct +    //load and return the tune result      tune_result_t tune_result;      tune_result.target_inter_freq = target_inter_freq;      tune_result.actual_inter_freq = actual_inter_freq;      tune_result.target_dsp_freq = target_dxc_freq;      tune_result.actual_dsp_freq = actual_dxc_freq; -    tune_result.spectrum_inverted = inverted;      return tune_result;  } +static double derive_freq_from_xx_subdev_and_dxc( +    dboard_iface::unit_t unit, +    wax::obj subdev, wax::obj dxc +){ +    //extract actual dsp and IF frequencies +    double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>(); +    double actual_dxc_freq = dxc[DSP_PROP_FREQ_SHIFT].as<double>(); + +    //invert the sign on the dxc freq given the following conditions +    if (unit == dboard_iface::UNIT_TX) actual_dxc_freq *= -1.0; + +    return actual_inter_freq - actual_dxc_freq; +} +  /***********************************************************************   * RX Tune   **********************************************************************/ -tune_result_t uhd::usrp::tune_rx_subdev_and_ddc( +tune_result_t usrp::tune_rx_subdev_and_dsp(      wax::obj subdev, wax::obj ddc,      double target_freq, double lo_offset  ){ -    bool is_tx = false; -    return tune_xx_subdev_and_dxc(is_tx, subdev, ddc, target_freq, lo_offset); +    return tune_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, target_freq, lo_offset);  } -tune_result_t uhd::usrp::tune_rx_subdev_and_ddc( +tune_result_t usrp::tune_rx_subdev_and_dsp(      wax::obj subdev, wax::obj ddc,      double target_freq  ){ @@ -100,21 +96,24 @@ tune_result_t uhd::usrp::tune_rx_subdev_and_ddc(      if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){          lo_offset = 2.0*ddc[DSP_PROP_HOST_RATE].as<double>();      } -    return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset); +    return tune_rx_subdev_and_dsp(subdev, ddc, target_freq, lo_offset); +} + +double usrp::derive_freq_from_rx_subdev_and_dsp(wax::obj subdev, wax::obj ddc){ +    return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc);  }  /***********************************************************************   * TX Tune   **********************************************************************/ -tune_result_t uhd::usrp::tune_tx_subdev_and_duc( +tune_result_t usrp::tune_tx_subdev_and_dsp(      wax::obj subdev, wax::obj duc,      double target_freq, double lo_offset  ){ -    bool is_tx = true; -    return tune_xx_subdev_and_dxc(is_tx, subdev, duc, target_freq, lo_offset); +    return tune_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, target_freq, lo_offset);  } -tune_result_t uhd::usrp::tune_tx_subdev_and_duc( +tune_result_t usrp::tune_tx_subdev_and_dsp(      wax::obj subdev, wax::obj duc,      double target_freq  ){ @@ -123,5 +122,9 @@ tune_result_t uhd::usrp::tune_tx_subdev_and_duc(      if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){          lo_offset = 2.0*duc[DSP_PROP_HOST_RATE].as<double>();      } -    return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset); +    return tune_tx_subdev_and_dsp(subdev, duc, target_freq, lo_offset); +} + +double usrp::derive_freq_from_tx_subdev_and_dsp(wax::obj subdev, wax::obj duc){ +    return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc);  } diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index fa8d1a674..8942f9d31 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -104,8 +104,7 @@ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){              wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0));              std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl;              _iface->poke32(U2_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( -                rx_subdev[SUBDEV_PROP_QUADRATURE].as<bool>(), -                rx_subdev[SUBDEV_PROP_IQ_SWAPPED].as<bool>() +                rx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()              ));          }          return; @@ -164,7 +163,7 @@ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){              wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0));              std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl;              _iface->poke32(U2_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( -                tx_subdev[SUBDEV_PROP_IQ_SWAPPED].as<bool>() +                tx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()              ));          }          return; diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index 74f3376e6..b7dcb741a 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -27,6 +27,7 @@ ADD_EXECUTABLE(main_test      dict_test.cpp      error_test.cpp      gain_handler_test.cpp +    tune_helper_test.cpp      vrt_test.cpp      wax_test.cpp  ) diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp new file mode 100644 index 000000000..570f47293 --- /dev/null +++ b/host/test/tune_helper_test.cpp @@ -0,0 +1,174 @@ +// +// 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 <boost/test/unit_test.hpp> +#include <uhd/usrp/tune_helper.hpp> +#include <uhd/usrp/subdev_props.hpp> +#include <uhd/usrp/dsp_props.hpp> +#include <iostream> + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Dummy properties objects + **********************************************************************/ +class dummy_subdev : public wax::obj{ +public: +    dummy_subdev(double resolution): +        _resolution(resolution) +    { +        /* NOP */ +    } +private: +    void get(const wax::obj &key, wax::obj &val){ +        switch(key.as<subdev_prop_t>()){ + +        case SUBDEV_PROP_FREQ: +            val = _freq; +            return; + +        case SUBDEV_PROP_USE_LO_OFFSET: +            val = false; +            return; + +        default: UHD_THROW_PROP_GET_ERROR(); +        } +    } + +    void set(const wax::obj &key, const wax::obj &val){ +        switch(key.as<subdev_prop_t>()){ +        case SUBDEV_PROP_FREQ: +            _freq = _resolution*int(val.as<double>()/_resolution); +            return; + +        default: UHD_THROW_PROP_SET_ERROR(); +        } +    } + +    double _freq, _resolution; +}; + +class dummy_subdev_basic : public wax::obj{ +private: +    void get(const wax::obj &key, wax::obj &val){ +        switch(key.as<subdev_prop_t>()){ + +        case SUBDEV_PROP_FREQ: +            val = double(0.0); //always zero +            return; + +        case SUBDEV_PROP_USE_LO_OFFSET: +            val = false; +            return; + +        default: UHD_THROW_PROP_GET_ERROR(); +        } +    } + +    void set(const wax::obj &key, const wax::obj &){ +        switch(key.as<subdev_prop_t>()){ +        case SUBDEV_PROP_FREQ: +            // do nothing +            return; + +        default: UHD_THROW_PROP_SET_ERROR(); +        } +    } +}; + +class dummy_dsp : public wax::obj{ +public: +    dummy_dsp(double codec_rate): +        _codec_rate(codec_rate) +    { +        /* NOP */ +    } +private: +    void get(const wax::obj &key, wax::obj &val){ +        switch(key.as<dsp_prop_t>()){ +        case DSP_PROP_CODEC_RATE: +            val = _codec_rate; +            return; + +        case DSP_PROP_FREQ_SHIFT: +            val = _freq_shift; +            return; + +        default: UHD_THROW_PROP_GET_ERROR(); +        } +    } + +    void set(const wax::obj &key, const wax::obj &val){ +        switch(key.as<dsp_prop_t>()){ +        case DSP_PROP_FREQ_SHIFT: +            _freq_shift = val.as<double>(); +            return; + +        default: UHD_THROW_PROP_SET_ERROR(); +        } +    } + +    double _codec_rate, _freq_shift; +}; + +/*********************************************************************** + * Test cases + **********************************************************************/ +static const double tolerance = 0.001; + +BOOST_AUTO_TEST_CASE(test_tune_helper_rx){ +    dummy_subdev subdev(1e6); +    dummy_dsp dsp(100e6); + +    std::cout << "Testing tune helper RX automatic LO offset" << std::endl; +    tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); +    std::cout << tr.to_pp_string() << std::endl; +    BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); +    BOOST_CHECK_CLOSE(tr.actual_dsp_freq, -100e3, tolerance); + +    double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); +    BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance); +} + +BOOST_AUTO_TEST_CASE(test_tune_helper_tx){ +    dummy_subdev subdev(1e6); +    dummy_dsp dsp(100e6); + +    std::cout << "Testing tune helper TX automatic LO offset" << std::endl; +    tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 2.3451e9); +    std::cout << tr.to_pp_string() << std::endl; +    BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); +    BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 100e3, tolerance); + +    double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); +    BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance); +} + +BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){ +    dummy_subdev_basic subdev; +    dummy_dsp dsp(100e6); + +    std::cout << "Testing tune helper RX dummy basic board" << std::endl; +    tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6); +    std::cout << tr.to_pp_string() << std::endl; +    BOOST_CHECK_CLOSE(tr.actual_inter_freq, 0.0, tolerance); +    BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance); + +    double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link()); +    BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance); +} diff --git a/host/test/vrt_test.cpp b/host/test/vrt_test.cpp index b90b2fc15..9e131a10b 100644 --- a/host/test/vrt_test.cpp +++ b/host/test/vrt_test.cpp @@ -95,11 +95,13 @@ BOOST_AUTO_TEST_CASE(test_with_sid){      pack_and_unpack(if_packet_info);  } +static const bool cid_enb = false; +  BOOST_AUTO_TEST_CASE(test_with_cid){      vrt::if_packet_info_t if_packet_info;      if_packet_info.packet_count = 2;      if_packet_info.has_sid = false; -    if_packet_info.has_cid = true; +    if_packet_info.has_cid = cid_enb;      if_packet_info.has_tsi = false;      if_packet_info.has_tsf = false;      if_packet_info.has_tlr = false; @@ -126,7 +128,7 @@ BOOST_AUTO_TEST_CASE(test_with_all){      vrt::if_packet_info_t if_packet_info;      if_packet_info.packet_count = 4;      if_packet_info.has_sid = true; -    if_packet_info.has_cid = true; +    if_packet_info.has_cid = cid_enb;      if_packet_info.has_tsi = true;      if_packet_info.has_tsf = true;      if_packet_info.has_tlr = false; diff --git a/host/uhd.pc.in b/host/uhd.pc.in index 2a34e9cfd..536f254ed 100644 --- a/host/uhd.pc.in +++ b/host/uhd.pc.in @@ -1,10 +1,10 @@  prefix=@CMAKE_INSTALL_PREFIX@  exec_prefix=${prefix} -libdir=${prefix}/@LIBRARY_DIR@ +libdir=${exec_prefix}/@LIBRARY_DIR@  includedir=${prefix}/@INCLUDE_DIR@  Name: @CPACK_PACKAGE_NAME@ -Description: Universal Hardware Driver +Description: @CPACK_PACKAGE_DESCRIPTION_SUMMARY@  Requires:  Version: @CPACK_PACKAGE_VERSION@  Libs: -L${libdir} -luhd diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp index 1e8e726d2..1b73b5788 100644 --- a/host/utils/uhd_usrp_probe.cpp +++ b/host/utils/uhd_usrp_probe.cpp @@ -88,9 +88,7 @@ static std::string get_subdev_pp_string(const std::string &type, wax::obj subdev          ss << boost::format("Gain range %s: %.1f to %.1f step %.1f dB") % gain_name % gain_range.min % gain_range.max % gain_range.step << std::endl;      } -    ss << boost::format("Is Quadrature: %s") % (subdev[usrp::SUBDEV_PROP_QUADRATURE].as<bool>()? "Yes" : "No") << std::endl; -    ss << boost::format("Is IQ Swapped: %s") % (subdev[usrp::SUBDEV_PROP_IQ_SWAPPED].as<bool>()? "Yes" : "No") << std::endl; -    ss << boost::format("Is Spectrum Inverted: %s") % (subdev[usrp::SUBDEV_PROP_SPECTRUM_INVERTED].as<bool>()? "Yes" : "No") << std::endl; +    ss << boost::format("Connection Type: %c") % (subdev[usrp::SUBDEV_PROP_CONNECTION].as<usrp::subdev_conn_t>()) << std::endl;      ss << boost::format("Uses LO offset: %s") % (subdev[usrp::SUBDEV_PROP_USE_LO_OFFSET].as<bool>()? "Yes" : "No") << std::endl;      return ss.str();  | 
