aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/x300
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/x300')
-rw-r--r--host/lib/usrp/x300/CMakeLists.txt2
-rw-r--r--host/lib/usrp/x300/x300_dboard_iface.cpp105
-rw-r--r--host/lib/usrp/x300/x300_fw_common.h2
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp178
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp25
-rw-r--r--host/lib/usrp/x300/x300_io_impl.cpp18
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp6
7 files changed, 189 insertions, 147 deletions
diff --git a/host/lib/usrp/x300/CMakeLists.txt b/host/lib/usrp/x300/CMakeLists.txt
index 3d6348eec..f8b129f89 100644
--- a/host/lib/usrp/x300/CMakeLists.txt
+++ b/host/lib/usrp/x300/CMakeLists.txt
@@ -22,8 +22,6 @@
########################################################################
# Conditionally configure the X300 support
########################################################################
-LIBUHD_REGISTER_COMPONENT("X300" ENABLE_X300 ON "ENABLE_LIBUHD" OFF OFF)
-
IF(ENABLE_X300)
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/x300_impl.cpp
diff --git a/host/lib/usrp/x300/x300_dboard_iface.cpp b/host/lib/usrp/x300/x300_dboard_iface.cpp
index 502630109..ef55368c8 100644
--- a/host/lib/usrp/x300/x300_dboard_iface.cpp
+++ b/host/lib/usrp/x300/x300_dboard_iface.cpp
@@ -45,17 +45,19 @@ public:
void write_aux_dac(unit_t, aux_dac_t, double);
double read_aux_adc(unit_t, aux_adc_t);
- void _set_pin_ctrl(unit_t, boost::uint16_t);
- void _set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
- void _set_gpio_ddr(unit_t, boost::uint16_t);
- void _set_gpio_out(unit_t, boost::uint16_t);
+ void set_pin_ctrl(unit_t unit, boost::uint32_t value, boost::uint32_t mask = 0xffffffff);
+ boost::uint32_t get_pin_ctrl(unit_t unit);
+ void set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint32_t value, boost::uint32_t mask = 0xffffffff);
+ boost::uint32_t get_atr_reg(unit_t unit, atr_reg_t reg);
+ void set_gpio_ddr(unit_t unit, boost::uint32_t value, boost::uint32_t mask = 0xffffffff);
+ boost::uint32_t get_gpio_ddr(unit_t unit);
+ void set_gpio_out(unit_t unit, boost::uint32_t value, boost::uint32_t mask = 0xffffffff);
+ boost::uint32_t get_gpio_out(unit_t unit);
+ boost::uint32_t read_gpio(unit_t unit);
void set_command_time(const uhd::time_spec_t& t);
uhd::time_spec_t get_command_time(void);
- void set_gpio_debug(unit_t, int);
- boost::uint16_t read_gpio(unit_t);
-
void write_i2c(boost::uint16_t, const byte_vector_t &);
byte_vector_t read_i2c(boost::uint16_t, size_t);
@@ -116,27 +118,6 @@ x300_dboard_iface::x300_dboard_iface(const x300_dboard_iface_config_t &config):
this->set_clock_enabled(UNIT_RX, false);
this->set_clock_enabled(UNIT_TX, false);
-
-
- //some test code
- /*
- {
-
- this->write_aux_dac(UNIT_TX, AUX_DAC_A, .1);
- this->write_aux_dac(UNIT_TX, AUX_DAC_B, 1);
- this->write_aux_dac(UNIT_RX, AUX_DAC_A, 2);
- this->write_aux_dac(UNIT_RX, AUX_DAC_B, 3);
- while (1)
- {
- UHD_VAR(this->read_aux_adc(UNIT_TX, AUX_ADC_A));
- UHD_VAR(this->read_aux_adc(UNIT_TX, AUX_ADC_B));
- UHD_VAR(this->read_aux_adc(UNIT_RX, AUX_ADC_A));
- UHD_VAR(this->read_aux_adc(UNIT_RX, AUX_ADC_B));
- sleep(1);
- }
- }
- */
-
}
x300_dboard_iface::~x300_dboard_iface(void)
@@ -153,6 +134,8 @@ x300_dboard_iface::~x300_dboard_iface(void)
**********************************************************************/
void x300_dboard_iface::set_clock_rate(unit_t unit, double rate)
{
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
+
// Just return if the requested rate is already set
if (std::fabs(_clock_rates[unit] - rate) < std::numeric_limits<double>::epsilon())
return;
@@ -165,17 +148,21 @@ void x300_dboard_iface::set_clock_rate(unit_t unit, double rate)
case UNIT_TX:
_config.clock->set_dboard_rate(_config.which_tx_clk, rate);
break;
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
}
_clock_rates[unit] = rate; //set to shadow
}
double x300_dboard_iface::get_clock_rate(unit_t unit)
{
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
return _clock_rates[unit]; //get from shadow
}
std::vector<double> x300_dboard_iface::get_clock_rates(unit_t unit)
{
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
switch(unit)
{
case UNIT_RX:
@@ -189,6 +176,7 @@ std::vector<double> x300_dboard_iface::get_clock_rates(unit_t unit)
void x300_dboard_iface::set_clock_enabled(unit_t unit, bool enb)
{
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
switch(unit)
{
case UNIT_RX:
@@ -200,57 +188,74 @@ void x300_dboard_iface::set_clock_enabled(unit_t unit, bool enb)
}
}
-double x300_dboard_iface::get_codec_rate(unit_t)
+double x300_dboard_iface::get_codec_rate(unit_t unit)
{
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
return _config.clock->get_master_clock_rate();
}
/***********************************************************************
* GPIO
**********************************************************************/
-void x300_dboard_iface::_set_pin_ctrl(unit_t unit, boost::uint16_t value)
+void x300_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint32_t value, boost::uint32_t mask)
{
- return _config.gpio->set_pin_ctrl(unit, value);
+ _config.gpio->set_pin_ctrl(unit, value, mask);
}
-void x300_dboard_iface::_set_gpio_ddr(unit_t unit, boost::uint16_t value)
+boost::uint32_t x300_dboard_iface::get_pin_ctrl(unit_t unit)
{
- return _config.gpio->set_gpio_ddr(unit, value);
+ return _config.gpio->get_pin_ctrl(unit);
}
-void x300_dboard_iface::_set_gpio_out(unit_t unit, boost::uint16_t value)
+void x300_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint32_t value, boost::uint32_t mask)
{
- return _config.gpio->set_gpio_out(unit, value);
+ _config.gpio->set_atr_reg(unit, reg, value, mask);
}
-boost::uint16_t x300_dboard_iface::read_gpio(unit_t unit)
+boost::uint32_t x300_dboard_iface::get_atr_reg(unit_t unit, atr_reg_t reg)
{
- return _config.gpio->read_gpio(unit);
+ return _config.gpio->get_atr_reg(unit, reg);
}
-void x300_dboard_iface::_set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value)
+void x300_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint32_t value, boost::uint32_t mask)
{
- return _config.gpio->set_atr_reg(unit, atr, value);
+ _config.gpio->set_gpio_ddr(unit, value, mask);
}
-void x300_dboard_iface::set_gpio_debug(unit_t, int)
+boost::uint32_t x300_dboard_iface::get_gpio_ddr(unit_t unit)
{
- throw uhd::not_implemented_error("no set_gpio_debug implemented");
+ return _config.gpio->get_gpio_ddr(unit);
+}
+
+void x300_dboard_iface::set_gpio_out(unit_t unit, boost::uint32_t value, boost::uint32_t mask)
+{
+ _config.gpio->set_gpio_out(unit, value, mask);
+}
+
+boost::uint32_t x300_dboard_iface::get_gpio_out(unit_t unit)
+{
+ return _config.gpio->get_gpio_out(unit);
+}
+
+boost::uint32_t x300_dboard_iface::read_gpio(unit_t unit)
+{
+ return _config.gpio->read_gpio(unit);
}
/***********************************************************************
* SPI
**********************************************************************/
-#define toslaveno(unit) \
- (((unit) == dboard_iface::UNIT_TX)? _config.tx_spi_slaveno : _config.rx_spi_slaveno)
-
void x300_dboard_iface::write_spi(
unit_t unit,
const spi_config_t &config,
boost::uint32_t data,
size_t num_bits
){
- _config.spi->write_spi(toslaveno(unit), config, data, num_bits);
+ boost::uint32_t slave = 0;
+ if (unit == UNIT_TX) slave |= _config.tx_spi_slaveno;
+ if (unit == UNIT_RX) slave |= _config.rx_spi_slaveno;
+
+ _config.spi->write_spi(int(slave), config, data, num_bits);
}
boost::uint32_t x300_dboard_iface::read_write_spi(
@@ -259,7 +264,10 @@ boost::uint32_t x300_dboard_iface::read_write_spi(
boost::uint32_t data,
size_t num_bits
){
- return _config.spi->read_spi(toslaveno(unit), config, data, num_bits);
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
+ return _config.spi->read_spi(
+ (unit==dboard_iface::UNIT_TX)?_config.tx_spi_slaveno:_config.rx_spi_slaveno,
+ config, data, num_bits);
}
/***********************************************************************
@@ -284,6 +292,7 @@ void x300_dboard_iface::_write_aux_dac(unit_t unit)
(UNIT_RX, DB_RX_LSDAC_SEN)
(UNIT_TX, DB_TX_LSDAC_SEN)
;
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
_config.spi->write_spi(
unit_to_spi_dac[unit], spi_config_t::EDGE_FALL,
_dac_regs[unit].get_reg(), 24
@@ -292,6 +301,8 @@ void x300_dboard_iface::_write_aux_dac(unit_t unit)
void x300_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, double value)
{
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
+
_dac_regs[unit].data = boost::math::iround(4095*value/3.3);
_dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N;
@@ -321,6 +332,8 @@ double x300_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which)
(UNIT_TX, DB_TX_LSADC_SEN)
;
+ if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported.");
+
//setup spi config args
spi_config_t config;
config.mosi_edge = spi_config_t::EDGE_FALL;
diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h
index 549fc9dfa..6039ee376 100644
--- a/host/lib/usrp/x300/x300_fw_common.h
+++ b/host/lib/usrp/x300/x300_fw_common.h
@@ -33,7 +33,7 @@ extern "C" {
#define X300_REVISION_MIN 2
#define X300_FW_COMPAT_MAJOR 4
#define X300_FW_COMPAT_MINOR 0
-#define X300_FPGA_COMPAT_MAJOR 19
+#define X300_FPGA_COMPAT_MAJOR 20
//shared memory sections - in between the stack and the program space
#define X300_FW_SHMEM_BASE 0x6000
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index c13c2ac07..80953ac20 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -47,23 +47,38 @@ using namespace uhd;
using namespace uhd::usrp;
using namespace uhd::transport;
using namespace uhd::niusrprio;
+using namespace uhd::usrp::gpio_atr;
using namespace uhd::usrp::x300;
namespace asio = boost::asio;
-/***********************************************************************
- * Discovery over the udp and pcie transport
- **********************************************************************/
+static bool has_dram_buff(wb_iface::sptr zpu_ctrl) {
+ bool dramR0 = dma_fifo_core_3000::check(
+ zpu_ctrl, SR_ADDR(SET0_BASE, ZPU_SR_DRAM_FIFO0), SR_ADDR(SET0_BASE, ZPU_RB_DRAM_FIFO0));
+ bool dramR1 = dma_fifo_core_3000::check(
+ zpu_ctrl, SR_ADDR(SET0_BASE, ZPU_SR_DRAM_FIFO1), SR_ADDR(SET0_BASE, ZPU_RB_DRAM_FIFO1));
+ return (dramR0 and dramR1);
+}
+
static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) {
- //1G = {0:1G, 1:1G} w/ DRAM, HG = {0:1G, 1:10G} w/ DRAM, XG = {0:10G, 1:10G} w/ DRAM
- //HGS = {0:1G, 1:10G} w/ SRAM, XGS = {0:10G, 1:10G} w/ SRAM
+ //Possible options:
+ //1G = {0:1G, 1:1G} w/ DRAM, HG = {0:1G, 1:10G} w/ DRAM, XG = {0:10G, 1:10G} w/ DRAM
+ //1GS = {0:1G, 1:1G} w/ SRAM, HGS = {0:1G, 1:10G} w/ SRAM, XGS = {0:10G, 1:10G} w/ SRAM
- //In the default configuration, UHD does not support the HG and XG images so
- //they are never autodetected.
+ std::string option;
bool eth0XG = (zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_ETH_TYPE0)) == 0x1);
bool eth1XG = (zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_ETH_TYPE1)) == 0x1);
- return (eth0XG && eth1XG) ? "XGS" : (eth1XG ? "HGS" : "1G");
+ option = (eth0XG && eth1XG) ? "XG" : (eth1XG ? "HG" : "1G");
+
+ if (not has_dram_buff(zpu_ctrl)) {
+ option += "S";
+ }
+ return option;
}
+/***********************************************************************
+ * Discovery over the udp and pcie transport
+ **********************************************************************/
+
//@TODO: Refactor the find functions to collapse common code for ethernet and PCIe
static device_addrs_t x300_find_with_addr(const device_addr_t &hint)
{
@@ -348,6 +363,8 @@ static void x300_load_fw(wb_iface::sptr fw_reg_ctrl, const std::string &file_nam
if ((i & 0x1fff) == 0) UHD_MSG(status) << "." << std::flush;
}
+ //Wait for fimrware to reboot. 3s is an upper bound
+ boost::this_thread::sleep(boost::posix_time::milliseconds(3000));
UHD_MSG(status) << " done!" << std::endl;
}
@@ -561,7 +578,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
const mboard_eeprom_t mb_eeprom(*eeprom16, "X300");
_tree->create<mboard_eeprom_t>(mb_path / "eeprom")
.set(mb_eeprom)
- .subscribe(boost::bind(&x300_impl::set_mb_eeprom, this, mb.zpu_i2c, _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_mb_eeprom, this, mb.zpu_i2c, _1));
bool recover_mb_eeprom = dev_addr.has_key("recover_mb_eeprom");
if (recover_mb_eeprom) {
@@ -684,7 +701,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
// create clock properties
////////////////////////////////////////////////////////////////////
_tree->create<double>(mb_path / "tick_rate")
- .publish(boost::bind(&x300_clock_ctrl::get_master_clock_rate, mb.clock));
+ .set_publisher(boost::bind(&x300_clock_ctrl::get_master_clock_rate, mb.clock));
_tree->create<time_spec_t>(mb_path / "time" / "cmd");
@@ -713,7 +730,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
BOOST_FOREACH(const std::string &name, mb.gps->get_sensors())
{
_tree->create<sensor_value_t>(mb_path / "sensors" / name)
- .publish(boost::bind(&gps_ctrl::get_sensor, mb.gps, name));
+ .set_publisher(boost::bind(&gps_ctrl::get_sensor, mb.gps, name));
}
}
else
@@ -730,6 +747,36 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
}
////////////////////////////////////////////////////////////////////
+ // DRAM FIFO initialization
+ ////////////////////////////////////////////////////////////////////
+ mb.has_dram_buff = has_dram_buff(mb.zpu_ctrl);
+ if (mb.has_dram_buff) {
+ for (size_t i = 0; i < mboard_members_t::NUM_RADIOS; i++) {
+ static const size_t NUM_REGS = 8;
+ mb.dram_buff_ctrl[i] = dma_fifo_core_3000::make(
+ mb.zpu_ctrl,
+ SR_ADDR(SET0_BASE, ZPU_SR_DRAM_FIFO0+(i*NUM_REGS)),
+ SR_ADDR(SET0_BASE, ZPU_RB_DRAM_FIFO0+i));
+ mb.dram_buff_ctrl[i]->resize(X300_DRAM_FIFO_SIZE * i, X300_DRAM_FIFO_SIZE);
+
+ if (mb.dram_buff_ctrl[i]->ext_bist_supported()) {
+ UHD_MSG(status) << boost::format("Running BIST for DRAM FIFO %d... ") % i;
+ boost::uint32_t bisterr = mb.dram_buff_ctrl[i]->run_bist();
+ if (bisterr != 0) {
+ throw uhd::runtime_error(str(boost::format("DRAM FIFO BIST failed! (code: %d)\n") % bisterr));
+ } else {
+ double throughput = mb.dram_buff_ctrl[i]->get_bist_throughput(X300_BUS_CLOCK_RATE);
+ UHD_MSG(status) << (boost::format("pass (Throughput: %.1fMB/s)") % (throughput/1e6)) << std::endl;
+ }
+ } else {
+ if (mb.dram_buff_ctrl[i]->run_bist() != 0) {
+ throw uhd::runtime_error(str(boost::format("DRAM FIFO %d BIST failed!\n") % i));
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////
// setup radios
////////////////////////////////////////////////////////////////////
this->setup_radio(mb_i, "A", dev_addr);
@@ -750,40 +797,40 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
////////////////////////////////////////////////////////////////////
// front panel gpio
////////////////////////////////////////////////////////////////////
- mb.fp_gpio = gpio_core_200::make(mb.radio_perifs[0].ctrl, radio::sr_addr(radio::FP_GPIO), radio::RB32_FP_GPIO);
+ mb.fp_gpio = gpio_atr_3000::make(mb.radio_perifs[0].ctrl, radio::sr_addr(radio::FP_GPIO), radio::RB32_FP_GPIO);
BOOST_FOREACH(const gpio_attr_map_t::value_type attr, gpio_attr_map)
{
_tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / attr.second)
.set(0)
- .subscribe(boost::bind(&x300_impl::set_fp_gpio, this, mb.fp_gpio, attr.first, _1));
+ .add_coerced_subscriber(boost::bind(&gpio_atr_3000::set_gpio_attr, mb.fp_gpio, attr.first, _1));
}
_tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / "READBACK")
- .publish(boost::bind(&x300_impl::get_fp_gpio, this, mb.fp_gpio));
+ .set_publisher(boost::bind(&gpio_atr_3000::read_gpio, mb.fp_gpio));
////////////////////////////////////////////////////////////////////
// register the time keepers - only one can be the highlander
////////////////////////////////////////////////////////////////////
_tree->create<time_spec_t>(mb_path / "time" / "now")
- .publish(boost::bind(&time_core_3000::get_time_now, mb.radio_perifs[0].time64))
- .subscribe(boost::bind(&x300_impl::sync_times, this, mb, _1))
+ .set_publisher(boost::bind(&time_core_3000::get_time_now, mb.radio_perifs[0].time64))
+ .add_coerced_subscriber(boost::bind(&x300_impl::sync_times, this, mb, _1))
.set(0.0);
_tree->create<time_spec_t>(mb_path / "time" / "pps")
- .publish(boost::bind(&time_core_3000::get_time_last_pps, mb.radio_perifs[0].time64))
- .subscribe(boost::bind(&time_core_3000::set_time_next_pps, mb.radio_perifs[0].time64, _1))
- .subscribe(boost::bind(&time_core_3000::set_time_next_pps, mb.radio_perifs[1].time64, _1));
+ .set_publisher(boost::bind(&time_core_3000::get_time_last_pps, mb.radio_perifs[0].time64))
+ .add_coerced_subscriber(boost::bind(&time_core_3000::set_time_next_pps, mb.radio_perifs[0].time64, _1))
+ .add_coerced_subscriber(boost::bind(&time_core_3000::set_time_next_pps, mb.radio_perifs[1].time64, _1));
////////////////////////////////////////////////////////////////////
// setup time sources and properties
////////////////////////////////////////////////////////////////////
_tree->create<std::string>(mb_path / "time_source" / "value")
.set("internal")
- .subscribe(boost::bind(&x300_impl::update_time_source, this, boost::ref(mb), _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_time_source, this, boost::ref(mb), _1));
static const std::vector<std::string> time_sources = boost::assign::list_of("internal")("external")("gpsdo");
_tree->create<std::vector<std::string> >(mb_path / "time_source" / "options").set(time_sources);
//setup the time output, default to ON
_tree->create<bool>(mb_path / "time_source" / "output")
- .subscribe(boost::bind(&x300_impl::set_time_source_out, this, boost::ref(mb), _1))
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_time_source_out, this, boost::ref(mb), _1))
.set(true);
////////////////////////////////////////////////////////////////////
@@ -791,7 +838,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
////////////////////////////////////////////////////////////////////
_tree->create<std::string>(mb_path / "clock_source" / "value")
.set("internal")
- .subscribe(boost::bind(&x300_impl::update_clock_source, this, boost::ref(mb), _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_clock_source, this, boost::ref(mb), _1));
static const std::vector<std::string> clock_source_options = boost::assign::list_of("internal")("external")("gpsdo");
_tree->create<std::vector<std::string> >(mb_path / "clock_source" / "options").set(clock_source_options);
@@ -807,12 +854,12 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
//setup the clock output, default to ON
_tree->create<bool>(mb_path / "clock_source" / "output")
- .subscribe(boost::bind(&x300_clock_ctrl::set_ref_out, mb.clock, _1));
+ .add_coerced_subscriber(boost::bind(&x300_clock_ctrl::set_ref_out, mb.clock, _1));
//initialize tick rate (must be done before setting time)
_tree->access<double>(mb_path / "tick_rate")
- .subscribe(boost::bind(&x300_impl::set_tick_rate, this, boost::ref(mb), _1))
- .subscribe(boost::bind(&x300_impl::update_tick_rate, this, boost::ref(mb), _1))
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_tick_rate, this, boost::ref(mb), _1))
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_tick_rate, this, boost::ref(mb), _1))
.set(mb.clock->get_master_clock_rate());
////////////////////////////////////////////////////////////////////
@@ -822,15 +869,15 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
_tree->create<std::vector<size_t> >(mb_path / "rx_chan_dsp_mapping").set(default_map);
_tree->create<std::vector<size_t> >(mb_path / "tx_chan_dsp_mapping").set(default_map);
_tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec")
- .subscribe(boost::bind(&x300_impl::update_subdev_spec, this, "rx", mb_i, _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_subdev_spec, this, "rx", mb_i, _1));
_tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec")
- .subscribe(boost::bind(&x300_impl::update_subdev_spec, this, "tx", mb_i, _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_subdev_spec, this, "tx", mb_i, _1));
////////////////////////////////////////////////////////////////////
// and do the misc mboard sensors
////////////////////////////////////////////////////////////////////
_tree->create<sensor_value_t>(mb_path / "sensors" / "ref_locked")
- .publish(boost::bind(&x300_impl::get_ref_locked, this, mb));
+ .set_publisher(boost::bind(&x300_impl::get_ref_locked, this, mb));
////////////////////////////////////////////////////////////////////
// do some post-init tasks
@@ -931,7 +978,8 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
perif.spi = spi_core_3000::make(perif.ctrl, radio::sr_addr(radio::SPI), radio::RB32_SPI);
perif.adc = x300_adc_ctrl::make(perif.spi, DB_ADC_SEN);
perif.dac = x300_dac_ctrl::make(perif.spi, DB_DAC_SEN, mb.clock->get_master_clock_rate());
- perif.leds = gpio_core_200_32wo::make(perif.ctrl, radio::sr_addr(radio::LEDS));
+ perif.leds = gpio_atr_3000::make_write_only(perif.ctrl, radio::sr_addr(radio::LEDS));
+ perif.leds->set_atr_mode(MODE_ATR, 0xFFFFFFFF);
perif.rx_fe = rx_frontend_core_200::make(perif.ctrl, radio::sr_addr(radio::RX_FRONT));
perif.rx_fe->set_dc_offset(rx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE);
perif.rx_fe->set_dc_offset_auto(rx_frontend_core_200::DEFAULT_DC_OFFSET_ENABLE);
@@ -941,7 +989,10 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
perif.framer = rx_vita_core_3000::make(perif.ctrl, radio::sr_addr(radio::RX_CTRL));
perif.ddc = rx_dsp_core_3000::make(perif.ctrl, radio::sr_addr(radio::RX_DSP));
perif.ddc->set_link_rate(10e9/8); //whatever
- perif.deframer = tx_vita_core_3000::make(perif.ctrl, radio::sr_addr(radio::TX_CTRL));
+ //The DRAM FIFO is treated as in internal radio FIFO for flow control purposes
+ tx_vita_core_3000::fc_monitor_loc fc_loc =
+ mb.has_dram_buff ? tx_vita_core_3000::FC_PRE_FIFO : tx_vita_core_3000::FC_PRE_RADIO;
+ perif.deframer = tx_vita_core_3000::make(perif.ctrl, radio::sr_addr(radio::TX_CTRL), fc_loc);
perif.duc = tx_dsp_core_3000::make(perif.ctrl, radio::sr_addr(radio::TX_DSP));
perif.duc->set_link_rate(10e9/8); //whatever
@@ -958,7 +1009,7 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
self_cal_adc_capture_delay(mb, radio_index, dev_addr.has_key("self_cal_adc_delay"));
_tree->access<time_spec_t>(mb_path / "time" / "cmd")
- .subscribe(boost::bind(&radio_ctrl_core_3000::set_time, perif.ctrl, _1));
+ .add_coerced_subscriber(boost::bind(&radio_ctrl_core_3000::set_time, perif.ctrl, _1));
////////////////////////////////////////////////////////////////
// create codec control objects
@@ -970,7 +1021,7 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
_tree->create<meta_range_t>(mb_path / "rx_codecs" / slot_name / "gains" / "digital" / "range").set(meta_range_t(0, 6.0, 0.5));
_tree->create<double>(mb_path / "rx_codecs" / slot_name / "gains" / "digital" / "value")
- .subscribe(boost::bind(&x300_adc_ctrl::set_gain, perif.adc, _1)).set(0);
+ .add_coerced_subscriber(boost::bind(&x300_adc_ctrl::set_gain, perif.adc, _1)).set(0);
////////////////////////////////////////////////////////////////////
// front end corrections
@@ -984,10 +1035,10 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
const fs_path rx_dsp_path = mb_path / "rx_dsps" / str(boost::format("%u") % radio_index);
perif.ddc->populate_subtree(_tree->subtree(rx_dsp_path));
_tree->access<double>(rx_dsp_path / "rate" / "value")
- .subscribe(boost::bind(&x300_impl::update_rx_samp_rate, this, boost::ref(mb), radio_index, _1))
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_rx_samp_rate, this, boost::ref(mb), radio_index, _1))
;
_tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd")
- .subscribe(boost::bind(&rx_vita_core_3000::issue_stream_command, perif.framer, _1));
+ .add_coerced_subscriber(boost::bind(&rx_vita_core_3000::issue_stream_command, perif.framer, _1));
////////////////////////////////////////////////////////////////////
// connect tx dsp control objects
@@ -995,7 +1046,7 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
const fs_path tx_dsp_path = mb_path / "tx_dsps" / str(boost::format("%u") % radio_index);
perif.duc->populate_subtree(_tree->subtree(tx_dsp_path));
_tree->access<double>(tx_dsp_path / "rate" / "value")
- .subscribe(boost::bind(&x300_impl::update_tx_samp_rate, this, boost::ref(mb), radio_index, _1))
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_tx_samp_rate, this, boost::ref(mb), radio_index, _1))
;
////////////////////////////////////////////////////////////////////
@@ -1005,17 +1056,17 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
const size_t j = (slot_name == "B")? 0x2 : 0x0;
_tree->create<dboard_eeprom_t>(db_path / "rx_eeprom")
.set(mb.db_eeproms[X300_DB0_RX_EEPROM | j])
- .subscribe(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_RX_EEPROM | j), _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_RX_EEPROM | j), _1));
_tree->create<dboard_eeprom_t>(db_path / "tx_eeprom")
.set(mb.db_eeproms[X300_DB0_TX_EEPROM | j])
- .subscribe(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_TX_EEPROM | j), _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_TX_EEPROM | j), _1));
_tree->create<dboard_eeprom_t>(db_path / "gdb_eeprom")
.set(mb.db_eeproms[X300_DB0_GDB_EEPROM | j])
- .subscribe(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_GDB_EEPROM | j), _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_GDB_EEPROM | j), _1));
//create a new dboard interface
x300_dboard_iface_config_t db_config;
- db_config.gpio = gpio_core_200::make(perif.ctrl, radio::sr_addr(radio::GPIO), radio::RB32_GPIO);
+ db_config.gpio = db_gpio_atr_3000::make(perif.ctrl, radio::sr_addr(radio::GPIO), radio::RB32_GPIO);
db_config.spi = perif.spi;
db_config.rx_spi_slaveno = DB_RX_SEN;
db_config.tx_spi_slaveno = DB_TX_SEN;
@@ -1025,34 +1076,32 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name, con
db_config.which_tx_clk = (slot_name == "A")? X300_CLOCK_WHICH_DB0_TX : X300_CLOCK_WHICH_DB1_TX;
db_config.dboard_slot = (slot_name == "A")? 0 : 1;
db_config.cmd_time_ctrl = perif.ctrl;
- _dboard_ifaces[db_path] = x300_make_dboard_iface(db_config);
//create a new dboard manager
- _tree->create<dboard_iface::sptr>(db_path / "iface").set(_dboard_ifaces[db_path]);
_dboard_managers[db_path] = dboard_manager::make(
mb.db_eeproms[X300_DB0_RX_EEPROM | j].id,
mb.db_eeproms[X300_DB0_TX_EEPROM | j].id,
mb.db_eeproms[X300_DB0_GDB_EEPROM | j].id,
- _dboard_ifaces[db_path],
+ x300_make_dboard_iface(db_config),
_tree->subtree(db_path)
);
//now that dboard is created -- register into rx antenna event
const std::string fe_name = _tree->list(db_path / "rx_frontends").front();
_tree->access<std::string>(db_path / "rx_frontends" / fe_name / "antenna" / "value")
- .subscribe(boost::bind(&x300_impl::update_atr_leds, this, mb.radio_perifs[radio_index].leds, _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::update_atr_leds, this, mb.radio_perifs[radio_index].leds, _1));
this->update_atr_leds(mb.radio_perifs[radio_index].leds, ""); //init anyway, even if never called
//bind frontend corrections to the dboard freq props
const fs_path db_tx_fe_path = db_path / "tx_frontends";
BOOST_FOREACH(const std::string &name, _tree->list(db_tx_fe_path)) {
_tree->access<double>(db_tx_fe_path / name / "freq" / "value")
- .subscribe(boost::bind(&x300_impl::set_tx_fe_corrections, this, mb_path, slot_name, _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_tx_fe_corrections, this, mb_path, slot_name, _1));
}
const fs_path db_rx_fe_path = db_path / "rx_frontends";
BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)) {
_tree->access<double>(db_rx_fe_path / name / "freq" / "value")
- .subscribe(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, slot_name, _1));
+ .add_coerced_subscriber(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, slot_name, _1));
}
}
@@ -1144,7 +1193,7 @@ x300_impl::both_xports_t x300_impl::make_transport(
* connection type.*/
size_t eth_data_rec_frame_size = 0;
- if (mb.loaded_fpga_image == "HGS") {
+ if (mb.loaded_fpga_image.substr(0,2) == "HG") {
if (mb.router_dst_here == X300_XB_DST_E0) {
eth_data_rec_frame_size = X300_1GE_DATA_FRAME_MAX_SIZE;
_tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_1GIGE);
@@ -1152,7 +1201,7 @@ x300_impl::both_xports_t x300_impl::make_transport(
eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
_tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_10GIGE);
}
- } else if (mb.loaded_fpga_image == "XGS") {
+ } else if (mb.loaded_fpga_image.substr(0,2) == "XG") {
eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
_tree->access<double>("/mboards/"+boost::lexical_cast<std::string>(mb_index) / "link_max_rate").set(X300_MAX_RATE_10GIGE);
}
@@ -1296,16 +1345,16 @@ boost::uint32_t x300_impl::allocate_sid(mboard_members_t &mb, const sid_config_t
return sid;
}
-void x300_impl::update_atr_leds(gpio_core_200_32wo::sptr leds, const std::string &rx_ant)
+void x300_impl::update_atr_leds(gpio_atr_3000::sptr leds, const std::string &rx_ant)
{
const bool is_txrx = (rx_ant == "TX/RX");
const int rx_led = (1 << 2);
const int tx_led = (1 << 1);
const int txrx_led = (1 << 0);
- leds->set_atr_reg(dboard_iface::ATR_REG_IDLE, 0);
- leds->set_atr_reg(dboard_iface::ATR_REG_RX_ONLY, is_txrx? txrx_led : rx_led);
- leds->set_atr_reg(dboard_iface::ATR_REG_TX_ONLY, tx_led);
- leds->set_atr_reg(dboard_iface::ATR_REG_FULL_DUPLEX, rx_led | tx_led);
+ leds->set_atr_reg(ATR_REG_IDLE, 0);
+ leds->set_atr_reg(ATR_REG_RX_ONLY, is_txrx? txrx_led : rx_led);
+ leds->set_atr_reg(ATR_REG_TX_ONLY, tx_led);
+ leds->set_atr_reg(ATR_REG_FULL_DUPLEX, rx_led | tx_led);
}
void x300_impl::set_tick_rate(mboard_members_t &mb, const double rate)
@@ -1315,7 +1364,6 @@ void x300_impl::set_tick_rate(mboard_members_t &mb, const double rate)
perif.time64->set_tick_rate(rate);
perif.framer->set_tick_rate(rate);
perif.ddc->set_tick_rate(rate);
- perif.deframer->set_tick_rate(rate);
perif.duc->set_tick_rate(rate);
}
}
@@ -1518,30 +1566,6 @@ void x300_impl::set_mb_eeprom(i2c_iface::sptr i2c, const mboard_eeprom_t &mb_eep
}
/***********************************************************************
- * front-panel GPIO
- **********************************************************************/
-
-boost::uint32_t x300_impl::get_fp_gpio(gpio_core_200::sptr gpio)
-{
- return boost::uint32_t(gpio->read_gpio(dboard_iface::UNIT_RX));
-}
-
-void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const gpio_attr_t attr, const boost::uint32_t value)
-{
- switch (attr)
- {
- case GPIO_CTRL: return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value);
- case GPIO_DDR: return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value);
- case GPIO_OUT: return gpio->set_gpio_out(dboard_iface::UNIT_RX, value);
- case GPIO_ATR_0X: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value);
- case GPIO_ATR_RX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value);
- case GPIO_ATR_TX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value);
- case GPIO_ATR_XX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, value);
- default: UHD_THROW_INVALID_CODE_PATH();
- }
-}
-
-/***********************************************************************
* claimer logic
**********************************************************************/
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index e04b06d65..6ebea0161 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -41,7 +41,8 @@
#include "radio_ctrl_core_3000.hpp"
#include "rx_frontend_core_200.hpp"
#include "tx_frontend_core_200.hpp"
-#include "gpio_core_200.hpp"
+#include "gpio_atr_3000.hpp"
+#include "dma_fifo_core_3000.hpp"
#include <boost/weak_ptr.hpp>
#include <uhd/usrp/gps_ctrl.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
@@ -57,8 +58,11 @@ static const double X300_DEFAULT_TICK_RATE = 200e6; //Hz
static const double X300_DEFAULT_DBOARD_CLK_RATE = 50e6; //Hz
static const double X300_BUS_CLOCK_RATE = 166.666667e6; //Hz
-static const size_t X300_TX_HW_BUFF_SIZE = 520*1024; //512K SRAM buffer + 8K 2Clk FIFO
-static const size_t X300_TX_FC_RESPONSE_FREQ = 8; //per flow-control window
+static const size_t X300_TX_HW_BUFF_SIZE_SRAM = 520*1024; //512K SRAM buffer + 8K 2Clk FIFO
+static const size_t X300_TX_FC_RESPONSE_FREQ_SRAM = 8; //per flow-control window
+static const size_t X300_TX_HW_BUFF_SIZE_DRAM = 128*1024;
+static const size_t X300_TX_FC_RESPONSE_FREQ_DRAM = 32;
+static const boost::uint32_t X300_DRAM_FIFO_SIZE = 32*1024*1024;
static const size_t X300_RX_SW_BUFF_SIZE_ETH = 0x2000000;//32MiB For an ~8k frame size any size >32MiB is just wasted buffer space
static const size_t X300_RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib
@@ -124,7 +128,7 @@ enum
struct x300_dboard_iface_config_t
{
- gpio_core_200::sptr gpio;
+ uhd::usrp::gpio_atr::db_gpio_atr_3000::sptr gpio;
spi_core_3000::sptr spi;
size_t rx_spi_slaveno;
size_t tx_spi_slaveno;
@@ -186,7 +190,7 @@ private:
rx_dsp_core_3000::sptr ddc;
tx_vita_core_3000::sptr deframer;
tx_dsp_core_3000::sptr duc;
- gpio_core_200_32wo::sptr leds;
+ uhd::usrp::gpio_atr::gpio_atr_3000::sptr leds;
rx_frontend_core_200::sptr rx_fe;
tx_frontend_core_200::sptr tx_fe;
//Registers
@@ -227,10 +231,14 @@ private:
return slot_name == "A" ? 0 : 1;
}
+ bool has_dram_buff;
+ dma_fifo_core_3000::sptr dram_buff_ctrl[NUM_RADIOS];
+
+
//other perifs on mboard
x300_clock_ctrl::sptr clock;
uhd::gps_ctrl::sptr gps;
- gpio_core_200::sptr fp_gpio;
+ uhd::usrp::gpio_atr::gpio_atr_3000::sptr fp_gpio;
uhd::usrp::x300::fw_regmap_t::sptr fw_regmap;
@@ -328,7 +336,6 @@ private:
////////////////////////////////////////////////////////////////////
uhd::dict<std::string, uhd::usrp::dboard_manager::sptr> _dboard_managers;
- uhd::dict<std::string, uhd::usrp::dboard_iface::sptr> _dboard_ifaces;
void set_rx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq);
void set_tx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq);
@@ -367,9 +374,7 @@ private:
void check_fw_compat(const uhd::fs_path &mb_path, uhd::wb_iface::sptr iface);
void check_fpga_compat(const uhd::fs_path &mb_path, const mboard_members_t &members);
- void update_atr_leds(gpio_core_200_32wo::sptr, const std::string &ant);
- boost::uint32_t get_fp_gpio(gpio_core_200::sptr);
- void set_fp_gpio(gpio_core_200::sptr, const gpio_attr_t, const boost::uint32_t);
+ void update_atr_leds(uhd::usrp::gpio_atr::gpio_atr_3000::sptr, const std::string &ant);
void self_cal_adc_capture_delay(mboard_members_t& mb, const size_t radio_i, bool print_status = false);
double self_cal_adc_xfer_delay(mboard_members_t& mb, bool apply_delay = false);
diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp
index e3515af0c..01cbc3ca7 100644
--- a/host/lib/usrp/x300/x300_io_impl.cpp
+++ b/host/lib/usrp/x300/x300_io_impl.cpp
@@ -107,16 +107,12 @@ void x300_impl::update_subdev_spec(const std::string &tx_rx, const size_t mb_i,
//extract connection
const std::string conn = _tree->access<std::string>(mb_root / "dboards" / spec[i].db_name / (tx_rx + "_frontends") / spec[i].sd_name / "connection").get();
-
if (tx_rx == "tx") {
//swap condition
_mb[mb_i].radio_perifs[radio_idx].tx_fe->set_mux(conn);
} else {
- //swap condition
- const bool fe_swapped = (conn == "QI" or conn == "Q");
- _mb[mb_i].radio_perifs[radio_idx].ddc->set_mux(conn, fe_swapped);
- //see usrp/io_impl.cpp if multiple DSPs share the frontend:
- _mb[mb_i].radio_perifs[radio_idx].rx_fe->set_mux(fe_swapped);
+ _mb[mb_i].radio_perifs[radio_idx].ddc->set_mux(conn);
+ _mb[mb_i].radio_perifs[radio_idx].rx_fe->set_mux(false);
}
}
@@ -216,9 +212,10 @@ struct x300_tx_fc_guts_t
* FC credit we have is C = F + M - N (i.e. we can send C more packets
* before getting another ack).
*/
-static size_t get_tx_flow_control_window(size_t frame_size, const device_addr_t& tx_args)
+static size_t get_tx_flow_control_window(size_t frame_size, const bool dram_buff, const device_addr_t& tx_args)
{
- double hw_buff_size = tx_args.cast<double>("send_buff_size", X300_TX_HW_BUFF_SIZE);
+ double default_buff_size = dram_buff ? X300_TX_HW_BUFF_SIZE_DRAM : X300_TX_HW_BUFF_SIZE_SRAM;
+ double hw_buff_size = tx_args.cast<double>("send_buff_size", default_buff_size);
size_t window_in_pkts = (static_cast<size_t>(hw_buff_size) / frame_size);
if (window_in_pkts == 0) {
throw uhd::value_error("send_buff_size must be larger than the send_frame_size.");
@@ -580,8 +577,9 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_)
perif.duc->setup(args);
//flow control setup
- size_t fc_window = get_tx_flow_control_window(xport.send->get_send_frame_size(), device_addr); //In packets
- const size_t fc_handle_window = std::max<size_t>(1, fc_window/X300_TX_FC_RESPONSE_FREQ);
+ size_t fc_window = get_tx_flow_control_window(xport.send->get_send_frame_size(), mb.has_dram_buff, device_addr); //In packets
+ const size_t fc_handle_window = std::max<size_t>(1,
+ fc_window/ (mb.has_dram_buff ? X300_TX_FC_RESPONSE_FREQ_DRAM : X300_TX_FC_RESPONSE_FREQ_SRAM));
UHD_LOG << "TX Flow Control Window = " << fc_window << ", TX Flow Control Handler Window = " << fc_handle_window << std::endl;
diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp
index 3e0966c83..de3a3161a 100644
--- a/host/lib/usrp/x300/x300_regs.hpp
+++ b/host/lib/usrp/x300/x300_regs.hpp
@@ -42,7 +42,7 @@ static const uint32_t TIME = 128;
static const uint32_t RX_DSP = 144;
static const uint32_t TX_DSP = 184;
static const uint32_t LEDS = 195;
-static const uint32_t FP_GPIO = 200;
+static const uint32_t FP_GPIO = 201;
static const uint32_t RX_FRONT = 208;
static const uint32_t TX_FRONT = 216;
@@ -77,6 +77,8 @@ localparam ZPU_SR_XB_LOCAL = 03;
localparam ZPU_SR_SPI = 32;
localparam ZPU_SR_ETHINT0 = 40;
localparam ZPU_SR_ETHINT1 = 56;
+localparam ZPU_SR_DRAM_FIFO0 = 72;
+localparam ZPU_SR_DRAM_FIFO1 = 80;
//reset bits
#define ZPU_SR_SW_RST_ETH_PHY (1<<0)
@@ -89,6 +91,8 @@ localparam ZPU_RB_CLK_STATUS = 3;
localparam ZPU_RB_COMPAT_NUM = 6;
localparam ZPU_RB_ETH_TYPE0 = 4;
localparam ZPU_RB_ETH_TYPE1 = 5;
+localparam ZPU_RB_DRAM_FIFO0 = 10;
+localparam ZPU_RB_DRAM_FIFO1 = 11;
//spi slaves on radio
#define DB_DAC_SEN (1 << 7)