summaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/usrp2
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-02-21 12:59:41 -0800
committerJosh Blum <josh@joshknows.com>2010-02-21 12:59:41 -0800
commitadd5d32f9b0cb3cda15624fb7aef3998096ff3f6 (patch)
treee5c10c2952b173b977e5835c34ac27ece92a0b45 /host/lib/usrp/usrp2
parentaab51fa40769bb77af73aba69e16c9ac28e4943f (diff)
downloaduhd-add5d32f9b0cb3cda15624fb7aef3998096ff3f6.tar.gz
uhd-add5d32f9b0cb3cda15624fb7aef3998096ff3f6.tar.bz2
uhd-add5d32f9b0cb3cda15624fb7aef3998096ff3f6.zip
Moved lib and include contents of dboard and mboard one directory up and prefixed them with dboard_ and mboard_.
And yes, the code is compiling.
Diffstat (limited to 'host/lib/usrp/usrp2')
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp123
-rw-r--r--host/lib/usrp/usrp2/dboard_interface.cpp284
-rw-r--r--host/lib/usrp/usrp2/dboard_interface.hpp63
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp293
-rw-r--r--host/lib/usrp/usrp2/fw_common.h190
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp196
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp102
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp160
8 files changed, 1411 insertions, 0 deletions
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
new file mode 100644
index 000000000..b38a51b04
--- /dev/null
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -0,0 +1,123 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils.hpp>
+#include "usrp2_impl.hpp"
+#include "dboard_interface.hpp"
+
+using namespace uhd;
+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 = ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE);
+ std::cout << boost::format("rx id 0x%.2x, tx id 0x%.2x")
+ % ntohs(in_data.data.dboard_ids.rx_id)
+ % ntohs(in_data.data.dboard_ids.tx_id) << std::endl;
+
+ //extract the dboard ids an convert them to enums
+ dboard_id_t rx_dboard_id = static_cast<dboard_id_t>(
+ ntohs(in_data.data.dboard_ids.rx_id)
+ );
+ dboard_id_t tx_dboard_id = static_cast<dboard_id_t>(
+ ntohs(in_data.data.dboard_ids.tx_id)
+ );
+
+ //create a new dboard interface and manager
+ dboard_interface::sptr _dboard_interface(
+ new usrp2_dboard_interface(this)
+ );
+ dboard_manager::sptr _dboard_manager(
+ new dboard_manager(rx_dboard_id, tx_dboard_id, _dboard_interface)
+ );
+
+ //load dboards
+ _rx_dboards[""] = wax_obj_proxy(
+ boost::bind(&usrp2_impl::rx_dboard_get, this, _1, _2),
+ boost::bind(&usrp2_impl::rx_dboard_set, this, _1, _2)
+ );
+ _tx_dboards[""] = wax_obj_proxy(
+ boost::bind(&usrp2_impl::tx_dboard_get, this, _1, _2),
+ boost::bind(&usrp2_impl::tx_dboard_set, this, _1, _2)
+ );
+}
+
+/***********************************************************************
+ * RX DBoard Properties
+ **********************************************************************/
+void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(wax::cast<dboard_prop_t>(key)){
+ case DBOARD_PROP_NAME:
+ val = std::string("usrp2 dboard (rx unit)");
+ return;
+
+ case DBOARD_PROP_SUBDEV:
+ val = _dboard_manager->get_rx_subdev(name);
+ return;
+
+ case DBOARD_PROP_SUBDEV_NAMES:
+ val = _dboard_manager->get_rx_subdev_names();
+ return;
+
+ case DBOARD_PROP_CODEC:
+ throw std::runtime_error("unhandled prop in usrp2 dboard");
+ }
+}
+
+void usrp2_impl::rx_dboard_set(const wax::obj &, const wax::obj &){
+ throw std::runtime_error("Cannot set on usrp2 dboard");
+}
+
+/***********************************************************************
+ * TX DBoard Properties
+ **********************************************************************/
+void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(wax::cast<dboard_prop_t>(key)){
+ case DBOARD_PROP_NAME:
+ val = std::string("usrp2 dboard (tx unit)");
+ return;
+
+ case DBOARD_PROP_SUBDEV:
+ val = _dboard_manager->get_tx_subdev(name);
+ return;
+
+ case DBOARD_PROP_SUBDEV_NAMES:
+ val = _dboard_manager->get_tx_subdev_names();
+ return;
+
+ case DBOARD_PROP_CODEC:
+ throw std::runtime_error("unhandled prop in usrp2 dboard");
+ }
+}
+
+void usrp2_impl::tx_dboard_set(const wax::obj &, const wax::obj &){
+ throw std::runtime_error("Cannot set on usrp2 dboard");
+}
diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp
new file mode 100644
index 000000000..f12b101f3
--- /dev/null
+++ b/host/lib/usrp/usrp2/dboard_interface.cpp
@@ -0,0 +1,284 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils.hpp>
+#include "dboard_interface.hpp"
+#include "usrp2_impl.hpp"
+
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Structors
+ **********************************************************************/
+usrp2_dboard_interface::usrp2_dboard_interface(usrp2_impl *impl){
+ _impl = impl;
+}
+
+usrp2_dboard_interface::~usrp2_dboard_interface(void){
+ /* NOP */
+}
+
+/***********************************************************************
+ * Clock Rates
+ **********************************************************************/
+double usrp2_dboard_interface::get_rx_clock_rate(void){
+ return _impl->get_master_clock_freq();
+}
+
+double usrp2_dboard_interface::get_tx_clock_rate(void){
+ return _impl->get_master_clock_freq();
+}
+
+/***********************************************************************
+ * GPIO
+ **********************************************************************/
+/*!
+ * Static function to convert a gpio bank enum
+ * to an over-the-wire value for the usrp2 control.
+ * \param bank the dboard interface gpio bank enum
+ * \return an over the wire representation
+ */
+static uint8_t gpio_bank_to_otw(dboard_interface::gpio_bank_t bank){
+ switch(bank){
+ case uhd::usrp::dboard_interface::GPIO_TX_BANK: return USRP2_DIR_TX;
+ case uhd::usrp::dboard_interface::GPIO_RX_BANK: return USRP2_DIR_RX;
+ }
+ throw std::invalid_argument("unknown gpio bank type");
+}
+
+void usrp2_dboard_interface::set_gpio_ddr(gpio_bank_t bank, uint16_t value, uint16_t mask){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_USE_THESE_GPIO_DDR_SETTINGS_BRO);
+ out_data.data.gpio_config.bank = gpio_bank_to_otw(bank);
+ out_data.data.gpio_config.value = htons(value);
+ out_data.data.gpio_config.mask = htons(mask);
+
+ //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_GOT_THE_GPIO_DDR_SETTINGS_DUDE);
+}
+
+void usrp2_dboard_interface::write_gpio(gpio_bank_t bank, uint16_t value, uint16_t mask){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_SET_YOUR_GPIO_PIN_OUTS_BRO);
+ out_data.data.gpio_config.bank = gpio_bank_to_otw(bank);
+ out_data.data.gpio_config.value = htons(value);
+ out_data.data.gpio_config.mask = htons(mask);
+
+ //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_I_SET_THE_GPIO_PIN_OUTS_DUDE);
+}
+
+uint16_t usrp2_dboard_interface::read_gpio(gpio_bank_t bank){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_GPIO_PIN_VALS_BRO);
+ out_data.data.gpio_config.bank = gpio_bank_to_otw(bank);
+
+ //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_HERE_IS_YOUR_GPIO_PIN_VALS_DUDE);
+ return ntohs(in_data.data.gpio_config.value);
+}
+
+void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, uint16_t tx_value, uint16_t rx_value, uint16_t mask){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_USE_THESE_ATR_SETTINGS_BRO);
+ out_data.data.atr_config.bank = gpio_bank_to_otw(bank);
+ out_data.data.atr_config.tx_value = htons(tx_value);
+ out_data.data.atr_config.rx_value = htons(rx_value);
+ out_data.data.atr_config.mask = htons(mask);
+
+ //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_GOT_THE_ATR_SETTINGS_DUDE);
+}
+
+/***********************************************************************
+ * 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
+ * \return an over the wire representation
+ */
+static uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){
+ switch(dev){
+ case uhd::usrp::dboard_interface::SPI_TX_DEV: return USRP2_DIR_TX;
+ case uhd::usrp::dboard_interface::SPI_RX_DEV: return USRP2_DIR_RX;
+ }
+ throw std::invalid_argument("unknown spi device type");
+}
+
+/*!
+ * Static function to convert a spi latch enum
+ * to an over-the-wire value for the usrp2 control.
+ * \param latch the dboard interface spi latch enum
+ * \return an over the wire representation
+ */
+static uint8_t spi_latch_to_otw(dboard_interface::spi_latch_t latch){
+ switch(latch){
+ case uhd::usrp::dboard_interface::SPI_LATCH_RISE: return USRP2_CLK_EDGE_RISE;
+ case uhd::usrp::dboard_interface::SPI_LATCH_FALL: return USRP2_CLK_EDGE_FALL;
+ }
+ throw std::invalid_argument("unknown spi latch type");
+}
+
+/*!
+ * Static function to convert a spi push enum
+ * to an over-the-wire value for the usrp2 control.
+ * \param push the dboard interface spi push enum
+ * \return an over the wire representation
+ */
+static uint8_t spi_push_to_otw(dboard_interface::spi_push_t push){
+ switch(push){
+ case uhd::usrp::dboard_interface::SPI_PUSH_RISE: return USRP2_CLK_EDGE_RISE;
+ case uhd::usrp::dboard_interface::SPI_PUSH_FALL: return USRP2_CLK_EDGE_FALL;
+ }
+ throw std::invalid_argument("unknown spi push type");
+}
+
+dboard_interface::byte_vector_t usrp2_dboard_interface::transact_spi(
+ spi_dev_t dev,
+ spi_latch_t latch,
+ spi_push_t push,
+ const byte_vector_t &buf,
+ 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.latch = spi_latch_to_otw(latch);
+ out_data.data.spi_args.push = spi_push_to_otw(push);
+ 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
+ for (size_t i = 0; i < buf.size(); i++){
+ out_data.data.spi_args.data[i] = buf[i];
+ }
+
+ //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;
+ for (size_t i = 0; i < buf.size(); i++){
+ result.push_back(in_data.data.spi_args.data[i]);
+ }
+ return result;
+}
+
+/***********************************************************************
+ * 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
+ for (size_t i = 0; i < buf.size(); i++){
+ out_data.data.i2c_args.data[i] = buf[i];
+ }
+
+ //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;
+ for (size_t i = 0; i < num_bytes; i++){
+ result.push_back(in_data.data.i2c_args.data[i]);
+ }
+ 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 uint8_t spi_dev_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;
+ }
+ 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){
+ //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.which = which;
+ out_data.data.aux_args.dir = 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(dboard_interface::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.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/dboard_interface.hpp b/host/lib/usrp/usrp2/dboard_interface.hpp
new file mode 100644
index 000000000..a06359e5e
--- /dev/null
+++ b/host/lib/usrp/usrp2/dboard_interface.hpp
@@ -0,0 +1,63 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/usrp/dboard_interface.hpp>
+
+#ifndef INCLUDED_DBOARD_INTERFACE_HPP
+#define INCLUDED_DBOARD_INTERFACE_HPP
+
+class usrp2_impl; //dummy class declaration
+
+class usrp2_dboard_interface : public uhd::usrp::dboard_interface{
+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 set_atr_reg(gpio_bank_t, uint16_t, uint16_t, uint16_t);
+
+ void set_gpio_ddr(gpio_bank_t, uint16_t, uint16_t);
+
+ void write_gpio(gpio_bank_t, uint16_t, uint16_t);
+
+ uint16_t read_gpio(gpio_bank_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);
+
+private:
+ byte_vector_t transact_spi(
+ spi_dev_t dev,
+ spi_latch_t latch,
+ spi_push_t push,
+ const byte_vector_t &buf,
+ bool readback
+ );
+
+ usrp2_impl *_impl;
+};
+
+#endif /* INCLUDED_DBOARD_INTERFACE_HPP */
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
new file mode 100644
index 000000000..22c00d99a
--- /dev/null
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -0,0 +1,293 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils.hpp>
+#include <boost/assign/list_of.hpp>
+#include "usrp2_impl.hpp"
+
+using namespace uhd;
+
+/***********************************************************************
+ * DDC Helper Methods
+ **********************************************************************/
+static uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t clock_freq){
+ double scale_factor = pow(2.0, 32);
+
+ //calculate the freq register word
+ uint32_t freq_word = rint((freq / clock_freq) * scale_factor);
+
+ //update the actual frequency
+ freq = (double(freq_word) / scale_factor) * clock_freq;
+
+ return freq_word;
+}
+
+void usrp2_impl::init_ddc_config(void){
+ //create the ddc in the rx dsp dict
+ _rx_dsps["ddc0"] = wax_obj_proxy(
+ boost::bind(&usrp2_impl::ddc_get, this, _1, _2),
+ boost::bind(&usrp2_impl::ddc_set, this, _1, _2)
+ );
+
+ //initial config and update
+ _ddc_decim = 16;
+ _ddc_freq = 0;
+ update_ddc_config();
+
+ _ddc_stream_at = time_spec_t();
+ _ddc_enabled = false;
+ update_ddc_enabled();
+}
+
+void usrp2_impl::update_ddc_config(void){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO);
+ out_data.data.ddc_args.freq_word = htonl(
+ calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq())
+ );
+ out_data.data.ddc_args.decim = htonl(_ddc_decim);
+
+ //send and recv
+ usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE);
+}
+
+void usrp2_impl::update_ddc_enabled(void){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO);
+ out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0;
+ out_data.data.streaming.secs = htonl(_ddc_stream_at.secs);
+ out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks);
+
+ //send and recv
+ usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE);
+
+ //clear the stream at time spec (it must be set for the next round of enable/disable)
+ _ddc_stream_at = time_spec_t();
+}
+
+/***********************************************************************
+ * DDC Properties
+ **********************************************************************/
+void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
+ //handle the case where the key is an expected dsp property
+ if (key.type() == typeid(dsp_prop_t)){
+ switch(wax::cast<dsp_prop_t>(key)){
+ case DSP_PROP_NAME:
+ val = std::string("usrp2 ddc0");
+ return;
+
+ case DSP_PROP_OTHERS:{
+ prop_names_t others = boost::assign::list_of
+ ("rate")
+ ("decim")
+ ("decim_rates")
+ ("freq")
+ ("enabled")
+ ("stream_at")
+ ;
+ val = others;
+ }
+ return;
+ }
+ }
+
+ //handle string-based properties specific to this dsp
+ std::string key_name = wax::cast<std::string>(key);
+ if (key_name == "rate"){
+ val = get_master_clock_freq();
+ return;
+ }
+ else if (key_name == "decim"){
+ val = _ddc_decim;
+ return;
+ }
+ else if (key_name == "decim_rates"){
+ val = _allowed_decim_and_interp_rates;
+ return;
+ }
+ else if (key_name == "freq"){
+ val = _ddc_freq;
+ return;
+ }
+ else if (key_name == "enabled"){
+ val = _ddc_enabled;
+ return;
+ }
+
+ throw std::invalid_argument(str(
+ boost::format("error getting: unknown key with name %s") % key_name
+ ));
+}
+
+void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){
+ //handle string-based properties specific to this dsp
+ std::string key_name = wax::cast<std::string>(key);
+ if (key_name == "decim"){
+ size_t new_decim = wax::cast<size_t>(val);
+ ASSERT_THROW(std::has(
+ _allowed_decim_and_interp_rates.begin(),
+ _allowed_decim_and_interp_rates.end(),
+ new_decim
+ ));
+ _ddc_decim = new_decim; //shadow
+ update_ddc_config();
+ return;
+ }
+ else if (key_name == "freq"){
+ freq_t new_freq = wax::cast<freq_t>(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
+ update_ddc_config();
+ return;
+ }
+ else if (key_name == "enabled"){
+ bool new_enabled = wax::cast<bool>(val);
+ _ddc_enabled = new_enabled; //shadow
+ update_ddc_enabled();
+ return;
+ }
+ else if (key_name == "stream_at"){
+ time_spec_t new_stream_at = wax::cast<time_spec_t>(val);
+ _ddc_stream_at = new_stream_at; //shadow
+ //update_ddc_enabled(); //dont update from here
+ return;
+ }
+
+ throw std::invalid_argument(str(
+ boost::format("error setting: unknown key with name %s") % key_name
+ ));
+}
+
+/***********************************************************************
+ * DUC Helper Methods
+ **********************************************************************/
+void usrp2_impl::init_duc_config(void){
+ //create the duc in the tx dsp dict
+ _tx_dsps["duc0"] = wax_obj_proxy(
+ boost::bind(&usrp2_impl::duc_get, this, _1, _2),
+ boost::bind(&usrp2_impl::duc_set, this, _1, _2)
+ );
+
+ //initial config and update
+ _duc_interp = 16;
+ _duc_freq = 0;
+ update_duc_config();
+}
+
+void usrp2_impl::update_duc_config(void){
+ // Calculate CIC interpolation (i.e., without halfband interpolators)
+ size_t tmp_interp = _duc_interp;
+ while(tmp_interp > 128) tmp_interp /= 2;
+
+ // Calculate closest multiplier constant to reverse gain absent scale multipliers
+ size_t interp_cubed = pow(tmp_interp, 3);
+ size_t scale = rint((4096*pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed));
+
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO);
+ out_data.data.duc_args.freq_word = htonl(
+ calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq())
+ );
+ out_data.data.duc_args.interp = htonl(_duc_interp);
+ out_data.data.duc_args.scale_iq = htonl(scale);
+
+ //send and recv
+ usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE);
+}
+
+/***********************************************************************
+ * DUC Properties
+ **********************************************************************/
+void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
+ //handle the case where the key is an expected dsp property
+ if (key.type() == typeid(dsp_prop_t)){
+ switch(wax::cast<dsp_prop_t>(key)){
+ case DSP_PROP_NAME:
+ val = std::string("usrp2 duc0");
+ return;
+
+ case DSP_PROP_OTHERS:{
+ prop_names_t others = boost::assign::list_of
+ ("rate")
+ ("interp")
+ ("interp_rates")
+ ("freq")
+ ;
+ val = others;
+ }
+ return;
+ }
+ }
+
+ //handle string-based properties specific to this dsp
+ std::string key_name = wax::cast<std::string>(key);
+ if (key_name == "rate"){
+ val = get_master_clock_freq();
+ return;
+ }
+ else if (key_name == "interp"){
+ val = _duc_interp;
+ return;
+ }
+ else if (key_name == "interp_rates"){
+ val = _allowed_decim_and_interp_rates;
+ return;
+ }
+ else if (key_name == "freq"){
+ val = _duc_freq;
+ return;
+ }
+
+ throw std::invalid_argument(str(
+ boost::format("error getting: unknown key with name %s") % key_name
+ ));
+}
+
+void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){
+ //handle string-based properties specific to this dsp
+ std::string key_name = wax::cast<std::string>(key);
+ if (key_name == "interp"){
+ size_t new_interp = wax::cast<size_t>(val);
+ ASSERT_THROW(std::has(
+ _allowed_decim_and_interp_rates.begin(),
+ _allowed_decim_and_interp_rates.end(),
+ new_interp
+ ));
+ _duc_interp = new_interp; //shadow
+ update_duc_config();
+ return;
+ }
+ else if (key_name == "freq"){
+ freq_t new_freq = wax::cast<freq_t>(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
+ update_duc_config();
+ return;
+ }
+
+ throw std::invalid_argument(str(
+ boost::format("error setting: unknown key with name %s") % key_name
+ ));
+}
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
new file mode 100644
index 000000000..3def8ddaa
--- /dev/null
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -0,0 +1,190 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_USRP2_FW_COMMON_H
+#define INCLUDED_USRP2_FW_COMMON_H
+
+/*!
+ * Structs and constants for usrp2 communication.
+ * This header is shared by the firmware and host code.
+ * Therefore, this header may only contain valid C code.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// udp ports for the usrp2 communication
+// Dynamic and/or private ports: 49152-65535
+#define USRP2_UDP_CTRL_PORT 49152
+#define USRP2_UDP_DATA_PORT 49153
+
+typedef enum{
+ USRP2_CTRL_ID_HUH_WHAT,
+ //USRP2_CTRL_ID_FOR_SURE, //TODO error condition enums
+ //USRP2_CTRL_ID_SUX_MAN,
+
+ USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO,
+ USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE,
+ USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO,
+
+ USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO,
+ USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE,
+ USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO,
+
+ USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO,
+ USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE,
+
+ USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO,
+ USRP2_CTRL_ID_GOT_THE_NEW_CLOCK_CONFIG_DUDE,
+
+ USRP2_CTRL_ID_USE_THESE_GPIO_DDR_SETTINGS_BRO,
+ USRP2_CTRL_ID_GOT_THE_GPIO_DDR_SETTINGS_DUDE,
+
+ USRP2_CTRL_ID_SET_YOUR_GPIO_PIN_OUTS_BRO,
+ USRP2_CTRL_ID_I_SET_THE_GPIO_PIN_OUTS_DUDE,
+
+ USRP2_CTRL_ID_GIVE_ME_YOUR_GPIO_PIN_VALS_BRO,
+ USRP2_CTRL_ID_HERE_IS_YOUR_GPIO_PIN_VALS_DUDE,
+
+ USRP2_CTRL_ID_USE_THESE_ATR_SETTINGS_BRO,
+ USRP2_CTRL_ID_GOT_THE_ATR_SETTINGS_DUDE,
+
+ USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO,
+ USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE,
+
+ USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO,
+ USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE,
+
+ USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO,
+ USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE,
+
+ USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO,
+ USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE,
+
+ USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO,
+ USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE,
+
+ USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO,
+ USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE,
+
+ USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO,
+ USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE,
+
+ USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO,
+ USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE,
+
+ USRP2_CTRL_ID_PEACE_OUT
+
+} usrp2_ctrl_id_t;
+
+typedef enum{
+ USRP2_PPS_SOURCE_SMA,
+ USRP2_PPS_SOURCE_MIMO
+} usrp2_pps_source_t;
+
+typedef enum{
+ USRP2_PPS_POLARITY_POS,
+ USRP2_PPS_POLARITY_NEG
+} usrp2_pps_polarity_t;
+
+typedef enum{
+ USRP2_REF_SOURCE_INT,
+ USRP2_REF_SOURCE_SMA,
+ USRP2_REF_SOURCE_MIMO
+} usrp2_ref_source_t;
+
+typedef enum{
+ USRP2_DIR_RX,
+ USRP2_DIR_TX
+} usrp2_dir_which_t;
+
+typedef enum{
+ USRP2_CLK_EDGE_RISE,
+ USRP2_CLK_EDGE_FALL
+} usrp2_clk_edge_t;
+
+typedef struct{
+ uint32_t id;
+ uint32_t seq;
+ union{
+ uint32_t ip_addr;
+ uint8_t mac_addr[6];
+ struct {
+ uint16_t rx_id;
+ uint16_t tx_id;
+ } dboard_ids;
+ struct {
+ uint8_t pps_source;
+ uint8_t pps_polarity;
+ uint8_t ref_source;
+ uint8_t _pad;
+ } clock_config;
+ struct {
+ uint8_t bank;
+ uint8_t _pad[3];
+ uint16_t value;
+ uint16_t mask;
+ } gpio_config;
+ struct {
+ uint8_t bank;
+ uint8_t _pad[3];
+ uint16_t tx_value;
+ uint16_t rx_value;
+ uint16_t mask;
+ } atr_config;
+ struct {
+ uint8_t dev;
+ uint8_t latch;
+ uint8_t push;
+ uint8_t readback;
+ uint8_t bytes;
+ uint8_t data[sizeof(uint32_t)];
+ } spi_args;
+ struct {
+ uint8_t addr;
+ uint8_t bytes;
+ uint8_t data[sizeof(uint32_t)];
+ } i2c_args;
+ struct {
+ uint8_t dir;
+ uint8_t which;
+ uint8_t _pad[2];
+ uint32_t value;
+ } aux_args;
+ struct {
+ uint32_t freq_word;
+ uint32_t decim;
+ } ddc_args;
+ struct {
+ uint8_t enabled;
+ uint8_t _pad[3];
+ uint32_t secs;
+ uint32_t ticks;
+ } streaming;
+ struct {
+ uint32_t freq_word;
+ uint32_t interp;
+ uint32_t scale_iq;
+ } duc_args;
+ } data;
+} usrp2_ctrl_data_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_USRP2_FW_COMMON_H */
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
new file mode 100644
index 000000000..2e4a0715f
--- /dev/null
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -0,0 +1,196 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils.hpp>
+#include "usrp2_impl.hpp"
+
+using namespace uhd;
+
+/***********************************************************************
+ * Helper Methods
+ **********************************************************************/
+void usrp2_impl::init_clock_config(void){
+ //init the pps source clock config
+ _pps_source_dict["sma"] = USRP2_PPS_SOURCE_SMA;
+ _pps_source_dict["mimo"] = USRP2_PPS_SOURCE_MIMO;
+ _pps_source = "sma";
+
+ //init the pps polarity clock config
+ _pps_polarity_dict["pos"] = USRP2_PPS_POLARITY_POS;
+ _pps_polarity_dict["neg"] = USRP2_PPS_POLARITY_NEG;
+ _pps_polarity = "neg";
+
+ //init the ref source clock config
+ _ref_source_dict["int"] = USRP2_REF_SOURCE_INT;
+ _ref_source_dict["sma"] = USRP2_REF_SOURCE_SMA;
+ _ref_source_dict["mimo"] = USRP2_REF_SOURCE_MIMO;
+ _ref_source = "int";
+
+ //update the clock config (sends a control packet)
+ update_clock_config();
+}
+
+void usrp2_impl::update_clock_config(void){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO);
+ out_data.data.clock_config.pps_source = _pps_source_dict [_pps_source];
+ out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_pps_polarity];
+ out_data.data.clock_config.ref_source = _ref_source_dict [_ref_source];
+
+ //send and recv
+ usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THE_NEW_CLOCK_CONFIG_DUDE);
+}
+
+/***********************************************************************
+ * MBoard Get Properties
+ **********************************************************************/
+void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(wax::cast<mboard_prop_t>(key)){
+ case MBOARD_PROP_NAME:
+ val = std::string("usrp2 mboard");
+ return;
+
+ case MBOARD_PROP_OTHERS:
+ val = prop_names_t(); //empty other props
+ return;
+
+ case MBOARD_PROP_RX_DBOARD:
+ val = _rx_dboards[name].get_link();
+ return;
+
+ case MBOARD_PROP_RX_DBOARD_NAMES:
+ val = prop_names_t(_rx_dboards.get_keys());
+ return;
+
+ case MBOARD_PROP_TX_DBOARD:
+ val = _tx_dboards[name].get_link();
+ return;
+
+ case MBOARD_PROP_TX_DBOARD_NAMES:
+ val = prop_names_t(_tx_dboards.get_keys());
+ return;
+
+ case MBOARD_PROP_MTU:
+ // FIXME we dont know the real MTU...
+ // give them something to fragment about
+ val = size_t(1500);
+ return;
+
+ case MBOARD_PROP_CLOCK_RATE:
+ val = freq_t(get_master_clock_freq());
+ return;
+
+ case MBOARD_PROP_RX_DSP:
+ val = _rx_dsps[name].get_link();
+ return;
+
+ case MBOARD_PROP_RX_DSP_NAMES:
+ val = prop_names_t(_rx_dsps.get_keys());
+ return;
+
+ case MBOARD_PROP_TX_DSP:
+ val = _tx_dsps[name].get_link();
+ return;
+
+ case MBOARD_PROP_TX_DSP_NAMES:
+ val = prop_names_t(_tx_dsps.get_keys());
+ return;
+
+ case MBOARD_PROP_PPS_SOURCE:
+ val = _pps_source;
+ return;
+
+ case MBOARD_PROP_PPS_SOURCE_NAMES:
+ val = prop_names_t(_pps_source_dict.get_keys());
+ return;
+
+ case MBOARD_PROP_PPS_POLARITY:
+ val = _pps_polarity;
+ return;
+
+ case MBOARD_PROP_REF_SOURCE:
+ val = _ref_source;
+ return;
+
+ case MBOARD_PROP_REF_SOURCE_NAMES:
+ val = prop_names_t(_ref_source_dict.get_keys());
+ return;
+
+ case MBOARD_PROP_TIME_NOW:
+ case MBOARD_PROP_TIME_NEXT_PPS:
+ throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard");
+
+ }
+}
+
+/***********************************************************************
+ * MBoard Set Properties
+ **********************************************************************/
+void usrp2_impl::set(const wax::obj &key, const wax::obj &val){
+ //handle the get request conditioned on the key
+ switch(wax::cast<mboard_prop_t>(key)){
+
+ case MBOARD_PROP_PPS_SOURCE:{
+ std::string name = wax::cast<std::string>(val);
+ ASSERT_THROW(_pps_source_dict.has_key(name));
+ _pps_source = name; //shadow
+ update_clock_config();
+ }
+ return;
+
+ case MBOARD_PROP_PPS_POLARITY:{
+ std::string name = wax::cast<std::string>(val);
+ ASSERT_THROW(_pps_polarity_dict.has_key(name));
+ _pps_polarity = name; //shadow
+ update_clock_config();
+ }
+ return;
+
+ case MBOARD_PROP_REF_SOURCE:{
+ std::string name = wax::cast<std::string>(val);
+ ASSERT_THROW(_ref_source_dict.has_key(name));
+ _ref_source = name; //shadow
+ update_clock_config();
+ }
+ return;
+
+ case MBOARD_PROP_NAME:
+ case MBOARD_PROP_OTHERS:
+ case MBOARD_PROP_MTU:
+ case MBOARD_PROP_CLOCK_RATE:
+ case MBOARD_PROP_RX_DSP:
+ case MBOARD_PROP_RX_DSP_NAMES:
+ case MBOARD_PROP_TX_DSP:
+ case MBOARD_PROP_TX_DSP_NAMES:
+ case MBOARD_PROP_RX_DBOARD:
+ case MBOARD_PROP_RX_DBOARD_NAMES:
+ case MBOARD_PROP_TX_DBOARD:
+ case MBOARD_PROP_TX_DBOARD_NAMES:
+ case MBOARD_PROP_PPS_SOURCE_NAMES:
+ case MBOARD_PROP_REF_SOURCE_NAMES:
+ case MBOARD_PROP_TIME_NOW:
+ case MBOARD_PROP_TIME_NEXT_PPS:
+ throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard");
+
+ }
+}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
new file mode 100644
index 000000000..dbf740f2b
--- /dev/null
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/format.hpp>
+#include <boost/bind.hpp>
+#include <uhd/utils.hpp>
+#include <iostream>
+#include "usrp2_impl.hpp"
+
+using namespace uhd;
+
+/***********************************************************************
+ * Structors
+ **********************************************************************/
+usrp2_impl::usrp2_impl(
+ uhd::transport::udp::sptr ctrl_transport,
+ uhd::transport::udp::sptr data_transport
+){
+ _ctrl_transport = ctrl_transport;
+ _data_transport = data_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();
+ for (size_t i = 4; i <= 128; i+=1){
+ _allowed_decim_and_interp_rates.push_back(i);
+ }
+ for (size_t i = 130; i <= 256; i+=2){
+ _allowed_decim_and_interp_rates.push_back(i);
+ }
+ for (size_t i = 260; i <= 512; i+=4){
+ _allowed_decim_and_interp_rates.push_back(i);
+ }
+
+ //init the tx and rx dboards
+ dboard_init();
+
+ //init the ddc
+ init_ddc_config();
+
+ //init the duc
+ init_duc_config();
+
+ //initialize the clock configuration
+ init_clock_config();
+}
+
+usrp2_impl::~usrp2_impl(void){
+ /* NOP */
+}
+
+/***********************************************************************
+ * Misc Access Methods
+ **********************************************************************/
+double usrp2_impl::get_master_clock_freq(void){
+ return 100e6;
+}
+
+/***********************************************************************
+ * 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 and recieve until the time is up
+ size_t num_timeouts = 0;
+ while(true){
+ uhd::shared_iovec iov = _ctrl_transport->recv();
+ if (iov.len < sizeof(usrp2_ctrl_data_t)){
+ //sleep a little so we dont burn cpu
+ if (num_timeouts++ > 50) break;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1));
+ }else{
+ //handle the received data
+ usrp2_ctrl_data_t in_data = *reinterpret_cast<const usrp2_ctrl_data_t *>(iov.base);
+ if (ntohl(in_data.seq) == _ctrl_seq_num){
+ return in_data;
+ }
+ //didnt get seq, continue on...
+ }
+ }
+ throw std::runtime_error("usrp2 no control response");
+}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
new file mode 100644
index 000000000..be457a91c
--- /dev/null
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -0,0 +1,160 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/dict.hpp>
+#include <uhd/props.hpp>
+#include <uhd/time_spec.hpp>
+#include <boost/thread.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <uhd/transport/udp.hpp>
+#include <uhd/usrp/dboard_manager.hpp>
+#include "fw_common.h"
+
+#ifndef INCLUDED_USRP2_IMPL_HPP
+#define INCLUDED_USRP2_IMPL_HPP
+
+/*!
+ * Simple wax obj proxy class:
+ * Provides a wax obj interface for a set and a get function.
+ * This allows us to create nested properties structures
+ * while maintaining flattened code within the implementation.
+ */
+class wax_obj_proxy : public wax::obj{
+public:
+ typedef boost::function<void(const wax::obj &, wax::obj &)> get_t;
+ typedef boost::function<void(const wax::obj &, const wax::obj &)> set_t;
+
+ wax_obj_proxy(void){
+ /* NOP */
+ }
+
+ wax_obj_proxy(const get_t &get, const set_t &set){
+ _get = get;
+ _set = set;
+ };
+
+ ~wax_obj_proxy(void){
+ /* NOP */
+ }
+
+ void get(const wax::obj &key, wax::obj &val){
+ return _get(key, val);
+ }
+
+ void set(const wax::obj &key, const wax::obj &val){
+ return _set(key, val);
+ }
+
+private:
+ get_t _get;
+ set_t _set;
+};
+
+/*!
+ * USRP2 implementation guts:
+ * The implementation details are encapsulated here.
+ * Handles properties on the mboard, dboard, dsps...
+ */
+class usrp2_impl : boost::noncopyable, public wax::obj{
+public:
+ typedef boost::shared_ptr<usrp2_impl> sptr;
+
+ /*!
+ * Create a new usrp2 impl base.
+ * \param ctrl_transport the udp transport for control
+ * \param data_transport the udp transport for data
+ */
+ usrp2_impl(
+ uhd::transport::udp::sptr ctrl_transport,
+ uhd::transport::udp::sptr data_transport
+ );
+
+ ~usrp2_impl(void);
+
+ //properties interface
+ void get(const wax::obj &, wax::obj &);
+ void set(const wax::obj &, const wax::obj &);
+
+ //performs a control transaction
+ usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &);
+
+ //misc access methods
+ double get_master_clock_freq(void);
+
+private:
+ //udp transports for control and data
+ uhd::transport::udp::sptr _ctrl_transport;
+ uhd::transport::udp::sptr _data_transport;
+
+ //private vars for dealing with send/recv control
+ uint32_t _ctrl_seq_num;
+ boost::mutex _ctrl_mutex;
+
+ //methods and shadows for clock configuration
+ std::string _pps_source, _pps_polarity, _ref_source;
+ void init_clock_config(void);
+ void update_clock_config(void);
+
+ //mappings from clock config strings to over the wire enums
+ uhd::dict<std::string, usrp2_pps_source_t> _pps_source_dict;
+ uhd::dict<std::string, usrp2_pps_polarity_t> _pps_polarity_dict;
+ uhd::dict<std::string, usrp2_ref_source_t> _ref_source_dict;
+
+ //rx and tx dboard methods and objects
+ uhd::usrp::dboard_manager::sptr _dboard_manager;
+ void dboard_init(void);
+
+ //properties interface for rx dboard
+ void rx_dboard_get(const wax::obj &, wax::obj &);
+ void rx_dboard_set(const wax::obj &, const wax::obj &);
+ uhd::dict<std::string, wax_obj_proxy> _rx_dboards;
+
+ //properties interface for tx dboard
+ void tx_dboard_get(const wax::obj &, wax::obj &);
+ void tx_dboard_set(const wax::obj &, const wax::obj &);
+ uhd::dict<std::string, wax_obj_proxy> _tx_dboards;
+
+ //methods and shadows for the ddc dsp
+ std::vector<size_t> _allowed_decim_and_interp_rates;
+ size_t _ddc_decim;
+ uhd::freq_t _ddc_freq;
+ bool _ddc_enabled;
+ uhd::time_spec_t _ddc_stream_at;
+ void init_ddc_config(void);
+ void update_ddc_config(void);
+ void update_ddc_enabled(void);
+
+ //methods and shadows for the duc dsp
+ size_t _duc_interp;
+ uhd::freq_t _duc_freq;
+ void init_duc_config(void);
+ void update_duc_config(void);
+
+ //properties interface for ddc
+ void ddc_get(const wax::obj &, wax::obj &);
+ void ddc_set(const wax::obj &, const wax::obj &);
+ uhd::dict<std::string, wax_obj_proxy> _rx_dsps;
+
+ //properties interface for duc
+ void duc_get(const wax::obj &, wax::obj &);
+ void duc_set(const wax::obj &, const wax::obj &);
+ uhd::dict<std::string, wax_obj_proxy> _tx_dsps;
+
+};
+
+#endif /* INCLUDED_USRP2_IMPL_HPP */