diff options
author | Josh Blum <josh@joshknows.com> | 2010-04-13 17:48:48 -0700 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2010-04-13 17:48:48 -0700 |
commit | 51a9c2d42d12caa607ae33feb12a6f16ab8a3fe5 (patch) | |
tree | 6d0e494d5d9c8365c14fe916ff17737576c74955 | |
parent | 3109f123dd1942874e356cc0c3049e8529118c2e (diff) | |
download | uhd-51a9c2d42d12caa607ae33feb12a6f16ab8a3fe5.tar.gz uhd-51a9c2d42d12caa607ae33feb12a6f16ab8a3fe5.tar.bz2 uhd-51a9c2d42d12caa607ae33feb12a6f16ab8a3fe5.zip |
Created a usrp2 interface class with the control, spi, peek/poke functionality.
Its used in all the implementation level code
-rw-r--r-- | host/lib/CMakeLists.txt | 3 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/clock_control.cpp | 16 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/clock_control.hpp | 7 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_iface.cpp (renamed from host/lib/usrp/usrp2/dboard_interface.cpp) | 77 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_impl.cpp | 10 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 13 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 1 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 37 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 168 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.hpp | 103 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 110 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 55 |
12 files changed, 378 insertions, 222 deletions
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 4f38c94c5..b9e525bad 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -103,10 +103,11 @@ UHD_PYTHON_GEN_SOURCE_FILE( LIST(APPEND libuhd_sources usrp/usrp2/clock_control.cpp usrp/usrp2/dboard_impl.cpp - usrp/usrp2/dboard_interface.cpp + usrp/usrp2/dboard_iface.cpp usrp/usrp2/dsp_impl.cpp usrp/usrp2/io_impl.cpp usrp/usrp2/mboard_impl.cpp + usrp/usrp2/usrp2_iface.cpp usrp/usrp2/usrp2_impl.cpp ) diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_control.cpp index 2d27361a8..dcd7ce9da 100644 --- a/host/lib/usrp/usrp2/clock_control.cpp +++ b/host/lib/usrp/usrp2/clock_control.cpp @@ -28,8 +28,8 @@ using namespace uhd::usrp; */ class clock_control_ad9510 : public clock_control{ public: - clock_control_ad9510(usrp2_impl *impl){ - _impl = impl; + clock_control_ad9510(usrp2_iface::sptr iface){ + _iface = iface; _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; this->write_reg(0x09); @@ -71,8 +71,8 @@ public: ~clock_control_ad9510(void){ /* private clock enables, must be set here */ - //this->enable_dac_clock(false); - //this->enable_adc_clock(false); //FIXME cant do yet + this->enable_dac_clock(false); + this->enable_adc_clock(false); } //uses output clock 7 (cmos) @@ -114,7 +114,7 @@ private: */ void write_reg(boost::uint8_t addr){ boost::uint32_t data = _ad9510_regs.get_write_reg(addr); - _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); + _iface->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); } /*! @@ -144,13 +144,13 @@ private: this->update_regs(); } - usrp2_impl *_impl; + usrp2_iface::sptr _iface; ad9510_regs_t _ad9510_regs; }; /*********************************************************************** * Public make function for the ad9510 clock control **********************************************************************/ -clock_control::sptr clock_control::make_ad9510(usrp2_impl *impl){ - return clock_control::sptr(new clock_control_ad9510(impl)); +clock_control::sptr clock_control::make_ad9510(usrp2_iface::sptr iface){ + return clock_control::sptr(new clock_control_ad9510(iface)); } diff --git a/host/lib/usrp/usrp2/clock_control.hpp b/host/lib/usrp/usrp2/clock_control.hpp index 4302941f0..b64a53196 100644 --- a/host/lib/usrp/usrp2/clock_control.hpp +++ b/host/lib/usrp/usrp2/clock_control.hpp @@ -18,8 +18,7 @@ #ifndef INCLUDED_CLOCK_CONTROL_HPP #define INCLUDED_CLOCK_CONTROL_HPP -class usrp2_impl; //dummy class - +#include "usrp2_iface.hpp" #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> @@ -29,10 +28,10 @@ public: /*! * Make a clock config for the ad9510 ic. - * \param impl a pointer to the usrp2 implementation object + * \param _iface a pointer to the usrp2 interface object * \return a new clock control object */ - static sptr make_ad9510(usrp2_impl *impl); + static sptr make_ad9510(usrp2_iface::sptr iface); /*! * Enable/disable the rx dboard clock. diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index c74bdaf44..d0c4bf6c1 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -15,19 +15,21 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#include "usrp2_impl.hpp" +#include "usrp2_iface.hpp" +#include "clock_control.hpp" #include "usrp2_regs.hpp" #include <uhd/types/dict.hpp> #include <uhd/utils/assert.hpp> #include <boost/assign/list_of.hpp> +#include <boost/asio.hpp> //htonl and ntohl #include <algorithm> using namespace uhd::usrp; -class usrp2_dboard_interface : public dboard_interface{ +class usrp2_dboard_iface : public dboard_interface{ public: - usrp2_dboard_interface(usrp2_impl *impl); - ~usrp2_dboard_interface(void); + usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl); + ~usrp2_dboard_iface(void); void write_aux_dac(unit_t, int, int); int read_aux_adc(unit_t, int); @@ -58,22 +60,27 @@ public: ); private: - usrp2_impl *_impl; + usrp2_iface::sptr _iface; + clock_control::sptr _clk_ctrl; boost::uint32_t _ddr_shadow; }; /*********************************************************************** * Make Function **********************************************************************/ -dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl){ - return dboard_interface::sptr(new usrp2_dboard_interface(impl)); +dboard_interface::sptr make_usrp2_dboard_iface( + usrp2_iface::sptr iface, + clock_control::sptr clk_ctrl +){ + return dboard_interface::sptr(new usrp2_dboard_iface(iface, clk_ctrl)); } /*********************************************************************** * Structors **********************************************************************/ -usrp2_dboard_interface::usrp2_dboard_interface(usrp2_impl *impl){ - _impl = impl; +usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl){ + _iface = iface; + _clk_ctrl = clk_ctrl; _ddr_shadow = 0; //set the selection mux to use atr @@ -81,28 +88,28 @@ usrp2_dboard_interface::usrp2_dboard_interface(usrp2_impl *impl){ for(size_t i = 0; i < 16; i++){ new_sels |= FRF_GPIO_SEL_ATR << (i*2); } - _impl->poke32(FR_GPIO_TX_SEL, new_sels); - _impl->poke32(FR_GPIO_RX_SEL, new_sels); + _iface->poke32(FR_GPIO_TX_SEL, new_sels); + _iface->poke32(FR_GPIO_RX_SEL, new_sels); } -usrp2_dboard_interface::~usrp2_dboard_interface(void){ +usrp2_dboard_iface::~usrp2_dboard_iface(void){ /* NOP */ } /*********************************************************************** * Clocks **********************************************************************/ -double usrp2_dboard_interface::get_clock_rate(unit_t){ - return _impl->get_master_clock_freq(); +double usrp2_dboard_iface::get_clock_rate(unit_t){ + return _iface->get_master_clock_freq(); } -void usrp2_dboard_interface::set_clock_enabled(unit_t unit, bool enb){ +void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ switch(unit){ case UNIT_RX: - _impl->get_clock_control()->enable_rx_dboard_clock(enb); + _clk_ctrl->enable_rx_dboard_clock(enb); return; case UNIT_TX: - _impl->get_clock_control()->enable_tx_dboard_clock(enb); + _clk_ctrl->enable_tx_dboard_clock(enb); return; } } @@ -118,18 +125,18 @@ static int unit_to_shift(dboard_interface::unit_t unit){ throw std::runtime_error("unknown unit type"); } -void usrp2_dboard_interface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ +void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ _ddr_shadow = \ (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) | (boost::uint32_t(value) << unit_to_shift(unit)); - _impl->poke32(FR_GPIO_DDR, _ddr_shadow); + _iface->poke32(FR_GPIO_DDR, _ddr_shadow); } -boost::uint16_t usrp2_dboard_interface::read_gpio(unit_t unit){ - return boost::uint16_t(_impl->peek32(FR_GPIO_IO) >> unit_to_shift(unit)); +boost::uint16_t usrp2_dboard_iface::read_gpio(unit_t unit){ + return boost::uint16_t(_iface->peek32(FR_GPIO_IO) >> unit_to_shift(unit)); } -void usrp2_dboard_interface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ +void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ //define mapping of unit to atr regs to register address static const uhd::dict< unit_t, uhd::dict<atr_reg_t, boost::uint32_t> @@ -147,7 +154,7 @@ void usrp2_dboard_interface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE) ) ; - _impl->poke16(unit_to_atr_to_addr[unit][atr], value); + _iface->poke16(unit_to_atr_to_addr[unit][atr], value); } /*********************************************************************** @@ -167,28 +174,28 @@ static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ throw std::invalid_argument("unknown unit type"); } -void usrp2_dboard_interface::write_spi( +void usrp2_dboard_iface::write_spi( unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ){ - _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); + _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); } -boost::uint32_t usrp2_dboard_interface::read_write_spi( +boost::uint32_t usrp2_dboard_iface::read_write_spi( unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ){ - return _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); + return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); } /*********************************************************************** * I2C **********************************************************************/ -void usrp2_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){ +void usrp2_dboard_iface::write_i2c(int i2c_addr, const byte_vector_t &buf){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO); @@ -202,11 +209,11 @@ void usrp2_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){ std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data); //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE); } -dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, size_t num_bytes){ +dboard_interface::byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); @@ -217,7 +224,7 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data)); //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE); ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes); @@ -244,7 +251,7 @@ static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ throw std::invalid_argument("unknown unit type"); } -void usrp2_dboard_interface::write_aux_dac(unit_t unit, int which, int value){ +void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, int value){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); @@ -253,11 +260,11 @@ void usrp2_dboard_interface::write_aux_dac(unit_t unit, int which, int value){ out_data.data.aux_args.value = htonl(value); //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); } -int usrp2_dboard_interface::read_aux_adc(unit_t unit, int which){ +int usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO); @@ -265,7 +272,7 @@ int usrp2_dboard_interface::read_aux_adc(unit_t unit, int which){ out_data.data.aux_args.which = which; //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE); return ntohl(in_data.data.aux_args.value); } diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 3ac805421..4b300de68 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -22,6 +22,8 @@ #include <uhd/usrp/dboard_props.hpp> #include <uhd/utils/assert.hpp> #include <boost/format.hpp> +#include <boost/bind.hpp> +#include <boost/asio.hpp> //htonl and ntohl #include <iostream> using namespace uhd; @@ -34,7 +36,7 @@ void usrp2_impl::dboard_init(void){ //grab the dboard ids over the control line usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO); - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE); //extract the dboard ids an convert them @@ -43,7 +45,7 @@ void usrp2_impl::dboard_init(void){ //create a new dboard interface and manager dboard_interface::sptr _dboard_interface( - make_usrp2_dboard_interface(this) + make_usrp2_dboard_iface(_iface, _clk_ctrl) ); _dboard_manager = dboard_manager::make( rx_dboard_id, tx_dboard_id, _dboard_interface @@ -82,7 +84,7 @@ void usrp2_impl::update_rx_mux_config(void){ rx_mux = (((rx_mux >> 0) & 0x3) << 2) | (((rx_mux >> 2) & 0x3) << 0); } - this->poke32(FR_DSP_RX_MUX, rx_mux); + _iface->poke32(FR_DSP_RX_MUX, rx_mux); } void usrp2_impl::update_tx_mux_config(void){ @@ -95,7 +97,7 @@ void usrp2_impl::update_tx_mux_config(void){ tx_mux = (((tx_mux >> 0) & 0x1) << 1) | (((tx_mux >> 1) & 0x1) << 0); } - this->poke32(FR_DSP_TX_MUX, tx_mux); + _iface->poke32(FR_DSP_TX_MUX, tx_mux); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 92b55d029..664d69948 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -20,6 +20,7 @@ #include <uhd/usrp/dsp_props.hpp> #include <uhd/utils/assert.hpp> #include <boost/format.hpp> +#include <boost/bind.hpp> #include <boost/assign/list_of.hpp> #include <boost/math/special_functions/round.hpp> @@ -82,11 +83,11 @@ void usrp2_impl::init_ddc_config(void){ void usrp2_impl::update_ddc_config(void){ //set the decimation - this->poke32(FR_DSP_RX_DECIM_RATE, _ddc_decim); + _iface->poke32(FR_DSP_RX_DECIM_RATE, _ddc_decim); //set the scaling static const boost::int16_t default_rx_scale_iq = 1024; - this->poke32(FR_DSP_RX_SCALE_IQ, + _iface->poke32(FR_DSP_RX_SCALE_IQ, calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq) ); } @@ -126,7 +127,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _ddc_freq = new_freq; //shadow - this->poke32(FR_DSP_RX_FREQ, + _iface->poke32(FR_DSP_RX_FREQ, calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq()) ); } @@ -170,10 +171,10 @@ void usrp2_impl::update_duc_config(void){ boost::int16_t scale = rint((4096*std::pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed)); //set the interpolation - this->poke32(FR_DSP_TX_INTERP_RATE, _ddc_decim); + _iface->poke32(FR_DSP_TX_INTERP_RATE, _ddc_decim); //set the scaling - this->poke32(FR_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale)); + _iface->poke32(FR_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale)); } /*********************************************************************** @@ -211,7 +212,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _duc_freq = new_freq; //shadow - this->poke32(FR_DSP_TX_FREQ, + _iface->poke32(FR_DSP_TX_FREQ, calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq()) ); } diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 87fc88ceb..367a1d9fb 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -18,6 +18,7 @@ #include "usrp2_impl.hpp" #include <uhd/transport/convert_types.hpp> #include <boost/format.hpp> +#include <boost/asio.hpp> //htonl and ntohl #include <iostream> using namespace uhd; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index ea268651a..1521de1fe 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -22,6 +22,9 @@ #include <uhd/utils/assert.hpp> #include <uhd/types/mac_addr.hpp> #include <uhd/types/dict.hpp> +#include <boost/bind.hpp> +#include <boost/asio.hpp> //htonl and ntohl +#include <boost/assign/list_of.hpp> using namespace uhd; using namespace uhd::usrp; @@ -35,7 +38,7 @@ void usrp2_impl::mboard_init(void){ boost::bind(&usrp2_impl::mboard_set, this, _1, _2) ); - _clock_control = clock_control::make_ad9510(this); + _clk_ctrl = clock_control::make_ad9510(_iface); //setup the ad9777 dac ad9777_regs_t ad9777_regs; @@ -58,14 +61,10 @@ void usrp2_impl::mboard_init(void){ //write all regs for(boost::uint8_t addr = 0; addr <= 0xC; addr++){ boost::uint16_t data = ad9777_regs.get_write_reg(addr); - this->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/); + _iface->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/); } } -clock_control::sptr usrp2_impl::get_clock_control(void){ - return _clock_control; -} - void usrp2_impl::init_clock_config(void){ //setup the clock configuration settings _clock_config.ref_source = clock_config_t::REF_INT; @@ -94,28 +93,28 @@ void usrp2_impl::update_clock_config(void){ } //set the pps flags - this->poke32(FR_TIME64_FLAGS, pps_flags); + _iface->poke32(FR_TIME64_FLAGS, pps_flags); //clock source ref 10mhz switch(_clock_config.ref_source){ - case clock_config_t::REF_INT : this->poke32(FR_CLOCK_CONTROL, 0x10); break; - case clock_config_t::REF_SMA : this->poke32(FR_CLOCK_CONTROL, 0x1C); break; - case clock_config_t::REF_MIMO: this->poke32(FR_CLOCK_CONTROL, 0x15); break; + case clock_config_t::REF_INT : _iface->poke32(FR_CLOCK_CONTROL, 0x10); break; + case clock_config_t::REF_SMA : _iface->poke32(FR_CLOCK_CONTROL, 0x1C); break; + case clock_config_t::REF_MIMO: _iface->poke32(FR_CLOCK_CONTROL, 0x15); break; } //clock source ref 10mhz bool use_external = _clock_config.ref_source != clock_config_t::REF_INT; - this->get_clock_control()->enable_external_ref(use_external); + _clk_ctrl->enable_external_ref(use_external); } void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){ //set ticks and seconds - this->poke32(FR_TIME64_SECS, time_spec.secs); - this->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq())); + _iface->poke32(FR_TIME64_SECS, time_spec.secs); + _iface->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq())); //set the register to latch it all in boost::uint32_t imm_flags = (now)? FRF_TIME64_LATCH_NOW : FRF_TIME64_LATCH_NEXT_PPS; - this->poke32(FR_TIME64_IMM, imm_flags); + _iface->poke32(FR_TIME64_IMM, imm_flags); } void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ @@ -151,7 +150,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ } //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE); } @@ -170,7 +169,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); //extract the address @@ -184,7 +183,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); //extract the address @@ -272,7 +271,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); return; } @@ -284,7 +283,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_ulong()); //send and recv - usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); + usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); return; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp new file mode 100644 index 000000000..5c84fd8d3 --- /dev/null +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -0,0 +1,168 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include "usrp2_iface.hpp" +#include <uhd/utils/assert.hpp> +#include <uhd/types/dict.hpp> +#include <boost/thread.hpp> +#include <boost/asio.hpp> //used for htonl and ntohl +#include <boost/assign/list_of.hpp> +#include <stdexcept> + +using namespace uhd; +using namespace uhd::usrp; + +class usrp2_iface_impl : public usrp2_iface{ +public: +/*********************************************************************** + * Structors + **********************************************************************/ + usrp2_iface_impl(transport::udp_simple::sptr ctrl_transport){ + _ctrl_transport = ctrl_transport; + } + + ~usrp2_iface_impl(void){ + /* NOP */ + } + +/*********************************************************************** + * Peek and Poke + **********************************************************************/ + void poke32(boost::uint32_t addr, boost::uint32_t data){ + return this->poke<boost::uint32_t>(addr, data); + } + + boost::uint32_t peek32(boost::uint32_t addr){ + return this->peek<boost::uint32_t>(addr); + } + + void poke16(boost::uint32_t addr, boost::uint16_t data){ + return this->poke<boost::uint16_t>(addr, data); + } + + boost::uint16_t peek16(boost::uint32_t addr){ + return this->peek<boost::uint16_t>(addr); + } + +/*********************************************************************** + * SPI + **********************************************************************/ + boost::uint32_t transact_spi( + int which_slave, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ){ + static const uhd::dict<spi_config_t::edge_t, int> spi_edge_to_otw = boost::assign::map_list_of + (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE) + (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL) + ; + + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); + out_data.data.spi_args.dev = which_slave; + out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge]; + out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge]; + out_data.data.spi_args.readback = (readback)? 1 : 0; + out_data.data.spi_args.num_bits = num_bits; + out_data.data.spi_args.data = htonl(data); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); + + return ntohl(out_data.data.spi_args.data); + } + +/*********************************************************************** + * Send/Recv over control + **********************************************************************/ + usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){ + boost::mutex::scoped_lock lock(_ctrl_mutex); + + //fill in the seq number and send + usrp2_ctrl_data_t out_copy = out_data; + out_copy.seq = htonl(++_ctrl_seq_num); + _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); + + //loop until we get the packet or timeout + while(true){ + usrp2_ctrl_data_t in_data; + size_t len = _ctrl_transport->recv(boost::asio::buffer(&in_data, sizeof(in_data))); + if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){ + return in_data; + } + if (len == 0) break; //timeout + //didnt get seq or bad packet, continue looking... + } + throw std::runtime_error("usrp2 no control response"); + } + +/*********************************************************************** + * Master Clock! Ahhhhh + **********************************************************************/ + double get_master_clock_freq(void){ + return 100e6; + } + +private: + //this lovely lady makes it all possible + transport::udp_simple::sptr _ctrl_transport; + + //used in send/recv + boost::mutex _ctrl_mutex; + boost::uint32_t _ctrl_seq_num; + +/*********************************************************************** + * Private Templated Peek and Poke + **********************************************************************/ + template <class T> void poke(boost::uint32_t addr, T data){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO); + out_data.data.poke_args.addr = htonl(addr); + out_data.data.poke_args.data = htonl(boost::uint32_t(data)); + out_data.data.poke_args.num_bytes = sizeof(T); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE); + } + + template <class T> T peek(boost::uint32_t addr){ + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO); + out_data.data.poke_args.addr = htonl(addr); + out_data.data.poke_args.num_bytes = sizeof(T); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE); + return T(ntohl(out_data.data.poke_args.data)); + } + +}; + +/*********************************************************************** + * Public make function for usrp2 interface + **********************************************************************/ +usrp2_iface::sptr usrp2_iface::make(transport::udp_simple::sptr ctrl_transport){ + return usrp2_iface::sptr(new usrp2_iface_impl(ctrl_transport)); +} diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp new file mode 100644 index 000000000..7b4321c0b --- /dev/null +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -0,0 +1,103 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_USRP2_IFACE_HPP +#define INCLUDED_USRP2_IFACE_HPP + +#include <uhd/transport/udp_simple.hpp> +#include <uhd/usrp/dboard_interface.hpp> //spi config +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <boost/cstdint.hpp> +#include "fw_common.h" + +/*! + * The usrp2 interface class: + * Provides a set of functions to implementation layer. + * Including spi, peek, poke, control... + */ +class usrp2_iface : boost::noncopyable{ +public: + typedef boost::shared_ptr<usrp2_iface> sptr; + + /*! + * Make a new usrp2 interface with the control transport. + * \param ctrl_transport the udp transport object + * \return a new usrp2 interface object + */ + static sptr make(uhd::transport::udp_simple::sptr ctrl_transport); + + /*! + * Perform a control transaction. + * \param data a control data struct + * \return the result control data + */ + virtual usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &data) = 0; + + /*! + * Write a register (32 bits) + * \param addr the address + * \param data the 32bit data + */ + virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; + + /*! + * Read a register (32 bits) + * \param addr the address + * \return the 32bit data + */ + virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; + + /*! + * Write a register (16 bits) + * \param addr the address + * \param data the 16bit data + */ + virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; + + /*! + * Read a register (16 bits) + * \param addr the address + * \return the 16bit data + */ + virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; + + /*! + * Perform an spi transaction. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write + * \param num_bits how many bits in data + * \param readback true to readback a value + * \return spi data if readback set + */ + virtual boost::uint32_t transact_spi( + int which_slave, + const uhd::usrp::spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ) = 0; + + /*! + * Get the master clock frequency. + * \return the frequency in Hz + */ + virtual double get_master_clock_freq(void) = 0; +}; + +#endif /* INCLUDED_USRP2_IFACE_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 6d8c1a86c..3bdc5bd02 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -17,6 +17,7 @@ #include "usrp2_impl.hpp" #include <uhd/transport/if_addrs.hpp> +#include <uhd/transport/udp_simple.hpp> #include <uhd/usrp/device_props.hpp> #include <uhd/utils/assert.hpp> #include <uhd/utils/static.hpp> @@ -24,6 +25,7 @@ #include <boost/format.hpp> #include <boost/foreach.hpp> #include <boost/bind.hpp> +#include <boost/asio.hpp> //htonl and ntohl #include <iostream> using namespace uhd; @@ -61,7 +63,6 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){ } //create a udp transport to communicate - //TODO if an addr is not provided, search all interfaces? std::string ctrl_port = boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT); udp_simple::sptr udp_transport = udp_simple::make_broadcast( hint["addr"], ctrl_port @@ -128,9 +129,11 @@ usrp2_impl::usrp2_impl( udp_simple::sptr ctrl_transport, udp_zero_copy::sptr data_transport ){ - _ctrl_transport = ctrl_transport; _data_transport = data_transport; + //make a new interface for usrp2 stuff + _iface = usrp2_iface::make(ctrl_transport); + //load the allowed decim/interp rates //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) _allowed_decim_and_interp_rates.clear(); @@ -169,109 +172,6 @@ usrp2_impl::~usrp2_impl(void){ } /*********************************************************************** - * Misc Access Methods - **********************************************************************/ -double usrp2_impl::get_master_clock_freq(void){ - return 100e6; -} - -template <class T> void impl_poke(usrp2_impl *impl, boost::uint32_t addr, T data){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO); - out_data.data.poke_args.addr = htonl(addr); - out_data.data.poke_args.data = htonl(boost::uint32_t(data)); - out_data.data.poke_args.num_bytes = sizeof(T); - - //send and recv - usrp2_ctrl_data_t in_data = impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE); -} - -template <class T> T impl_peek(usrp2_impl *impl, boost::uint32_t addr){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO); - out_data.data.poke_args.addr = htonl(addr); - out_data.data.poke_args.num_bytes = sizeof(T); - - //send and recv - usrp2_ctrl_data_t in_data = impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE); - return T(ntohl(out_data.data.poke_args.data)); -} - - -void usrp2_impl::poke32(boost::uint32_t addr, boost::uint32_t data){ - return impl_poke<boost::uint32_t>(this, addr, data); -} - -boost::uint32_t usrp2_impl::peek32(boost::uint32_t addr){ - return impl_peek<boost::uint32_t>(this, addr); -} - -void usrp2_impl::poke16(boost::uint32_t addr, boost::uint16_t data){ - return impl_poke<boost::uint16_t>(this, addr, data); -} - -boost::uint16_t usrp2_impl::peek16(boost::uint32_t addr){ - return impl_peek<boost::uint16_t>(this, addr); -} - -boost::uint32_t usrp2_impl::transact_spi( - int which_slave, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits, - bool readback -){ - static const uhd::dict<spi_config_t::edge_t, int> spi_edge_to_otw = boost::assign::map_list_of - (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE) - (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL) - ; - - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); - out_data.data.spi_args.dev = which_slave; - out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge]; - out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge]; - out_data.data.spi_args.readback = (readback)? 1 : 0; - out_data.data.spi_args.num_bits = num_bits; - out_data.data.spi_args.data = htonl(data); - - //send and recv - usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); - - return ntohl(out_data.data.spi_args.data); -} - -/*********************************************************************** - * Control Send/Recv - **********************************************************************/ -usrp2_ctrl_data_t usrp2_impl::ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){ - boost::mutex::scoped_lock lock(_ctrl_mutex); - - //fill in the seq number and send - usrp2_ctrl_data_t out_copy = out_data; - out_copy.seq = htonl(++_ctrl_seq_num); - _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); - - //loop until we get the packet or timeout - while(true){ - usrp2_ctrl_data_t in_data; - size_t len = _ctrl_transport->recv(asio::buffer(&in_data, sizeof(in_data))); - if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){ - return in_data; - } - if (len == 0) break; //timeout - //didnt get seq or bad packet, continue looking... - } - throw std::runtime_error("usrp2 no control response"); -} - -/*********************************************************************** * Device Properties **********************************************************************/ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index f2e823391..7eea1e250 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -18,31 +18,29 @@ #ifndef INCLUDED_USRP2_IMPL_HPP #define INCLUDED_USRP2_IMPL_HPP +#include "usrp2_iface.hpp" #include "clock_control.hpp" #include <uhd/usrp/usrp2.hpp> #include <uhd/types/dict.hpp> #include <uhd/types/otw_type.hpp> #include <uhd/types/stream_cmd.hpp> #include <uhd/types/clock_config.hpp> -#include <boost/asio.hpp> -#include <boost/thread.hpp> #include <boost/shared_ptr.hpp> #include <boost/function.hpp> -#include <boost/assign/list_of.hpp> #include <uhd/transport/vrt.hpp> -#include <uhd/transport/udp_simple.hpp> #include <uhd/transport/udp_zero_copy.hpp> #include <uhd/usrp/dboard_manager.hpp> -#include "fw_common.h" - -class usrp2_impl; //dummy class declaration /*! * Make a usrp2 dboard interface. - * \param impl a pointer to the usrp2 impl object + * \param iface the usrp2 interface object + * \param clk_ctrl the clock control object * \return a sptr to a new dboard interface */ -uhd::usrp::dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl); +uhd::usrp::dboard_interface::sptr make_usrp2_dboard_iface( + usrp2_iface::sptr iface, + clock_control::sptr clk_ctrl +); /*! * Simple wax obj proxy class: @@ -101,40 +99,22 @@ public: ~usrp2_impl(void); - //performs a control transaction - usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &); - - //peek and poke registers - void poke32(boost::uint32_t addr, boost::uint32_t data); - boost::uint32_t peek32(boost::uint32_t addr); - - void poke16(boost::uint32_t addr, boost::uint16_t data); - boost::uint16_t peek16(boost::uint32_t addr); - - //clock control - clock_control::sptr get_clock_control(void); - - //spi read and write - boost::uint32_t transact_spi( - int which_slave, - const uhd::usrp::spi_config_t &config, - boost::uint32_t data, - size_t num_bits, - bool readback - ); - - //misc access methods - double get_master_clock_freq(void); - //the io interface size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &); size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &); private: + double get_master_clock_freq(void){ + return _iface->get_master_clock_freq(); + } + //device properties interface void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); - clock_control::sptr _clock_control; + + //interfaces + clock_control::sptr _clk_ctrl; + usrp2_iface::sptr _iface; //the raw io interface (samples are in the usrp2 native format) void recv_raw(uhd::rx_metadata_t &); @@ -158,13 +138,8 @@ private: void io_init(void); //udp transports for control and data - uhd::transport::udp_simple::sptr _ctrl_transport; uhd::transport::udp_zero_copy::sptr _data_transport; - //private vars for dealing with send/recv control - boost::uint32_t _ctrl_seq_num; - boost::mutex _ctrl_mutex; - //methods and shadows for clock configuration uhd::clock_config_t _clock_config; void init_clock_config(void); |