From 9cb9e7d52255d3e14e57867eee76b555f705954c Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Fri, 13 Aug 2010 16:20:41 -0700 Subject: usrp1: Add usrp1 implementation --- host/lib/usrp/usrp1/usrp1_impl.hpp | 182 +++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 host/lib/usrp/usrp1/usrp1_impl.hpp (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp new file mode 100644 index 000000000..5abc37c7f --- /dev/null +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -0,0 +1,182 @@ +// +// 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 . +// + +#include "usrp1_iface.hpp" +#include "usrp1_ctrl.hpp" +#include "clock_ctrl.hpp" +#include "codec_ctrl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef INCLUDED_USRP1_IMPL_HPP +#define INCLUDED_USRP1_IMPL_HPP + +static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control + +/*! + * Make a usrp1 dboard interface. + * \param iface the usrp1 interface object + * \param clock the clock control interface + * \param codec the codec control interface + * \return a sptr to a new dboard interface + */ +uhd::usrp::dboard_iface::sptr make_usrp1_dboard_iface(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + usrp1_codec_ctrl::sptr codec); + +/*! + * Simple wax obj proxy class: + * Provides a wax obj interface for a set and a get function. + * This allows us to create nested properties structures + * while maintaining flattened code within the implementation. + */ +class wax_obj_proxy : public wax::obj { +public: + typedef boost::function get_t; + typedef boost::function set_t; + typedef boost::shared_ptr sptr; + + static sptr make(const get_t &get, const set_t &set) + { + return sptr(new wax_obj_proxy(get, set)); + } + +private: + get_t _get; set_t _set; + wax_obj_proxy(const get_t &get, const set_t &set): _get(get), _set(set) {}; + void get(const wax::obj &key, wax::obj &val) {return _get(key, val);} + void set(const wax::obj &key, const wax::obj &val) {return _set(key, val);} +}; + +/*! + * USRP1 implementation guts: + * The implementation details are encapsulated here. + * Handles properties on the mboard, dboard, dsps... + */ +class usrp1_impl : public uhd::device { +public: + //structors + usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, + usrp_ctrl::sptr ctrl_transport); + + ~usrp1_impl(void); + + //the io interface + size_t send(const std::vector &, + size_t, + const uhd::tx_metadata_t &, + const uhd::io_type_t &, + send_mode_t); + + size_t recv(const std::vector &, + size_t, uhd::rx_metadata_t &, + const uhd::io_type_t &, + recv_mode_t, + size_t timeout); + + size_t get_max_send_samps_per_packet(void) const { return 0; } + size_t get_max_recv_samps_per_packet(void) const { return 0; } + + bool recv_async_msg(uhd::async_metadata_t &, size_t) { return true; } + +private: + //interface to ioctls and file descriptor + usrp1_iface::sptr _iface; + + //handle io stuff + UHD_PIMPL_DECL(io_impl) _io_impl; + void io_init(void); + void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); + void handle_overrun(size_t); + + //otw types + uhd::otw_type_t _rx_otw_type; + uhd::otw_type_t _tx_otw_type; + + //configuration shadows + uhd::clock_config_t _clock_config; + + //clock control + usrp1_clock_ctrl::sptr _clock_ctrl; + + //ad9862 codec control interface + usrp1_codec_ctrl::sptr _codec_ctrl; + + //codec properties interfaces + void codec_init(void); + void rx_codec_get(const wax::obj &, wax::obj &); + void rx_codec_set(const wax::obj &, const wax::obj &); + void tx_codec_get(const wax::obj &, wax::obj &); + void tx_codec_set(const wax::obj &, const wax::obj &); + wax_obj_proxy::sptr _rx_codec_proxy; + wax_obj_proxy::sptr _tx_codec_proxy; + + //device functions and settings + void get(const wax::obj &, wax::obj &); + void set(const wax::obj &, const wax::obj &); + + //mboard functions and settings + void mboard_init(void); + void mboard_get(const wax::obj &, wax::obj &); + void mboard_set(const wax::obj &, const wax::obj &); + wax_obj_proxy::sptr _mboard_proxy; + + //xx dboard functions and settings + void dboard_init(void); + uhd::usrp::dboard_manager::sptr _dboard_manager; + uhd::usrp::dboard_iface::sptr _dboard_iface; + + //rx dboard functions and settings + uhd::usrp::dboard_eeprom_t _rx_db_eeprom; + void rx_dboard_get(const wax::obj &, wax::obj &); + void rx_dboard_set(const wax::obj &, const wax::obj &); + uhd::prop_names_t _rx_subdevs_in_use; + wax_obj_proxy::sptr _rx_dboard_proxy; + + //tx dboard functions and settings + uhd::usrp::dboard_eeprom_t _tx_db_eeprom; + void tx_dboard_get(const wax::obj &, wax::obj &); + void tx_dboard_set(const wax::obj &, const wax::obj &); + uhd::prop_names_t _tx_subdevs_in_use; + wax_obj_proxy::sptr _tx_dboard_proxy; + + //rx ddc functions and settings + void rx_ddc_init(void); + void rx_ddc_get(const wax::obj &, wax::obj &); + void rx_ddc_set(const wax::obj &, const wax::obj &); + double _ddc_freq; size_t _ddc_decim; + wax_obj_proxy::sptr _rx_ddc_proxy; + + //tx duc functions and settings + void tx_duc_init(void); + void tx_duc_get(const wax::obj &, wax::obj &); + void tx_duc_set(const wax::obj &, const wax::obj &); + double _duc_freq; size_t _duc_interp; + wax_obj_proxy::sptr _tx_duc_proxy; + + //transports + uhd::transport::usb_zero_copy::sptr _data_transport; + usrp_ctrl::sptr _ctrl_transport; +}; + +#endif /* INCLUDED_USRP1_IMPL_HPP */ -- cgit v1.2.3 From 5c0d3d30606b25c72c98785d49c13cc27ad49ec1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 15 Aug 2010 18:49:06 -0700 Subject: usrp1: created daughterboard duality everything that should have two is now stored into a dictionary of slot to type the set and get functions are now bound with a third argument for dboard slot the dboard iface has yet to be completed with the correct registers for a vs b --- host/lib/usrp/usrp1/codec_ctrl.cpp | 16 ++-- host/lib/usrp/usrp1/codec_ctrl.hpp | 3 +- host/lib/usrp/usrp1/codec_impl.cpp | 42 +++++----- host/lib/usrp/usrp1/dboard_iface.cpp | 28 +++++-- host/lib/usrp/usrp1/dboard_impl.cpp | 148 +++++++++++++++++++---------------- host/lib/usrp/usrp1/dsp_impl.cpp | 55 +++++++------ host/lib/usrp/usrp1/mboard_impl.cpp | 21 +++-- host/lib/usrp/usrp1/usrp1_impl.cpp | 13 ++- host/lib/usrp/usrp1/usrp1_impl.hpp | 103 +++++++++++++----------- 9 files changed, 246 insertions(+), 183 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index d0576a769..01617de94 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -17,8 +17,6 @@ #include "codec_ctrl.hpp" #include "usrp_commands.h" -#include "fpga_regs_standard.h" -#include "usrp_spi_defs.h" #include "ad9862_regs.hpp" #include #include @@ -45,7 +43,7 @@ const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1); class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl { public: //structors - usrp1_codec_ctrl_impl(usrp1_iface::sptr iface); + usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave); ~usrp1_codec_ctrl_impl(void); //aux adc and dac control @@ -63,6 +61,7 @@ public: private: usrp1_iface::sptr _iface; + int _spi_slave; ad9862_regs_t _ad9862_regs; aux_adc_t _last_aux_adc_a, _last_aux_adc_b; void send_reg(boost::uint8_t addr); @@ -78,9 +77,10 @@ private: /*********************************************************************** * Codec Control Structors **********************************************************************/ -usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface) +usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave) { _iface = iface; + _spi_slave = spi_slave; //soft reset _ad9862_regs.soft_reset = 1; @@ -295,7 +295,7 @@ void usrp1_codec_ctrl_impl::send_reg(boost::uint8_t addr) std::cout << "codec control write reg: 0x"; std::cout << std::setw(8) << std::hex << reg << std::endl; } - _iface->transact_spi(SPI_ENABLE_CODEC_A, + _iface->transact_spi(_spi_slave, spi_config_t::EDGE_RISE, reg, 16, false); } @@ -309,7 +309,7 @@ void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr) std::cout << std::setw(8) << std::hex << reg << std::endl; } - boost::uint32_t ret = _iface->transact_spi(SPI_ENABLE_CODEC_A, + boost::uint32_t ret = _iface->transact_spi(_spi_slave, spi_config_t::EDGE_RISE, reg, 16, true); if (codec_debug) { @@ -435,7 +435,7 @@ bool usrp1_codec_ctrl_impl::set_duc_freq(double freq) /*********************************************************************** * Codec Control Make **********************************************************************/ -usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface) +usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, int spi_slave) { - return sptr(new usrp1_codec_ctrl_impl(iface)); + return sptr(new usrp1_codec_ctrl_impl(iface, spi_slave)); } diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 0605e3228..6440f97d1 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -38,9 +38,10 @@ public: /*! * Make a new clock control object. * \param iface the usrp1 iface object + * \param spi_slave which spi device * \return the clock control object */ - static sptr make(usrp1_iface::sptr iface); + static sptr make(usrp1_iface::sptr iface, int spi_slave); //! aux adc identifier constants enum aux_adc_t{ diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp index 7bf5631fb..766a7948f 100644 --- a/host/lib/usrp/usrp1/codec_impl.cpp +++ b/host/lib/usrp/usrp1/codec_impl.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include using namespace uhd; using namespace uhd::usrp; @@ -29,13 +31,15 @@ using namespace uhd::usrp; void usrp1_impl::codec_init(void) { //make proxies - _rx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::rx_codec_get, this, _1, _2), - boost::bind(&usrp1_impl::rx_codec_set, this, _1, _2)); - - _tx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::tx_codec_get, this, _1, _2), - boost::bind(&usrp1_impl::tx_codec_set, this, _1, _2)); + BOOST_FOREACH(dboard_slot_t dboard_slot, _dboard_slots){ + _rx_codec_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_codec_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::rx_codec_set, this, _1, _2, dboard_slot)); + + _tx_codec_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_codec_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::tx_codec_set, this, _1, _2, dboard_slot)); + } } /*********************************************************************** @@ -43,14 +47,14 @@ void usrp1_impl::codec_init(void) **********************************************************************/ static const std::string ad9862_pga_gain_name = "ad9862 pga"; -void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val) +void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()) { case CODEC_PROP_NAME: - val = std::string("usrp1 adc - ad9862"); + val = str(boost::format("usrp1 adc - ad9862 - slot %c") % dboard_slot); return; case CODEC_PROP_OTHERS: @@ -68,19 +72,19 @@ void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val) case CODEC_PROP_GAIN_I: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_rx_pga_gain('A'); + val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('A'); return; case CODEC_PROP_GAIN_Q: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_rx_pga_gain('B'); + val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('B'); return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val) +void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); @@ -88,12 +92,12 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val) switch(key.as()) { case CODEC_PROP_GAIN_I: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_rx_pga_gain(val.as(), 'A'); + _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'A'); return; case CODEC_PROP_GAIN_Q: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_rx_pga_gain(val.as(), 'B'); + _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'B'); return; default: UHD_THROW_PROP_SET_ERROR(); @@ -103,14 +107,14 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val) /*********************************************************************** * TX Codec Properties **********************************************************************/ -void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val) +void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()) { case CODEC_PROP_NAME: - val = std::string("usrp1 dac - ad9862"); + val = str(boost::format("usrp1 dac - ad9862 - slot %c") % dboard_slot); return; case CODEC_PROP_OTHERS: @@ -129,14 +133,14 @@ void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val) case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_tx_pga_gain(); + val = _codec_ctrls[dboard_slot]->get_tx_pga_gain(); return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val) +void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); @@ -145,7 +149,7 @@ void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val) case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_tx_pga_gain(val.as()); + _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as()); return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index ef6a1e67b..82ef9e65b 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -16,6 +16,7 @@ // #include "usrp1_iface.hpp" +#include "usrp1_impl.hpp" #include "fpga_regs_common.h" #include "usrp_spi_defs.h" #include "clock_ctrl.hpp" @@ -30,16 +31,27 @@ using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; +/*********************************************************************** + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * + * check the _dboard_slot and handle conditionally... + **********************************************************************/ + class usrp1_dboard_iface : public dboard_iface { public: usrp1_dboard_iface(usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, - usrp1_codec_ctrl::sptr codec) - { + usrp1_codec_ctrl::sptr codec, + usrp1_impl::dboard_slot_t dboard_slot + ){ _iface = iface; _clock = clock; _codec = codec; + _dboard_slot = dboard_slot; //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_master_clock_freq()); @@ -55,7 +67,7 @@ public: { special_props_t props; props.soft_clock_divider = true; - props.mangle_i2c_addrs = false; //TODO true on side B + props.mangle_i2c_addrs = (_dboard_slot == usrp1_impl::DBOARD_SLOT_B); return props; } @@ -91,16 +103,18 @@ private: usrp1_clock_ctrl::sptr _clock; usrp1_codec_ctrl::sptr _codec; uhd::dict _clock_rates; + usrp1_impl::dboard_slot_t _dboard_slot; }; /*********************************************************************** * Make Function **********************************************************************/ -dboard_iface::sptr make_usrp1_dboard_iface(usrp1_iface::sptr iface, +dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, - usrp1_codec_ctrl::sptr codec) -{ - return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec)); + usrp1_codec_ctrl::sptr codec, + usrp1_impl::dboard_slot_t dboard_slot +){ + return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec, dboard_slot)); } /*********************************************************************** diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index 9df87432d..ba826d2f5 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -23,96 +23,107 @@ #include #include #include +#include +#include #include using namespace uhd; using namespace uhd::usrp; /*********************************************************************** - * Dboard Initialization + * Helper Functions **********************************************************************/ -void usrp1_impl::dboard_init(void) -{ - _rx_db_eeprom = dboard_eeprom_t( - _iface->read_eeprom(I2C_ADDR_RX_A, 0, dboard_eeprom_t::num_bytes())); - - _tx_db_eeprom = dboard_eeprom_t( - _iface->read_eeprom(I2C_ADDR_TX_A, 0, dboard_eeprom_t::num_bytes())); - - - //create a new dboard interface and manager - _dboard_iface = make_usrp1_dboard_iface(_iface, _clock_ctrl, _codec_ctrl); - - _dboard_manager = dboard_manager::make(_rx_db_eeprom.id, - _tx_db_eeprom.id, - _dboard_iface); - - //setup the dboard proxies - _rx_dboard_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::rx_dboard_get, this, _1, _2), - boost::bind(&usrp1_impl::rx_dboard_set, this, _1, _2)); - - _tx_dboard_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::tx_dboard_get, this, _1, _2), - boost::bind(&usrp1_impl::tx_dboard_set, this, _1, _2)); +static boost::uint8_t get_rx_ee_addr(usrp1_impl::dboard_slot_t dboard_slot){ + switch(dboard_slot){ + case usrp1_impl::DBOARD_SLOT_A: return I2C_ADDR_RX_A; + case usrp1_impl::DBOARD_SLOT_B: return I2C_ADDR_RX_B; + default: UHD_THROW_INVALID_CODE_PATH(); + } +} +static boost::uint8_t get_tx_ee_addr(usrp1_impl::dboard_slot_t dboard_slot){ + switch(dboard_slot){ + case usrp1_impl::DBOARD_SLOT_A: return I2C_ADDR_TX_A; + case usrp1_impl::DBOARD_SLOT_B: return I2C_ADDR_TX_B; + default: UHD_THROW_INVALID_CODE_PATH(); + } } + /*********************************************************************** - * Helper functions + * Dboard Initialization **********************************************************************/ -//static int slot_to_i2c_addr (int slot) -//{ -// switch (slot) { -// case SLOT_TX_A: -// return I2C_ADDR_TX_A; -// case SLOT_RX_A: -// return I2C_ADDR_RX_A; -// case SLOT_TX_B: -// return I2C_ADDR_TX_B; -// case SLOT_RX_B: -// return I2C_ADDR_RX_B; -// default: -// return -1; -// } -//} +void usrp1_impl::dboard_init(void) +{ + BOOST_FOREACH(dboard_slot_t dboard_slot, _dboard_slots){ + + //read the tx and rx dboard eeproms + _rx_db_eeproms[dboard_slot] = dboard_eeprom_t(_iface->read_eeprom( + get_rx_ee_addr(dboard_slot), 0, dboard_eeprom_t::num_bytes() + )); + + _tx_db_eeproms[dboard_slot] = dboard_eeprom_t(_iface->read_eeprom( + get_tx_ee_addr(dboard_slot), 0, dboard_eeprom_t::num_bytes() + )); + + //create a new dboard interface and manager + _dboard_ifaces[dboard_slot] = make_dboard_iface( + _iface, _clock_ctrl, _codec_ctrls[dboard_slot], dboard_slot + ); + + _dboard_managers[dboard_slot] = dboard_manager::make( + _rx_db_eeproms[dboard_slot].id, + _tx_db_eeproms[dboard_slot].id, + _dboard_ifaces[dboard_slot] + ); + + //setup the dboard proxies + _rx_dboard_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_dboard_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::rx_dboard_set, this, _1, _2, dboard_slot)); + + _tx_dboard_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_dboard_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::tx_dboard_set, this, _1, _2, dboard_slot)); + } +} /*********************************************************************** * RX Dboard Get **********************************************************************/ -void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val) +void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ case DBOARD_PROP_NAME: - val = std::string("usrp1 dboard (rx unit)"); + val = str(boost::format("usrp1 dboard (rx unit) - %c") % dboard_slot); return; case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_rx_subdev(key.name); + val = _dboard_managers[dboard_slot]->get_rx_subdev(key.name); return; case DBOARD_PROP_SUBDEV_NAMES: - val = _dboard_manager->get_rx_subdev_names(); + val = _dboard_managers[dboard_slot]->get_rx_subdev_names(); return; case DBOARD_PROP_DBOARD_ID: - val = _rx_db_eeprom.id; + val = _rx_db_eeproms[dboard_slot].id; return; case DBOARD_PROP_DBOARD_IFACE: - val = _dboard_iface; + val = _dboard_ifaces[dboard_slot]; return; case DBOARD_PROP_CODEC: - val = _rx_codec_proxy->get_link(); + val = _rx_codec_proxies[dboard_slot]->get_link(); return; case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group(_dboard_manager->get_rx_subdev(key.name), - _rx_codec_proxy->get_link()); + val = make_gain_group(_dboard_managers[dboard_slot]->get_rx_subdev(key.name), + _rx_codec_proxies[dboard_slot]->get_link()); return; default: UHD_THROW_PROP_GET_ERROR(); @@ -122,13 +133,15 @@ void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val) /*********************************************************************** * RX Dboard Set **********************************************************************/ -void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val, dboard_slot_t dboard_slot) { switch(key.as()) { case DBOARD_PROP_DBOARD_ID: - _rx_db_eeprom.id = val.as(); - _iface->write_eeprom(I2C_ADDR_RX_A, 0, - _rx_db_eeprom.get_eeprom_bytes()); + _rx_db_eeproms[dboard_slot].id = val.as(); + _iface->write_eeprom( + get_rx_ee_addr(dboard_slot), 0, + _rx_db_eeproms[dboard_slot].get_eeprom_bytes() + ); return; default: @@ -139,39 +152,39 @@ void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val) /*********************************************************************** * TX Dboard Get **********************************************************************/ -void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val) +void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ case DBOARD_PROP_NAME: - val = std::string("usrp1 dboard (tx unit)"); + val = str(boost::format("usrp1 dboard (tx unit) - %c") % dboard_slot); return; case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_tx_subdev(key.name); + val = _dboard_managers[dboard_slot]->get_tx_subdev(key.name); return; case DBOARD_PROP_SUBDEV_NAMES: - val = _dboard_manager->get_tx_subdev_names(); + val = _dboard_managers[dboard_slot]->get_tx_subdev_names(); return; case DBOARD_PROP_DBOARD_ID: - val = _tx_db_eeprom.id; + val = _tx_db_eeproms[dboard_slot].id; return; case DBOARD_PROP_DBOARD_IFACE: - val = _dboard_iface; + val = _dboard_ifaces[dboard_slot]; return; case DBOARD_PROP_CODEC: - val = _tx_codec_proxy->get_link(); + val = _tx_codec_proxies[dboard_slot]->get_link(); return; case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group(_dboard_manager->get_tx_subdev(key.name), - _tx_codec_proxy->get_link()); + val = make_gain_group(_dboard_managers[dboard_slot]->get_tx_subdev(key.name), + _tx_codec_proxies[dboard_slot]->get_link()); return; default: UHD_THROW_PROP_GET_ERROR(); @@ -181,12 +194,15 @@ void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val) /*********************************************************************** * TX Dboard Set **********************************************************************/ -void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val, dboard_slot_t dboard_slot) { switch(key.as()) { case DBOARD_PROP_DBOARD_ID: - _tx_db_eeprom.id = val.as(); - _iface->write_eeprom(I2C_ADDR_TX_A, 0, _tx_db_eeprom.get_eeprom_bytes()); + _tx_db_eeproms[dboard_slot].id = val.as(); + _iface->write_eeprom( + get_tx_ee_addr(dboard_slot), 0, + _tx_db_eeproms[dboard_slot].get_eeprom_bytes() + ); return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index e9900131f..1a8993a01 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -29,19 +29,19 @@ using namespace uhd::usrp; /*********************************************************************** * RX DDC Initialization **********************************************************************/ -void usrp1_impl::rx_ddc_init(void) +void usrp1_impl::rx_dsp_init(void) { - _rx_ddc_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::rx_ddc_get, this, _1, _2), - boost::bind(&usrp1_impl::rx_ddc_set, this, _1, _2)); + _rx_dsp_proxy = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2), + boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2)); - rx_ddc_set(DSP_PROP_HOST_RATE, double(64e6/10)); + rx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number } /*********************************************************************** * RX DDC Get **********************************************************************/ -void usrp1_impl::rx_ddc_get(const wax::obj &key, wax::obj &val) +void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) { switch(key.as()){ case DSP_PROP_NAME: @@ -53,7 +53,7 @@ void usrp1_impl::rx_ddc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_FREQ_SHIFT: - val = _ddc_freq; + val = _rx_dsp_freq; return; case DSP_PROP_CODEC_RATE: @@ -61,7 +61,7 @@ void usrp1_impl::rx_ddc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_HOST_RATE: - val = _clock_ctrl->get_master_clock_freq()/_ddc_decim; + val = _clock_ctrl->get_master_clock_freq()/_rx_dsp_decim; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -90,13 +90,13 @@ unsigned int compute_freq_word(double master, double target) return (unsigned int) v; } -void usrp1_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _iface->poke32(FR_RX_FREQ_0, compute_freq_word(64e6, new_freq)); - _ddc_freq = new_freq; + _iface->poke32(FR_RX_FREQ_0, compute_freq_word(64e6, new_freq)); //FIXME magic rate + _tx_dsp_freq = new_freq; return; } case DSP_PROP_HOST_RATE: { @@ -110,8 +110,8 @@ void usrp1_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val) return; } - _ddc_decim = rate; - _iface->poke32(FR_DECIM_RATE, _ddc_decim/2 - 1); + _rx_dsp_decim = rate; + _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1); } return; @@ -123,20 +123,20 @@ void usrp1_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val) /*********************************************************************** * TX DUC Initialization **********************************************************************/ -void usrp1_impl::tx_duc_init(void) +void usrp1_impl::tx_dsp_init(void) { - _tx_duc_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::tx_duc_get, this, _1, _2), - boost::bind(&usrp1_impl::tx_duc_set, this, _1, _2)); + _tx_dsp_proxy = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2), + boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2)); //initial config and update - tx_duc_set(DSP_PROP_HOST_RATE, double(64e6/10)); + tx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number } /*********************************************************************** * TX DUC Get **********************************************************************/ -void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) +void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) { switch(key.as()) { case DSP_PROP_NAME: @@ -148,7 +148,7 @@ void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_FREQ_SHIFT: - val = _duc_freq; + val = _tx_dsp_freq; return; case DSP_PROP_CODEC_RATE: @@ -156,7 +156,7 @@ void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_HOST_RATE: - val = _clock_ctrl->get_master_clock_freq() * 2 / _duc_interp; + val = _clock_ctrl->get_master_clock_freq() * 2 / _tx_dsp_interp; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -167,16 +167,19 @@ void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) /*********************************************************************** * TX DUC Set **********************************************************************/ -void usrp1_impl::tx_duc_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _codec_ctrl->set_duc_freq(new_freq); - _duc_freq = new_freq; + _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); + _tx_dsp_freq = new_freq; return; } + + //TODO freq prop secondary: DBOARD_SLOT_B codec... + case DSP_PROP_HOST_RATE: { unsigned int rate = _clock_ctrl->get_master_clock_freq() * 2 / val.as(); @@ -187,8 +190,8 @@ void usrp1_impl::tx_duc_set(const wax::obj &key, const wax::obj &val) return; } - _duc_interp = rate; - _iface->poke32(FR_INTERP_RATE, _duc_interp / 4 - 1); + _tx_dsp_interp = rate; + _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1); return; } default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 2514072e0..e0a7fefb1 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -19,6 +19,7 @@ #include "usrp_commands.h" #include #include +#include #include #include @@ -109,6 +110,8 @@ void usrp1_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd) /*********************************************************************** * Mboard Get **********************************************************************/ +static prop_names_t dboard_names = boost::assign::list_of("A")("B"); + void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) { named_prop_t key = named_prop_t::extract(key_); @@ -124,26 +127,28 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) return; case MBOARD_PROP_RX_DBOARD: - UHD_ASSERT_THROW(key.name == ""); - val = _rx_dboard_proxy->get_link(); + uhd::assert_has(dboard_names, key.name, "dboard name"); + if (key.name == "A") val = _rx_dboard_proxies[DBOARD_SLOT_A]->get_link(); + if (key.name == "B") val = _rx_dboard_proxies[DBOARD_SLOT_B]->get_link(); return; case MBOARD_PROP_RX_DBOARD_NAMES: - val = prop_names_t(1, ""); //vector of size 1 with empty string + val = dboard_names; return; case MBOARD_PROP_TX_DBOARD: - UHD_ASSERT_THROW(key.name == ""); - val = _tx_dboard_proxy->get_link(); + uhd::assert_has(dboard_names, key.name, "dboard name"); + if (key.name == "A") val = _tx_dboard_proxies[DBOARD_SLOT_A]->get_link(); + if (key.name == "B") val = _tx_dboard_proxies[DBOARD_SLOT_B]->get_link(); return; case MBOARD_PROP_TX_DBOARD_NAMES: - val = prop_names_t(1, ""); //vector of size 1 with empty string + val = dboard_names; return; case MBOARD_PROP_RX_DSP: UHD_ASSERT_THROW(key.name == ""); - val = _rx_ddc_proxy->get_link(); + val = _rx_dsp_proxy->get_link(); return; case MBOARD_PROP_RX_DSP_NAMES: @@ -152,7 +157,7 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) case MBOARD_PROP_TX_DSP: UHD_ASSERT_THROW(key.name == ""); - val = _tx_duc_proxy->get_link(); + val = _tx_dsp_proxy->get_link(); return; case MBOARD_PROP_TX_DSP_NAMES: diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 1435b981c..ece5f1dea 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -18,11 +18,13 @@ #include "usrp1_impl.hpp" #include "usrp1_ctrl.hpp" #include "fpga_regs_standard.h" +#include "usrp_spi_defs.h" #include #include #include #include #include +#include #include #include @@ -30,6 +32,10 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; +const std::vector usrp1_impl::_dboard_slots = boost::assign::list_of + (usrp1_impl::DBOARD_SLOT_A)(usrp1_impl::DBOARD_SLOT_B) +; + /*********************************************************************** * Discovery **********************************************************************/ @@ -132,7 +138,8 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, _clock_ctrl = usrp1_clock_ctrl::make(_iface); //create codec interface - _codec_ctrl = usrp1_codec_ctrl::make(_iface); + _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_A); + _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_B); //initialize the codecs codec_init(); @@ -144,10 +151,10 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, dboard_init(); //initialize the dsps - rx_ddc_init(); + rx_dsp_init(); //initialize the dsps - tx_duc_init(); + tx_dsp_init(); //initialize the send/recv io_init(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 5abc37c7f..84ec26827 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -21,6 +21,7 @@ #include "codec_ctrl.hpp" #include #include +#include #include #include #include @@ -33,17 +34,6 @@ static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control -/*! - * Make a usrp1 dboard interface. - * \param iface the usrp1 interface object - * \param clock the clock control interface - * \param codec the codec control interface - * \return a sptr to a new dboard interface - */ -uhd::usrp::dboard_iface::sptr make_usrp1_dboard_iface(usrp1_iface::sptr iface, - usrp1_clock_ctrl::sptr clock, - usrp1_codec_ctrl::sptr codec); - /*! * Simple wax obj proxy class: * Provides a wax obj interface for a set and a get function. @@ -75,6 +65,14 @@ private: */ class usrp1_impl : public uhd::device { public: + //! used everywhere to differentiate slots/sides... + enum dboard_slot_t{ + DBOARD_SLOT_A = 'A', + DBOARD_SLOT_B = 'B' + }; + //and a way to enumerate through a list of the above... + static const std::vector _dboard_slots; + //structors usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, usrp_ctrl::sptr ctrl_transport); @@ -97,9 +95,27 @@ public: size_t get_max_send_samps_per_packet(void) const { return 0; } size_t get_max_recv_samps_per_packet(void) const { return 0; } - bool recv_async_msg(uhd::async_metadata_t &, size_t) { return true; } + bool recv_async_msg(uhd::async_metadata_t &, size_t) { + //TODO sleep the number of ms supplied (dont want to hog CPU) + return false; + } private: + /*! + * Make a usrp1 dboard interface. + * \param iface the usrp1 interface object + * \param clock the clock control interface + * \param codec the codec control interface + * \param dboard_slot the slot identifier + * \return a sptr to a new dboard interface + */ + static uhd::usrp::dboard_iface::sptr make_dboard_iface( + usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + usrp1_codec_ctrl::sptr codec, + dboard_slot_t dboard_slot + ); + //interface to ioctls and file descriptor usrp1_iface::sptr _iface; @@ -120,16 +136,15 @@ private: usrp1_clock_ctrl::sptr _clock_ctrl; //ad9862 codec control interface - usrp1_codec_ctrl::sptr _codec_ctrl; + uhd::dict _codec_ctrls; //codec properties interfaces void codec_init(void); - void rx_codec_get(const wax::obj &, wax::obj &); - void rx_codec_set(const wax::obj &, const wax::obj &); - void tx_codec_get(const wax::obj &, wax::obj &); - void tx_codec_set(const wax::obj &, const wax::obj &); - wax_obj_proxy::sptr _rx_codec_proxy; - wax_obj_proxy::sptr _tx_codec_proxy; + void rx_codec_get(const wax::obj &, wax::obj &, dboard_slot_t); + void rx_codec_set(const wax::obj &, const wax::obj &, dboard_slot_t); + void tx_codec_get(const wax::obj &, wax::obj &, dboard_slot_t); + void tx_codec_set(const wax::obj &, const wax::obj &, dboard_slot_t); + uhd::dict _rx_codec_proxies, _tx_codec_proxies; //device functions and settings void get(const wax::obj &, wax::obj &); @@ -143,36 +158,34 @@ private: //xx dboard functions and settings void dboard_init(void); - uhd::usrp::dboard_manager::sptr _dboard_manager; - uhd::usrp::dboard_iface::sptr _dboard_iface; + uhd::dict _dboard_managers; + uhd::dict _dboard_ifaces; //rx dboard functions and settings - uhd::usrp::dboard_eeprom_t _rx_db_eeprom; - void rx_dboard_get(const wax::obj &, wax::obj &); - void rx_dboard_set(const wax::obj &, const wax::obj &); - uhd::prop_names_t _rx_subdevs_in_use; - wax_obj_proxy::sptr _rx_dboard_proxy; + uhd::dict _rx_db_eeproms; + void rx_dboard_get(const wax::obj &, wax::obj &, dboard_slot_t); + void rx_dboard_set(const wax::obj &, const wax::obj &, dboard_slot_t); + uhd::dict _rx_dboard_proxies; //tx dboard functions and settings - uhd::usrp::dboard_eeprom_t _tx_db_eeprom; - void tx_dboard_get(const wax::obj &, wax::obj &); - void tx_dboard_set(const wax::obj &, const wax::obj &); - uhd::prop_names_t _tx_subdevs_in_use; - wax_obj_proxy::sptr _tx_dboard_proxy; - - //rx ddc functions and settings - void rx_ddc_init(void); - void rx_ddc_get(const wax::obj &, wax::obj &); - void rx_ddc_set(const wax::obj &, const wax::obj &); - double _ddc_freq; size_t _ddc_decim; - wax_obj_proxy::sptr _rx_ddc_proxy; - - //tx duc functions and settings - void tx_duc_init(void); - void tx_duc_get(const wax::obj &, wax::obj &); - void tx_duc_set(const wax::obj &, const wax::obj &); - double _duc_freq; size_t _duc_interp; - wax_obj_proxy::sptr _tx_duc_proxy; + uhd::dict _tx_db_eeproms; + void tx_dboard_get(const wax::obj &, wax::obj &, dboard_slot_t); + void tx_dboard_set(const wax::obj &, const wax::obj &, dboard_slot_t); + uhd::dict _tx_dboard_proxies; + + //rx dsp functions and settings + void rx_dsp_init(void); + void rx_dsp_get(const wax::obj &, wax::obj &); + void rx_dsp_set(const wax::obj &, const wax::obj &); + double _rx_dsp_freq; size_t _rx_dsp_decim; + wax_obj_proxy::sptr _rx_dsp_proxy; + + //tx dsp functions and settings + void tx_dsp_init(void); + void tx_dsp_get(const wax::obj &, wax::obj &); + void tx_dsp_set(const wax::obj &, const wax::obj &); + double _tx_dsp_freq; size_t _tx_dsp_interp; + wax_obj_proxy::sptr _tx_dsp_proxy; //transports uhd::transport::usb_zero_copy::sptr _data_transport; -- cgit v1.2.3 From e7d4233a94571a2479b21bc081567214c38cc155 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 15 Aug 2010 19:12:41 -0700 Subject: usrp1: add skeleton code for setting subdev spec --- host/lib/usrp/usrp1/dboard_iface.cpp | 3 ++- host/lib/usrp/usrp1/mboard_impl.cpp | 33 +++++++++++++++++++++++++++++++-- host/lib/usrp/usrp1/usrp1_impl.hpp | 2 ++ 3 files changed, 35 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 82ef9e65b..142907e57 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -112,7 +112,7 @@ private: dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, usrp1_codec_ctrl::sptr codec, - usrp1_impl::dboard_slot_t dboard_slot + dboard_slot_t dboard_slot ){ return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec, dboard_slot)); } @@ -221,6 +221,7 @@ void usrp1_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value) { if ((atr == ATR_REG_IDLE) || (atr == ATR_REG_FULL_DUPLEX)) { + //TODO probably just ignore these two atr settings because all dboards will try to set them std::cerr << "error: set_atr_reg(): unsupported state" << std::endl; return; } diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index e0a7fefb1..5e0285dfd 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -17,6 +17,7 @@ #include "usrp1_impl.hpp" #include "usrp_commands.h" +#include "../misc_utils.hpp" #include #include #include @@ -168,6 +169,14 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) val = _clock_config; return; + case MBOARD_PROP_RX_SUBDEV_SPEC: + val = _rx_subdev_spec; + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + val = _tx_subdev_spec; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -184,8 +193,28 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) issue_stream_cmd(val.as()); return; - case MBOARD_PROP_TIME_NOW: - case MBOARD_PROP_TIME_NEXT_PPS: + case MBOARD_PROP_RX_SUBDEV_SPEC: + _rx_subdev_spec = val.as(); + verify_rx_subdev_spec(_rx_subdev_spec, this->get_link()); + //sanity check + UHD_ASSERT_THROW(_rx_subdev_spec.size() <= 2); + //set the mux and set the number of rx channels + //-------------------------------------------------- + // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + //-------------------------------------------------- + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + _tx_subdev_spec = val.as(); + verify_tx_subdev_spec(_tx_subdev_spec, this->get_link()); + //sanity check + UHD_ASSERT_THROW(_tx_subdev_spec.size() <= 2); + //set the mux and set the number of tx channels + //-------------------------------------------------- + // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + //-------------------------------------------------- + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 84ec26827..5166f989f 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -131,6 +132,7 @@ private: //configuration shadows uhd::clock_config_t _clock_config; + uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; //clock control usrp1_clock_ctrl::sptr _clock_ctrl; -- cgit v1.2.3 From 43e5480dee9f6068ffe84bf1b86526189043ee87 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Mon, 16 Aug 2010 17:03:06 -0700 Subject: usrp1: Remove hard coded clock values Get clock values from clock control, where the master setting lives. --- host/lib/usrp/usrp1/dsp_impl.cpp | 10 ++++++---- host/lib/usrp/usrp1/usrp1_impl.hpp | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 260c01ea8..0db3cb473 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -36,7 +36,7 @@ void usrp1_impl::rx_dsp_init(void) boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2), boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2)); - rx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number + rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16); } /*********************************************************************** @@ -95,7 +95,9 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _iface->poke32(FR_RX_FREQ_0, compute_freq_word(64e6, new_freq)); //FIXME magic rate + boost::uint32_t hw_freq_word = compute_freq_word( + _clock_ctrl->get_master_clock_freq(), new_freq); + _iface->poke32(FR_RX_FREQ_0, hw_freq_word); _tx_dsp_freq = new_freq; return; } @@ -130,7 +132,7 @@ void usrp1_impl::tx_dsp_init(void) boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2)); //initial config and update - tx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number + tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() * 2 / 16); } /*********************************************************************** @@ -152,7 +154,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_CODEC_RATE: - val = MASTER_CLOCK_RATE; + val = _clock_ctrl->get_master_clock_freq() * 2; return; case DSP_PROP_HOST_RATE: diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 5166f989f..f57f9a09a 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -33,8 +33,6 @@ #ifndef INCLUDED_USRP1_IMPL_HPP #define INCLUDED_USRP1_IMPL_HPP -static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control - /*! * Simple wax obj proxy class: * Provides a wax obj interface for a set and a get function. -- cgit v1.2.3 From 2f3269f359043290fcaa7659e90292919306a8bc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 19 Aug 2010 18:23:19 -0700 Subject: usrp1: images for usrp1, makefile checks for image generation dependencies --- firmware/fx2/.gitignore | 5 +++++ host/AUTHORS | 10 +++++++++- host/lib/usrp/usrp1/usrp1_impl.cpp | 34 ++++++++++++++++++++++------------ host/lib/usrp/usrp1/usrp1_impl.hpp | 6 +----- images/Makefile | 27 +++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 18 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/firmware/fx2/.gitignore b/firmware/fx2/.gitignore index 75bb241c8..affc0b779 100644 --- a/firmware/fx2/.gitignore +++ b/firmware/fx2/.gitignore @@ -23,3 +23,8 @@ /missing /make.log /usrp.pc +/INSTALL +/config.guess +/config.sub +/install-sh +/ltmain.sh diff --git a/host/AUTHORS b/host/AUTHORS index 137eba0e6..7292da8f9 100644 --- a/host/AUTHORS +++ b/host/AUTHORS @@ -1,5 +1,6 @@ Matt Ettus - matt@ettus.com - USRP1/USRP2 FPGA code + USRP1 FPGA code + USRP2 FPGA code Josh Blum - josh@ettus.com driver framework @@ -14,4 +15,11 @@ Jason Abele - jason@ettus.com WBX host code Eric Blossom - eb@comsec.com + USRP1 firmware USRP2 firmware + +Tom Tsou - ttsou@vt.edu + UHD-USB framework + LIBUSB host code + USRP1 host code + USRP1 firmware diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index ece5f1dea..33a069bc6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -23,9 +23,11 @@ #include #include #include +#include #include #include #include +#include #include using namespace uhd; @@ -42,11 +44,16 @@ const std::vector usrp1_impl::_dboard_slots = boost:: static device_addrs_t usrp1_find(const device_addr_t &hint) { device_addrs_t usrp1_addrs; - std::string filename = "/usr/local/share/usrp/rev4/std.ihx"; //return an empty list of addresses when type is set to non-usrp1 if (hint.has_key("type") and hint["type"] != "usrp1") return usrp1_addrs; + //extract the firmware path for the USRP1 + std::string usrp1_fw_image = find_image_path( + hint.has_key("fw")? hint["fw"] : "usrp1_fw.ihx" + ); + std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl; + //see what we got on the USB bus usb_descriptors_t usb_descriptors; usb_descriptors = usb_control::get_device_list(); @@ -56,12 +63,12 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) if (desc.vendor_id == 0xfffe && desc.product_id == 0x0002) { usb_control::sptr ctrl_transport = usb_control::make(desc); usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); - usrp_ctrl->usrp_load_firmware(filename); + usrp_ctrl->usrp_load_firmware(usrp1_fw_image); } } //wait for things to settle - sleep(1); + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); //get descriptors again with serial number usb_descriptors = usb_control::get_device_list(); @@ -83,14 +90,11 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) **********************************************************************/ static device::sptr usrp1_make(const device_addr_t &device_addr) { - std::string filename; - - if (device_addr.has_key("fpga")) - filename = device_addr["fpga"]; - else - filename = "/usr/local/share/usrp/rev4/std_2rxhb_2tx.rbf"; - - std::cout << "Make usrp1 with " << filename << std::endl; + //extract the FPGA path for the USRP1 + std::string usrp1_fpga_image = find_image_path( + device_addr.has_key("fpga")? device_addr["fpga"] : "usrp1_fpga.rbf" + ); + std::cout << "USRP1 FPGA image: " << usrp1_fpga_image << std::endl; //try to match the given device address with something on the USB bus usb_descriptors_t usb_descriptors; @@ -106,7 +110,7 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) usb_control::sptr ctrl_transport = usb_control::make(desc); usrp_ctrl = usrp_ctrl::make(ctrl_transport); - usrp_ctrl->usrp_load_fpga(filename); + usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); data_transport = usb_zero_copy::make(desc, // identifier 6, // IN endpoint @@ -167,6 +171,12 @@ usrp1_impl::~usrp1_impl(void){ /* NOP */ } +bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, size_t timeout_ms){ + //dummy fill-in for the recv_async_msg + boost::this_thread::sleep(boost::posix_time::milliseconds(timeout_ms)); + return false; +} + /*********************************************************************** * Device Get **********************************************************************/ diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index f57f9a09a..cbd3d5315 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -93,11 +93,7 @@ public: size_t get_max_send_samps_per_packet(void) const { return 0; } size_t get_max_recv_samps_per_packet(void) const { return 0; } - - bool recv_async_msg(uhd::async_metadata_t &, size_t) { - //TODO sleep the number of ms supplied (dont want to hog CPU) - return false; - } + bool recv_async_msg(uhd::async_metadata_t &, size_t); private: /*! diff --git a/images/Makefile b/images/Makefile index 0a829a296..0e58fbb18 100644 --- a/images/Makefile +++ b/images/Makefile @@ -30,9 +30,26 @@ CMAKE_BUILD_DIR = $(TOP_DIR)/build ##filled in below IMAGES_LIST = +######################################################################## +# Utility Checks +######################################################################## +ifeq ($(shell sdcc --help > /dev/null 2>&1 && echo $$?),0) + HAS_SDCC=1 +endif + +ifeq ($(shell mb-gcc --help > /dev/null 2>&1 && echo $$?),0) + HAS_MB_GCC=1 +endif + +ifeq ($(shell xtclsh -h > /dev/null 2>&1 && echo $$?),0) + HAS_XTCLSH=1 +endif + ######################################################################## # USRP1 firmware ######################################################################## +ifdef HAS_SDCC + _usrp1_fw_dir = $(TOP_FW_DIR)/fx2 _usrp1_fw_ihx = $(BUILT_IMAGES_DIR)/usrp1_fw.ihx IMAGES_LIST += $(_usrp1_fw_ihx) @@ -44,6 +61,8 @@ $(_usrp1_fw_ihx): make -C $(_usrp1_fw_dir) all cp $(_usrp1_fw_dir)/src/usrp1/std.ihx $@ +endif + ######################################################################## # USRP1 fpga ######################################################################## @@ -57,6 +76,8 @@ $(_usrp1_fpga_rbf): ######################################################################## # USRP2 firmware ######################################################################## +ifdef HAS_MB_GCC + _usrp2_fw_dir = $(TOP_FW_DIR)/microblaze _usrp2_fw_bin = $(BUILT_IMAGES_DIR)/usrp2_fw.bin IMAGES_LIST += $(_usrp2_fw_bin) @@ -68,9 +89,13 @@ $(_usrp2_fw_bin): make -C $(_usrp2_fw_dir) all cp $(_usrp2_fw_dir)/usrp2/usrp2_txrx_uhd.bin $@ +endif + ######################################################################## # USRP2 fpga ######################################################################## +ifdef HAS_XTCLSH + _usrp2_fpga_dir = $(TOP_FPGA_DIR)/usrp2/top/u2_rev3 _usrp2_fpga_bin = $(BUILT_IMAGES_DIR)/usrp2_fpga.bin IMAGES_LIST += $(_usrp2_fpga_bin) @@ -80,6 +105,8 @@ $(_usrp2_fpga_bin): cd $(_usrp2_fpga_dir) && make -f Makefile.udp bin cp $(_usrp2_fpga_dir)/build-udp/u2_rev3.bin $@ +endif + ######################################################################## # Build rules ######################################################################## -- cgit v1.2.3 From 4021779856d6b971fa8add5f617528158bf727a2 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Mon, 23 Aug 2010 15:13:44 -0700 Subject: usrp1: Refactor I/O implementation --- host/lib/usrp/usrp1/dsp_impl.cpp | 4 + host/lib/usrp/usrp1/io_impl.cpp | 337 +++++++++++++++++++++++-------------- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 + 3 files changed, 215 insertions(+), 130 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index ce0c12e4b..ddd1e811b 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -95,6 +95,8 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) } _rx_dsp_decim = rate; + _rx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() / rate; + _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1); } return; @@ -175,6 +177,8 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) } _tx_dsp_interp = rate; + _tx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate; + _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1); return; } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 71b2c4fc5..33a04ffe6 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -35,41 +35,53 @@ namespace asio = boost::asio; static const float poll_interval = 0.1; //100ms -/* - * The FX2 firmware bursts data to the FPGA in 512 byte chunks so - * maintain send state to make sure that happens. - */ struct usrp1_send_state { uhd::transport::managed_send_buffer::sptr send_buff; - size_t bytes_used; + size_t bytes_written; size_t bytes_free; + size_t underrun_poll_samp_count; +}; + +struct usrp1_recv_state { + uhd::transport::managed_recv_buffer::sptr recv_buff; + size_t bytes_read; + size_t bytes_avail; + size_t overrun_poll_samp_count; }; /*********************************************************************** * IO Implementation Details **********************************************************************/ struct usrp1_impl::io_impl { - io_impl(zero_copy_if::sptr zc_if); + io_impl(); ~io_impl(void); - bool get_recv_buff(managed_recv_buffer::sptr buff); - - //state management for the vrt packet handler code - vrt_packet_handler::recv_state packet_handler_recv_state; + //state handling for buffer management + usrp1_recv_state recv_state; usrp1_send_state send_state; - zero_copy_if::sptr data_transport; - - //overun-underrun values - unsigned int tx_underrun_count; - unsigned int rx_overrun_count; + //send transport management + bool get_send_buffer(zero_copy_if::sptr zc_if); + size_t copy_convert_send_samps(const void *buff, size_t num_samps, + size_t sample_offset, const io_type_t io_type, + otw_type_t otw_type); + bool conditional_buff_commit(bool force); + bool check_underrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, bool force); + + //recv transport management + bool get_recv_buffer(zero_copy_if::sptr zc_if); + size_t copy_convert_recv_samps(void *buff, size_t num_samps, + size_t sample_offset, const io_type_t io_type, + otw_type_t otw_type); + bool check_overrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, bool force); }; -usrp1_impl::io_impl::io_impl(zero_copy_if::sptr zc_if) - : packet_handler_recv_state(1), data_transport(zc_if), - tx_underrun_count(0), rx_overrun_count(0) +usrp1_impl::io_impl::io_impl() { - /* NOP */ + send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); + recv_state.recv_buff = uhd::transport::managed_recv_buffer::sptr(); } usrp1_impl::io_impl::~io_impl(void) @@ -87,12 +99,94 @@ void usrp1_impl::io_init(void) _tx_otw_type.shift = 0; _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); + _io_impl = UHD_PIMPL_MAKE(io_impl, ()); } /*********************************************************************** * Data Send **********************************************************************/ +bool usrp1_impl::io_impl::get_send_buffer(zero_copy_if::sptr zc_if) +{ + if (send_state.send_buff == NULL) { + + send_state.send_buff = zc_if->get_send_buff(); + if (send_state.send_buff == NULL) + return false; + + send_state.bytes_free = send_state.send_buff->size(); + send_state.bytes_written = 0; + } + + return true; +} + +size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff, + size_t num_samps, + size_t sample_offset, + const io_type_t io_type, + otw_type_t otw_type) +{ + UHD_ASSERT_THROW(send_state.bytes_free % otw_type.get_sample_size() == 0); + + size_t samps_free = send_state.bytes_free / otw_type.get_sample_size(); + size_t copy_samps = std::min(num_samps - sample_offset, samps_free); + + const boost::uint8_t *io_mem = + reinterpret_cast(buff); + + boost::uint8_t *otw_mem = send_state.send_buff->cast(); + + convert_io_type_to_otw_type(io_mem + sample_offset * io_type.size, + io_type, + otw_mem + send_state.bytes_written, + otw_type, + copy_samps); + + send_state.bytes_written += copy_samps * otw_type.get_sample_size(); + send_state.bytes_free -= copy_samps * otw_type.get_sample_size(); + send_state.underrun_poll_samp_count += copy_samps; + + return copy_samps; +} + +bool usrp1_impl::io_impl::conditional_buff_commit(bool force) +{ + if (send_state.bytes_written % 512) + return false; + + if (force || send_state.bytes_free == 0) { + send_state.send_buff->commit(send_state.bytes_written); + send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); + return true; + } + + return false; +} + +bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, + bool force) +{ + unsigned char underrun = 0; + + bool ready_to_poll = send_state.underrun_poll_samp_count > poll_interval; + + if (force || ready_to_poll) { + int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, + 0, + GS_TX_UNDERRUN, + &underrun, sizeof(char)); + if (ret < 0) + std::cerr << "USRP: underrun check failed" << std::endl; + if (underrun) + std::cerr << "U" << std::endl; + + send_state.underrun_poll_samp_count = 0; + } + + return (bool) underrun; +} + size_t usrp1_impl::send(const std::vector &buffs, size_t num_samps, const tx_metadata_t &, @@ -104,57 +198,21 @@ size_t usrp1_impl::send(const std::vector &buffs, size_t total_samps_sent = 0; while (total_samps_sent < num_samps) { - - if (_io_impl->send_state.send_buff == NULL) { - _io_impl->send_state.send_buff = _data_transport->get_send_buff(); - if (_io_impl->send_state.send_buff == NULL) { - return 0; - } - _io_impl->send_state.bytes_used = 0; - _io_impl->send_state.bytes_free = _io_impl->send_state.send_buff->size(); - } - - size_t copy_samps = - std::min(num_samps - total_samps_sent, _io_impl->send_state.bytes_free / _tx_otw_type.get_sample_size()); - - const boost::uint8_t *io_mem = - reinterpret_cast(buffs[0]); - - boost::uint8_t *otw_mem = _io_impl->send_state.send_buff->cast(); - - // Type conversion and copy - convert_io_type_to_otw_type( - io_mem + total_samps_sent * io_type.size, - io_type, - otw_mem + _io_impl->send_state.bytes_used, - _tx_otw_type, - copy_samps); - - _io_impl->send_state.bytes_used += copy_samps * _tx_otw_type.get_sample_size(); - _io_impl->send_state.bytes_free -= copy_samps * _tx_otw_type.get_sample_size(); - - if (_io_impl->send_state.bytes_free == 0) { - _io_impl->send_state.send_buff->commit(_io_impl->send_state.bytes_used); - _io_impl->send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); - } - - total_samps_sent += copy_samps; - _io_impl->tx_underrun_count += copy_samps * _tx_otw_type.get_sample_size(); - - //check for underruns - if (!(_io_impl->tx_underrun_count > _tx_dsp_freq * poll_interval * _tx_otw_type.get_sample_size())) { - unsigned char underrun; - int ret = _ctrl_transport->usrp_control_read(VRQ_GET_STATUS, - 0, - GS_TX_UNDERRUN, - &underrun, sizeof(char)); - if (ret < 0) - std::cerr << "error: underrun check failed" << std::endl; - if (underrun) - std::cerr << "U" << std::endl; - - _io_impl->tx_underrun_count = 0; - } + if (!_io_impl->get_send_buffer(_data_transport)) + return 0; + + total_samps_sent += _io_impl->copy_convert_send_samps(buffs[0], + num_samps, + total_samps_sent, + io_type, + _tx_otw_type); + if (total_samps_sent == num_samps) + _io_impl->conditional_buff_commit(true); + else + _io_impl->conditional_buff_commit(false); + + _io_impl->check_underrun(_ctrl_transport, + _tx_samps_per_poll_interval, false); } return total_samps_sent; @@ -163,17 +221,72 @@ size_t usrp1_impl::send(const std::vector &buffs, /*********************************************************************** * Data Recv **********************************************************************/ -void _recv_helper(vrt_packet_handler::recv_state &state) +bool usrp1_impl::io_impl::get_recv_buffer(zero_copy_if::sptr zc_if) +{ + if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail == 0)) { + + recv_state.recv_buff = zc_if->get_recv_buff(); + if (recv_state.recv_buff == NULL) + return false; + + recv_state.bytes_read = 0; + recv_state.bytes_avail = recv_state.recv_buff->size(); + } + + return true; +} + +size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff, + size_t num_samps, + size_t sample_offset, + const io_type_t io_type, + otw_type_t otw_type) +{ + UHD_ASSERT_THROW(recv_state.bytes_avail % otw_type.get_sample_size() == 0); + + size_t samps_avail = recv_state.bytes_avail / otw_type.get_sample_size(); + size_t copy_samps = std::min(num_samps - sample_offset, samps_avail); + + const boost::uint8_t *otw_mem = + recv_state.recv_buff->cast(); + + boost::uint8_t *io_mem = reinterpret_cast(buff); + + convert_otw_type_to_io_type(otw_mem + recv_state.bytes_read, + otw_type, + io_mem + sample_offset * io_type.size, + io_type, + copy_samps); + + recv_state.bytes_read += copy_samps * otw_type.get_sample_size(); + recv_state.bytes_avail -= copy_samps * otw_type.get_sample_size(); + recv_state.overrun_poll_samp_count += copy_samps; + + return copy_samps; +} + +bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, + bool force) { - size_t num_packet_words32 = - state.managed_buffs[0]->size() / sizeof(boost::uint32_t); + unsigned char overrun = 0; + + bool ready_to_poll = recv_state.overrun_poll_samp_count > poll_interval; - const boost::uint32_t *data = - state.managed_buffs[0]->cast(); + if (force || ready_to_poll) { + int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, + 0, + GS_RX_OVERRUN, + &overrun, sizeof(char)); + if (ret < 0) + std::cerr << "USRP: overrrun check failed" << std::endl; + if (overrun) + std::cerr << "O" << std::endl; + + recv_state.overrun_poll_samp_count = 0; + } - state.copy_buffs[0] = reinterpret_cast(data); - size_t num_payload_bytes = num_packet_words32 * sizeof(boost::uint32_t); - state.size_of_copy_buffs = num_payload_bytes; + return (bool) overrun; } size_t usrp1_impl::recv(const std::vector &buffs, @@ -183,59 +296,23 @@ size_t usrp1_impl::recv(const std::vector &buffs, recv_mode_t, size_t) { - UHD_ASSERT_THROW(_io_impl->packet_handler_recv_state.width == 1); UHD_ASSERT_THROW(buffs.size() == 1); - size_t sent_samps = 0; - size_t nsamps_to_copy = 0;; - - while (sent_samps < num_samps) { - if (_io_impl->packet_handler_recv_state.size_of_copy_buffs == 0) { - _io_impl->packet_handler_recv_state.fragment_offset_in_samps = 0; - _io_impl->packet_handler_recv_state.managed_buffs[0] = - _io_impl->data_transport->get_recv_buff(); - - //timeout or something bad returns zero - if (!_io_impl->packet_handler_recv_state.managed_buffs[0].get()) - return 0; - - _recv_helper(_io_impl->packet_handler_recv_state); - } - - size_t bytes_per_item = _rx_otw_type.get_sample_size(); - size_t nsamps_available = - _io_impl->packet_handler_recv_state.size_of_copy_buffs / bytes_per_item; - nsamps_to_copy = std::min(num_samps, nsamps_available); - size_t bytes_to_copy = nsamps_to_copy * bytes_per_item; - - convert_otw_type_to_io_type( - _io_impl->packet_handler_recv_state.copy_buffs[0], - _rx_otw_type, - reinterpret_cast(buffs[0]) + sent_samps * io_type.size, - io_type, - nsamps_to_copy); - - _io_impl->packet_handler_recv_state.copy_buffs[0] += bytes_to_copy; - _io_impl->packet_handler_recv_state.size_of_copy_buffs -= bytes_to_copy; - _io_impl->rx_overrun_count += nsamps_to_copy; - - sent_samps += nsamps_to_copy; - - //check for overruns - if (_io_impl->rx_overrun_count > (8e6 * poll_interval)) { - unsigned char overrun; - int ret = _ctrl_transport->usrp_control_read(VRQ_GET_STATUS, - 0, - GS_RX_OVERRUN, - &overrun, sizeof(char)); - if (ret < 0) - std::cerr << "error: overrun check failed" << std::endl; - if (overrun) - std::cerr << "O" << std::endl; - - _io_impl->rx_overrun_count = 0; - } + size_t total_samps_recv = 0; + + while (total_samps_recv < num_samps) { + + if (!_io_impl->get_recv_buffer(_data_transport)) + return 0; + + total_samps_recv += _io_impl->copy_convert_recv_samps(buffs[0], + num_samps, + total_samps_recv, + io_type, + _rx_otw_type); + _io_impl->check_overrun(_ctrl_transport, + _rx_samps_per_poll_interval, false); } - return sent_samps; + return total_samps_recv; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index f57f9a09a..5934d1779 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -124,6 +124,10 @@ private: void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); void handle_overrun(size_t); + //underrun and overrun poll intervals + size_t _rx_samps_per_poll_interval; + size_t _tx_samps_per_poll_interval; + //otw types uhd::otw_type_t _rx_otw_type; uhd::otw_type_t _tx_otw_type; -- cgit v1.2.3 From c9569736930cf436f340d70c7537a5f46f3ab3aa Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 26 Aug 2010 22:15:12 -0700 Subject: usrp1: handle special dbsrx clocking case --- host/lib/usrp/usrp1/clock_ctrl.cpp | 64 -------------------------------- host/lib/usrp/usrp1/clock_ctrl.hpp | 38 ------------------- host/lib/usrp/usrp1/dboard_iface.cpp | 72 ++++++++++++++++++++++++------------ host/lib/usrp/usrp1/dboard_impl.cpp | 3 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 8 ++-- 5 files changed, 55 insertions(+), 130 deletions(-) (limited to 'host/lib/usrp/usrp1/usrp1_impl.hpp') diff --git a/host/lib/usrp/usrp1/clock_ctrl.cpp b/host/lib/usrp/usrp1/clock_ctrl.cpp index 54f7b0b98..68c5f5320 100644 --- a/host/lib/usrp/usrp1/clock_ctrl.cpp +++ b/host/lib/usrp/usrp1/clock_ctrl.cpp @@ -46,70 +46,6 @@ public: return master_clock_rate; } - /*********************************************************************** - * RX Dboard Clock Control (output 9, divider 3) - **********************************************************************/ - void enable_rx_dboard_clock(bool) - { - std::cerr << "USRP: enable_rx_dboard_clock() disabled" << std::endl; - _iface->poke32(FR_RX_A_REFCLK, 0); - _iface->poke32(FR_RX_B_REFCLK, 0); - } - - std::vector get_rx_dboard_clock_rates(void) - { -#if 0 - std::vector rates; - for (size_t div = 1; div <= 127; div++) - rates.push_back(master_clock_rate / div); - return rates; -#else - return std::vector(1, master_clock_rate); -#endif - } - - /* - * Daughterboard reference clock register - * - * Bit 7 - 1 turns on refclk, 0 allows IO use - * Bits 6:0 - Divider value - */ - void set_rx_dboard_clock_rate(double) - { -#if 0 - assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate"); - size_t divider = size_t(rate/master_clock_rate); - _iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80); -#else - std::cerr << "USRP: set_rx_dboard_clock_rate() disabled" << std::endl; - _iface->poke32(FR_RX_A_REFCLK, 0); - _iface->poke32(FR_RX_B_REFCLK, 0); -#endif - } - - /*********************************************************************** - * TX Dboard Clock Control - **********************************************************************/ - void enable_tx_dboard_clock(bool) - { - std::cerr << "USRP: set_tx_dboard_clock() disabled" << std::endl; - _iface->poke32(FR_TX_A_REFCLK, 0); - _iface->poke32(FR_TX_B_REFCLK, 0); - - } - - std::vector get_tx_dboard_clock_rates(void) - { - return get_rx_dboard_clock_rates(); //same master clock, same dividers... - } - - void set_tx_dboard_clock_rate(double) - { - std::cerr << "USRP: set_tx_dboard_clock_rate() disabled" << std::endl; - _iface->poke32(FR_TX_A_REFCLK, 0); - _iface->poke32(FR_TX_B_REFCLK, 0); - } - private: usrp1_iface::sptr _iface; diff --git a/host/lib/usrp/usrp1/clock_ctrl.hpp b/host/lib/usrp/usrp1/clock_ctrl.hpp index 9ba4d56e3..366869dab 100644 --- a/host/lib/usrp/usrp1/clock_ctrl.hpp +++ b/host/lib/usrp/usrp1/clock_ctrl.hpp @@ -45,44 +45,6 @@ public: */ virtual double get_master_clock_freq(void) = 0; - /*! - * Get the possible rates of the rx dboard clock. - * \return a vector of clock rates in Hz - */ - virtual std::vector get_rx_dboard_clock_rates(void) = 0; - - /*! - * Get the possible rates of the tx dboard clock. - * \return a vector of clock rates in Hz - */ - virtual std::vector get_tx_dboard_clock_rates(void) = 0; - - /*! - * Set the rx dboard clock rate to a possible rate. - * \param rate the new clock rate in Hz - * \throw exception when rate cannot be achieved - */ - virtual void set_rx_dboard_clock_rate(double rate) = 0; - - /*! - * Set the tx dboard clock rate to a possible rate. - * \param rate the new clock rate in Hz - * \throw exception when rate cannot be achieved - */ - virtual void set_tx_dboard_clock_rate(double rate) = 0; - - /*! - * Enable/disable the rx dboard clock. - * \param enb true to enable - */ - virtual void enable_rx_dboard_clock(bool enb) = 0; - - /*! - * Enable/disable the tx dboard clock. - * \param enb true to enable - */ - virtual void enable_tx_dboard_clock(bool enb) = 0; - }; #endif /* INCLUDED_USRP1_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 3078b884d..b2221e221 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -19,6 +19,7 @@ #include "usrp1_impl.hpp" #include "fpga_regs_common.h" #include "usrp_spi_defs.h" +#include "fpga_regs_standard.h" #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" #include @@ -37,12 +38,15 @@ public: usrp1_dboard_iface(usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, usrp1_codec_ctrl::sptr codec, - usrp1_impl::dboard_slot_t dboard_slot - ){ + usrp1_impl::dboard_slot_t dboard_slot, + const dboard_id_t &rx_dboard_id + ): + _dboard_slot(dboard_slot), + _rx_dboard_id(rx_dboard_id) + { _iface = iface; _clock = clock; _codec = codec; - _dboard_slot = dboard_slot; //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_master_clock_freq()); @@ -95,7 +99,8 @@ private: usrp1_clock_ctrl::sptr _clock; usrp1_codec_ctrl::sptr _codec; uhd::dict _clock_rates; - usrp1_impl::dboard_slot_t _dboard_slot; + const usrp1_impl::dboard_slot_t _dboard_slot; + const dboard_id_t &_rx_dboard_id; }; /*********************************************************************** @@ -104,33 +109,55 @@ private: dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, usrp1_codec_ctrl::sptr codec, - dboard_slot_t dboard_slot + dboard_slot_t dboard_slot, + const dboard_id_t &rx_dboard_id ){ - return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec, dboard_slot)); + return dboard_iface::sptr(new usrp1_dboard_iface( + iface, clock, codec, dboard_slot, rx_dboard_id + )); } /*********************************************************************** * Clock Rates **********************************************************************/ +static const dboard_id_t dbsrx_classic_id(0x0002); + +/* + * Daughterboard reference clock register + * + * Bit 7 - 1 turns on refclk, 0 allows IO use + * Bits 6:0 - Divider value + */ void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate) { + assert_has(this->get_clock_rates(unit), rate, "dboard clock rate"); _clock_rates[unit] = rate; - switch(unit) { - case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate); - case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate); + + if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ + size_t divider = size_t(rate/_clock->get_master_clock_freq()); + switch(_dboard_slot){ + case usrp1_impl::DBOARD_SLOT_A: + _iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80); + break; + + case usrp1_impl::DBOARD_SLOT_B: + _iface->poke32(FR_RX_B_REFCLK, (divider & 0x7f) | 0x80); + break; + } } } -/* - * TODO: if this is a dbsrx return the rate of 4MHZ and set FPGA magic - */ std::vector usrp1_dboard_iface::get_clock_rates(unit_t unit) { - switch(unit) { - case UNIT_RX: return _clock->get_rx_dboard_clock_rates(); - case UNIT_TX: return _clock->get_tx_dboard_clock_rates(); - default: UHD_THROW_INVALID_CODE_PATH(); + std::vector rates; + if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ + for (size_t div = 1; div <= 127; div++) + rates.push_back(_clock->get_master_clock_freq() / div); } + else{ + rates.push_back(_clock->get_master_clock_freq()); + } + return rates; } double usrp1_dboard_iface::get_clock_rate(unit_t unit) @@ -138,12 +165,9 @@ double usrp1_dboard_iface::get_clock_rate(unit_t unit) return _clock_rates[unit]; } -void usrp1_dboard_iface::set_clock_enabled(unit_t unit, bool enb) +void usrp1_dboard_iface::set_clock_enabled(unit_t, bool) { - switch(unit) { - case UNIT_RX: return _clock->enable_rx_dboard_clock(enb); - case UNIT_TX: return _clock->enable_tx_dboard_clock(enb); - } + //TODO we can only enable for special case anyway... } /*********************************************************************** @@ -241,7 +265,7 @@ void usrp1_dboard_iface::set_atr_reg(unit_t unit, _iface->poke32(FR_ATR_RXVAL_1, value); else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B) _iface->poke32(FR_ATR_RXVAL_3, value); - break; + break; case UNIT_TX: if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A) _iface->poke32(FR_ATR_TXVAL_0, value); @@ -265,14 +289,14 @@ static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit, switch(unit) { case dboard_iface::UNIT_TX: if (slot == usrp1_impl::DBOARD_SLOT_A) - return SPI_ENABLE_TX_A; + return SPI_ENABLE_TX_A; else if (slot == usrp1_impl::DBOARD_SLOT_B) return SPI_ENABLE_TX_B; else break; case dboard_iface::UNIT_RX: if (slot == usrp1_impl::DBOARD_SLOT_A) - return SPI_ENABLE_RX_A; + return SPI_ENABLE_RX_A; else if (slot == usrp1_impl::DBOARD_SLOT_B) return SPI_ENABLE_RX_B; else diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index f52117c34..3a8480e1b 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -67,7 +67,8 @@ void usrp1_impl::dboard_init(void) //create a new dboard interface and manager _dboard_ifaces[dboard_slot] = make_dboard_iface( - _iface, _clock_ctrl, _codec_ctrls[dboard_slot], dboard_slot + _iface, _clock_ctrl, _codec_ctrls[dboard_slot], + dboard_slot, _rx_db_eeproms[dboard_slot].id ); _dboard_managers[dboard_slot] = dboard_manager::make( diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 4b4ac51dd..c2f693eeb 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -45,8 +46,7 @@ public: typedef boost::function set_t; typedef boost::shared_ptr sptr; - static sptr make(const get_t &get, const set_t &set) - { + static sptr make(const get_t &get, const set_t &set){ return sptr(new wax_obj_proxy(get, set)); } @@ -102,13 +102,15 @@ private: * \param clock the clock control interface * \param codec the codec control interface * \param dboard_slot the slot identifier + * \param rx_dboard_id the db id for the rx board (used for evil dbsrx purposes) * \return a sptr to a new dboard interface */ static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, usrp1_codec_ctrl::sptr codec, - dboard_slot_t dboard_slot + dboard_slot_t dboard_slot, + const uhd::usrp::dboard_id_t &rx_dboard_id ); //interface to ioctls and file descriptor -- cgit v1.2.3