summaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/usrp2
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/usrp2')
-rw-r--r--host/lib/usrp/usrp2/clock_control.cpp1
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp141
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp58
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp12
-rw-r--r--host/lib/usrp/usrp2/fw_common.h32
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp27
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp61
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.hpp15
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp6
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp3
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);