From b66a74ff1f629af714e26040b410d472c08be522 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Apr 2010 00:46:42 -0700 Subject: Reworked the spi part of the dboard interface. It turns out to be more complicated. The integer type is better for holding the bits. The edges can be different, so the spi config hold 2 edge setting for mosi and miso. --- host/lib/usrp/usrp2/dboard_interface.cpp | 95 +++++++++++++++++++------------- 1 file changed, 57 insertions(+), 38 deletions(-) (limited to 'host/lib/usrp/usrp2/dboard_interface.cpp') diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index 6dd756420..eee7c087a 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -42,9 +42,35 @@ public: double get_rx_clock_rate(void); double get_tx_clock_rate(void); + void write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ){ + transact_spi(unit, config, data, num_bits, false /*no rb*/); + } + + boost::uint32_t read_spi( + unit_type_t unit, + const spi_config_t &config, + size_t num_bits + ){ + return transact_spi(unit, config, 0, num_bits, true /*rb*/); + } + + boost::uint32_t read_write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ){ + return transact_spi(unit, config, data, num_bits, true /*rb*/); + } + private: - byte_vector_t transact_spi( - spi_dev_t, spi_edge_t, const byte_vector_t &, bool + boost::uint32_t transact_spi( + unit_type_t, const spi_config_t &, boost::uint32_t, size_t, bool ); usrp2_impl *_impl; @@ -136,17 +162,17 @@ void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost: * SPI **********************************************************************/ /*! - * Static function to convert a spi dev enum - * to an over-the-wire value for the usrp2 control. - * \param dev the dboard interface spi dev enum + * Static function to convert a unit type enum + * to an over-the-wire value for the spi device. + * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ - switch(dev){ - case uhd::usrp::dboard_interface::SPI_DEV_TX: return SPI_SS_TX_DB; - case uhd::usrp::dboard_interface::SPI_DEV_RX: return SPI_SS_RX_DB; +static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){ + switch(unit){ + case dboard_interface::UNIT_TYPE_TX: return SPI_SS_TX_DB; + case dboard_interface::UNIT_TYPE_RX: return SPI_SS_RX_DB; } - throw std::invalid_argument("unknown spi device type"); + throw std::invalid_argument("unknown unit type type"); } /*! @@ -155,43 +181,36 @@ static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ * \param edge the dboard interface spi edge enum * \return an over the wire representation */ -static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_edge_t edge){ +static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_config_t::edge_t edge){ switch(edge){ - case uhd::usrp::dboard_interface::SPI_EDGE_RISE: return USRP2_CLK_EDGE_RISE; - case uhd::usrp::dboard_interface::SPI_EDGE_FALL: return USRP2_CLK_EDGE_FALL; + case dboard_interface::spi_config_t::EDGE_RISE: return USRP2_CLK_EDGE_RISE; + case dboard_interface::spi_config_t::EDGE_FALL: return USRP2_CLK_EDGE_FALL; } throw std::invalid_argument("unknown spi edge type"); } -dboard_interface::byte_vector_t usrp2_dboard_interface::transact_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf, +boost::uint32_t usrp2_dboard_interface::transact_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits, bool readback ){ //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 = spi_dev_to_otw(dev); - out_data.data.spi_args.edge = spi_edge_to_otw(edge); + out_data.data.spi_args.dev = unit_to_otw_dev(unit); + 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.bytes = buf.size(); - - //limitation of spi transaction size - ASSERT_THROW(buf.size() <= sizeof(out_data.data.spi_args.data)); - - //copy in the data - std::copy(buf.begin(), buf.end(), out_data.data.spi_args.data); + 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 = _impl->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); - ASSERT_THROW(in_data.data.spi_args.bytes == buf.size()); - //copy out the data - byte_vector_t result(buf.size()); - std::copy(in_data.data.spi_args.data, in_data.data.spi_args.data + buf.size(), result.begin()); - return result; + return ntohl(out_data.data.spi_args.data); } /*********************************************************************** @@ -245,19 +264,19 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t spi_dev_to_otw(dboard_interface::unit_type_t unit){ +static boost::uint8_t unit_to_otw(dboard_interface::unit_type_t unit){ switch(unit){ - case uhd::usrp::dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; - case uhd::usrp::dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; + case dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; + case dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; } throw std::invalid_argument("unknown unit type type"); } -void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, int which, int value){ +void usrp2_dboard_interface::write_aux_dac(unit_type_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); - out_data.data.aux_args.dir = spi_dev_to_otw(unit); + out_data.data.aux_args.dir = unit_to_otw(unit); out_data.data.aux_args.which = which; out_data.data.aux_args.value = htonl(value); @@ -266,11 +285,11 @@ void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, i ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); } -int usrp2_dboard_interface::read_aux_adc(dboard_interface::unit_type_t unit, int which){ +int usrp2_dboard_interface::read_aux_adc(unit_type_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); - out_data.data.aux_args.dir = spi_dev_to_otw(unit); + out_data.data.aux_args.dir = unit_to_otw(unit); out_data.data.aux_args.which = which; //send and recv -- cgit v1.2.3 From 40c231937e1ab4fb70ffb241a5ddb2455db0e907 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 16:10:29 -0700 Subject: moved spi transact to usrp2 impl, and removed spi read --- host/include/uhd/usrp/dboard_interface.hpp | 68 ++++++++++++------------------ host/lib/usrp/dboard/db_rfx.cpp | 2 +- host/lib/usrp/usrp2/dboard_interface.cpp | 60 ++++++-------------------- host/lib/usrp/usrp2/usrp2_impl.cpp | 32 +++++++++++++- host/lib/usrp/usrp2/usrp2_impl.hpp | 9 ++++ 5 files changed, 80 insertions(+), 91 deletions(-) (limited to 'host/lib/usrp/usrp2/dboard_interface.cpp') diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index dab5a2281..43fd1f143 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -25,6 +25,33 @@ namespace uhd{ namespace usrp{ +//spi configuration struct +struct UHD_API spi_config_t{ + /*! + * The edge type specifies when data is valid + * relative to the edge of the serial clock. + */ + enum edge_t{ + EDGE_RISE = 'r', + EDGE_FALL = 'f' + }; + + //! on what edge is the mosi data valid? + edge_t mosi_edge; + + //! on what edge is the miso data valid? + edge_t miso_edge; + + /*! + * Create a new spi config. + * \param edge the default edge for mosi and miso + */ + spi_config_t(edge_t edge = EDGE_RISE){ + mosi_edge = edge; + miso_edge = edge; + } +}; + /*! * The daughter board dboard_interface to be subclassed. * A dboard instance dboard_interfaces with the mboard though this api. @@ -42,33 +69,6 @@ public: UNIT_TYPE_TX = 't' }; - //spi configuration struct - struct UHD_API spi_config_t{ - /*! - * The edge type specifies when data is valid - * relative to the edge of the serial clock. - */ - enum edge_t{ - EDGE_RISE = 'r', - EDGE_FALL = 'f' - }; - - //! on what edge is the mosi data valid? - edge_t mosi_edge; - - //! on what edge is the miso data valid? - edge_t miso_edge; - - /*! - * Create a new spi config. - * \param edge the default edge for mosi and miso - */ - spi_config_t(edge_t edge = EDGE_RISE){ - mosi_edge = edge; - miso_edge = edge; - } - }; - //tell the host which gpio bank enum gpio_bank_t{ GPIO_BANK_RX = 'r', @@ -154,20 +154,6 @@ public: size_t num_bits ) = 0; - /*! - * \brief Read data to SPI bus peripheral. - * - * \param unit which unit, rx or tx - * \param config configuration settings - * \param num_bits the number of bits - * \return the data that was read - */ - virtual boost::uint32_t read_spi( - unit_type_t unit, - const spi_config_t &config, - size_t num_bits - ) = 0; - /*! * \brief Read and write data to SPI bus peripheral. * The data read back will be the same length as the input buffer. diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 68fa51144..4bf931660 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -138,7 +138,7 @@ void rfx_xcvr::reload_adf4360_regs(void){ BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ this->get_interface()->write_spi( dboard_interface::UNIT_TYPE_TX, - dboard_interface::spi_config_t::EDGE_RISE, + spi_config_t::EDGE_RISE, _adf4360_regs.get_reg(addr), 24 ); } diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index eee7c087a..d10cfa37e 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -47,32 +47,16 @@ public: const spi_config_t &config, boost::uint32_t data, size_t num_bits - ){ - transact_spi(unit, config, data, num_bits, false /*no rb*/); - } - - boost::uint32_t read_spi( - unit_type_t unit, - const spi_config_t &config, - size_t num_bits - ){ - return transact_spi(unit, config, 0, num_bits, true /*rb*/); - } + ); boost::uint32_t read_write_spi( unit_type_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits - ){ - return transact_spi(unit, config, data, num_bits, true /*rb*/); - } - -private: - boost::uint32_t transact_spi( - unit_type_t, const spi_config_t &, boost::uint32_t, size_t, bool ); +private: usrp2_impl *_impl; boost::uint32_t _ddr_shadow; }; @@ -175,42 +159,22 @@ static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){ throw std::invalid_argument("unknown unit type type"); } -/*! - * Static function to convert a spi edge enum - * to an over-the-wire value for the usrp2 control. - * \param edge the dboard interface spi edge enum - * \return an over the wire representation - */ -static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_config_t::edge_t edge){ - switch(edge){ - case dboard_interface::spi_config_t::EDGE_RISE: return USRP2_CLK_EDGE_RISE; - case dboard_interface::spi_config_t::EDGE_FALL: return USRP2_CLK_EDGE_FALL; - } - throw std::invalid_argument("unknown spi edge type"); +void usrp2_dboard_interface::write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, false /*no rb*/); } -boost::uint32_t usrp2_dboard_interface::transact_spi( +boost::uint32_t usrp2_dboard_interface::read_write_spi( unit_type_t unit, const spi_config_t &config, boost::uint32_t data, - size_t num_bits, - bool readback + size_t num_bits ){ - //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 = unit_to_otw_dev(unit); - 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 = _impl->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); + return _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, true /*rb*/); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index a7be2da8c..6d8c1a86c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -15,15 +15,16 @@ // along with this program. If not, see . // +#include "usrp2_impl.hpp" #include #include #include #include +#include #include #include #include #include -#include "usrp2_impl.hpp" using namespace uhd; using namespace uhd::usrp; @@ -217,6 +218,35 @@ boost::uint16_t usrp2_impl::peek16(boost::uint32_t addr){ return impl_peek(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_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 **********************************************************************/ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 4e7154afa..5a02b33dc 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -110,6 +110,15 @@ public: void poke16(boost::uint32_t addr, boost::uint16_t data); boost::uint16_t peek16(boost::uint32_t addr); + //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); -- cgit v1.2.3 From 389a72ef592d9826eac67ab001da5734909dbfcd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 16:52:18 -0700 Subject: merged unit type and gpio bank for dboard interface into one type, expanded dboard clock config api --- host/include/uhd/usrp/dboard_interface.hpp | 79 ++++++++++++++----------- host/lib/usrp/dboard/db_rfx.cpp | 2 +- host/lib/usrp/dboard_manager.cpp | 8 +-- host/lib/usrp/usrp2/dboard_interface.cpp | 93 ++++++++++++++++-------------- host/lib/usrp/usrp2/io_impl.cpp | 1 - 5 files changed, 98 insertions(+), 85 deletions(-) (limited to 'host/lib/usrp/usrp2/dboard_interface.cpp') diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index 43fd1f143..2fa05c09d 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -56,7 +56,7 @@ struct UHD_API spi_config_t{ * The daughter board dboard_interface to be subclassed. * A dboard instance dboard_interfaces with the mboard though this api. * This dboard_interface provides i2c, spi, gpio, atr, aux dac/adc access. - * Each mboard should have a specially tailored dboard dboard_interface. + * Each mboard should have a specially tailored interface for its dboard. */ class UHD_API dboard_interface{ public: @@ -64,15 +64,9 @@ public: typedef std::vector byte_vector_t; //tells the host which unit to use - enum unit_type_t{ - UNIT_TYPE_RX = 'r', - UNIT_TYPE_TX = 't' - }; - - //tell the host which gpio bank - enum gpio_bank_t{ - GPIO_BANK_RX = 'r', - GPIO_BANK_TX = 't' + enum unit_t{ + UNIT_RX = 'r', + UNIT_TX = 't' }; //possible atr registers @@ -85,54 +79,58 @@ public: /*! * Write to an aux dac. + * * \param unit which unit rx or tx * \param which_dac the dac index 0, 1, 2, 3... * \param value the value to write */ - virtual void write_aux_dac(unit_type_t unit, int which_dac, int value) = 0; + virtual void write_aux_dac(unit_t unit, int which_dac, int value) = 0; /*! * Read from an aux adc. + * * \param unit which unit rx or tx * \param which_adc the adc index 0, 1, 2, 3... * \return the value that was read */ - virtual int read_aux_adc(unit_type_t unit, int which_adc) = 0; + virtual int read_aux_adc(unit_t unit, int which_adc) = 0; /*! * Set a daughterboard ATR register. * - * \param bank GPIO_TX_BANK or GPIO_RX_BANK - * \param reg which ATR register to set - * \param value 16-bits, 0=FPGA output low, 1=FPGA output high + * \param unit which unit rx or tx + * \param reg which ATR register to set + * \param value 16-bits, 0=FPGA output low, 1=FPGA output high */ - virtual void set_atr_reg(gpio_bank_t bank, atr_reg_t reg, boost::uint16_t value) = 0; + virtual void set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint16_t value) = 0; /*! * Set daughterboard GPIO data direction register. * - * \param bank GPIO_TX_BANK or GPIO_RX_BANK - * \param value 16-bits, 0=FPGA input, 1=FPGA output + * \param unit which unit rx or tx + * \param value 16-bits, 0=FPGA input, 1=FPGA output */ - virtual void set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value) = 0; + virtual void set_gpio_ddr(unit_t unit, boost::uint16_t value) = 0; /*! - * Read daughterboard GPIO pin values + * Read daughterboard GPIO pin values. * - * \param bank GPIO_TX_BANK or GPIO_RX_BANK - * \return the value of the gpio bank + * \param unit which unit rx or tx + * \return the value of the gpio unit */ - virtual boost::uint16_t read_gpio(gpio_bank_t bank) = 0; + virtual boost::uint16_t read_gpio(unit_t unit) = 0; /*! - * \brief Write to I2C peripheral + * Write to an I2C peripheral. + * * \param i2c_addr I2C bus address (7-bits) * \param buf the data to write */ virtual void write_i2c(int i2c_addr, const byte_vector_t &buf) = 0; /*! - * \brief Read from I2C peripheral + * Read from an I2C peripheral. + * * \param i2c_addr I2C bus address (7-bits) * \param num_bytes number of bytes to read * \return the data read if successful, else a zero length string. @@ -140,7 +138,7 @@ public: virtual byte_vector_t read_i2c(int i2c_addr, size_t num_bytes) = 0; /*! - * \brief Write data to SPI bus peripheral. + * Write data to SPI bus peripheral. * * \param unit which unit, rx or tx * \param config configuration settings @@ -148,15 +146,14 @@ public: * \param num_bits the number of bits in data */ virtual void write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ) = 0; /*! - * \brief Read and write data to SPI bus peripheral. - * The data read back will be the same length as the input buffer. + * Read and write data to SPI bus peripheral. * * \param unit which unit, rx or tx * \param config configuration settings @@ -165,23 +162,35 @@ public: * \return the data that was read */ virtual boost::uint32_t read_write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ) = 0; /*! - * \brief Get the rate of the rx dboard clock. + * Get the rate of a dboard clock. + * + * \param unit which unit rx or tx * \return the clock rate in Hz */ - virtual double get_rx_clock_rate(void) = 0; + virtual double get_clock_rate(unit_t unit) = 0; /*! - * \brief Get the rate of the tx dboard clock. - * \return the clock rate in Hz + * Enable or disable a dboard clock. + * + * \param unit which unit rx or tx + * \param enb true for enabled + */ + virtual void set_clock_enabled(unit_t unit, bool enb) = 0; + + /*! + * Get the enabled status of a dboard block. + * + * \param unit which unit rx or tx + * \return true for enabled */ - virtual double get_tx_clock_rate(void) = 0; + virtual bool get_clock_enabled(unit_t unit) = 0; }; }} //namespace diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 4bf931660..60f6b1a60 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -137,7 +137,7 @@ void rfx_xcvr::reload_adf4360_regs(void){ ; BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ this->get_interface()->write_spi( - dboard_interface::UNIT_TYPE_TX, + dboard_interface::UNIT_TX, spi_config_t::EDGE_RISE, _adf4360_regs.get_reg(addr), 24 ); diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 4cf2e5820..f8ff38c39 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -276,9 +276,9 @@ wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ void dboard_manager_impl::set_nice_gpio_pins(void){ //std::cout << "Set nice GPIO pins" << std::endl; - _interface->set_gpio_ddr(dboard_interface::GPIO_BANK_RX, 0x0000); //all inputs - _interface->set_atr_reg(dboard_interface::GPIO_BANK_RX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low + _interface->set_gpio_ddr(dboard_interface::UNIT_RX, 0x0000); //all inputs + _interface->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low - _interface->set_gpio_ddr(dboard_interface::GPIO_BANK_TX, 0x0000); //all inputs - _interface->set_atr_reg(dboard_interface::GPIO_BANK_TX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low + _interface->set_gpio_ddr(dboard_interface::UNIT_TX, 0x0000); //all inputs + _interface->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low } diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index d10cfa37e..db8679b9b 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -29,28 +29,29 @@ public: usrp2_dboard_interface(usrp2_impl *impl); ~usrp2_dboard_interface(void); - void write_aux_dac(unit_type_t, int, int); - int read_aux_adc(unit_type_t, int); + void write_aux_dac(unit_t, int, int); + int read_aux_adc(unit_t, int); - void set_atr_reg(gpio_bank_t, atr_reg_t, boost::uint16_t); - void set_gpio_ddr(gpio_bank_t, boost::uint16_t); - boost::uint16_t read_gpio(gpio_bank_t); + void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); + void set_gpio_ddr(unit_t, boost::uint16_t); + boost::uint16_t read_gpio(unit_t); void write_i2c(int, const byte_vector_t &); byte_vector_t read_i2c(int, size_t); - double get_rx_clock_rate(void); - double get_tx_clock_rate(void); + double get_clock_rate(unit_t); + void set_clock_enabled(unit_t, bool); + bool get_clock_enabled(unit_t); void write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ); boost::uint32_t read_write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits @@ -89,57 +90,61 @@ usrp2_dboard_interface::~usrp2_dboard_interface(void){ } /*********************************************************************** - * Clock Rates + * Clocks **********************************************************************/ -double usrp2_dboard_interface::get_rx_clock_rate(void){ +double usrp2_dboard_interface::get_clock_rate(unit_t){ return _impl->get_master_clock_freq(); } -double usrp2_dboard_interface::get_tx_clock_rate(void){ - return _impl->get_master_clock_freq(); +void usrp2_dboard_interface::set_clock_enabled(unit_t, bool){ + //TODO +} + +bool usrp2_dboard_interface::get_clock_enabled(unit_t){ + return false; //TODO } /*********************************************************************** * GPIO **********************************************************************/ -static int bank_to_shift(dboard_interface::gpio_bank_t bank){ - switch(bank){ - case dboard_interface::GPIO_BANK_RX: return 0; - case dboard_interface::GPIO_BANK_TX: return 16; +static int unit_to_shift(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_RX: return 0; + case dboard_interface::UNIT_TX: return 16; } - throw std::runtime_error("unknown gpio bank type"); + throw std::runtime_error("unknown unit type"); } -void usrp2_dboard_interface::set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value){ +void usrp2_dboard_interface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ _ddr_shadow = \ - (_ddr_shadow & ~(0xffff << bank_to_shift(bank))) | - (boost::uint32_t(value) << bank_to_shift(bank)); + (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) | + (boost::uint32_t(value) << unit_to_shift(unit)); _impl->poke32(FR_GPIO_DDR, _ddr_shadow); } -boost::uint16_t usrp2_dboard_interface::read_gpio(gpio_bank_t bank){ - return boost::uint16_t(_impl->peek32(FR_GPIO_IO) >> bank_to_shift(bank)); +boost::uint16_t usrp2_dboard_interface::read_gpio(unit_t unit){ + return boost::uint16_t(_impl->peek32(FR_GPIO_IO) >> unit_to_shift(unit)); } -void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost::uint16_t value){ - //define mapping of bank to atr regs to register address +void usrp2_dboard_interface::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< - gpio_bank_t, uhd::dict - > bank_to_atr_to_addr = boost::assign::map_list_of - (GPIO_BANK_RX, boost::assign::map_list_of + unit_t, uhd::dict + > unit_to_atr_to_addr = boost::assign::map_list_of + (UNIT_RX, boost::assign::map_list_of (ATR_REG_IDLE, FR_ATR_IDLE_RXSIDE) (ATR_REG_TX_ONLY, FR_ATR_INTX_RXSIDE) (ATR_REG_RX_ONLY, FR_ATR_INRX_RXSIDE) (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE) ) - (GPIO_BANK_TX, boost::assign::map_list_of + (UNIT_TX, boost::assign::map_list_of (ATR_REG_IDLE, FR_ATR_IDLE_TXSIDE) (ATR_REG_TX_ONLY, FR_ATR_INTX_TXSIDE) (ATR_REG_RX_ONLY, FR_ATR_INRX_TXSIDE) (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE) ) ; - _impl->poke16(bank_to_atr_to_addr[bank][atr], value); + _impl->poke16(unit_to_atr_to_addr[unit][atr], value); } /*********************************************************************** @@ -151,30 +156,30 @@ void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost: * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){ +static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ switch(unit){ - case dboard_interface::UNIT_TYPE_TX: return SPI_SS_TX_DB; - case dboard_interface::UNIT_TYPE_RX: return SPI_SS_RX_DB; + case dboard_interface::UNIT_TX: return SPI_SS_TX_DB; + case dboard_interface::UNIT_RX: return SPI_SS_RX_DB; } - throw std::invalid_argument("unknown unit type type"); + throw std::invalid_argument("unknown unit type"); } void usrp2_dboard_interface::write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ){ - _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, false /*no rb*/); + _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); } boost::uint32_t usrp2_dboard_interface::read_write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ){ - return _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, true /*rb*/); + return _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); } /*********************************************************************** @@ -228,15 +233,15 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t unit_to_otw(dboard_interface::unit_type_t unit){ +static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ switch(unit){ - case dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; - case dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; + case dboard_interface::UNIT_TX: return USRP2_DIR_TX; + case dboard_interface::UNIT_RX: return USRP2_DIR_RX; } - throw std::invalid_argument("unknown unit type type"); + throw std::invalid_argument("unknown unit type"); } -void usrp2_dboard_interface::write_aux_dac(unit_type_t unit, int which, int value){ +void usrp2_dboard_interface::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); @@ -249,7 +254,7 @@ void usrp2_dboard_interface::write_aux_dac(unit_type_t unit, int which, int valu ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); } -int usrp2_dboard_interface::read_aux_adc(unit_type_t unit, int which){ +int usrp2_dboard_interface::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); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index a760cbe3d..87fc88ceb 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -18,7 +18,6 @@ #include "usrp2_impl.hpp" #include #include -#include #include using namespace uhd; -- cgit v1.2.3 From cbf2109e7ea123870988aae852b0b1af1b2ab222 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 19:37:38 -0700 Subject: controlling dboard clock enables from host --- host/lib/ic_reg_maps/gen_ad9510_regs.py | 19 ++++++++++++++----- host/lib/usrp/dboard_manager.cpp | 28 +++++++++++++++++----------- host/lib/usrp/usrp2/dboard_interface.cpp | 30 ++++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 20 deletions(-) (limited to 'host/lib/usrp/usrp2/dboard_interface.cpp') diff --git a/host/lib/ic_reg_maps/gen_ad9510_regs.py b/host/lib/ic_reg_maps/gen_ad9510_regs.py index 624249563..90230b8f9 100755 --- a/host/lib/ic_reg_maps/gen_ad9510_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9510_regs.py @@ -60,7 +60,7 @@ prescaler_value A[2:4] 0 div1, div2, 2_3, 4_5, 8_9, 1 b_counter_bypass A[6] 0 ref_counter_msb B[0:5] 0 ref_counter_lsb C[0:7] 0 -antibacklash_pw D[0:1] 0 1_3ns, 2_9ns, 6_0ns, 1_3ns +antibacklash_pw D[0:1] 0 1_3ns, 2_9ns, 6_0ns dld_window D[5] 0 9_5ns, 3_5ns lock_detect_disable D[6] 0 enb, dis ######################################################################## @@ -69,7 +69,7 @@ lock_detect_disable D[6] 0 enb, dis #for $i, $o in ((5, 0), (6, 4)) delay_control_out$i $hex(0x34+$o)[0] 0 ramp_current_out$i $hex(0x35+$o)[0:2] 0 200ua, 400ua, 600ua, 800ua, 1000ua, 1200ua, 1400ua, 1600ua -ramp_capacitor_out$i $hex(0x35+$o)[3:5] 0 4caps=0, 3caps=1, 2caps=3, 3caps=4, 1cap=7 +ramp_capacitor_out$i $hex(0x35+$o)[3:5] 0 4caps=0, 3caps=1, 2caps=3, 1cap=7 delay_fine_adjust_out$i $hex(0x36+$o)[1:5] 0 #end for ######################################################################## @@ -130,7 +130,7 @@ HEADER_TEXT=""" \#include -struct adf4360_regs_t{ +struct ad9510_regs_t{ #for $reg in $regs #if $reg.get_enums() enum $(reg.get_name())_t{ @@ -144,13 +144,13 @@ struct adf4360_regs_t{ #end if #end for - adf4360_regs_t(void){ + ad9510_regs_t(void){ #for $reg in $regs $reg.get_name() = $reg.get_default(); #end for } - boost::uint8_t get_reg(boost::uint8_t addr){ + boost::uint8_t get_reg(boost::uint16_t addr){ boost::uint8_t reg = 0; switch(addr){ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) @@ -163,6 +163,15 @@ struct adf4360_regs_t{ } return reg; } + + boost::uint32_t get_write_reg(boost::uint16_t addr){ + return (boost::uint32_t(addr) << 8) | get_reg(addr); + } + + boost::uint32_t get_read_reg(boost::uint16_t addr){ + return (boost::uint32_t(addr) << 8) | (1 << 15); + } + }; \#endif /* INCLUDED_AD9510_REGS_HPP */ diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index f8ff38c39..5e62b5564 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -141,7 +142,7 @@ private: uhd::dict _rx_dboards; uhd::dict _tx_dboards; dboard_interface::sptr _interface; - void set_nice_gpio_pins(void); + void set_nice_dboard_if(void); }; /*********************************************************************** @@ -200,7 +201,7 @@ dboard_manager_impl::dboard_manager_impl( boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(tx_dboard_id, "tx"); //initialize the gpio pins before creating subdevs - set_nice_gpio_pins(); + set_nice_dboard_if(); //make xcvr subdevs (make one subdev for both rx and tx dboards) if (rx_dboard_ctor == tx_dboard_ctor){ @@ -246,7 +247,7 @@ dboard_manager_impl::dboard_manager_impl( } dboard_manager_impl::~dboard_manager_impl(void){ - set_nice_gpio_pins(); + set_nice_dboard_if(); } prop_names_t dboard_manager_impl::get_rx_subdev_names(void){ @@ -273,12 +274,17 @@ wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ return _tx_dboards[subdev_name]->get_link(); } -void dboard_manager_impl::set_nice_gpio_pins(void){ - //std::cout << "Set nice GPIO pins" << std::endl; - - _interface->set_gpio_ddr(dboard_interface::UNIT_RX, 0x0000); //all inputs - _interface->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low - - _interface->set_gpio_ddr(dboard_interface::UNIT_TX, 0x0000); //all inputs - _interface->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low +void dboard_manager_impl::set_nice_dboard_if(void){ + //make a list of possible unit types + std::vector units = boost::assign::list_of + (dboard_interface::UNIT_RX) + (dboard_interface::UNIT_TX) + ; + + //set nice settings on each unit + BOOST_FOREACH(dboard_interface::unit_t unit, units){ + _interface->set_gpio_ddr(unit, 0x0000); //all inputs + _interface->set_atr_reg(unit, dboard_interface::ATR_REG_IDLE, 0x0000); //all low + _interface->set_clock_enabled(unit, false); //clock off + } } diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index db8679b9b..8a3df08cb 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -17,6 +17,7 @@ #include "usrp2_impl.hpp" #include "usrp2_regs.hpp" +#include "ad9510_regs.hpp" #include #include #include @@ -60,6 +61,8 @@ public: private: usrp2_impl *_impl; boost::uint32_t _ddr_shadow; + ad9510_regs_t _ad9510_regs; + uhd::dict _clock_enb_shadow; }; /*********************************************************************** @@ -96,12 +99,31 @@ double usrp2_dboard_interface::get_clock_rate(unit_t){ return _impl->get_master_clock_freq(); } -void usrp2_dboard_interface::set_clock_enabled(unit_t, bool){ - //TODO +void usrp2_dboard_interface::set_clock_enabled(unit_t unit, bool enb){ + uint16_t data = 0; + switch(unit){ + case UNIT_RX: + _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; + _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; + data = _ad9510_regs.get_write_reg(0x43); + break; + case UNIT_TX: + _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS; + _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; + data = _ad9510_regs.get_write_reg(0x42); + break; + } + _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); + + _ad9510_regs.update_registers = 1; + _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, _ad9510_regs.get_write_reg(0x5a), 24, false /*no rb*/); + _clock_enb_shadow[unit] = unit; } -bool usrp2_dboard_interface::get_clock_enabled(unit_t){ - return false; //TODO +bool usrp2_dboard_interface::get_clock_enabled(unit_t unit){ + return _clock_enb_shadow[unit]; } /*********************************************************************** -- cgit v1.2.3 From ad0d641b38dd79cc29b4ca7a3a02c02e35eb8f71 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 13 Apr 2010 12:42:23 -0700 Subject: Moved clock control into abstraction clock control class. --- host/include/uhd/usrp/dboard_interface.hpp | 8 --- host/lib/CMakeLists.txt | 19 ++++--- host/lib/usrp/usrp2/clock_control.cpp | 84 ++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/clock_control.hpp | 55 +++++++++++++++++++ host/lib/usrp/usrp2/dboard_interface.cpp | 27 ++-------- host/lib/usrp/usrp2/mboard_impl.cpp | 6 +++ host/lib/usrp/usrp2/usrp2_impl.hpp | 5 ++ 7 files changed, 167 insertions(+), 37 deletions(-) create mode 100644 host/lib/usrp/usrp2/clock_control.cpp create mode 100644 host/lib/usrp/usrp2/clock_control.hpp (limited to 'host/lib/usrp/usrp2/dboard_interface.cpp') diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index 2fa05c09d..c4e822751 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -183,14 +183,6 @@ public: * \param enb true for enabled */ virtual void set_clock_enabled(unit_t unit, bool enb) = 0; - - /*! - * Get the enabled status of a dboard block. - * - * \param unit which unit rx or tx - * \return true for enabled - */ - virtual bool get_clock_enabled(unit_t unit) = 0; }; }} //namespace diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 0483cd11c..b25ba38e2 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -60,12 +60,6 @@ SET(libuhd_sources usrp/simple_usrp.cpp usrp/dboard_manager.cpp usrp/tune_helper.cpp - usrp/usrp2/dboard_impl.cpp - usrp/usrp2/dboard_interface.cpp - usrp/usrp2/dsp_impl.cpp - usrp/usrp2/io_impl.cpp - usrp/usrp2/mboard_impl.cpp - usrp/usrp2/usrp2_impl.cpp ) ######################################################################## @@ -97,6 +91,19 @@ UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9510_regs.hpp ) +######################################################################## +# Add usrp2 sources +######################################################################## +LIST(APPEND libuhd_sources + usrp/usrp2/clock_control.cpp + usrp/usrp2/dboard_impl.cpp + usrp/usrp2/dboard_interface.cpp + usrp/usrp2/dsp_impl.cpp + usrp/usrp2/io_impl.cpp + usrp/usrp2/mboard_impl.cpp + usrp/usrp2/usrp2_impl.cpp +) + ######################################################################## # Conditionally add the udp sources ######################################################################## diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_control.cpp new file mode 100644 index 000000000..74db5958a --- /dev/null +++ b/host/lib/usrp/usrp2/clock_control.cpp @@ -0,0 +1,84 @@ +// +// 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 "usrp2_impl.hpp" +#include "clock_control.hpp" +#include "ad9510_regs.hpp" +#include "usrp2_regs.hpp" //spi slave constants +#include + +using namespace uhd::usrp; + +/*! + * A usrp2 clock control specific to the ad9510 ic. + */ +class clock_control_ad9510 : public clock_control{ +public: + clock_control_ad9510(usrp2_impl *impl){ + _impl = impl; + this->enable_rx_dboard_clock(false); + this->enable_tx_dboard_clock(false); + } + + ~clock_control_ad9510(void){ + /* NOP */ + } + + void enable_rx_dboard_clock(bool enb){ + _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; + _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; + this->write_reg(0x43); + this->update_regs(); + } + + void enable_tx_dboard_clock(bool enb){ + _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS; + _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; + this->write_reg(0x42); + this->update_regs(); + } + +private: + /*! + * Write a single register to the spi regs. + * \param addr the address to write + */ + 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*/); + } + + /*! + * Tells the ad9510 to latch the settings into the operational registers. + */ + void update_regs(void){ + _ad9510_regs.update_registers = 1; + this->write_reg(0x5a); + } + + usrp2_impl *_impl; + 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)); +} diff --git a/host/lib/usrp/usrp2/clock_control.hpp b/host/lib/usrp/usrp2/clock_control.hpp new file mode 100644 index 000000000..366e09c28 --- /dev/null +++ b/host/lib/usrp/usrp2/clock_control.hpp @@ -0,0 +1,55 @@ +// +// 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 . +// + +#ifndef INCLUDED_CLOCK_CONTROL_HPP +#define INCLUDED_CLOCK_CONTROL_HPP + +class usrp2_impl; //dummy class + +#include +#include + +class clock_control : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a clock config for the ad9510 ic. + * \param impl a pointer to the usrp2 implementation object + * \return a new clock control object + */ + static sptr make_ad9510(usrp2_impl *impl); + + /*! + * 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; + + /*! + * TODO other clock control api here.... + */ + +}; + +#endif /* INCLUDED_CLOCK_CONTROL_HPP */ diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index 8a3df08cb..c74bdaf44 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -17,7 +17,6 @@ #include "usrp2_impl.hpp" #include "usrp2_regs.hpp" -#include "ad9510_regs.hpp" #include #include #include @@ -61,8 +60,6 @@ public: private: usrp2_impl *_impl; boost::uint32_t _ddr_shadow; - ad9510_regs_t _ad9510_regs; - uhd::dict _clock_enb_shadow; }; /*********************************************************************** @@ -100,30 +97,14 @@ double usrp2_dboard_interface::get_clock_rate(unit_t){ } void usrp2_dboard_interface::set_clock_enabled(unit_t unit, bool enb){ - uint16_t data = 0; switch(unit){ case UNIT_RX: - _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; - _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; - data = _ad9510_regs.get_write_reg(0x43); - break; + _impl->get_clock_control()->enable_rx_dboard_clock(enb); + return; case UNIT_TX: - _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS; - _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; - data = _ad9510_regs.get_write_reg(0x42); - break; + _impl->get_clock_control()->enable_tx_dboard_clock(enb); + return; } - _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/); - - _ad9510_regs.update_registers = 1; - _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, _ad9510_regs.get_write_reg(0x5a), 24, false /*no rb*/); - _clock_enb_shadow[unit] = unit; -} - -bool usrp2_dboard_interface::get_clock_enabled(unit_t unit){ - return _clock_enb_shadow[unit]; } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 2fa2e5211..faa34d0b3 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -33,6 +33,12 @@ void usrp2_impl::mboard_init(void){ boost::bind(&usrp2_impl::mboard_get, this, _1, _2), boost::bind(&usrp2_impl::mboard_set, this, _1, _2) ); + + _clock_control = clock_control::make_ad9510(this); +} + +clock_control::sptr usrp2_impl::get_clock_control(void){ + return _clock_control; } void usrp2_impl::init_clock_config(void){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 5a02b33dc..f2e823391 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -18,6 +18,7 @@ #ifndef INCLUDED_USRP2_IMPL_HPP #define INCLUDED_USRP2_IMPL_HPP +#include "clock_control.hpp" #include #include #include @@ -110,6 +111,9 @@ public: 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, @@ -130,6 +134,7 @@ private: //device properties interface void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); + clock_control::sptr _clock_control; //the raw io interface (samples are in the usrp2 native format) void recv_raw(uhd::rx_metadata_t &); -- cgit v1.2.3 From 51a9c2d42d12caa607ae33feb12a6f16ab8a3fe5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 13 Apr 2010 17:48:48 -0700 Subject: Created a usrp2 interface class with the control, spi, peek/poke functionality. Its used in all the implementation level code --- host/lib/CMakeLists.txt | 3 +- host/lib/usrp/usrp2/clock_control.cpp | 16 +- host/lib/usrp/usrp2/clock_control.hpp | 7 +- host/lib/usrp/usrp2/dboard_iface.cpp | 278 +++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/dboard_impl.cpp | 10 +- host/lib/usrp/usrp2/dboard_interface.cpp | 271 ------------------------------ host/lib/usrp/usrp2/dsp_impl.cpp | 13 +- host/lib/usrp/usrp2/io_impl.cpp | 1 + host/lib/usrp/usrp2/mboard_impl.cpp | 37 ++-- host/lib/usrp/usrp2/usrp2_iface.cpp | 168 +++++++++++++++++++ host/lib/usrp/usrp2/usrp2_iface.hpp | 103 ++++++++++++ host/lib/usrp/usrp2/usrp2_impl.cpp | 110 +----------- host/lib/usrp/usrp2/usrp2_impl.hpp | 55 ++---- 13 files changed, 614 insertions(+), 458 deletions(-) create mode 100644 host/lib/usrp/usrp2/dboard_iface.cpp delete mode 100644 host/lib/usrp/usrp2/dboard_interface.cpp create mode 100644 host/lib/usrp/usrp2/usrp2_iface.cpp create mode 100644 host/lib/usrp/usrp2/usrp2_iface.hpp (limited to 'host/lib/usrp/usrp2/dboard_interface.cpp') 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 #include @@ -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_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp new file mode 100644 index 000000000..d0c4bf6c1 --- /dev/null +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -0,0 +1,278 @@ +// +// 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 "usrp2_iface.hpp" +#include "clock_control.hpp" +#include "usrp2_regs.hpp" +#include +#include +#include +#include //htonl and ntohl +#include + +using namespace uhd::usrp; + +class usrp2_dboard_iface : public dboard_interface{ +public: + 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); + + void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); + void set_gpio_ddr(unit_t, boost::uint16_t); + boost::uint16_t read_gpio(unit_t); + + void write_i2c(int, const byte_vector_t &); + byte_vector_t read_i2c(int, size_t); + + double get_clock_rate(unit_t); + void set_clock_enabled(unit_t, bool); + bool get_clock_enabled(unit_t); + + void write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + + boost::uint32_t read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ); + +private: + usrp2_iface::sptr _iface; + clock_control::sptr _clk_ctrl; + boost::uint32_t _ddr_shadow; +}; + +/*********************************************************************** + * Make Function + **********************************************************************/ +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_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 + boost::uint32_t new_sels = 0x0; + for(size_t i = 0; i < 16; i++){ + new_sels |= FRF_GPIO_SEL_ATR << (i*2); + } + _iface->poke32(FR_GPIO_TX_SEL, new_sels); + _iface->poke32(FR_GPIO_RX_SEL, new_sels); +} + +usrp2_dboard_iface::~usrp2_dboard_iface(void){ + /* NOP */ +} + +/*********************************************************************** + * Clocks + **********************************************************************/ +double usrp2_dboard_iface::get_clock_rate(unit_t){ + return _iface->get_master_clock_freq(); +} + +void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ + switch(unit){ + case UNIT_RX: + _clk_ctrl->enable_rx_dboard_clock(enb); + return; + case UNIT_TX: + _clk_ctrl->enable_tx_dboard_clock(enb); + return; + } +} + +/*********************************************************************** + * GPIO + **********************************************************************/ +static int unit_to_shift(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_RX: return 0; + case dboard_interface::UNIT_TX: return 16; + } + throw std::runtime_error("unknown unit type"); +} + +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)); + _iface->poke32(FR_GPIO_DDR, _ddr_shadow); +} + +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_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 + > unit_to_atr_to_addr = boost::assign::map_list_of + (UNIT_RX, boost::assign::map_list_of + (ATR_REG_IDLE, FR_ATR_IDLE_RXSIDE) + (ATR_REG_TX_ONLY, FR_ATR_INTX_RXSIDE) + (ATR_REG_RX_ONLY, FR_ATR_INRX_RXSIDE) + (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE) + ) + (UNIT_TX, boost::assign::map_list_of + (ATR_REG_IDLE, FR_ATR_IDLE_TXSIDE) + (ATR_REG_TX_ONLY, FR_ATR_INTX_TXSIDE) + (ATR_REG_RX_ONLY, FR_ATR_INRX_TXSIDE) + (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE) + ) + ; + _iface->poke16(unit_to_atr_to_addr[unit][atr], value); +} + +/*********************************************************************** + * SPI + **********************************************************************/ +/*! + * Static function to convert a unit type enum + * to an over-the-wire value for the spi device. + * \param unit the dboard interface unit type enum + * \return an over the wire representation + */ +static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_TX: return SPI_SS_TX_DB; + case dboard_interface::UNIT_RX: return SPI_SS_RX_DB; + } + throw std::invalid_argument("unknown unit type"); +} + +void usrp2_dboard_iface::write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); +} + +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 _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); +} + +/*********************************************************************** + * I2C + **********************************************************************/ +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); + out_data.data.i2c_args.addr = i2c_addr; + out_data.data.i2c_args.bytes = buf.size(); + + //limitation of i2c transaction size + ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data)); + + //copy in the data + std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data); + + //send and recv + 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_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); + out_data.data.i2c_args.addr = i2c_addr; + out_data.data.i2c_args.bytes = num_bytes; + + //limitation of i2c transaction size + ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data)); + + //send and recv + 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); + + //copy out the data + byte_vector_t result(num_bytes); + std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin()); + return result; +} + +/*********************************************************************** + * Aux DAX/ADC + **********************************************************************/ +/*! + * Static function to convert a unit type enum + * to an over-the-wire value for the usrp2 control. + * \param unit the dboard interface unit type enum + * \return an over the wire representation + */ +static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_TX: return USRP2_DIR_TX; + case dboard_interface::UNIT_RX: return USRP2_DIR_RX; + } + throw std::invalid_argument("unknown unit type"); +} + +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); + out_data.data.aux_args.dir = unit_to_otw(unit); + out_data.data.aux_args.which = which; + out_data.data.aux_args.value = htonl(value); + + //send and recv + 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_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); + out_data.data.aux_args.dir = unit_to_otw(unit); + out_data.data.aux_args.which = which; + + //send and recv + 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 #include #include +#include +#include //htonl and ntohl #include 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/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp deleted file mode 100644 index c74bdaf44..000000000 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// -// 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 "usrp2_impl.hpp" -#include "usrp2_regs.hpp" -#include -#include -#include -#include - -using namespace uhd::usrp; - -class usrp2_dboard_interface : public dboard_interface{ -public: - usrp2_dboard_interface(usrp2_impl *impl); - ~usrp2_dboard_interface(void); - - void write_aux_dac(unit_t, int, int); - int read_aux_adc(unit_t, int); - - void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); - void set_gpio_ddr(unit_t, boost::uint16_t); - boost::uint16_t read_gpio(unit_t); - - void write_i2c(int, const byte_vector_t &); - byte_vector_t read_i2c(int, size_t); - - double get_clock_rate(unit_t); - void set_clock_enabled(unit_t, bool); - bool get_clock_enabled(unit_t); - - void write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ); - - boost::uint32_t read_write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ); - -private: - usrp2_impl *_impl; - 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)); -} - -/*********************************************************************** - * Structors - **********************************************************************/ -usrp2_dboard_interface::usrp2_dboard_interface(usrp2_impl *impl){ - _impl = impl; - _ddr_shadow = 0; - - //set the selection mux to use atr - boost::uint32_t new_sels = 0x0; - 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); -} - -usrp2_dboard_interface::~usrp2_dboard_interface(void){ - /* NOP */ -} - -/*********************************************************************** - * Clocks - **********************************************************************/ -double usrp2_dboard_interface::get_clock_rate(unit_t){ - return _impl->get_master_clock_freq(); -} - -void usrp2_dboard_interface::set_clock_enabled(unit_t unit, bool enb){ - switch(unit){ - case UNIT_RX: - _impl->get_clock_control()->enable_rx_dboard_clock(enb); - return; - case UNIT_TX: - _impl->get_clock_control()->enable_tx_dboard_clock(enb); - return; - } -} - -/*********************************************************************** - * GPIO - **********************************************************************/ -static int unit_to_shift(dboard_interface::unit_t unit){ - switch(unit){ - case dboard_interface::UNIT_RX: return 0; - case dboard_interface::UNIT_TX: return 16; - } - throw std::runtime_error("unknown unit type"); -} - -void usrp2_dboard_interface::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); -} - -boost::uint16_t usrp2_dboard_interface::read_gpio(unit_t unit){ - return boost::uint16_t(_impl->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){ - //define mapping of unit to atr regs to register address - static const uhd::dict< - unit_t, uhd::dict - > unit_to_atr_to_addr = boost::assign::map_list_of - (UNIT_RX, boost::assign::map_list_of - (ATR_REG_IDLE, FR_ATR_IDLE_RXSIDE) - (ATR_REG_TX_ONLY, FR_ATR_INTX_RXSIDE) - (ATR_REG_RX_ONLY, FR_ATR_INRX_RXSIDE) - (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE) - ) - (UNIT_TX, boost::assign::map_list_of - (ATR_REG_IDLE, FR_ATR_IDLE_TXSIDE) - (ATR_REG_TX_ONLY, FR_ATR_INTX_TXSIDE) - (ATR_REG_RX_ONLY, FR_ATR_INRX_TXSIDE) - (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE) - ) - ; - _impl->poke16(unit_to_atr_to_addr[unit][atr], value); -} - -/*********************************************************************** - * SPI - **********************************************************************/ -/*! - * Static function to convert a unit type enum - * to an over-the-wire value for the spi device. - * \param unit the dboard interface unit type enum - * \return an over the wire representation - */ -static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ - switch(unit){ - case dboard_interface::UNIT_TX: return SPI_SS_TX_DB; - case dboard_interface::UNIT_RX: return SPI_SS_RX_DB; - } - throw std::invalid_argument("unknown unit type"); -} - -void usrp2_dboard_interface::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*/); -} - -boost::uint32_t usrp2_dboard_interface::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*/); -} - -/*********************************************************************** - * I2C - **********************************************************************/ -void usrp2_dboard_interface::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); - out_data.data.i2c_args.addr = i2c_addr; - out_data.data.i2c_args.bytes = buf.size(); - - //limitation of i2c transaction size - ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data)); - - //copy in the data - 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); - 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){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); - out_data.data.i2c_args.addr = i2c_addr; - out_data.data.i2c_args.bytes = num_bytes; - - //limitation of i2c transaction size - 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); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE); - ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes); - - //copy out the data - byte_vector_t result(num_bytes); - std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin()); - return result; -} - -/*********************************************************************** - * Aux DAX/ADC - **********************************************************************/ -/*! - * Static function to convert a unit type enum - * to an over-the-wire value for the usrp2 control. - * \param unit the dboard interface unit type enum - * \return an over the wire representation - */ -static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ - switch(unit){ - case dboard_interface::UNIT_TX: return USRP2_DIR_TX; - case dboard_interface::UNIT_RX: return USRP2_DIR_RX; - } - throw std::invalid_argument("unknown unit type"); -} - -void usrp2_dboard_interface::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); - out_data.data.aux_args.dir = unit_to_otw(unit); - out_data.data.aux_args.which = which; - out_data.data.aux_args.value = htonl(value); - - //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_DONE_WITH_THAT_AUX_DAC_DUDE); -} - -int usrp2_dboard_interface::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); - out_data.data.aux_args.dir = unit_to_otw(unit); - out_data.data.aux_args.which = which; - - //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_DONE_WITH_THAT_AUX_ADC_DUDE); - return ntohl(in_data.data.aux_args.value); -} 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 #include #include +#include #include #include @@ -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 #include +#include //htonl and ntohl #include 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 #include #include +#include +#include //htonl and ntohl +#include 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()).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 . +// + +#include "usrp2_iface.hpp" +#include +#include +#include +#include //used for htonl and ntohl +#include +#include + +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(addr, data); + } + + boost::uint32_t peek32(boost::uint32_t addr){ + return this->peek(addr); + } + + void poke16(boost::uint32_t addr, boost::uint16_t data){ + return this->poke(addr, data); + } + + boost::uint16_t peek16(boost::uint32_t addr){ + return this->peek(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_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 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 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 . +// + +#ifndef INCLUDED_USRP2_IFACE_HPP +#define INCLUDED_USRP2_IFACE_HPP + +#include +#include //spi config +#include +#include +#include +#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 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 +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include //htonl and ntohl #include 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(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(); @@ -168,109 +171,6 @@ usrp2_impl::~usrp2_impl(void){ /* NOP */ } -/*********************************************************************** - * Misc Access Methods - **********************************************************************/ -double usrp2_impl::get_master_clock_freq(void){ - return 100e6; -} - -template 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 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(this, addr, data); -} - -boost::uint32_t usrp2_impl::peek32(boost::uint32_t addr){ - return impl_peek(this, addr); -} - -void usrp2_impl::poke16(boost::uint32_t addr, boost::uint16_t data){ - return impl_poke(this, addr, data); -} - -boost::uint16_t usrp2_impl::peek16(boost::uint32_t addr){ - return impl_peek(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_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 **********************************************************************/ 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 #include #include #include #include -#include -#include #include #include -#include #include -#include #include #include -#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); -- cgit v1.2.3