diff options
Diffstat (limited to 'host/lib/usrp')
| -rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 32 | ||||
| -rw-r--r-- | host/lib/usrp/cores/rx_dsp_core_200.cpp | 3 | ||||
| -rw-r--r-- | host/lib/usrp/cores/rx_dsp_core_3000.cpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/gps_ctrl.cpp | 45 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_fw_uart.cpp | 93 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 31 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 10 | 
7 files changed, 167 insertions, 49 deletions
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index f2b3885e6..f88d787ca 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -427,7 +427,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr)      //setup time source props      _tree->create<std::string>(mb_path / "time_source" / "value")          .subscribe(boost::bind(&b200_impl::update_time_source, this, _1)); -    static const std::vector<std::string> time_sources = boost::assign::list_of("none")("external")("gpsdo"); +    static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external")("gpsdo");      _tree->create<std::vector<std::string> >(mb_path / "time_source" / "options").set(time_sources);      //setup reference source props      _tree->create<std::string>(mb_path / "clock_source" / "value") @@ -464,10 +464,6 @@ b200_impl::b200_impl(const device_addr_t &device_addr)      _tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(rx_spec);      _tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_spec); -    //init to internal clock and time source -    _tree->access<std::string>(mb_path / "clock_source/value").set("internal"); -    _tree->access<std::string>(mb_path / "time_source/value").set("none"); -      //GPS installed: use external ref, time, and init time spec      if (_gps and _gps->gps_detected())      { @@ -482,6 +478,10 @@ b200_impl::b200_impl(const device_addr_t &device_addr)          time_spec_t pps_time = _tree->access<time_spec_t>(mb_path / "time" / "pps").get();          for (size_t i = 0; i < 10 && _tree->access<time_spec_t>(mb_path / "time" / "pps").get() == pps_time; i++)              boost::this_thread::sleep(boost::posix_time::milliseconds(100)); +    } else { +        //init to internal clock and time source +        _tree->access<std::string>(mb_path / "clock_source/value").set("internal"); +        _tree->access<std::string>(mb_path / "time_source/value").set("internal");      }  } @@ -686,10 +686,10 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co      else      {          const double max_tick_rate = ((chan_count <= 1) ? AD9361_1_CHAN_CLOCK_RATE_MAX : AD9361_2_CHAN_CLOCK_RATE_MAX); -        if (tick_rate > max_tick_rate) +        if (tick_rate - max_tick_rate >= 1.0)          {              throw uhd::value_error(boost::str( -                boost::format("current master clock rate (%.2f MHz) exceeds maximum possible master clock rate (%.2f MHz) when using %d %s channels") +                boost::format("current master clock rate (%.6f MHz) exceeds maximum possible master clock rate (%.6f MHz) when using %d %s channels")                      % (tick_rate/1e6)                      % (max_tick_rate/1e6)                      % chan_count @@ -701,12 +701,12 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co  double b200_impl::set_tick_rate(const double rate)  { -    UHD_MSG(status) << "Asking for clock rate " << rate/1e6 << " MHz\n"; +    UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz\n") % (rate/1e6));      check_tick_rate_with_current_streamers(rate);   // Defined in b200_io_impl.cpp      _tick_rate = _codec_ctrl->set_clock_rate(rate); -    UHD_MSG(status) << "Actually got clock rate " << _tick_rate/1e6 << " MHz\n"; +    UHD_MSG(status) << (boost::format("Actually got clock rate %.6f MHz\n") % (_tick_rate/1e6));      //reset after clock rate change      this->reset_codec_dcm(); @@ -791,11 +791,17 @@ void b200_impl::update_clock_source(const std::string &source)  void b200_impl::update_time_source(const std::string &source)  { -    if (source == "none"){} -    else if (source == "external"){} -    else if (source == "gpsdo"){} +    boost::uint32_t value = 0; +    if (source == "none") +        value = 3; +    else if (source == "internal") +        value = 2; +    else if (source == "external") +        value = 1; +    else if (source == "gpsdo") +        value = 0;      else throw uhd::key_error("update_time_source: unknown source: " + source); -    _local_ctrl->poke32(TOREG(SR_CORE_PPS_SEL), (source == "external")? 1 : 0); +    _local_ctrl->poke32(TOREG(SR_CORE_PPS_SEL), value);  }  /*********************************************************************** diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index 2fdc220b5..2e5ca8e7a 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -176,7 +176,8 @@ public:          //determine which half-band filters are activated          int hb0 = 0, hb1 = 0; -        if (decim % 2 == 0){ +        // hb0 can only be enabled if the rate will be decimated by at least 2 between the CIC and hb1 +        if (decim >= 4 && decim % 2 == 0){              hb0 = 1;              decim /= 2;          } diff --git a/host/lib/usrp/cores/rx_dsp_core_3000.cpp b/host/lib/usrp/cores/rx_dsp_core_3000.cpp index 584dd6a94..07399d462 100644 --- a/host/lib/usrp/cores/rx_dsp_core_3000.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_3000.cpp @@ -177,7 +177,7 @@ public:      void update_scalar(void){          const double factor = 1.0 + std::max(ceil_log2(_scaling_adjustment), 0.0); -        const double target_scalar = (1 << 15)*_scaling_adjustment/_dsp_extra_scaling/factor; +        const double target_scalar = (1 << (_is_b200 ? 17 : 15))*_scaling_adjustment/_dsp_extra_scaling/factor;          const boost::int32_t actual_scalar = boost::math::iround(target_scalar);          _fxpt_scalar_correction = target_scalar/actual_scalar*factor; //should be small          _iface->poke32(REG_DSP_RX_SCALE_IQ, actual_scalar); diff --git a/host/lib/usrp/gps_ctrl.cpp b/host/lib/usrp/gps_ctrl.cpp index d327a84f9..f4d5cd8e8 100644 --- a/host/lib/usrp/gps_ctrl.cpp +++ b/host/lib/usrp/gps_ctrl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2011,2014 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 @@ -17,6 +17,7 @@  #include <uhd/usrp/gps_ctrl.hpp>  #include <uhd/utils/msg.hpp> +#include <uhd/utils/log.hpp>  #include <uhd/exception.hpp>  #include <uhd/types/sensors.hpp>  #include <boost/algorithm/string.hpp> @@ -62,6 +63,27 @@ private:      return std::string();    } +    static bool is_nmea_checksum_ok(std::string nmea) +    { +        if (nmea.length() < 5 || nmea[0] != '$' || nmea[nmea.length()-3] != '*') +            return false; + +        std::stringstream ss; +        boost::uint32_t string_crc; +        boost::uint32_t calculated_crc = 0; + +        // get crc from string +        ss << std::hex << nmea.substr(nmea.length()-2, 2); +        ss >> string_crc; + +        // calculate crc +        for (size_t i = 1; i < nmea.length()-3; i++) +            calculated_crc ^= nmea[i]; + +        // return comparison +        return (string_crc == calculated_crc); +    } +    std::string update_cached_sensors(const std::string sensor) {      if(not gps_detected() || (gps_type != GPS_TYPE_INTERNAL_GPSDO)) {          UHD_MSG(error) << "get_stat(): unsupported GPS or no GPS detected"; @@ -70,24 +92,36 @@ private:      const std::list<std::string> list = boost::assign::list_of("GPGGA")("GPRMC")("SERVO");      static const boost::regex status_regex("\\d\\d-\\d\\d-\\d\\d"); +    static const boost::regex gp_msg_regex("^\\$GP.*,\\*[0-9A-F]{2}$");      std::map<std::string,std::string> msgs;      // Get all GPSDO messages available      // Creating a map here because we only want the latest of each message type      for (std::string msg = _recv(); msg.length(); msg = _recv())      { -        if (msg.length() < 6) -            continue; -          // Strip any end of line characters          erase_all(msg, "\r");          erase_all(msg, "\n"); +        if (msg.length() < 6) +        { +            UHD_LOGV(regularly) << __FUNCTION__ << ": Short NMEA string: " << msg << std::endl; +            continue; +        } +          // Look for SERVO message          if (boost::regex_search(msg, status_regex, boost::regex_constants::match_continuous)) +        {              msgs["SERVO"] = msg; -        else +        } +        else if (boost::regex_match(msg, gp_msg_regex) and is_nmea_checksum_ok(msg)) +        {              msgs[msg.substr(1,5)] = msg; +        } +        else +        { +            UHD_LOGV(regularly) << __FUNCTION__ << ": Malformed NMEA string: " << msg << std::endl; +        }      }      boost::system_time time = boost::get_system_time(); @@ -131,7 +165,6 @@ public:        }        else if(reply.substr(0, 3) == "$GP") i_heard_some_nmea = true; //but keep looking for that "Command Error" response        else if(reply.length() != 0) i_heard_something_weird = true; //probably wrong baud rate -      sleep(milliseconds(GPS_TIMEOUT_DELAY_MS));      }      if((i_heard_some_nmea) && (gps_type != GPS_TYPE_INTERNAL_GPSDO)) gps_type = GPS_TYPE_GENERIC_NMEA; diff --git a/host/lib/usrp/x300/x300_fw_uart.cpp b/host/lib/usrp/x300/x300_fw_uart.cpp index 943b2d9fa..b0fae124d 100644 --- a/host/lib/usrp/x300/x300_fw_uart.cpp +++ b/host/lib/usrp/x300/x300_fw_uart.cpp @@ -38,6 +38,8 @@ struct x300_uart_iface : uart_iface          rxpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_ADDR));          txpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_ADDR));          poolsize = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_WORDS32)); +        _rxcache.resize(poolsize); +        _last_device_rxoffset = rxoffset;          //this->write_uart("HELLO UART\n");          //this->read_uart(0.1);      } @@ -54,6 +56,7 @@ struct x300_uart_iface : uart_iface      void write_uart(const std::string &buff)      { +        boost::mutex::scoped_lock(_write_mutex);          BOOST_FOREACH(const char ch, buff)          {              if (ch == '\n') this->putchar('\r'); @@ -63,39 +66,99 @@ struct x300_uart_iface : uart_iface      int getchar(void)      { -        if (_iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)) != rxoffset) +        if (rxoffset == _last_device_rxoffset) +            return -1; + +        rxoffset++; +        return static_cast<int>(_rxcache[(rxoffset/4) % poolsize] >> ((rxoffset%4)*8) & 0xFF); +    } + +    void update_cache(void) +    { +        boost::uint32_t device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); +        boost::uint32_t delta = device_rxoffset - rxoffset; + +        while (delta)          { -            const int shift = ((rxoffset%4) * 8); -            const char ch = _iface->peek32(SR_ADDR(rxpool, rxoffset/4)) >> shift; -            rxoffset = (rxoffset + 1) % (poolsize*4); -            return ch; +            if (delta >= poolsize*4) +            { +                // all the data is new - reload the entire cache +                for (boost::uint32_t i = 0; i < poolsize; i++) +                    _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); + +                // set rxoffset to the end of the first string +                rxoffset = device_rxoffset - (poolsize*4) + 1; +                while (static_cast<char>((_rxcache[(rxoffset/4) % poolsize] >> ((rxoffset%4)*8) & 0xFF)) != '\n') +                    ++rxoffset; + +                // clear the partial string in the buffer; +                _rxbuff.clear(); +            } +            else if (rxoffset == _last_device_rxoffset) +            { +                // new data was added - refresh the portion of the cache that was updated +                for (boost::uint32_t i = ((_last_device_rxoffset+1)/4) % poolsize; i != (((device_rxoffset)/4)+1) % poolsize; i = (i+1) % poolsize) +                { +                    _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); +                } +            } else { +                // there is new data, but we aren't done with what we have - check back later +                break; +            } + +            _last_device_rxoffset = device_rxoffset; + +            // check again to see if anything changed while we were updating the cache +            device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); +            delta = device_rxoffset - rxoffset;          } -        return -1;      }      std::string read_uart(double timeout)      { +        boost::mutex::scoped_lock(_read_mutex);          const boost::system_time exit_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1e6));          std::string buff; +          while (true)          { -            const int ch = this->getchar(); -            if (ch == -1) +            // Update cache +            this->update_cache(); + +            // Get available characters +            for (int ch = this->getchar(); ch != -1; ch = this->getchar())              { -                if (boost::get_system_time() > exit_time) break; -                boost::this_thread::sleep(boost::posix_time::milliseconds(1)); -                continue; +                // skip carriage returns +                if (ch == '\r') +                    continue; + +                // store character to buffer +                _rxbuff += std::string(1, (char)ch); + +                // newline found - return string +                if (ch == '\n') +                { +                    buff = _rxbuff; +                    _rxbuff.clear(); +                    return buff; +                }              } -            if (ch == '\r') continue; -            buff += std::string(1, (char)ch); -            if (ch == '\n') break; + +            // no more characters - check time +            if (boost::get_system_time() > exit_time) +                break;          } -        //UHD_VAR(buff); +          return buff;      }      wb_iface::sptr _iface;      boost::uint32_t rxoffset, txoffset, txword32, rxpool, txpool, poolsize; +    boost::uint32_t _last_device_rxoffset; +    std::vector<boost::uint32_t> _rxcache; +    std::string _rxbuff; +    boost::mutex _read_mutex; +    boost::mutex _write_mutex;  };  uart_iface::sptr x300_make_uart_iface(wb_iface::sptr iface) diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index fdf216cf2..3561bc2f1 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -841,8 +841,9 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)              try {                  wait_for_ref_locked(mb.zpu_ctrl, 1.0);              } catch (uhd::exception::runtime_error &e) { -                UHD_MSG(warning) << "Clock reference failed to lock to internal source during device initialization.  " << -                    "Check for the lock before operation or ignore this warning if using another clock source." << std::endl; +                // Ignore for now - It can sometimes take longer than 1 second to lock and that is OK. +                //UHD_MSG(warning) << "Clock reference failed to lock to internal source during device initialization.  " << +                //    "Check for the lock before operation or ignore this warning if using another clock source." << std::endl;              }              _tree->access<std::string>(mb_path / "time_source" / "value").set("internal");              UHD_MSG(status) << "References initialized to internal sources" << std::endl; @@ -1079,9 +1080,13 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name)      this->update_atr_leds(mb.radio_perifs[radio_index].leds, ""); //init anyway, even if never called      //bind frontend corrections to the dboard freq props +    const fs_path db_tx_fe_path = db_path / "tx_frontends"; +    BOOST_FOREACH(const std::string &name, _tree->list(db_tx_fe_path)) { +        _tree->access<double>(db_tx_fe_path / name / "freq" / "value") +            .subscribe(boost::bind(&x300_impl::set_tx_fe_corrections, this, mb_path, slot_name, _1)); +    }      const fs_path db_rx_fe_path = db_path / "rx_frontends"; -    BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)) -    { +    BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)) {          _tree->access<double>(db_rx_fe_path / name / "freq" / "value")              .subscribe(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, slot_name, _1));      } @@ -1092,6 +1097,11 @@ void x300_impl::set_rx_fe_corrections(const uhd::fs_path &mb_path, const std::st      apply_rx_fe_corrections(this->get_tree()->subtree(mb_path), fe_name, lo_freq);  } +void x300_impl::set_tx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq) +{ +    apply_tx_fe_corrections(this->get_tree()->subtree(mb_path), fe_name, lo_freq); +} +  boost::uint32_t get_pcie_dma_channel(boost::uint8_t destination, boost::uint8_t prefix)  {      static const boost::uint32_t RADIO_GRP_SIZE = 3; @@ -1108,8 +1118,7 @@ x300_impl::both_xports_t x300_impl::make_transport(      const boost::uint8_t& destination,      const boost::uint8_t& prefix,      const uhd::device_addr_t& args, -    boost::uint32_t& sid -) +    boost::uint32_t& sid)  {      mboard_members_t &mb = _mb[mb_index];      both_xports_t xports; @@ -1131,12 +1140,12 @@ x300_impl::both_xports_t x300_impl::make_transport(      if (mb.xport_path == "nirio") {          default_buff_args.send_frame_size =              (prefix == X300_RADIO_DEST_PREFIX_TX) -            ? X300_PCIE_DATA_FRAME_SIZE +            ? X300_PCIE_TX_DATA_FRAME_SIZE              : X300_PCIE_MSG_FRAME_SIZE;          default_buff_args.recv_frame_size =              (prefix == X300_RADIO_DEST_PREFIX_RX) -            ? X300_PCIE_DATA_FRAME_SIZE +            ? X300_PCIE_RX_DATA_FRAME_SIZE              : X300_PCIE_MSG_FRAME_SIZE;          default_buff_args.num_send_frames = @@ -1206,10 +1215,10 @@ x300_impl::both_xports_t x300_impl::make_transport(                  << std::endl;          } -	size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; -	size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; +    size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; +    size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; -	// Make sure frame sizes do not exceed the max available value supported by UHD +    // Make sure frame sizes do not exceed the max available value supported by UHD          default_buff_args.send_frame_size =              (prefix == X300_RADIO_DEST_PREFIX_TX)              ? std::min(system_max_send_frame_size, X300_10GE_DATA_FRAME_MAX_SIZE) diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 80f3e8faa..578e96383 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -63,7 +63,11 @@ static const size_t X300_RX_SW_BUFF_SIZE_ETH_MACOS  = 0x100000; //1Mib  static const double X300_RX_SW_BUFF_FULL_FACTOR     = 0.90;     //Buffer should ideally be 90% full.  static const size_t X300_RX_FC_REQUEST_FREQ         = 32;       //per flow-control window -static const size_t X300_PCIE_DATA_FRAME_SIZE       = 8192;     //bytes +//The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements deep for TX +//where an element is 8 bytes. For best throughput ensure that the data frame fits in these buffers. +//Also ensure that the kernel has enough frames to hold buffered TX and RX data +static const size_t X300_PCIE_RX_DATA_FRAME_SIZE    = 8184;     //bytes +static const size_t X300_PCIE_TX_DATA_FRAME_SIZE    = 8192;     //bytes  static const size_t X300_PCIE_DATA_NUM_FRAMES       = 2048;  static const size_t X300_PCIE_MSG_FRAME_SIZE        = 256;      //bytes  static const size_t X300_PCIE_MSG_NUM_FRAMES        = 32; @@ -207,7 +211,7 @@ private:          //perifs in each radio          radio_perifs_t radio_perifs[2]; //!< This is hardcoded s.t. radio_perifs[0] points to slot A and [1] to B          uhd::usrp::dboard_eeprom_t db_eeproms[8]; -	//! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs +        //! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs          size_t get_radio_index(const std::string &slot_name) {               UHD_ASSERT_THROW(slot_name == "A" or slot_name == "B");               return slot_name == "A" ? 0 : 1; @@ -317,6 +321,8 @@ private:      uhd::dict<std::string, uhd::usrp::dboard_iface::sptr> _dboard_ifaces;      void set_rx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq); +    void set_tx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq); +      /*! Update the IQ MUX settings for the radio peripheral according to given subdev spec.       *  | 
