diff options
author | Philip Balister <philip@opensdr.com> | 2010-04-27 08:21:35 +0000 |
---|---|---|
committer | Philip Balister <philip@opensdr.com> | 2010-04-27 08:21:35 +0000 |
commit | 7dba88b257f6a0fd5c35677ed5c7ce577cebbc74 (patch) | |
tree | 3b44059774229d69fe521cbf035758115493c4ce /host/lib/usrp/usrp2 | |
parent | 245b46da0b603e3c12c56fdad782ff884b2a6432 (diff) | |
parent | 1c4e9bd614dc8b7a17dc2bd95c322bbea940ca35 (diff) | |
download | uhd-7dba88b257f6a0fd5c35677ed5c7ce577cebbc74.tar.gz uhd-7dba88b257f6a0fd5c35677ed5c7ce577cebbc74.tar.bz2 uhd-7dba88b257f6a0fd5c35677ed5c7ce577cebbc74.zip |
Merge branch 'usrp_e' of git@ettus.sourcerepo.com:ettus/uhdpriv into usrp_e
Diffstat (limited to 'host/lib/usrp/usrp2')
-rw-r--r-- | host/lib/usrp/usrp2/clock_control.cpp | 1 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_iface.cpp | 141 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_impl.cpp | 58 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 12 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 32 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 27 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 61 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.hpp | 15 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 3 |
10 files changed, 209 insertions, 147 deletions
diff --git a/host/lib/usrp/usrp2/clock_control.cpp b/host/lib/usrp/usrp2/clock_control.cpp index dcd7ce9da..72f1f1c7a 100644 --- a/host/lib/usrp/usrp2/clock_control.cpp +++ b/host/lib/usrp/usrp2/clock_control.cpp @@ -21,6 +21,7 @@ #include "usrp2_regs.hpp" //spi slave constants #include <boost/cstdint.hpp> +using namespace uhd; using namespace uhd::usrp; /*! diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index 2859a7981..74d80163c 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -17,14 +17,17 @@ #include "usrp2_iface.hpp" #include "clock_control.hpp" -#include "usrp2_regs.hpp" +#include "usrp2_regs.hpp" //wishbone address constants +#include <uhd/usrp/dboard_iface.hpp> #include <uhd/types/dict.hpp> #include <uhd/utils/assert.hpp> #include <boost/assign/list_of.hpp> #include <boost/asio.hpp> //htonl and ntohl #include <boost/math/special_functions/round.hpp> -#include <algorithm> +#include "ad7922_regs.hpp" //aux adc +#include "ad5624_regs.hpp" //aux dac +using namespace uhd; using namespace uhd::usrp; class usrp2_dboard_iface : public dboard_iface{ @@ -39,8 +42,8 @@ public: 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); + void write_i2c(boost::uint8_t, const byte_vector_t &); + byte_vector_t read_i2c(boost::uint8_t, size_t); double get_clock_rate(unit_t); void set_clock_enabled(unit_t, bool); @@ -64,6 +67,9 @@ private: usrp2_iface::sptr _iface; clock_control::sptr _clk_ctrl; boost::uint32_t _ddr_shadow; + + uhd::dict<unit_t, ad5624_regs_t> _dac_regs; + void _write_aux_dac(unit_t); }; /*********************************************************************** @@ -91,6 +97,16 @@ usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::s } _iface->poke32(FR_GPIO_TX_SEL, new_sels); _iface->poke32(FR_GPIO_RX_SEL, new_sels); + + //reset the aux dacs + _dac_regs[UNIT_RX] = ad5624_regs_t(); + _dac_regs[UNIT_TX] = ad5624_regs_t(); + BOOST_FOREACH(unit_t unit, _dac_regs.keys()){ + _dac_regs[unit].data = 1; + _dac_regs[unit].addr = ad5624_regs_t::ADDR_ALL; + _dac_regs[unit].cmd = ad5624_regs_t::CMD_RESET; + this->_write_aux_dac(unit); + } } usrp2_dboard_iface::~usrp2_dboard_iface(void){ @@ -196,84 +212,67 @@ boost::uint32_t usrp2_dboard_iface::read_write_spi( /*********************************************************************** * 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); +void usrp2_dboard_iface::write_i2c(boost::uint8_t addr, const byte_vector_t &bytes){ + return _iface->write_i2c(addr, bytes); } -dboard_iface::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; +byte_vector_t usrp2_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes){ + return _iface->read_i2c(addr, num_bytes); } /*********************************************************************** * 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_iface::unit_t unit){ - switch(unit){ - case dboard_iface::UNIT_TX: return USRP2_DIR_TX; - case dboard_iface::UNIT_RX: return USRP2_DIR_RX; - } - throw std::invalid_argument("unknown unit type"); +void usrp2_dboard_iface::_write_aux_dac(unit_t unit){ + static const uhd::dict<unit_t, int> unit_to_spi_dac = boost::assign::map_list_of + (UNIT_RX, SPI_SS_RX_DAC) + (UNIT_TX, SPI_SS_TX_DAC) + ; + _iface->transact_spi( + unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, + _dac_regs[unit].get_reg(), 24, false /*no rb*/ + ); } void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, float 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(boost::math::iround(4095*value/3.3)); - - //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); + _dac_regs[unit].data = boost::math::iround(4095*value/3.3); + _dac_regs[unit].cmd = ad5624_regs_t::CMD_WR_UP_DAC_CHAN_N; + switch(which){ + case 0: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_A; break; + case 1: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_B; break; + case 2: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_C; break; + case 3: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_D; break; + default: throw std::runtime_error("not a possible aux dac, must be 0, 1, 2, or 3"); + } + this->_write_aux_dac(unit); } float 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 float(3.3*ntohl(in_data.data.aux_args.value)/4095); + static const uhd::dict<unit_t, int> unit_to_spi_adc = boost::assign::map_list_of + (UNIT_RX, SPI_SS_RX_ADC) + (UNIT_TX, SPI_SS_TX_ADC) + ; + + //setup spi config args + spi_config_t config; + config.mosi_edge = spi_config_t::EDGE_FALL; + config.miso_edge = spi_config_t::EDGE_RISE; + + //setup the spi registers + ad7922_regs_t ad7922_regs; + ad7922_regs.mod = which; //normal mode: mod == chn + ad7922_regs.chn = which; + + //write and read spi + _iface->transact_spi( + unit_to_spi_adc[unit], config, + ad7922_regs.get_reg(), 16, false /*no rb*/ + ); + ad7922_regs.set_reg(boost::uint16_t(_iface->transact_spi( + unit_to_spi_adc[unit], config, + ad7922_regs.get_reg(), 16, true /*rb*/ + ))); + + //convert to voltage and return + return float(3.3*ad7922_regs.result/4095); } diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index fe74219d6..403faf5cf 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -33,22 +33,16 @@ using namespace uhd::usrp; * Helper Methods **********************************************************************/ 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 = _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 - dboard_id_t rx_dboard_id = ntohs(in_data.data.dboard_ids.rx_id); - dboard_id_t tx_dboard_id = ntohs(in_data.data.dboard_ids.tx_id); + //read the dboard eeprom to extract the dboard ids + _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes())); + _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); //create a new dboard interface and manager dboard_iface::sptr _dboard_iface( make_usrp2_dboard_iface(_iface, _clk_ctrl) ); _dboard_manager = dboard_manager::make( - rx_dboard_id, tx_dboard_id, _dboard_iface + _rx_db_eeprom.id, _tx_db_eeprom.id, _dboard_iface ); //load dboards @@ -72,7 +66,7 @@ void usrp2_impl::dboard_init(void){ void usrp2_impl::update_rx_mux_config(void){ //calculate the rx mux boost::uint32_t rx_mux = 0; - ASSERT_THROW(_rx_subdevs_in_use.size() == 1); + UHD_ASSERT_THROW(_rx_subdevs_in_use.size() == 1); wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0)); std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl; if (rx_subdev[SUBDEV_PROP_QUADRATURE].as<bool>()){ @@ -90,11 +84,11 @@ void usrp2_impl::update_rx_mux_config(void){ void usrp2_impl::update_tx_mux_config(void){ //calculate the tx mux boost::uint32_t tx_mux = 0x10; - ASSERT_THROW(_tx_subdevs_in_use.size() == 1); + UHD_ASSERT_THROW(_tx_subdevs_in_use.size() == 1); wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl; if (tx_subdev[SUBDEV_PROP_IQ_SWAPPED].as<bool>()){ - tx_mux = (((tx_mux >> 0) & 0x1) << 1) | (((tx_mux >> 1) & 0x1) << 0); + tx_mux = (((tx_mux >> 0) & 0xf) << 4) | (((tx_mux >> 4) & 0xf) << 0); } _iface->poke32(FR_DSP_TX_MUX, tx_mux); @@ -125,19 +119,28 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _rx_subdevs_in_use; return; - //case DBOARD_PROP_CODEC: - // throw std::runtime_error("unhandled prop in usrp2 dboard"); + case DBOARD_PROP_DBOARD_ID: + val = _rx_db_eeprom.id; + return; + + default: UHD_THROW_PROP_GET_ERROR(); } } void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ - if (key.as<dboard_prop_t>() == DBOARD_PROP_USED_SUBDEVS){ + switch(key.as<dboard_prop_t>()){ + case DBOARD_PROP_USED_SUBDEVS: _rx_subdevs_in_use = val.as<prop_names_t>(); update_rx_mux_config(); //if the val is bad, this will throw return; - } - throw std::runtime_error("Cannot set on usrp2 dboard"); + case DBOARD_PROP_DBOARD_ID: + _rx_db_eeprom.id = val.as<dboard_id_t>(); + _iface->write_eeprom(I2C_ADDR_RX_DB, 0, _rx_db_eeprom.get_eeprom_bytes()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } /*********************************************************************** @@ -165,17 +168,26 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _tx_subdevs_in_use; return; - //case DBOARD_PROP_CODEC: - // throw std::runtime_error("unhandled prop in usrp2 dboard"); + case DBOARD_PROP_DBOARD_ID: + val = _tx_db_eeprom.id; + return; + + default: UHD_THROW_PROP_GET_ERROR(); } } void usrp2_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ - if (key.as<dboard_prop_t>() == DBOARD_PROP_USED_SUBDEVS){ + switch(key.as<dboard_prop_t>()){ + case DBOARD_PROP_USED_SUBDEVS: _tx_subdevs_in_use = val.as<prop_names_t>(); update_tx_mux_config(); //if the val is bad, this will throw return; - } - throw std::runtime_error("Cannot set on usrp2 dboard"); + case DBOARD_PROP_DBOARD_ID: + _tx_db_eeprom.id = val.as<dboard_id_t>(); + _iface->write_eeprom(I2C_ADDR_TX_DB, 0, _tx_db_eeprom.get_eeprom_bytes()); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } } diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 204277ba7..84314a656 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -40,7 +40,7 @@ template <class T> T log2(T num){ * DDC Helper Methods **********************************************************************/ static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq, double clock_freq){ - ASSERT_THROW(std::abs(freq) < clock_freq/2.0); + UHD_ASSERT_THROW(std::abs(freq) < clock_freq/2.0); static const double scale_factor = std::pow(2.0, 32); //calculate the freq register word @@ -117,6 +117,8 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ case DSP_PROP_HOST_RATE: val = get_master_clock_freq()/_ddc_decim; return; + + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -139,8 +141,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ } return; - default: - throw std::runtime_error("Error: trying to set read-only property on usrp2 ddc0"); + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -200,6 +201,8 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ case DSP_PROP_HOST_RATE: val = get_master_clock_freq()/_duc_interp; return; + + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -222,7 +225,6 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ } return; - default: - throw std::runtime_error("Error: trying to set read-only property on usrp2 duc0"); + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index b600a2a70..e80001ff2 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -32,6 +32,10 @@ extern "C" { #define _SINS_ #endif +//defines the protocol version in this shared header +//increment this value when the protocol is changed +#define USRP2_PROTO_VERSION 2 + //used to differentiate control packets over data port #define USRP2_INVALID_VRT_HEADER 0 @@ -57,9 +61,6 @@ typedef enum{ USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE = 'M', USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO = 'n', - USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO = 'd', - USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE = 'D', - USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO = 's', USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE = 'S', @@ -69,12 +70,6 @@ typedef enum{ USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO = 'h', USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE = 'H', - USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO = 'x', - USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE = 'X', - - USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO = 'y', - USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE = 'Y', - USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO = '{', USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE = '}', @@ -89,26 +84,23 @@ typedef enum{ } usrp2_ctrl_id_t; typedef enum{ - USRP2_DIR_RX, - USRP2_DIR_TX + USRP2_DIR_RX = 'r', + USRP2_DIR_TX = 't' } usrp2_dir_which_t; typedef enum{ - USRP2_CLK_EDGE_RISE, - USRP2_CLK_EDGE_FALL + USRP2_CLK_EDGE_RISE = 'r', + USRP2_CLK_EDGE_FALL = 'f' } usrp2_clk_edge_t; typedef struct{ + _SINS_ uint32_t proto_ver; _SINS_ uint32_t id; _SINS_ uint32_t seq; union{ _SINS_ uint32_t ip_addr; _SINS_ uint8_t mac_addr[6]; struct { - _SINS_ uint16_t rx_id; - _SINS_ uint16_t tx_id; - } dboard_ids; - struct { _SINS_ uint8_t dev; _SINS_ uint8_t miso_edge; _SINS_ uint8_t mosi_edge; @@ -122,12 +114,6 @@ typedef struct{ _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)]; } i2c_args; struct { - _SINS_ uint8_t dir; - _SINS_ uint8_t which; - _SINS_ uint8_t _pad[2]; - _SINS_ uint32_t value; - } aux_args; - struct { _SINS_ uint8_t now; //stream now? _SINS_ uint8_t continuous; //auto-reload commmands? _SINS_ uint8_t chain; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index d7728238c..36bef4f25 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -100,6 +100,7 @@ void usrp2_impl::update_clock_config(void){ 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; + default: throw std::runtime_error("usrp2: unhandled clock configuration reference source"); } //clock source ref 10mhz @@ -151,7 +152,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ //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_GOT_THAT_STREAM_COMMAND_DUDE); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE); } /*********************************************************************** @@ -170,7 +171,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ //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_THIS_IS_MY_MAC_ADDR_DUDE); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); //extract the address val = mac_addr_t::from_bytes(in_data.data.mac_addr).to_string(); @@ -184,7 +185,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ //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_THIS_IS_MY_IP_ADDR_DUDE); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); //extract the address val = boost::asio::ip::address_v4(ntohl(in_data.data.ip_addr)).to_string(); @@ -208,7 +209,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DBOARD: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _rx_dboard_proxy->get_link(); return; @@ -217,7 +218,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DBOARD: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _tx_dboard_proxy->get_link(); return; @@ -226,7 +227,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_RX_DSP: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _rx_dsp_proxy->get_link(); return; @@ -235,7 +236,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_TX_DSP: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _tx_dsp_proxy->get_link(); return; @@ -247,9 +248,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = _clock_config; return; - default: - throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard"); - + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -268,7 +267,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //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_THIS_IS_MY_MAC_ADDR_DUDE); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); return; } @@ -280,7 +279,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //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_THIS_IS_MY_IP_ADDR_DUDE); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE); return; } } @@ -305,8 +304,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ issue_ddc_stream_cmd(val.as<stream_cmd_t>()); return; - default: - throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard"); - + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 5c84fd8d3..e43b9678e 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -19,12 +19,13 @@ #include <uhd/utils/assert.hpp> #include <uhd/types/dict.hpp> #include <boost/thread.hpp> +#include <boost/foreach.hpp> #include <boost/asio.hpp> //used for htonl and ntohl #include <boost/assign/list_of.hpp> #include <stdexcept> +#include <algorithm> using namespace uhd; -using namespace uhd::usrp; class usrp2_iface_impl : public usrp2_iface{ public: @@ -85,9 +86,51 @@ public: //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); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); - return ntohl(out_data.data.spi_args.data); + return ntohl(in_data.data.spi_args.data); + } + +/*********************************************************************** + * I2C + **********************************************************************/ + void write_i2c(boost::uint8_t 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 = addr; + out_data.data.i2c_args.bytes = buf.size(); + + //limitation of i2c transaction size + UHD_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 = this->ctrl_send_and_recv(out_data); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE); + } + + byte_vector_t read_i2c(boost::uint8_t 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 = addr; + out_data.data.i2c_args.bytes = num_bytes; + + //limitation of i2c transaction size + UHD_ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data)); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE); + UHD_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; } /*********************************************************************** @@ -98,6 +141,7 @@ public: //fill in the seq number and send usrp2_ctrl_data_t out_copy = out_data; + out_copy.proto_ver = htonl(USRP2_PROTO_VERSION); out_copy.seq = htonl(++_ctrl_seq_num); _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t))); @@ -105,6 +149,13 @@ public: 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(boost::uint32_t) and ntohl(in_data.proto_ver) != USRP2_PROTO_VERSION){ + throw std::runtime_error(str( + boost::format("Expected protocol version %d, but got %d\n" + "The firmware build does not match the host code build." + ) % int(USRP2_PROTO_VERSION) % ntohl(in_data.proto_ver) + )); + } if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){ return in_data; } @@ -142,7 +193,7 @@ private: //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); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE); } template <class T> T peek(boost::uint32_t addr){ @@ -154,7 +205,7 @@ private: //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); + UHD_ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE); return T(ntohl(out_data.data.poke_args.data)); } diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 1298d87f1..7158c58d0 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -19,18 +19,27 @@ #define INCLUDED_USRP2_IFACE_HPP #include <uhd/transport/udp_simple.hpp> -#include <uhd/usrp/dboard_iface.hpp> //spi config +#include <uhd/types/serial.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include <boost/cstdint.hpp> #include "fw_common.h" +//////////////////////////////////////////////////////////////////////// +// I2C addresses +//////////////////////////////////////////////////////////////////////// +#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx +#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) +#define I2C_ADDR_TX_DB (I2C_DEV_EEPROM | 0x4) +#define I2C_ADDR_RX_DB (I2C_DEV_EEPROM | 0x5) +//////////////////////////////////////////////////////////////////////// + /*! * The usrp2 interface class: * Provides a set of functions to implementation layer. * Including spi, peek, poke, control... */ -class usrp2_iface : boost::noncopyable{ +class usrp2_iface : public uhd::i2c_iface, boost::noncopyable{ public: typedef boost::shared_ptr<usrp2_iface> sptr; @@ -87,7 +96,7 @@ public: */ virtual boost::uint32_t transact_spi( int which_slave, - const uhd::usrp::spi_config_t &config, + const uhd::spi_config_t &config, boost::uint32_t data, size_t num_bits, bool readback diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 3bdc5bd02..4079357f9 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -70,6 +70,7 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){ //send a hello control packet usrp2_ctrl_data_t ctrl_data_out; + ctrl_data_out.proto_ver = htonl(USRP2_PROTO_VERSION); ctrl_data_out.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); @@ -185,7 +186,7 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ return; case DEVICE_PROP_MBOARD: - ASSERT_THROW(name == ""); + UHD_ASSERT_THROW(name == ""); val = _mboard_proxy->get_link(); return; @@ -201,9 +202,10 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ val = size_t(_max_tx_samples_per_packet); return; + default: UHD_THROW_PROP_GET_ERROR(); } } void usrp2_impl::set(const wax::obj &, const wax::obj &){ - throw std::runtime_error("Cannot set in usrp2 device"); + UHD_THROW_PROP_SET_ERROR(); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index dbcee367b..1c9387744 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -25,6 +25,7 @@ #include <uhd/types/otw_type.hpp> #include <uhd/types/stream_cmd.hpp> #include <uhd/types/clock_config.hpp> +#include <uhd/usrp/dboard_eeprom.hpp> #include <boost/shared_ptr.hpp> #include <boost/function.hpp> #include <uhd/transport/vrt.hpp> @@ -161,12 +162,14 @@ private: void rx_dboard_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _rx_dboard_proxy; uhd::prop_names_t _rx_subdevs_in_use; + uhd::usrp::dboard_eeprom_t _rx_db_eeprom; //properties interface for tx dboard void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _tx_dboard_proxy; uhd::prop_names_t _tx_subdevs_in_use; + uhd::usrp::dboard_eeprom_t _tx_db_eeprom; void update_rx_mux_config(void); void update_tx_mux_config(void); |