diff options
Diffstat (limited to 'host/lib/usrp')
-rw-r--r-- | host/lib/usrp/b200/b200_iface.cpp | 183 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_iface.hpp | 45 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 60 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.hpp | 9 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_io_impl.cpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_regs.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/common/adf4001_ctrl.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/cores/time_core_3000.cpp | 13 | ||||
-rw-r--r-- | host/lib/usrp/cores/time_core_3000.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_fpga_defs.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_impl.cpp | 27 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_impl.hpp | 5 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_fw_common.h | 2 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 12 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 1 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_regs.hpp | 2 |
16 files changed, 157 insertions, 219 deletions
diff --git a/host/lib/usrp/b200/b200_iface.cpp b/host/lib/usrp/b200/b200_iface.cpp index 4754a6357..207c418fc 100644 --- a/host/lib/usrp/b200/b200_iface.cpp +++ b/host/lib/usrp/b200/b200_iface.cpp @@ -17,6 +17,7 @@ #include "b200_iface.hpp" +#include "../../utils/ihex.hpp" #include <uhd/config.hpp> #include <uhd/utils/msg.hpp> #include <uhd/utils/log.hpp> @@ -87,7 +88,7 @@ typedef boost::uint32_t hash_type; **********************************************************************/ /*! * Create a file hash - * The hash will be used to identify the loaded firmware and fpga image + * The hash will be used to identify the loaded fpga image * \param filename file used to generate hash value * \return hash value in a uint32_t type */ @@ -125,66 +126,6 @@ static hash_type generate_hash(const char *filename) } -/*! - * Verify checksum of a Intel HEX record - * \param record a line from an Intel HEX file - * \return true if record is valid, false otherwise - */ -bool checksum(const std::string& record) { - - size_t len = record.length(); - unsigned int i; - unsigned char sum = 0; - unsigned int val; - - for (i = 1; i < len; i += 2) { - std::istringstream(record.substr(i, 2)) >> std::hex >> val; - sum += val; - } - - if (sum == 0) - return true; - else - return false; -} - - -/*! - * Parse Intel HEX record - * - * \param record a line from an Intel HEX file - * \param len output length of record - * \param addr output address - * \param type output type - * \param data output data - * \return true if record is sucessfully read, false on error - */ -bool parse_record(const std::string& record, boost::uint16_t &len, \ - boost::uint16_t &addr, boost::uint16_t &type, unsigned char* data) { - - unsigned int i; - std::string _data; - unsigned int val; - - if (record.substr(0, 1) != ":") - return false; - - std::istringstream(record.substr(1, 2)) >> std::hex >> len; - std::istringstream(record.substr(3, 4)) >> std::hex >> addr; - std::istringstream(record.substr(7, 2)) >> std::hex >> type; - - if (len > (2 * (record.length() - 9))) // sanity check to prevent buffer overrun - return false; - - for (i = 0; i < len; i++) { - std::istringstream(record.substr(9 + 2 * i, 2)) >> std::hex >> val; - data[i] = (unsigned char) val; - } - - return true; -} - - /*********************************************************************** * The implementation class **********************************************************************/ @@ -270,109 +211,31 @@ public: void load_firmware(const std::string filestring, UHD_UNUSED(bool force) = false) { - const char *filename = filestring.c_str(); - - /* Fields used in each USB control transfer. */ - boost::uint16_t len = 0; - boost::uint16_t type = 0; - boost::uint16_t lower_address_bits = 0x0000; - unsigned char data[512]; - - /* Can be set by the Intel HEX record 0x04, used for all 0x00 records - * thereafter. Note this field takes the place of the 'index' parameter in - * libusb calls, and is necessary for FX3's 32-bit addressing. */ - boost::uint16_t upper_address_bits = 0x0000; - - std::ifstream file; - file.open(filename, std::ifstream::in); - - if(!file.good()) { - throw uhd::io_error("fx3_load_firmware: cannot open firmware input file"); + if (load_img_msg) + UHD_MSG(status) << "Loading firmware image: " + << filestring << "..." << std::flush; + + ihex_reader file_reader(filestring); + try { + file_reader.read( + boost::bind( + &b200_iface_impl::fx3_control_write, this, + FX3_FIRMWARE_LOAD, _1, _2, _3, _4, 0 + ) + ); + } catch (const uhd::io_error &e) { + throw uhd::io_error(str(boost::format("Could not load firmware: \n%s") % e.what())); } - if (load_img_msg) UHD_MSG(status) << "Loading firmware image: " \ - << filestring << "..." << std::flush; - - while (!file.eof()) { - boost::int32_t ret = 0; - std::string record; - file >> record; - - if (!(record.length() > 0)) - continue; - - /* Check for valid Intel HEX record. */ - if (!checksum(record) || !parse_record(record, len, \ - lower_address_bits, type, data)) { - throw uhd::io_error("fx3_load_firmware: bad intel hex record checksum"); - } - - /* Type 0x00: Data. */ - if (type == 0x00) { - ret = fx3_control_write(FX3_FIRMWARE_LOAD, \ - lower_address_bits, upper_address_bits, data, len); - - if (ret < 0) { - throw uhd::io_error("usrp_load_firmware: usrp_control_write failed"); - } - } - - /* Type 0x01: EOF. */ - else if (type == 0x01) { - if (lower_address_bits != 0x0000 || len != 0 ) { - throw uhd::io_error("fx3_load_firmware: For EOF record, address must be 0, length must be 0."); - } - - //TODO - //usrp_set_firmware_hash(hash); //set hash before reset - - /* Successful termination! */ - file.close(); + UHD_MSG(status) << std::endl; - /* Let the system settle. */ - boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); - return; - } - - /* Type 0x04: Extended Linear Address Record. */ - else if (type == 0x04) { - if (lower_address_bits != 0x0000 || len != 2 ) { - throw uhd::io_error("fx3_load_firmware: For ELA record, address must be 0, length must be 2."); - } - - upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\ - + ((boost::uint16_t)(data[1] & 0x00FF)); - } - - /* Type 0x05: Start Linear Address Record. */ - else if (type == 0x05) { - if (lower_address_bits != 0x0000 || len != 4 ) { - throw uhd::io_error("fx3_load_firmware: For SLA record, address must be 0, length must be 4."); - } - - /* The firmware load is complete. We now need to tell the CPU - * to jump to an execution address start point, now contained within - * the data field. Parse these address bits out, and then push the - * instruction. */ - upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\ - + ((boost::uint16_t)(data[1] & 0x00FF)); - lower_address_bits = ((boost::uint16_t)((data[2] & 0x00FF) << 8))\ - + ((boost::uint16_t)(data[3] & 0x00FF)); - - fx3_control_write(FX3_FIRMWARE_LOAD, lower_address_bits, \ - upper_address_bits, 0, 0); - - if (load_img_msg) UHD_MSG(status) << " done" << std::endl; - } - - /* If we receive an unknown record type, error out. */ - else { - throw uhd::io_error("fx3_load_firmware: unsupported record type."); - } - } + //TODO + //usrp_set_firmware_hash(hash); //set hash before reset - /* There was no valid EOF. */ - throw uhd::io_error("fx3_load_firmware: No EOF record found."); + /* Success! Let the system settle. */ + // TODO: Replace this with a polling loop in the FX3, or find out + // what the actual, correct timeout value is. + boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); } void reset_fx3(void) { diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 19ec561fa..e45c78d49 100644 --- a/host/lib/usrp/b200/b200_iface.hpp +++ b/host/lib/usrp/b200/b200_iface.hpp @@ -30,25 +30,28 @@ enum b200_product_t { B200, B210, - B205 + B200MINI, + B205MINI }; // These are actual USB PIDs (not Ettus Product IDs) -const static boost::uint16_t B200_VENDOR_ID = 0x2500; -const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; -const static boost::uint16_t B200_PRODUCT_ID = 0x0020; -const static boost::uint16_t B205_PRODUCT_ID = 0x0021; -const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; -const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; -const static boost::uint16_t FX3_VID = 0x04b4; -const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; -const static boost::uint16_t FX3_REENUM_PID = 0x00f0; +const static boost::uint16_t B200_VENDOR_ID = 0x2500; +const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; +const static boost::uint16_t B200_PRODUCT_ID = 0x0020; +const static boost::uint16_t B200MINI_PRODUCT_ID = 0x0021; +const static boost::uint16_t B205MINI_PRODUCT_ID = 0x0022; +const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; +const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; +const static boost::uint16_t FX3_VID = 0x04b4; +const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; +const static boost::uint16_t FX3_REENUM_PID = 0x00f0; //! Map the USB PID to the product (only for PIDs that map to a single product) static const uhd::dict<boost::uint16_t, b200_product_t> B2XX_PID_TO_PRODUCT = boost::assign::map_list_of - (B200_PRODUCT_NI_ID, B200) - (B210_PRODUCT_NI_ID, B210) - (B205_PRODUCT_ID, B205) + (B200_PRODUCT_NI_ID, B200) + (B210_PRODUCT_NI_ID, B210) + (B200MINI_PRODUCT_ID, B200MINI) + (B205MINI_PRODUCT_ID, B205MINI) ; static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex"; @@ -61,21 +64,25 @@ static const uhd::dict<boost::uint16_t, b200_product_t> B2XX_PRODUCT_ID = boost: (0x0002, B210) (0x7738, B210) (B210_PRODUCT_NI_ID, B210) - (0x0003, B205) - (0x7739, B205) + (0x0003, B200MINI) + (0x7739, B200MINI) + (0x0004, B205MINI) + (0x773a, B205MINI) ; static const uhd::dict<b200_product_t, std::string> B2XX_STR_NAMES = boost::assign::map_list_of - (B200, "B200") - (B210, "B210") - (B205, "B200mini") + (B200, "B200") + (B210, "B210") + (B200MINI, "B200mini") + (B205MINI, "B205mini") ; static const uhd::dict<b200_product_t, std::string> B2XX_FPGA_FILE_NAME = boost::assign::map_list_of (B200, "usrp_b200_fpga.bin") (B210, "usrp_b210_fpga.bin") - (B205, "usrp_b200mini_fpga.bin") + (B200MINI, "usrp_b200mini_fpga.bin") + (B205MINI, "usrp_b205mini_fpga.bin") ; diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 3aaf28ab3..62690f09f 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -75,9 +75,9 @@ public: }; // B205 -class b205_ad9361_client_t : public ad9361_params { +class b2xxmini_ad9361_client_t : public ad9361_params { public: - ~b205_ad9361_client_t() {} + ~b2xxmini_ad9361_client_t() {} double get_band_edge(frequency_band_t band) { switch (band) { case AD9361_RX_BAND0: return 0; // Set these all to @@ -319,7 +319,8 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s else if (specified_vid) { vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200_PRODUCT_ID)); - vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B205_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200MINI_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B205MINI_PRODUCT_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200_PRODUCT_NI_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B210_PRODUCT_NI_ID)); } @@ -333,7 +334,8 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s else { vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID)); - vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200MINI_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205MINI_PRODUCT_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID)); } @@ -387,7 +389,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s UHD_MSG(status) << "Detected Device: " << B2XX_STR_NAMES[_product] << std::endl; - _gpsdo_capable = (_product != B205); + _gpsdo_capable = (not (_product == B200MINI or _product == B205MINI)); //////////////////////////////////////////////////////////////////// // Set up frontend mapping @@ -406,7 +408,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s _fe2 = 0; _gpio_state.swap_atr = 1; // Unswapped setup: - if (_product == B205 or (_product == B200 and _revision >= 5)) { + if (_product == B200MINI or _product == B205MINI or (_product == B200 and _revision >= 5)) { _fe1 = 0; //map radio0 to FE1 _fe2 = 1; //map radio1 to FE2 _gpio_state.swap_atr = 0; // ATRs for radio0 are mapped to FE1 @@ -513,7 +515,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s //////////////////////////////////////////////////////////////////// _tree->create<std::string>("/name").set("B-Series Device"); _tree->create<std::string>(mb_path / "name").set(product_name); - _tree->create<std::string>(mb_path / "codename").set((_product == B205) ? "Pixie" : "Sasquatch"); + _tree->create<std::string>(mb_path / "codename").set((_product == B200MINI or _product == B205MINI) ? "Pixie" : "Sasquatch"); //////////////////////////////////////////////////////////////////// // Create data transport @@ -541,7 +543,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s // create time and clock control objects //////////////////////////////////////////////////////////////////// _spi_iface = b200_local_spi_core::make(_local_ctrl); - if (_product != B205) { + if (not (_product == B200MINI or _product == B205MINI)) { _adf4001_iface = boost::make_shared<b200_ref_pll_ctrl>(_spi_iface); } @@ -550,13 +552,13 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s //////////////////////////////////////////////////////////////////// UHD_MSG(status) << "Initialize CODEC control..." << std::endl; ad9361_params::sptr client_settings; - if (_product == B205) { - client_settings = boost::make_shared<b205_ad9361_client_t>(); + if (_product == B200MINI or _product == B205MINI) { + client_settings = boost::make_shared<b2xxmini_ad9361_client_t>(); } else { client_settings = boost::make_shared<b200_ad9361_client_t>(); } _codec_ctrl = ad9361_ctrl::make_spi(client_settings, _spi_iface, AD9361_SLAVENO); - + //////////////////////////////////////////////////////////////////// // create codec control objects //////////////////////////////////////////////////////////////////// @@ -624,15 +626,18 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s //register time now and pps onto available radio cores _tree->create<time_spec_t>(mb_path / "time" / "now") - .publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64)); + .publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64)) + .subscribe(boost::bind(&b200_impl::set_time, this, _1)) + .set(0.0); + //re-sync the times when the tick rate changes + _tree->access<double>(mb_path / "tick_rate") + .subscribe(boost::bind(&b200_impl::sync_times, this)); _tree->create<time_spec_t>(mb_path / "time" / "pps") .publish(boost::bind(&time_core_3000::get_time_last_pps, _radio_perifs[0].time64)); - for (size_t i = 0; i < _radio_perifs.size(); i++) + BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { - _tree->access<time_spec_t>(mb_path / "time" / "now") - .subscribe(boost::bind(&time_core_3000::set_time_now, _radio_perifs[i].time64, _1)); _tree->access<time_spec_t>(mb_path / "time" / "pps") - .subscribe(boost::bind(&time_core_3000::set_time_next_pps, _radio_perifs[i].time64, _1)); + .subscribe(boost::bind(&time_core_3000::set_time_next_pps, perif.time64, _1)); } //setup time source props @@ -945,7 +950,7 @@ void b200_impl::check_fpga_compat(void) if (signature != 0xACE0BA5E) throw uhd::runtime_error( "b200::check_fpga_compat signature register readback failed"); - const boost::uint16_t expected = (_product == B205 ? B205_FPGA_COMPAT_NUM : B200_FPGA_COMPAT_NUM); + const boost::uint16_t expected = ((_product == B200MINI or _product == B205MINI) ? B205_FPGA_COMPAT_NUM : B200_FPGA_COMPAT_NUM); if (compat_major != expected) { throw uhd::runtime_error(str(boost::format( @@ -970,7 +975,7 @@ void b200_impl::set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &mb_eeprom) void b200_impl::update_clock_source(const std::string &source) { // For B205, ref_sel selects whether or not to lock to the external clock source - if (_product == B205) + if (_product == B200MINI or _product == B205MINI) { if (source == "external" and _time_source == EXTERNAL) { @@ -1032,7 +1037,7 @@ void b200_impl::update_clock_source(const std::string &source) void b200_impl::update_time_source(const std::string &source) { - if (_product == B205 and source == "external" and _gpio_state.ref_sel == 1) + if ((_product == B200MINI or _product == B205MINI) and source == "external" and _gpio_state.ref_sel == 1) { throw uhd::value_error("external reference cannot be both a time source and a clock source"); } @@ -1052,11 +1057,24 @@ void b200_impl::update_time_source(const std::string &source) throw uhd::key_error("update_time_source: unknown source: " + source); if (_time_source != value) { - _local_ctrl->poke32(TOREG(SR_CORE_PPS_SEL), value); + _local_ctrl->poke32(TOREG(SR_CORE_SYNC), value); _time_source = value; } } +void b200_impl::set_time(const uhd::time_spec_t& t) +{ + BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) + perif.time64->set_time_sync(t); + _local_ctrl->poke32(TOREG(SR_CORE_SYNC), 1 << 2 | boost::uint32_t(_time_source)); + _local_ctrl->poke32(TOREG(SR_CORE_SYNC), _time_source); +} + +void b200_impl::sync_times() +{ + set_time(_radio_perifs[0].time64->get_time_now()); +} + /*********************************************************************** * GPIO setup **********************************************************************/ @@ -1064,7 +1082,7 @@ void b200_impl::update_time_source(const std::string &source) void b200_impl::update_bandsel(const std::string& which, double freq) { // B205 does not have bandsels - if (_product == B205) { + if (_product == B200MINI or _product == B205MINI) { return; } diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index b406572fb..08ae68e9a 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -49,8 +49,8 @@ #include "recv_packet_demuxer_3000.hpp" static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 8; static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 12; -static const boost::uint16_t B205_FPGA_COMPAT_NUM = 3; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 13; +static const boost::uint16_t B205_FPGA_COMPAT_NUM = 4; static const double B200_BUS_CLOCK_RATE = 100e6; static const boost::uint32_t B200_GPSDO_ST_NONE = 0x83; static const size_t B200_MAX_RATE_USB2 = 53248000; // bytes/s @@ -95,7 +95,8 @@ static const unsigned char B200_USB_DATA_SEND_ENDPOINT = 2; static std::vector<uhd::transport::usb_device_handle::vid_pid_pair_t> b200_vid_pid_pairs = boost::assign::list_of (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID)) - (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205_PRODUCT_ID)) + (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200MINI_PRODUCT_ID)) + (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205MINI_PRODUCT_ID)) (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID)) (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID)) ; @@ -167,6 +168,8 @@ private: uhd::usrp::subdev_spec_t coerce_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &); void update_time_source(const std::string &); + void set_time(const uhd::time_spec_t&); + void sync_times(void); void update_clock_source(const std::string &); void update_bandsel(const std::string& which, double freq); void update_antenna_sel(const size_t which, const std::string &ant); diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index 41b4b8a74..279901208 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -227,7 +227,8 @@ uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec(const uhd::usrp::subdev_s // // Any other spec is probably illegal and will be caught by // validate_subdev_spec(). - if (spec.size() and (_product == B200 or _product == B205) and spec[0].sd_name == "B") { + if (spec.size() and (_product == B200 or _product == B200MINI or _product == B205MINI) and spec[0].sd_name == "B") + { spec[0].sd_name = "A"; } return spec; diff --git a/host/lib/usrp/b200/b200_regs.hpp b/host/lib/usrp/b200/b200_regs.hpp index 8f2dd03f3..e9ab81bae 100644 --- a/host/lib/usrp/b200/b200_regs.hpp +++ b/host/lib/usrp/b200/b200_regs.hpp @@ -28,7 +28,7 @@ localparam SR_CORE_SPI = 8; localparam SR_CORE_MISC = 16; localparam SR_CORE_COMPAT = 24; localparam SR_CORE_GPSDO_ST = 40; -localparam SR_CORE_PPS_SEL = 48; +localparam SR_CORE_SYNC = 48; localparam RB32_CORE_SPI = 8; localparam RB32_CORE_MISC = 16; localparam RB32_CORE_STATUS = 20; diff --git a/host/lib/usrp/common/adf4001_ctrl.cpp b/host/lib/usrp/common/adf4001_ctrl.cpp index a7510c272..001b68b7a 100644 --- a/host/lib/usrp/common/adf4001_ctrl.cpp +++ b/host/lib/usrp/common/adf4001_ctrl.cpp @@ -81,7 +81,7 @@ boost::uint32_t adf4001_regs_t::get_reg(boost::uint8_t addr) { reg |= (boost::uint32_t(timer_counter_control) & 0x00000F) << 11; reg |= (boost::uint32_t(charge_pump_current_1) & 0x000007) << 15; reg |= (boost::uint32_t(charge_pump_current_2) & 0x000007) << 18; - reg |= (boost::uint32_t(power_down) & 0x000002) << 21; + reg |= (boost::uint32_t(power_down) & 0x000002) << 20; break; default: break; @@ -128,15 +128,15 @@ void adf4001_ctrl::set_lock_to_ext_ref(bool external) { void adf4001_ctrl::program_regs(void) { //no control over CE, only LE, therefore we use the initialization latch method write_reg(3); - boost::this_thread::sleep(boost::posix_time::microseconds(1)); + + //conduct a function latch (2) + write_reg(2); //write R counter latch (0) write_reg(0); - boost::this_thread::sleep(boost::posix_time::microseconds(1)); //write N counter latch (1) write_reg(1); - boost::this_thread::sleep(boost::posix_time::microseconds(1)); } diff --git a/host/lib/usrp/cores/time_core_3000.cpp b/host/lib/usrp/cores/time_core_3000.cpp index ffae5dc0d..694edf31c 100644 --- a/host/lib/usrp/cores/time_core_3000.cpp +++ b/host/lib/usrp/cores/time_core_3000.cpp @@ -24,8 +24,9 @@ #define REG_TIME_LO _base + 4 #define REG_TIME_CTRL _base + 8 -#define CTRL_LATCH_TIME_PPS (1 << 1) -#define CTRL_LATCH_TIME_NOW (1 << 0) +#define CTRL_LATCH_TIME_NOW (1 << 0) +#define CTRL_LATCH_TIME_PPS (1 << 1) +#define CTRL_LATCH_TIME_SYNC (1 << 2) using namespace uhd; @@ -99,6 +100,14 @@ struct time_core_3000_impl : time_core_3000 _iface->poke32(REG_TIME_CTRL, CTRL_LATCH_TIME_NOW); } + void set_time_sync(const uhd::time_spec_t &time) + { + const boost::uint64_t ticks = time.to_ticks(_tick_rate); + _iface->poke32(REG_TIME_HI, boost::uint32_t(ticks >> 32)); + _iface->poke32(REG_TIME_LO, boost::uint32_t(ticks >> 0)); + _iface->poke32(REG_TIME_CTRL, CTRL_LATCH_TIME_SYNC); + } + void set_time_next_pps(const uhd::time_spec_t &time) { const boost::uint64_t ticks = time.to_ticks(_tick_rate); diff --git a/host/lib/usrp/cores/time_core_3000.hpp b/host/lib/usrp/cores/time_core_3000.hpp index 7463386ba..7dde4e797 100644 --- a/host/lib/usrp/cores/time_core_3000.hpp +++ b/host/lib/usrp/cores/time_core_3000.hpp @@ -53,6 +53,8 @@ public: virtual void set_time_now(const uhd::time_spec_t &time) = 0; + virtual void set_time_sync(const uhd::time_spec_t &time) = 0; + virtual void set_time_next_pps(const uhd::time_spec_t &time) = 0; }; diff --git a/host/lib/usrp/e300/e300_fpga_defs.hpp b/host/lib/usrp/e300/e300_fpga_defs.hpp index dcfb05021..594461518 100644 --- a/host/lib/usrp/e300/e300_fpga_defs.hpp +++ b/host/lib/usrp/e300/e300_fpga_defs.hpp @@ -21,7 +21,7 @@ namespace uhd { namespace usrp { namespace e300 { namespace fpga { static const size_t NUM_RADIOS = 2; -static const boost::uint32_t COMPAT_MAJOR = 13; +static const boost::uint32_t COMPAT_MAJOR = 14; static const boost::uint32_t COMPAT_MINOR = 0; }}}} // namespace diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index c82ab3d0e..3242a7fe8 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -175,7 +175,7 @@ device_addrs_t e300_find(const device_addr_t &multi_dev_hint) device_addr_t new_hint = hint; new_hint["addr"] = if_addrs.bcast; - // call discover with the new hint ad append results + // call discover with the new hint and append results device_addrs_t new_e300_addrs = e300_find(new_hint); e300_addrs.insert(e300_addrs.begin(), new_e300_addrs.begin(), new_e300_addrs.end()); @@ -529,8 +529,11 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr) //////////////////////////////////////////////////////////////////// _tree->create<time_spec_t>(mb_path / "time" / "now") .publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64)) - .subscribe(boost::bind(&time_core_3000::set_time_now, _radio_perifs[0].time64, _1)) - .subscribe(boost::bind(&time_core_3000::set_time_now, _radio_perifs[1].time64, _1)); + .subscribe(boost::bind(&e300_impl::_set_time, this, _1)) + .set(0.0); + //re-sync the times when the tick rate changes + _tree->access<double>(mb_path / "tick_rate") + .subscribe(boost::bind(&e300_impl::_sync_times, this)); _tree->create<time_spec_t>(mb_path / "time" / "pps") .publish(boost::bind(&time_core_3000::get_time_last_pps, _radio_perifs[0].time64)) .subscribe(boost::bind(&time_core_3000::set_time_next_pps, _radio_perifs[0].time64, _1)) @@ -796,6 +799,21 @@ void e300_impl::_update_time_source(const std::string &source) _update_gpio_state(); } +void e300_impl::_set_time(const uhd::time_spec_t& t) +{ + BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) + perif.time64->set_time_sync(t); + _misc.time_sync = 1; + _update_gpio_state(); + _misc.time_sync = 0; + _update_gpio_state(); +} + +void e300_impl::_sync_times() +{ + _set_time(_radio_perifs[0].time64->get_time_now()); +} + size_t e300_impl::_get_axi_dma_channel( boost::uint8_t destination, boost::uint8_t prefix) @@ -1081,7 +1099,8 @@ void e300_impl::_update_gpio_state(void) | (_misc.tx_bandsels << gpio_t::TX_BANDSEL) | (_misc.rx_bandsel_a << gpio_t::RX_BANDSELA) | (_misc.rx_bandsel_b << gpio_t::RX_BANDSELB) - | (_misc.rx_bandsel_c << gpio_t::RX_BANDSELC); + | (_misc.rx_bandsel_c << gpio_t::RX_BANDSELC) + | (_misc.time_sync << gpio_t::TIME_SYNC); _global_regs->poke32(global_regs::SR_CORE_MISC, misc_reg); } diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp index 9b39c7468..1bf5cb950 100644 --- a/host/lib/usrp/e300/e300_impl.hpp +++ b/host/lib/usrp/e300/e300_impl.hpp @@ -200,6 +200,8 @@ private: // types boost::uint32_t rx_bandsel_b; boost::uint32_t rx_bandsel_c; + boost::uint32_t time_sync; + static const size_t PPS_SEL = 0; static const size_t MIMO = 2; static const size_t CODEC_ARST = 3; @@ -207,6 +209,7 @@ private: // types static const size_t RX_BANDSELA = 7; static const size_t RX_BANDSELB = 13; static const size_t RX_BANDSELC = 17; + static const size_t TIME_SYNC = 21; }; private: // methods @@ -257,6 +260,8 @@ private: // methods void _update_time_source(const std::string &source); void _update_clock_source(const std::string &); + void _set_time(const uhd::time_spec_t&); + void _sync_times(void); void _update_subdev_spec( const std::string &txrx, diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h index 4c5051eaa..549fc9dfa 100644 --- a/host/lib/usrp/x300/x300_fw_common.h +++ b/host/lib/usrp/x300/x300_fw_common.h @@ -33,7 +33,7 @@ extern "C" { #define X300_REVISION_MIN 2 #define X300_FW_COMPAT_MAJOR 4 #define X300_FW_COMPAT_MINOR 0 -#define X300_FPGA_COMPAT_MAJOR 18 +#define X300_FPGA_COMPAT_MAJOR 19 //shared memory sections - in between the stack and the program space #define X300_FW_SHMEM_BASE 0x6000 diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 0483ecf11..37461e2e5 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -809,8 +809,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// _tree->create<time_spec_t>(mb_path / "time" / "now") .publish(boost::bind(&time_core_3000::get_time_now, mb.radio_perifs[0].time64)) - .subscribe(boost::bind(&time_core_3000::set_time_now, mb.radio_perifs[0].time64, _1)) - .subscribe(boost::bind(&time_core_3000::set_time_now, mb.radio_perifs[1].time64, _1)); + .subscribe(boost::bind(&x300_impl::sync_times, this, mb, _1)) + .set(0.0); _tree->create<time_spec_t>(mb_path / "time" / "pps") .publish(boost::bind(&time_core_3000::get_time_last_pps, mb.radio_perifs[0].time64)) .subscribe(boost::bind(&time_core_3000::set_time_next_pps, mb.radio_perifs[0].time64, _1)) @@ -1505,6 +1505,14 @@ void x300_impl::update_time_source(mboard_members_t &mb, const std::string &sour */ } +void x300_impl::sync_times(mboard_members_t &mb, const uhd::time_spec_t& t) +{ + BOOST_FOREACH(radio_perifs_t &perif, mb.radio_perifs) + perif.time64->set_time_sync(t); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::TIME_SYNC, 1); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::TIME_SYNC, 0); +} + bool x300_impl::wait_for_clk_locked(mboard_members_t& mb, boost::uint32_t which, double timeout) { boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::milliseconds(timeout * 1000.0); diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 521ce8a0e..4de0344bf 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -362,6 +362,7 @@ private: void set_time_source_out(mboard_members_t&, const bool); void update_clock_source(mboard_members_t&, const std::string &); void update_time_source(mboard_members_t&, const std::string &); + void sync_times(mboard_members_t&, const uhd::time_spec_t&); uhd::sensor_value_t get_ref_locked(mboard_members_t& mb); bool wait_for_clk_locked(mboard_members_t& mb, boost::uint32_t which, double timeout); diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index 489d249ba..de3a3161a 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -213,6 +213,7 @@ namespace uhd { namespace usrp { namespace x300 { UHD_DEFINE_SOFT_REG_FIELD(PPS_OUT_EN, /*width*/ 1, /*shift*/ 4); //[4] UHD_DEFINE_SOFT_REG_FIELD(TCXO_EN, /*width*/ 1, /*shift*/ 5); //[5] UHD_DEFINE_SOFT_REG_FIELD(GPSDO_PWR_EN, /*width*/ 1, /*shift*/ 6); //[6] + UHD_DEFINE_SOFT_REG_FIELD(TIME_SYNC, /*width*/ 1, /*shift*/ 7); //[7] static const boost::uint32_t SRC_EXTERNAL = 0x0; static const boost::uint32_t SRC_INTERNAL = 0x2; @@ -225,6 +226,7 @@ namespace uhd { namespace usrp { namespace x300 { set(PPS_OUT_EN, 0); set(TCXO_EN, 1); set(GPSDO_PWR_EN, 1); //GPSDO power always ON + set(TIME_SYNC, 0); } } clock_ctrl_reg; |