summaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2012-02-17 18:18:26 -0800
committerJosh Blum <josh@joshknows.com>2012-02-17 18:18:26 -0800
commit3ddbcb6078593c39cb0e4bc8f9769f818a61466f (patch)
tree408e3f6a64e31b7d830b9f884ecebdaf100a5d2d /host/lib/usrp
parent1fab7e9d477aa98e489400c25a08358952c69c90 (diff)
parentace4489066d1621a09e70650a00d736f0b03ed8c (diff)
downloaduhd-3ddbcb6078593c39cb0e4bc8f9769f818a61466f.tar.gz
uhd-3ddbcb6078593c39cb0e4bc8f9769f818a61466f.tar.bz2
uhd-3ddbcb6078593c39cb0e4bc8f9769f818a61466f.zip
Merge branch 'next'
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/b100/b100_ctrl.cpp4
-rw-r--r--host/lib/usrp/b100/b100_impl.cpp48
-rw-r--r--host/lib/usrp/b100/b100_impl.hpp12
-rw-r--r--host/lib/usrp/b100/b100_regs.hpp36
-rw-r--r--host/lib/usrp/b100/io_impl.cpp61
-rw-r--r--host/lib/usrp/common/async_packet_handler.hpp71
-rw-r--r--host/lib/usrp/common/fx2_ctrl.cpp13
-rw-r--r--host/lib/usrp/common/fx2_ctrl.hpp6
-rw-r--r--host/lib/usrp/cores/CMakeLists.txt3
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_200.cpp60
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_200.hpp3
-rw-r--r--host/lib/usrp/cores/time64_core_200.cpp34
-rw-r--r--host/lib/usrp/cores/time64_core_200.hpp4
-rw-r--r--host/lib/usrp/cores/tx_dsp_core_200.cpp62
-rw-r--r--host/lib/usrp/cores/tx_dsp_core_200.hpp6
-rw-r--r--host/lib/usrp/cores/user_settings_core_200.cpp43
-rw-r--r--host/lib/usrp/cores/user_settings_core_200.hpp36
-rw-r--r--host/lib/usrp/e100/e100_impl.cpp17
-rw-r--r--host/lib/usrp/e100/e100_impl.hpp6
-rw-r--r--host/lib/usrp/e100/e100_regs.hpp32
-rw-r--r--host/lib/usrp/e100/io_impl.cpp46
-rw-r--r--host/lib/usrp/multi_usrp.cpp11
-rw-r--r--host/lib/usrp/usrp1/io_impl.cpp12
-rw-r--r--host/lib/usrp/usrp1/soft_time_ctrl.cpp4
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp1
-rw-r--r--host/lib/usrp/usrp2/fw_common.h4
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp44
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp13
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp17
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp4
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.hpp12
31 files changed, 502 insertions, 223 deletions
diff --git a/host/lib/usrp/b100/b100_ctrl.cpp b/host/lib/usrp/b100/b100_ctrl.cpp
index 7d40daa32..e6136c00e 100644
--- a/host/lib/usrp/b100/b100_ctrl.cpp
+++ b/host/lib/usrp/b100/b100_ctrl.cpp
@@ -165,7 +165,7 @@ int b100_ctrl_impl::write(boost::uint32_t addr, const ctrl_data_t &data) {
pkt.pkt_meta.seq = _seq++;
pkt.pkt_meta.len = pkt.data.size();
pkt.pkt_meta.addr = addr;
- boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)];
+ boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)] = {};
pack_ctrl_pkt(pkt_buff, pkt);
size_t result = send_pkt(pkt_buff);
@@ -181,7 +181,7 @@ ctrl_data_t b100_ctrl_impl::read(boost::uint32_t addr, size_t len) {
pkt.pkt_meta.seq = _seq++;
pkt.pkt_meta.len = len;
pkt.pkt_meta.addr = addr;
- boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)];
+ boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)] = {};
//flush anything that might be in the queue
while (get_ctrl_data(pkt.data, 0.0)){
diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp
index 61bc58bce..8b55494c5 100644
--- a/host/lib/usrp/b100/b100_impl.cpp
+++ b/host/lib/usrp/b100/b100_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2012 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
@@ -150,6 +150,10 @@ UHD_STATIC_BLOCK(register_b100_device){
* Structors
**********************************************************************/
b100_impl::b100_impl(const device_addr_t &device_addr){
+ size_t initialization_count = 0;
+ b100_impl_constructor_begin:
+ initialization_count++;
+
_tree = property_tree::make();
//extract the FPGA path for the B100
@@ -181,6 +185,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
//load FPGA image, gpif is disabled while loading
this->enable_gpif(false);
_fx2_ctrl->usrp_load_fpga(b100_fpga_image);
+ _fx2_ctrl->usrp_fpga_reset(false); //active low reset
+ _fx2_ctrl->usrp_fpga_reset(true);
this->enable_gpif(true);
//create the control transport
@@ -196,13 +202,28 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
3, 4, //interface, endpoint
ctrl_xport_args
);
+ while (_ctrl_transport->get_recv_buff(0.0)){} //flush ctrl xport
////////////////////////////////////////////////////////////////////
// Initialize FPGA wishbone communication
////////////////////////////////////////////////////////////////////
_fpga_ctrl = b100_ctrl::make(_ctrl_transport);
- this->reset_gpif(6); //always reset first to ensure communication
_fpga_ctrl->poke32(B100_REG_GLOBAL_RESET, 0); //global fpga reset
+ //perform a test peek operation
+ try{
+ _fpga_ctrl->peek32(0);
+ }
+ //try reset once in the case of failure
+ catch(const uhd::exception &e){
+ if (initialization_count > 1) throw;
+ UHD_MSG(warning) <<
+ "The control endpoint was left in a bad state.\n"
+ "Attempting endpoint re-enumeration...\n" << std::endl;
+ _fpga_ctrl.reset();
+ _ctrl_transport.reset();
+ _fx2_ctrl->usrp_fx2_reset();
+ goto b100_impl_constructor_begin;
+ }
this->check_fpga_compat(); //check after reset and making control
////////////////////////////////////////////////////////////////////
@@ -229,8 +250,10 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
2, 6, // IN interface, endpoint
1, 2, // OUT interface, endpoint
data_xport_args // param hints
- )
+ ),
+ B100_MAX_PKT_BYTE_LIMIT
);
+ while (_data_transport->get_recv_buff(0.0)){} //flush data xport
////////////////////////////////////////////////////////////////////
// Initialize the properties tree
@@ -361,10 +384,10 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
// create time control objects
////////////////////////////////////////////////////////////////////
time64_core_200::readback_bases_type time64_rb_bases;
- time64_rb_bases.rb_secs_now = B100_REG_RB_TIME_NOW_SECS;
- time64_rb_bases.rb_ticks_now = B100_REG_RB_TIME_NOW_TICKS;
- time64_rb_bases.rb_secs_pps = B100_REG_RB_TIME_PPS_SECS;
- time64_rb_bases.rb_ticks_pps = B100_REG_RB_TIME_PPS_TICKS;
+ time64_rb_bases.rb_hi_now = B100_REG_RB_TIME_NOW_HI;
+ time64_rb_bases.rb_lo_now = B100_REG_RB_TIME_NOW_LO;
+ time64_rb_bases.rb_hi_pps = B100_REG_RB_TIME_PPS_HI;
+ time64_rb_bases.rb_lo_pps = B100_REG_RB_TIME_PPS_LO;
_time64 = time64_core_200::make(
_fpga_ctrl, B100_REG_SR_ADDR(B100_SR_TIME64), time64_rb_bases
);
@@ -388,6 +411,13 @@ b100_impl::b100_impl(const device_addr_t &device_addr){
_tree->create<std::vector<std::string> >(mb_path / "clock_source/options").set(clock_sources);
////////////////////////////////////////////////////////////////////
+ // create user-defined control objects
+ ////////////////////////////////////////////////////////////////////
+ _user = user_settings_core_200::make(_fpga_ctrl, B100_REG_SR_ADDR(B100_SR_USER_REGS));
+ _tree->create<user_settings_core_200::user_reg_t>(mb_path / "user/regs")
+ .subscribe(boost::bind(&user_settings_core_200::set_reg, _user, _1));
+
+ ////////////////////////////////////////////////////////////////////
// create dboard control objects
////////////////////////////////////////////////////////////////////
@@ -505,10 +535,6 @@ void b100_impl::update_clock_source(const std::string &source){
}
////////////////// some GPIF preparation related stuff /////////////////
-void b100_impl::reset_gpif(const boost::uint16_t ep) {
- _fx2_ctrl->usrp_control_write(VRQ_RESET_GPIF, ep, ep, 0, 0);
-}
-
void b100_impl::enable_gpif(const bool en) {
_fx2_ctrl->usrp_control_write(VRQ_ENABLE_GPIF, en ? 1 : 0, 0, 0, 0);
}
diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp
index 96d90b14c..eab9c750b 100644
--- a/host/lib/usrp/b100/b100_impl.hpp
+++ b/host/lib/usrp/b100/b100_impl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 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
@@ -29,6 +29,7 @@
#include "rx_dsp_core_200.hpp"
#include "tx_dsp_core_200.hpp"
#include "time64_core_200.hpp"
+#include "user_settings_core_200.hpp"
#include <uhd/device.hpp>
#include <uhd/property_tree.hpp>
#include <uhd/utils/pimpl.hpp>
@@ -43,14 +44,15 @@
#include <uhd/transport/usb_zero_copy.hpp>
#include <boost/weak_ptr.hpp>
-static const double B100_LINK_RATE_BPS = 256e6/8; //pratical link rate (< 480 Mbps)
+static const double B100_LINK_RATE_BPS = 256e6/5; //pratical link rate (< 480 Mbps)
static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx";
static const std::string B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin";
-static const boost::uint16_t B100_FW_COMPAT_NUM = 0x02;
-static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x08;
+static const boost::uint16_t B100_FW_COMPAT_NUM = 0x03;
+static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x09;
static const boost::uint32_t B100_RX_SID_BASE = 2;
static const boost::uint32_t B100_TX_ASYNC_SID = 1;
static const double B100_DEFAULT_TICK_RATE = 64e6;
+static const size_t B100_MAX_PKT_BYTE_LIMIT = 2048;
//! Make a b100 dboard interface
uhd::usrp::dboard_iface::sptr make_b100_dboard_iface(
@@ -84,6 +86,7 @@ private:
std::vector<rx_dsp_core_200::sptr> _rx_dsps;
tx_dsp_core_200::sptr _tx_dsp;
time64_core_200::sptr _time64;
+ user_settings_core_200::sptr _user;
b100_clock_ctrl::sptr _clock_ctrl;
b100_codec_ctrl::sptr _codec_ctrl;
b100_ctrl::sptr _fpga_ctrl;
@@ -120,7 +123,6 @@ private:
void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &);
void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &);
void update_clock_source(const std::string &);
- void reset_gpif(const boost::uint16_t);
void enable_gpif(const bool);
void clear_fpga_fifo(void);
void handle_async_message(uhd::transport::managed_recv_buffer::sptr);
diff --git a/host/lib/usrp/b100/b100_regs.hpp b/host/lib/usrp/b100/b100_regs.hpp
index 491e16eef..987a09f03 100644
--- a/host/lib/usrp/b100/b100_regs.hpp
+++ b/host/lib/usrp/b100/b100_regs.hpp
@@ -1,4 +1,19 @@
-
+//
+// Copyright 2010-2012 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/>.
+//
////////////////////////////////////////////////////////////////
//
@@ -27,10 +42,6 @@
#define B100_REG_MISC_SW B100_REG_MISC_BASE + 2
#define B100_REG_MISC_CGEN_CTRL B100_REG_MISC_BASE + 4
#define B100_REG_MISC_CGEN_ST B100_REG_MISC_BASE + 6
-#define B100_REG_MISC_TEST B100_REG_MISC_BASE + 8
-#define B100_REG_MISC_RX_LEN B100_REG_MISC_BASE + 10
-#define B100_REG_MISC_TX_LEN B100_REG_MISC_BASE + 12
-#define B100_REG_MISC_XFER_RATE B100_REG_MISC_BASE + 14
/////////////////////////////////////////////////////
// Slave 1 -- UART
@@ -65,10 +76,10 @@
#define B100_REG_RB_MUX_32_BASE B100_REG_SLAVE(7)
-#define B100_REG_RB_TIME_NOW_SECS B100_REG_RB_MUX_32_BASE + 0
-#define B100_REG_RB_TIME_NOW_TICKS B100_REG_RB_MUX_32_BASE + 4
-#define B100_REG_RB_TIME_PPS_SECS B100_REG_RB_MUX_32_BASE + 8
-#define B100_REG_RB_TIME_PPS_TICKS B100_REG_RB_MUX_32_BASE + 12
+#define B100_REG_RB_TIME_NOW_HI B100_REG_RB_MUX_32_BASE + 0
+#define B100_REG_RB_TIME_NOW_LO B100_REG_RB_MUX_32_BASE + 4
+#define B100_REG_RB_TIME_PPS_HI B100_REG_RB_MUX_32_BASE + 8
+#define B100_REG_RB_TIME_PPS_LO B100_REG_RB_MUX_32_BASE + 12
#define B100_REG_RB_MISC_TEST32 B100_REG_RB_MUX_32_BASE + 16
#define B100_REG_RB_COMPAT B100_REG_RB_MUX_32_BASE + 24
#define B100_REG_RB_GPIO B100_REG_RB_MUX_32_BASE + 28
@@ -92,9 +103,9 @@
#define B100_SR_TX_FRONT 54 // 5 regs (+0 to +4)
#define B100_SR_REG_TEST32 60 // 1 reg
-#define B100_SR_CLEAR_RX_FIFO 61 // 1 reg
-#define B100_SR_CLEAR_TX_FIFO 62 // 1 reg
+#define B100_SR_CLEAR_FIFO 61 // 1 reg
#define B100_SR_GLOBAL_RESET 63 // 1 reg
+#define B100_SR_USER_REGS 64 // 2 regs
#define B100_SR_GPIO 128
@@ -105,8 +116,7 @@
/////////////////////////////////////////////////
// Magic reset regs
////////////////////////////////////////////////
-#define B100_REG_CLEAR_RX B100_REG_SR_ADDR(B100_SR_CLEAR_RX_FIFO)
-#define B100_REG_CLEAR_TX B100_REG_SR_ADDR(B100_SR_CLEAR_RX_FIFO)
+#define B100_REG_CLEAR_FIFO B100_REG_SR_ADDR(B100_SR_CLEAR_FIFO)
#define B100_REG_GLOBAL_RESET B100_REG_SR_ADDR(B100_SR_GLOBAL_RESET)
#endif
diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp
index 494d5d123..674380cca 100644
--- a/host/lib/usrp/b100/io_impl.cpp
+++ b/host/lib/usrp/b100/io_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 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
@@ -17,6 +17,7 @@
#include "recv_packet_demuxer.hpp"
#include "validate_subdev_spec.hpp"
+#include "async_packet_handler.hpp"
#include "../../transport/super_recv_packet_handler.hpp"
#include "../../transport/super_send_packet_handler.hpp"
#include "usrp_commands.h"
@@ -41,12 +42,13 @@ using namespace uhd::transport;
**********************************************************************/
struct b100_impl::io_impl{
io_impl(void):
- async_msg_fifo(100/*messages deep*/)
+ async_msg_fifo(1000/*messages deep*/)
{ /* NOP */ }
zero_copy_if::sptr data_transport;
bounded_buffer<async_metadata_t> async_msg_fifo;
recv_packet_demuxer::sptr demuxer;
+ double tick_rate;
};
/***********************************************************************
@@ -54,12 +56,8 @@ struct b100_impl::io_impl{
**********************************************************************/
void b100_impl::io_init(void){
- //clear state machines
- _fpga_ctrl->poke32(B100_REG_CLEAR_RX, 0);
- _fpga_ctrl->poke32(B100_REG_CLEAR_TX, 0);
-
- //set the expected packet size in USB frames
- _fpga_ctrl->poke32(B100_REG_MISC_RX_LEN, 4);
+ //clear fifo state machines
+ _fpga_ctrl->poke32(B100_REG_CLEAR_FIFO, 0);
//allocate streamer weak ptrs containers
_rx_streamers.resize(_rx_dsps.size());
@@ -85,26 +83,16 @@ void b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){
}
if (if_packet_info.sid == B100_TX_ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){
+
//fill in the async metadata
async_metadata_t metadata;
- metadata.channel = 0;
- metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf;
- metadata.time_spec = time_spec_t(
- time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), _clock_ctrl->get_fpga_clock_rate()
- );
- metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info));
+ load_metadata_from_buff(uhd::wtohx<boost::uint32_t>, metadata, if_packet_info, vrt_hdr, _io_impl->tick_rate);
+
+ //push the message onto the queue
_io_impl->async_msg_fifo.push_with_pop_on_full(metadata);
- if (metadata.event_code &
- ( async_metadata_t::EVENT_CODE_UNDERFLOW
- | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET)
- ) UHD_MSG(fastpath) << "U";
- else if (metadata.event_code &
- ( async_metadata_t::EVENT_CODE_SEQ_ERROR
- | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST)
- ) UHD_MSG(fastpath) << "S";
- else if (metadata.event_code &
- async_metadata_t::EVENT_CODE_TIME_ERROR
- ) UHD_MSG(fastpath) << "L";
+
+ //print some fastpath messages
+ standard_async_msg_prints(metadata);
}
else UHD_MSG(error) << "Unknown async packet" << std::endl;
}
@@ -123,6 +111,8 @@ void b100_impl::update_rates(void){
}
void b100_impl::update_tick_rate(const double rate){
+ _io_impl->tick_rate = rate;
+
//update the tick rate on all existing streamers -> thread safe
for (size_t i = 0; i < _rx_streamers.size(); i++){
boost::shared_ptr<sph::recv_packet_streamer> my_streamer =
@@ -154,6 +144,8 @@ void b100_impl::update_tx_samp_rate(const size_t dspno, const double rate){
if (my_streamer.get() == NULL) return;
my_streamer->set_samp_rate(rate);
+ const double adj = _tx_dsp->get_scaling_adjustment();
+ my_streamer->set_scale_factor(adj);
}
void b100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){
@@ -202,15 +194,15 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){
//setup defaults for unspecified values
args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
- const unsigned sc8_scalar = unsigned(args.args.cast<double>("scalar", 0x400));
//calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
- const size_t bpp = 2048 - hdr_size; //limited by FPGA pkt buffer size
+ const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size;
const size_t bpi = convert::get_bytes_per_item(args.otw_format);
const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi));
@@ -233,8 +225,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){
for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){
const size_t dsp = args.channels[chan_i];
_rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this
- if (not args.args.has_key("noclear")) _rx_dsps[dsp]->clear();
- _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar);
+ _rx_dsps[dsp]->setup(args);
my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
&recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1
), true /*flush*/);
@@ -260,16 +251,15 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){
args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
- if (args.otw_format != "sc16"){
- throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format);
- }
-
//calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
+ - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
- static const size_t bpp = 2048 - hdr_size;
+ static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size;
const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format);
//make the new streamer given the samples per packet
@@ -291,8 +281,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){
for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){
const size_t dsp = args.channels[chan_i];
UHD_ASSERT_THROW(dsp == 0); //always 0
- if (not args.args.has_key("noclear")) _tx_dsp->clear();
- if (args.args.has_key("underflow_policy")) _tx_dsp->set_underflow_policy(args.args["underflow_policy"]);
+ _tx_dsp->setup(args);
my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
&zero_copy_if::get_send_buff, _data_transport, _1
));
diff --git a/host/lib/usrp/common/async_packet_handler.hpp b/host/lib/usrp/common/async_packet_handler.hpp
new file mode 100644
index 000000000..fef03483f
--- /dev/null
+++ b/host/lib/usrp/common/async_packet_handler.hpp
@@ -0,0 +1,71 @@
+//
+// Copyright 2012 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_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP
+#define INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/transport/vrt_if_packet.hpp>
+#include <uhd/types/metadata.hpp>
+#include <uhd/utils/byteswap.hpp>
+#include <uhd/utils/msg.hpp>
+
+namespace uhd{ namespace usrp{
+
+ template <typename to_host_type>
+ void load_metadata_from_buff(
+ const to_host_type &to_host,
+ async_metadata_t &metadata,
+ const transport::vrt::if_packet_info_t &if_packet_info,
+ const boost::uint32_t *vrt_hdr,
+ const double tick_rate,
+ const size_t channel = 0
+ ){
+ const boost::uint32_t *payload = vrt_hdr + if_packet_info.num_header_words32;
+
+ //load into metadata
+ metadata.channel = channel;
+ metadata.has_time_spec = if_packet_info.has_tsf;
+ metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, tick_rate);
+ metadata.event_code = async_metadata_t::event_code_t(to_host(payload[0]) & 0xff);
+
+ //load user payload
+ for (size_t i = 1; i < if_packet_info.num_payload_words32; i++){
+ if (i-1 == 4) break; //limit of 4 words32
+ metadata.user_payload[i-1] = to_host(payload[i]);
+ }
+ }
+
+ UHD_INLINE void standard_async_msg_prints(const async_metadata_t &metadata)
+ {
+ if (metadata.event_code &
+ ( async_metadata_t::EVENT_CODE_UNDERFLOW
+ | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET)
+ ) UHD_MSG(fastpath) << "U";
+ else if (metadata.event_code &
+ ( async_metadata_t::EVENT_CODE_SEQ_ERROR
+ | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST)
+ ) UHD_MSG(fastpath) << "S";
+ else if (metadata.event_code &
+ async_metadata_t::EVENT_CODE_TIME_ERROR
+ ) UHD_MSG(fastpath) << "L";
+ }
+
+
+}} //namespace uhd::usrp
+
+#endif /* INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP */
diff --git a/host/lib/usrp/common/fx2_ctrl.cpp b/host/lib/usrp/common/fx2_ctrl.cpp
index 3c6df7079..7b8920eb1 100644
--- a/host/lib/usrp/common/fx2_ctrl.cpp
+++ b/host/lib/usrp/common/fx2_ctrl.cpp
@@ -139,6 +139,15 @@ public:
_ctrl_transport = ctrl_transport;
}
+ void usrp_fx2_reset(void){
+ unsigned char reset_y = 1;
+ unsigned char reset_n = 0;
+ usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1);
+ usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1);
+ //wait for things to settle
+ boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
+ }
+
void usrp_load_firmware(std::string filestring, bool force)
{
const char *filename = filestring.c_str();
@@ -419,7 +428,7 @@ public:
{
UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes);
- unsigned char buff[max_i2c_data_bytes];
+ unsigned char buff[max_i2c_data_bytes] = {};
std::copy(bytes.begin(), bytes.end(), buff);
int ret = this->usrp_i2c_write(addr & 0xff,
@@ -434,7 +443,7 @@ public:
{
UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes);
- unsigned char buff[max_i2c_data_bytes];
+ unsigned char buff[max_i2c_data_bytes] = {};
int ret = this->usrp_i2c_read(addr & 0xff,
buff,
num_bytes);
diff --git a/host/lib/usrp/common/fx2_ctrl.hpp b/host/lib/usrp/common/fx2_ctrl.hpp
index 691d64275..f2e060862 100644
--- a/host/lib/usrp/common/fx2_ctrl.hpp
+++ b/host/lib/usrp/common/fx2_ctrl.hpp
@@ -39,6 +39,9 @@ public:
//! Call init after the fpga is loaded
virtual void usrp_init(void) = 0;
+ //! For emergency situations
+ virtual void usrp_fx2_reset(void) = 0;
+
/*!
* Load firmware in Intel HEX Format onto device
* \param filename name of firmware file
@@ -116,6 +119,9 @@ public:
//! enable/disable the tx path
virtual void usrp_tx_enable(bool on) = 0;
+
+ //! reset the fpga
+ virtual void usrp_fpga_reset(bool on) = 0;
};
}} //namespace uhd::usrp
diff --git a/host/lib/usrp/cores/CMakeLists.txt b/host/lib/usrp/cores/CMakeLists.txt
index 2aa8f6b99..aa5f0bcbb 100644
--- a/host/lib/usrp/cores/CMakeLists.txt
+++ b/host/lib/usrp/cores/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2011 Ettus Research LLC
+# Copyright 2011-2012 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
@@ -30,4 +30,5 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/tx_dsp_core_200.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rx_frontend_core_200.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tx_frontend_core_200.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/user_settings_core_200.cpp
)
diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp
index 2e21cc895..0996952ff 100644
--- a/host/lib/usrp/cores/rx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 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
@@ -18,6 +18,7 @@
#include "rx_dsp_core_200.hpp"
#include <uhd/types/dict.hpp>
#include <uhd/exception.hpp>
+#include <uhd/utils/msg.hpp>
#include <uhd/utils/algorithm.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/thread/thread.hpp> //thread sleep
@@ -27,7 +28,7 @@
#include <cmath>
#define REG_DSP_RX_FREQ _dsp_base + 0
-//skip one right here
+#define REG_DSP_RX_SCALE_IQ _dsp_base + 4
#define REG_DSP_RX_DECIM _dsp_base + 8
#define REG_DSP_RX_MUX _dsp_base + 12
@@ -35,15 +36,15 @@
#define FLAG_DSP_RX_MUX_REAL_MODE (1 << 1)
#define REG_RX_CTRL_STREAM_CMD _ctrl_base + 0
-#define REG_RX_CTRL_TIME_SECS _ctrl_base + 4
-#define REG_RX_CTRL_TIME_TICKS _ctrl_base + 8
+#define REG_RX_CTRL_TIME_HI _ctrl_base + 4
+#define REG_RX_CTRL_TIME_LO _ctrl_base + 8
#define REG_RX_CTRL_CLEAR _ctrl_base + 12
#define REG_RX_CTRL_VRT_HDR _ctrl_base + 16
#define REG_RX_CTRL_VRT_SID _ctrl_base + 20
#define REG_RX_CTRL_VRT_TLR _ctrl_base + 24
#define REG_RX_CTRL_NSAMPS_PP _ctrl_base + 28
#define REG_RX_CTRL_NCHANNELS _ctrl_base + 32
-#define REG_RX_CTRL_FORMAT _ctrl_base + 36
+#define REG_RX_CTRL_FORMAT REG_RX_CTRL_CLEAR //re-use clear address
template <class T> T ceil_log2(T num){
return std::ceil(std::log(num)/std::log(T(2)));
@@ -60,6 +61,10 @@ public:
):
_iface(iface), _dsp_base(dsp_base), _ctrl_base(ctrl_base), _sid(sid)
{
+ //init to something so update method has reasonable defaults
+ _scaling_adjustment = 1.0;
+ _dsp_extra_scaling = 1.0;
+
//This is a hack/fix for the lingering packet problem.
//The caller should also flush the recv transports
if (lingering_packet){
@@ -78,7 +83,6 @@ public:
_iface->poke32(REG_RX_CTRL_VRT_HDR, 0
| (0x1 << 28) //if data with stream id
| (0x1 << 26) //has trailer
- | (0x3 << 22) //integer time other
| (0x1 << 20) //fractional time sample count
);
_iface->poke32(REG_RX_CTRL_VRT_SID, _sid);
@@ -117,8 +121,9 @@ public:
//issue the stream command
_iface->poke32(REG_RX_CTRL_STREAM_CMD, cmd_word);
- _iface->poke32(REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs()));
- _iface->poke32(REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_tick_rate)); //latches the command
+ const boost::uint64_t ticks = (stream_cmd.stream_now)? 0 : stream_cmd.time_spec.to_ticks(_tick_rate);
+ _iface->poke32(REG_RX_CTRL_TIME_HI, boost::uint32_t(ticks >> 32));
+ _iface->poke32(REG_RX_CTRL_TIME_LO, boost::uint32_t(ticks >> 0)); //latches the command
}
void set_mux(const std::string &mode, const bool fe_swapped){
@@ -175,12 +180,20 @@ public:
// Calculate closest multiplier constant to reverse gain absent scale multipliers
const double rate_pow = std::pow(double(decim & 0xff), 4);
_scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.65*rate_pow);
+ this->update_scalar();
return _tick_rate/decim_rate;
}
+ void update_scalar(void){
+ const double target_scalar = (1 << 16)*_scaling_adjustment/_dsp_extra_scaling;
+ const boost::int32_t actual_scalar = boost::math::iround(target_scalar);
+ _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small
+ _iface->poke32(REG_DSP_RX_SCALE_IQ, actual_scalar);
+ }
+
double get_scaling_adjustment(void){
- return _scaling_adjustment/_fxpt_scale_adj;
+ return _fxpt_scalar_correction*_host_extra_scaling/32767.;
}
double set_freq(const double freq_){
@@ -210,22 +223,27 @@ public:
if (_continuous_streaming) issue_stream_command(stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
}
- void set_format(const std::string &format, const unsigned scale){
+ void setup(const uhd::stream_args_t &stream_args){
+ if (not stream_args.args.has_key("noclear")) this->clear();
+
unsigned format_word = 0;
- if (format == "sc16"){
+ if (stream_args.otw_format == "sc16"){
format_word = 0;
- _fxpt_scale_adj = 32767.;
+ _dsp_extra_scaling = 1.0;
+ _host_extra_scaling = 1.0;
}
- else if (format == "sc8"){
- format_word = (1 << 18);
- _fxpt_scale_adj = 127. * scale;
- _fxpt_scale_adj /= 256; //engine 16to8 drops lower 8 bits
- _fxpt_scale_adj /= 4; //scale operation 2-bit pad
+ else if (stream_args.otw_format == "sc8"){
+ format_word = (1 << 0);
+ double peak = stream_args.args.cast<double>("peak", 1.0);
+ peak = std::max(peak, 1.0/256);
+ _host_extra_scaling = peak*256;
+ _dsp_extra_scaling = peak*256;
}
- else throw uhd::value_error("USRP RX cannot handle requested wire format: " + format);
+ else throw uhd::value_error("USRP RX cannot handle requested wire format: " + stream_args.otw_format);
+
+ this->update_scalar();
- const unsigned scale_word = scale & 0x3ffff; //18 bits;
- _iface->poke32(REG_RX_CTRL_FORMAT, format_word | scale_word);
+ _iface->poke32(REG_RX_CTRL_FORMAT, format_word);
}
private:
@@ -233,7 +251,7 @@ private:
const size_t _dsp_base, _ctrl_base;
double _tick_rate, _link_rate;
bool _continuous_streaming;
- double _scaling_adjustment, _fxpt_scale_adj;
+ double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction;
const boost::uint32_t _sid;
};
diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp
index 58be51eee..b01f751e9 100644
--- a/host/lib/usrp/cores/rx_dsp_core_200.hpp
+++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp
@@ -19,6 +19,7 @@
#define INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP
#include <uhd/config.hpp>
+#include <uhd/stream.hpp>
#include <uhd/types/ranges.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
@@ -60,7 +61,7 @@ public:
virtual void handle_overflow(void) = 0;
- virtual void set_format(const std::string &format, const unsigned scale) = 0;
+ virtual void setup(const uhd::stream_args_t &stream_args) = 0;
};
#endif /* INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP */
diff --git a/host/lib/usrp/cores/time64_core_200.cpp b/host/lib/usrp/cores/time64_core_200.cpp
index 23d1bdea2..e460d1106 100644
--- a/host/lib/usrp/cores/time64_core_200.cpp
+++ b/host/lib/usrp/cores/time64_core_200.cpp
@@ -20,11 +20,10 @@
#include <uhd/utils/assert_has.hpp>
#include <boost/math/special_functions/round.hpp>
-#define REG_TIME64_SECS _base + 0
-#define REG_TIME64_TICKS _base + 4
+#define REG_TIME64_TICKS_HI _base + 0
+#define REG_TIME64_TICKS_LO _base + 4
#define REG_TIME64_FLAGS _base + 8
#define REG_TIME64_IMM _base + 12
-#define REG_TIME64_TPS _base + 16
#define REG_TIME64_MIMO_SYNC _base + 20 //lower byte is delay cycles
//pps flags (see above)
@@ -59,39 +58,42 @@ public:
void set_tick_rate(const double rate){
_tick_rate = rate;
- _iface->poke32(REG_TIME64_TPS, boost::math::iround(rate));
}
uhd::time_spec_t get_time_now(void){
for (size_t i = 0; i < 3; i++){ //special algorithm because we cant read 64 bits synchronously
- const boost::uint32_t secs = _iface->peek32(_readback_bases.rb_secs_now);
- const boost::uint32_t ticks = _iface->peek32(_readback_bases.rb_ticks_now);
- if (secs != _iface->peek32(_readback_bases.rb_secs_now)) continue;
- return time_spec_t(secs, ticks, _tick_rate);
+ const boost::uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_now);
+ const boost::uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_now);
+ if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_now)) continue;
+ const boost::uint64_t ticks = (boost::uint64_t(ticks_hi) << 32) | ticks_lo;
+ return time_spec_t::from_ticks(ticks, _tick_rate);
}
throw uhd::runtime_error("time64_core_200: get time now timeout");
}
uhd::time_spec_t get_time_last_pps(void){
for (size_t i = 0; i < 3; i++){ //special algorithm because we cant read 64 bits synchronously
- const boost::uint32_t secs = _iface->peek32(_readback_bases.rb_secs_pps);
- const boost::uint32_t ticks = _iface->peek32(_readback_bases.rb_ticks_pps);
- if (secs != _iface->peek32(_readback_bases.rb_secs_pps)) continue;
- return time_spec_t(secs, ticks, _tick_rate);
+ const boost::uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_pps);
+ const boost::uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_pps);
+ if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_pps)) continue;
+ const boost::uint64_t ticks = (boost::uint64_t(ticks_hi) << 32) | ticks_lo;
+ return time_spec_t::from_ticks(ticks, _tick_rate);
}
throw uhd::runtime_error("time64_core_200: get time last pps timeout");
}
void set_time_now(const uhd::time_spec_t &time){
- _iface->poke32(REG_TIME64_TICKS, time.get_tick_count(_tick_rate));
+ const boost::uint64_t ticks = time.to_ticks(_tick_rate);
+ _iface->poke32(REG_TIME64_TICKS_LO, boost::uint32_t(ticks >> 0));
_iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NOW);
- _iface->poke32(REG_TIME64_SECS, boost::uint32_t(time.get_full_secs())); //latches all 3
+ _iface->poke32(REG_TIME64_TICKS_HI, boost::uint32_t(ticks >> 32)); //latches all 3
}
void set_time_next_pps(const uhd::time_spec_t &time){
- _iface->poke32(REG_TIME64_TICKS, time.get_tick_count(_tick_rate));
+ const boost::uint64_t ticks = time.to_ticks(_tick_rate);
+ _iface->poke32(REG_TIME64_TICKS_LO, boost::uint32_t(ticks >> 0));
_iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NEXT_PPS);
- _iface->poke32(REG_TIME64_SECS, boost::uint32_t(time.get_full_secs())); //latches all 3
+ _iface->poke32(REG_TIME64_TICKS_HI, boost::uint32_t(ticks >> 32)); //latches all 3
}
void set_time_source(const std::string &source){
diff --git a/host/lib/usrp/cores/time64_core_200.hpp b/host/lib/usrp/cores/time64_core_200.hpp
index ebd51a02f..7571573a5 100644
--- a/host/lib/usrp/cores/time64_core_200.hpp
+++ b/host/lib/usrp/cores/time64_core_200.hpp
@@ -31,8 +31,8 @@ public:
typedef boost::shared_ptr<time64_core_200> sptr;
struct readback_bases_type{
- size_t rb_secs_now, rb_ticks_now;
- size_t rb_secs_pps, rb_ticks_pps;
+ size_t rb_hi_now, rb_lo_now;
+ size_t rb_hi_pps, rb_lo_pps;
};
//! makes a new time64 core from iface and slave base
diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp
index c5de4e361..7f02d59ca 100644
--- a/host/lib/usrp/cores/tx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 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
@@ -18,10 +18,12 @@
#include "tx_dsp_core_200.hpp"
#include <uhd/types/dict.hpp>
#include <uhd/exception.hpp>
+#include <uhd/utils/msg.hpp>
#include <uhd/utils/algorithm.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/math/special_functions/sign.hpp>
+#include <boost/thread/thread.hpp> //sleep
#include <algorithm>
#include <cmath>
@@ -29,8 +31,8 @@
#define REG_DSP_TX_SCALE_IQ _dsp_base + 4
#define REG_DSP_TX_INTERP _dsp_base + 8
-#define REG_TX_CTRL_NUM_CHAN _ctrl_base + 0
-#define REG_TX_CTRL_CLEAR_STATE _ctrl_base + 4
+#define REG_TX_CTRL_CLEAR _ctrl_base + 0
+#define REG_TX_CTRL_FORMAT _ctrl_base + 4
#define REG_TX_CTRL_REPORT_SID _ctrl_base + 8
#define REG_TX_CTRL_POLICY _ctrl_base + 12
#define REG_TX_CTRL_CYCLES_PER_UP _ctrl_base + 16
@@ -58,14 +60,19 @@ public:
):
_iface(iface), _dsp_base(dsp_base), _ctrl_base(ctrl_base), _sid(sid)
{
+ //init to something so update method has reasonable defaults
+ _scaling_adjustment = 1.0;
+ _dsp_extra_scaling = 1.0;
+
//init the tx control registers
this->clear();
this->set_underflow_policy("next_packet");
}
void clear(void){
- _iface->poke32(REG_TX_CTRL_CLEAR_STATE, 1); //reset
- _iface->poke32(REG_TX_CTRL_NUM_CHAN, 0); //1 channel
+ _iface->poke32(REG_TX_CTRL_CLEAR, 1); //reset and flush technique
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+ _iface->poke32(REG_TX_CTRL_CLEAR, 0);
_iface->poke32(REG_TX_CTRL_REPORT_SID, _sid);
}
@@ -121,13 +128,24 @@ public:
// Calculate CIC interpolation (i.e., without halfband interpolators)
// Calculate closest multiplier constant to reverse gain absent scale multipliers
- double rate_cubed = std::pow(double(interp & 0xff), 3);
- const boost::int16_t scale = boost::math::iround((4096*std::pow(2, ceil_log2(rate_cubed)))/(1.65*rate_cubed));
- _iface->poke32(REG_DSP_TX_SCALE_IQ, (boost::uint32_t(scale) << 16) | (boost::uint32_t(scale) << 0));
+ const double rate_pow = std::pow(double(interp & 0xff), 3);
+ _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.65*rate_pow);
+ this->update_scalar();
return _tick_rate/interp_rate;
}
+ void update_scalar(void){
+ const double target_scalar = (1 << 17)*_scaling_adjustment/_dsp_extra_scaling;
+ const boost::int32_t actual_scalar = boost::math::iround(target_scalar);
+ _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small
+ _iface->poke32(REG_DSP_TX_SCALE_IQ, actual_scalar);
+ }
+
+ double get_scaling_adjustment(void){
+ return _fxpt_scalar_correction*_host_extra_scaling*32767.;
+ }
+
double set_freq(const double freq_){
//correct for outside of rate (wrap around)
double freq = std::fmod(freq_, _tick_rate);
@@ -156,10 +174,38 @@ public:
_iface->poke32(REG_TX_CTRL_PACKETS_PER_UP, (packets_per_up == 0)? 0 : (FLAG_TX_CTRL_UP_ENB | packets_per_up));
}
+ void setup(const uhd::stream_args_t &stream_args){
+ if (not stream_args.args.has_key("noclear")) this->clear();
+
+ unsigned format_word = 0;
+ if (stream_args.otw_format == "sc16"){
+ format_word = 0;
+ _dsp_extra_scaling = 1.0;
+ _host_extra_scaling = 1.0;
+ }
+ else if (stream_args.otw_format == "sc8"){
+ format_word = (1 << 0);
+ double peak = stream_args.args.cast<double>("peak", 1.0);
+ peak = std::max(peak, 1.0/256);
+ _host_extra_scaling = 1.0/peak/256;
+ _dsp_extra_scaling = 1.0/peak;
+ }
+ else throw uhd::value_error("USRP TX cannot handle requested wire format: " + stream_args.otw_format);
+
+ this->update_scalar();
+
+ _iface->poke32(REG_TX_CTRL_FORMAT, format_word);
+
+ if (stream_args.args.has_key("underflow_policy")){
+ this->set_underflow_policy(stream_args.args["underflow_policy"]);
+ }
+ }
+
private:
wb_iface::sptr _iface;
const size_t _dsp_base, _ctrl_base;
double _tick_rate, _link_rate;
+ double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction;
const boost::uint32_t _sid;
};
diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp
index 4b39a5b07..0e1cfb6bc 100644
--- a/host/lib/usrp/cores/tx_dsp_core_200.hpp
+++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp
@@ -19,6 +19,7 @@
#define INCLUDED_LIBUHD_USRP_TX_DSP_CORE_200_HPP
#include <uhd/config.hpp>
+#include <uhd/stream.hpp>
#include <uhd/types/ranges.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
@@ -44,14 +45,15 @@ public:
virtual uhd::meta_range_t get_host_rates(void) = 0;
+ virtual double get_scaling_adjustment(void) = 0;
+
virtual uhd::meta_range_t get_freq_range(void) = 0;
virtual double set_freq(const double freq) = 0;
virtual void set_updates(const size_t cycles_per_up, const size_t packets_per_up) = 0;
- virtual void set_underflow_policy(const std::string &policy) = 0;
-
+ virtual void setup(const uhd::stream_args_t &stream_args) = 0;
};
#endif /* INCLUDED_LIBUHD_USRP_TX_DSP_CORE_200_HPP */
diff --git a/host/lib/usrp/cores/user_settings_core_200.cpp b/host/lib/usrp/cores/user_settings_core_200.cpp
new file mode 100644
index 000000000..d262631b1
--- /dev/null
+++ b/host/lib/usrp/cores/user_settings_core_200.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright 2012 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 "user_settings_core_200.hpp"
+
+#define REG_USER_ADDR _base + 0
+#define REG_USER_DATA _base + 4
+
+class user_settings_core_200_impl : public user_settings_core_200{
+public:
+ user_settings_core_200_impl(wb_iface::sptr iface, const size_t base):
+ _iface(iface), _base(base)
+ {
+ //NOP
+ }
+
+ void set_reg(const user_reg_t &reg){
+ _iface->poke32(REG_USER_ADDR, reg.first);
+ _iface->poke32(REG_USER_DATA, reg.second);
+ }
+
+private:
+ wb_iface::sptr _iface;
+ const size_t _base;
+};
+
+user_settings_core_200::sptr user_settings_core_200::make(wb_iface::sptr iface, const size_t base){
+ return sptr(new user_settings_core_200_impl(iface, base));
+}
diff --git a/host/lib/usrp/cores/user_settings_core_200.hpp b/host/lib/usrp/cores/user_settings_core_200.hpp
new file mode 100644
index 000000000..1f5d13de7
--- /dev/null
+++ b/host/lib/usrp/cores/user_settings_core_200.hpp
@@ -0,0 +1,36 @@
+//
+// Copyright 2012 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_LIBUHD_USRP_USER_SETTINGS_CORE_200_HPP
+#define INCLUDED_LIBUHD_USRP_USER_SETTINGS_CORE_200_HPP
+
+#include <uhd/config.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include "wb_iface.hpp"
+
+class user_settings_core_200 : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<user_settings_core_200> sptr;
+ typedef std::pair<boost::uint8_t, boost::uint32_t> user_reg_t;
+
+ static sptr make(wb_iface::sptr iface, const size_t base);
+
+ virtual void set_reg(const user_reg_t &reg) = 0;
+};
+
+#endif /* INCLUDED_LIBUHD_USRP_USER_SETTINGS_CORE_200_HPP */
diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp
index f58138ae6..a01ce4a7b 100644
--- a/host/lib/usrp/e100/e100_impl.cpp
+++ b/host/lib/usrp/e100/e100_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -326,10 +326,10 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){
// create time control objects
////////////////////////////////////////////////////////////////////
time64_core_200::readback_bases_type time64_rb_bases;
- time64_rb_bases.rb_secs_now = E100_REG_RB_TIME_NOW_SECS;
- time64_rb_bases.rb_ticks_now = E100_REG_RB_TIME_NOW_TICKS;
- time64_rb_bases.rb_secs_pps = E100_REG_RB_TIME_PPS_SECS;
- time64_rb_bases.rb_ticks_pps = E100_REG_RB_TIME_PPS_TICKS;
+ time64_rb_bases.rb_hi_now = E100_REG_RB_TIME_NOW_HI;
+ time64_rb_bases.rb_lo_now = E100_REG_RB_TIME_NOW_LO;
+ time64_rb_bases.rb_hi_pps = E100_REG_RB_TIME_PPS_HI;
+ time64_rb_bases.rb_lo_pps = E100_REG_RB_TIME_PPS_LO;
_time64 = time64_core_200::make(
_fpga_ctrl, E100_REG_SR_ADDR(UE_SR_TIME64), time64_rb_bases
);
@@ -353,6 +353,13 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){
_tree->create<std::vector<std::string> >(mb_path / "clock_source/options").set(clock_sources);
////////////////////////////////////////////////////////////////////
+ // create user-defined control objects
+ ////////////////////////////////////////////////////////////////////
+ _user = user_settings_core_200::make(_fpga_ctrl, E100_REG_SR_ADDR(UE_SR_USER_REGS));
+ _tree->create<user_settings_core_200::user_reg_t>(mb_path / "user/regs")
+ .subscribe(boost::bind(&user_settings_core_200::set_reg, _user, _1));
+
+ ////////////////////////////////////////////////////////////////////
// create dboard control objects
////////////////////////////////////////////////////////////////////
diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp
index 2ea890375..1d36cb2ac 100644
--- a/host/lib/usrp/e100/e100_impl.hpp
+++ b/host/lib/usrp/e100/e100_impl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -25,6 +25,7 @@
#include "rx_dsp_core_200.hpp"
#include "tx_dsp_core_200.hpp"
#include "time64_core_200.hpp"
+#include "user_settings_core_200.hpp"
#include <uhd/device.hpp>
#include <uhd/property_tree.hpp>
#include <uhd/utils/pimpl.hpp>
@@ -48,7 +49,7 @@ static const double E100_RX_LINK_RATE_BPS = 166e6/3/2*2;
static const double E100_TX_LINK_RATE_BPS = 166e6/3/1*2;
static const std::string E100_I2C_DEV_NODE = "/dev/i2c-3";
static const std::string E100_UART_DEV_NODE = "/dev/ttyO0";
-static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x08;
+static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x09;
static const boost::uint32_t E100_RX_SID_BASE = 2;
static const boost::uint32_t E100_TX_ASYNC_SID = 1;
static const double E100_DEFAULT_CLOCK_RATE = 64e6;
@@ -92,6 +93,7 @@ private:
std::vector<rx_dsp_core_200::sptr> _rx_dsps;
tx_dsp_core_200::sptr _tx_dsp;
time64_core_200::sptr _time64;
+ user_settings_core_200::sptr _user;
e100_clock_ctrl::sptr _clock_ctrl;
e100_codec_ctrl::sptr _codec_ctrl;
e100_ctrl::sptr _fpga_ctrl;
diff --git a/host/lib/usrp/e100/e100_regs.hpp b/host/lib/usrp/e100/e100_regs.hpp
index f24f5895b..75be2cfbe 100644
--- a/host/lib/usrp/e100/e100_regs.hpp
+++ b/host/lib/usrp/e100/e100_regs.hpp
@@ -1,4 +1,19 @@
-
+//
+// Copyright 2010-2012 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/>.
+//
////////////////////////////////////////////////////////////////
//
@@ -71,10 +86,10 @@
#define E100_REG_RB_MUX_32_BASE E100_REG_SLAVE(7)
-#define E100_REG_RB_TIME_NOW_SECS E100_REG_RB_MUX_32_BASE + 0
-#define E100_REG_RB_TIME_NOW_TICKS E100_REG_RB_MUX_32_BASE + 4
-#define E100_REG_RB_TIME_PPS_SECS E100_REG_RB_MUX_32_BASE + 8
-#define E100_REG_RB_TIME_PPS_TICKS E100_REG_RB_MUX_32_BASE + 12
+#define E100_REG_RB_TIME_NOW_HI E100_REG_RB_MUX_32_BASE + 0
+#define E100_REG_RB_TIME_NOW_LO E100_REG_RB_MUX_32_BASE + 4
+#define E100_REG_RB_TIME_PPS_HI E100_REG_RB_MUX_32_BASE + 8
+#define E100_REG_RB_TIME_PPS_LO E100_REG_RB_MUX_32_BASE + 12
#define E100_REG_RB_MISC_TEST32 E100_REG_RB_MUX_32_BASE + 16
#define E100_REG_RB_ERR_STATUS E100_REG_RB_MUX_32_BASE + 20
#define E100_REG_RB_COMPAT E100_REG_RB_MUX_32_BASE + 24
@@ -101,9 +116,9 @@
#define UE_SR_TX_FRONT 54 // 5 regs (+0 to +4)
#define UE_SR_REG_TEST32 60 // 1 reg
-#define UE_SR_CLEAR_RX_FIFO 61 // 1 reg
-#define UE_SR_CLEAR_TX_FIFO 62 // 1 reg
+#define UE_SR_CLEAR_FIFO 61 // 1 reg
#define UE_SR_GLOBAL_RESET 63 // 1 reg
+#define UE_SR_USER_REGS 64 // 2 regs
#define UE_SR_GPIO 128
@@ -115,8 +130,7 @@
/////////////////////////////////////////////////
// Magic reset regs
////////////////////////////////////////////////
-#define E100_REG_CLEAR_RX E100_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO)
-#define E100_REG_CLEAR_TX E100_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO)
+#define E100_REG_CLEAR_FIFO E100_REG_SR_ADDR(UE_SR_CLEAR_FIFO)
#define E100_REG_GLOBAL_RESET E100_REG_SR_ADDR(UE_SR_GLOBAL_RESET)
#endif
diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp
index 441e32a8d..e9608125f 100644
--- a/host/lib/usrp/e100/io_impl.cpp
+++ b/host/lib/usrp/e100/io_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -17,6 +17,7 @@
#include "recv_packet_demuxer.hpp"
#include "validate_subdev_spec.hpp"
+#include "async_packet_handler.hpp"
#include "../../transport/super_recv_packet_handler.hpp"
#include "../../transport/super_send_packet_handler.hpp"
#include <linux/usrp_e.h> //ioctl structures and constants
@@ -50,7 +51,7 @@ using namespace uhd::transport;
**********************************************************************/
struct e100_impl::io_impl{
io_impl(void):
- false_alarm(0), async_msg_fifo(100/*messages deep*/)
+ false_alarm(0), async_msg_fifo(1000/*messages deep*/)
{ /* NOP */ }
double tick_rate; //set by update tick rate method
@@ -123,28 +124,13 @@ void e100_impl::io_impl::handle_irq(void){
//fill in the async metadata
async_metadata_t metadata;
- metadata.channel = 0;
- metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf;
- metadata.time_spec = time_spec_t(
- time_t(if_packet_info.tsi), long(if_packet_info.tsf), tick_rate
- );
- metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(data.buf, if_packet_info));
+ load_metadata_from_buff(uhd::wtohx<boost::uint32_t>, metadata, if_packet_info, data.buf, tick_rate);
//push the message onto the queue
async_msg_fifo.push_with_pop_on_full(metadata);
//print some fastpath messages
- if (metadata.event_code &
- ( async_metadata_t::EVENT_CODE_UNDERFLOW
- | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET)
- ) UHD_MSG(fastpath) << "U";
- else if (metadata.event_code &
- ( async_metadata_t::EVENT_CODE_SEQ_ERROR
- | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST)
- ) UHD_MSG(fastpath) << "S";
- else if (metadata.event_code &
- async_metadata_t::EVENT_CODE_TIME_ERROR
- ) UHD_MSG(fastpath) << "L";
+ standard_async_msg_prints(metadata);
}
//prepare for the next round
@@ -164,9 +150,8 @@ void e100_impl::io_init(void){
_io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), E100_RX_SID_BASE);
_io_impl->iface = _fpga_ctrl;
- //clear state machines
- _fpga_ctrl->poke32(E100_REG_CLEAR_RX, 0);
- _fpga_ctrl->poke32(E100_REG_CLEAR_TX, 0);
+ //clear fifo state machines
+ _fpga_ctrl->poke32(E100_REG_CLEAR_FIFO, 0);
//allocate streamer weak ptrs containers
_rx_streamers.resize(_rx_dsps.size());
@@ -217,6 +202,8 @@ void e100_impl::update_tx_samp_rate(const size_t dspno, const double rate){
if (my_streamer.get() == NULL) return;
my_streamer->set_samp_rate(rate);
+ const double adj = _tx_dsp->get_scaling_adjustment();
+ my_streamer->set_scale_factor(adj);
}
void e100_impl::update_rates(void){
@@ -278,13 +265,13 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){
//setup defaults for unspecified values
args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
- const unsigned sc8_scalar = unsigned(args.args.cast<double>("scalar", 0x400));
//calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size;
const size_t bpi = convert::get_bytes_per_item(args.otw_format);
@@ -309,8 +296,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){
for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){
const size_t dsp = args.channels[chan_i];
_rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this
- if (not args.args.has_key("noclear")) _rx_dsps[dsp]->clear();
- _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar);
+ _rx_dsps[dsp]->setup(args);
my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
&recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1
), true /*flush*/);
@@ -336,14 +322,13 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){
args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
- if (args.otw_format != "sc16"){
- throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format);
- }
-
//calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
+ - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size;
const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format);
@@ -367,8 +352,7 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){
for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){
const size_t dsp = args.channels[chan_i];
UHD_ASSERT_THROW(dsp == 0); //always 0
- if (not args.args.has_key("noclear")) _tx_dsp->clear();
- if (args.args.has_key("underflow_policy")) _tx_dsp->set_underflow_policy(args.args["underflow_policy"]);
+ _tx_dsp->setup(args);
my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
&zero_copy_if::get_send_buff, _data_transport, _1
));
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 6cd9f95bb..d9be19b83 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -445,6 +445,17 @@ public:
return _tree->list(mb_root(mboard) / "sensors");
}
+ void set_user_register(const boost::uint8_t addr, const boost::uint32_t data, size_t mboard){
+ if (mboard != ALL_MBOARDS){
+ typedef std::pair<boost::uint8_t, boost::uint32_t> user_reg_t;
+ _tree->access<user_reg_t>(mb_root(mboard) / "user/reg").set(user_reg_t(addr, data));
+ return;
+ }
+ for (size_t m = 0; m < get_num_mboards(); m++){
+ set_user_register(addr, data, m);
+ }
+ }
+
/*******************************************************************
* RX methods
******************************************************************/
diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp
index e9d9b65c2..f27135562 100644
--- a/host/lib/usrp/usrp1/io_impl.cpp
+++ b/host/lib/usrp/usrp1/io_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -221,17 +221,17 @@ void usrp1_impl::io_init(void){
_io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport));
- //create a new vandal thread to poll xerflow conditions
- _io_impl->vandal_task = task::make(boost::bind(
- &usrp1_impl::vandal_conquest_loop, this
- ));
-
//init as disabled, then call the real function (uses restore)
this->enable_rx(false);
this->enable_tx(false);
rx_stream_on_off(false);
tx_stream_on_off(false);
_io_impl->flush_send_buff();
+
+ //create a new vandal thread to poll xerflow conditions
+ _io_impl->vandal_task = task::make(boost::bind(
+ &usrp1_impl::vandal_conquest_loop, this
+ ));
}
void usrp1_impl::rx_stream_on_off(bool enb){
diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
index b8af8af06..90b3a92da 100644
--- a/host/lib/usrp/usrp1/soft_time_ctrl.cpp
+++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
@@ -39,8 +39,8 @@ public:
_nsamps_remaining(0),
_stream_mode(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS),
_cmd_queue(2),
- _async_msg_queue(100),
- _inline_msg_queue(100),
+ _async_msg_queue(1000),
+ _inline_msg_queue(1000),
_stream_on_off(stream_on_off)
{
//synchronously spawn a new thread
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index ef8ae950d..430ea59c8 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -210,6 +210,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){
////////////////////////////////////////////////////////////////////
// Initialize the properties tree
////////////////////////////////////////////////////////////////////
+ _rx_dc_offset_shadow = 0;
_tree = property_tree::make();
_tree->create<std::string>("/name").set("USRP1 Device");
const fs_path mb_path = "/mboards/0";
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 1af1db860..0babf7445 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -30,9 +30,9 @@ extern "C" {
#endif
//fpga and firmware compatibility numbers
-#define USRP2_FPGA_COMPAT_NUM 8
+#define USRP2_FPGA_COMPAT_NUM 9
#define USRP2_FW_COMPAT_NUM 11
-#define USRP2_FW_VER_MINOR 1
+#define USRP2_FW_VER_MINOR 2
//used to differentiate control packets over data port
#define USRP2_INVALID_VRT_HEADER 0
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index e3fa46920..d32ffb62c 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -16,6 +16,7 @@
//
#include "validate_subdev_spec.hpp"
+#include "async_packet_handler.hpp"
#include "../../transport/super_recv_packet_handler.hpp"
#include "../../transport/super_send_packet_handler.hpp"
#include "usrp2_impl.hpp"
@@ -135,7 +136,8 @@ private:
struct usrp2_impl::io_impl{
io_impl(void):
- async_msg_fifo(100/*messages deep*/)
+ async_msg_fifo(1000/*messages deep*/),
+ tick_rate(1 /*non-zero default*/)
{
/* NOP */
}
@@ -201,12 +203,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(
//fill in the async metadata
async_metadata_t metadata;
- metadata.channel = index;
- metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf;
- metadata.time_spec = time_spec_t(
- time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), tick_rate
- );
- metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info));
+ load_metadata_from_buff(uhd::ntohx<boost::uint32_t>, metadata, if_packet_info, vrt_hdr, tick_rate, index);
//catch the flow control packets and react
if (metadata.event_code == 0){
@@ -217,17 +214,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(
//else UHD_MSG(often) << "metadata.event_code " << metadata.event_code << std::endl;
async_msg_fifo.push_with_pop_on_full(metadata);
- if (metadata.event_code &
- ( async_metadata_t::EVENT_CODE_UNDERFLOW
- | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET)
- ) UHD_MSG(fastpath) << "U";
- else if (metadata.event_code &
- ( async_metadata_t::EVENT_CODE_SEQ_ERROR
- | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST)
- ) UHD_MSG(fastpath) << "S";
- else if (metadata.event_code &
- async_metadata_t::EVENT_CODE_TIME_ERROR
- ) UHD_MSG(fastpath) << "L";
+ standard_async_msg_prints(metadata);
}
else{
//TODO unknown received packet, may want to print error...
@@ -307,6 +294,8 @@ void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, co
if (my_streamer.get() == NULL) return;
my_streamer->set_samp_rate(rate);
+ const double adj = _mbc[mb].tx_dsp->get_scaling_adjustment();
+ my_streamer->set_scale_factor(adj);
}
void usrp2_impl::update_rates(void){
@@ -380,13 +369,13 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){
//setup defaults for unspecified values
args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
- const unsigned sc8_scalar = unsigned(args.args.cast<double>("scalar", 0x400));
//calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size;
const size_t bpi = convert::get_bytes_per_item(args.otw_format);
@@ -416,8 +405,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){
if (chan < num_chan_so_far){
const size_t dsp = chan + _mbc[mb].rx_chan_occ - num_chan_so_far;
_mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this
- if (not args.args.has_key("noclear")) _mbc[mb].rx_dsps[dsp]->clear();
- _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar);
+ _mbc[mb].rx_dsps[dsp]->setup(args);
my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
&zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1
), true /*flush*/);
@@ -447,15 +435,14 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){
args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
- if (args.otw_format != "sc16"){
- throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format);
- }
-
//calculate packet size
static const size_t hdr_size = 0
- + vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ vrt_send_header_offset_words32*sizeof(boost::uint32_t)
+ + vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
+ + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
+ - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used
+ - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size;
const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format);
@@ -485,10 +472,9 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){
if (chan < num_chan_so_far){
const size_t dsp = chan + _mbc[mb].tx_chan_occ - num_chan_so_far;
if (not args.args.has_key("noclear")){
- _mbc[mb].tx_dsp->clear();
_io_impl->fc_mons[abs]->clear();
}
- if (args.args.has_key("underflow_policy")) _mbc[mb].tx_dsp->set_underflow_policy(args.args["underflow_policy"]);
+ _mbc[mb].tx_dsp->setup(args);
my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(
&usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, _1
));
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index 4830c10d9..eeba6756e 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -87,7 +87,7 @@ public:
//Obtain the firmware's compat number.
//Save the response compat number for communication.
//TODO can choose to reject certain older compat numbers
- usrp2_ctrl_data_t ctrl_data;
+ usrp2_ctrl_data_t ctrl_data = usrp2_ctrl_data_t();
ctrl_data.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);
ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0);
if (ntohl(ctrl_data.id) != USRP2_CTRL_ID_WAZZUP_DUDE)
@@ -126,10 +126,9 @@ public:
bool is_device_locked(void){
boost::uint32_t lock_secs = this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_PEEK32>(U2_FW_REG_LOCK_TIME);
boost::uint32_t lock_gpid = this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_PEEK32>(U2_FW_REG_LOCK_GPID);
- boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_SECS_RB_IMM);
//if the difference is larger, assume not locked anymore
- if (curr_secs - lock_secs >= 3) return false;
+ if (this->get_curr_secs() - lock_secs >= 3) return false;
//otherwise only lock if the device hash is different that ours
return lock_gpid != boost::uint32_t(get_gpid());
@@ -137,12 +136,16 @@ public:
void lock_task(void){
//re-lock in task
- boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_SECS_RB_IMM);
- this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_POKE32>(U2_FW_REG_LOCK_TIME, curr_secs);
+ this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_POKE32>(U2_FW_REG_LOCK_TIME, this->get_curr_secs());
//sleep for a bit
boost::this_thread::sleep(boost::posix_time::milliseconds(1500));
}
+ boost::uint32_t get_curr_secs(void){
+ //may not be the right tick rate, but this is ok for locking purposes
+ return boost::uint32_t(this->peek32(U2_REG_TIME64_LO_RB_IMM)/100e6);
+ }
+
/***********************************************************************
* Peek and Poke
**********************************************************************/
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index ef7151cee..2077ab009 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -546,10 +546,10 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
// create time control objects
////////////////////////////////////////////////////////////////
time64_core_200::readback_bases_type time64_rb_bases;
- time64_rb_bases.rb_secs_now = U2_REG_TIME64_SECS_RB_IMM;
- time64_rb_bases.rb_ticks_now = U2_REG_TIME64_TICKS_RB_IMM;
- time64_rb_bases.rb_secs_pps = U2_REG_TIME64_SECS_RB_PPS;
- time64_rb_bases.rb_ticks_pps = U2_REG_TIME64_TICKS_RB_PPS;
+ time64_rb_bases.rb_hi_now = U2_REG_TIME64_HI_RB_IMM;
+ time64_rb_bases.rb_lo_now = U2_REG_TIME64_LO_RB_IMM;
+ time64_rb_bases.rb_hi_pps = U2_REG_TIME64_HI_RB_PPS;
+ time64_rb_bases.rb_lo_pps = U2_REG_TIME64_LO_RB_PPS;
_mbc[mb].time64 = time64_core_200::make(
_mbc[mb].iface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles
);
@@ -572,6 +572,13 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){
static const std::vector<std::string> clock_sources = boost::assign::list_of("internal")("external")("mimo");
_tree->create<std::vector<std::string> >(mb_path / "clock_source/options").set(clock_sources);
+ ////////////////////////////////////////////////////////////////////
+ // create user-defined control objects
+ ////////////////////////////////////////////////////////////////////
+ _mbc[mb].user = user_settings_core_200::make(_mbc[mb].iface, U2_REG_SR_ADDR(SR_USER_REGS));
+ _tree->create<user_settings_core_200::user_reg_t>(mb_path / "user/regs")
+ .subscribe(boost::bind(&user_settings_core_200::set_reg, _mbc[mb].user, _1));
+
////////////////////////////////////////////////////////////////
// create dboard control objects
////////////////////////////////////////////////////////////////
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 278dc713e..882a61f80 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -26,6 +26,7 @@
#include "rx_dsp_core_200.hpp"
#include "tx_dsp_core_200.hpp"
#include "time64_core_200.hpp"
+#include "user_settings_core_200.hpp"
#include <uhd/property_tree.hpp>
#include <uhd/usrp/gps_ctrl.hpp>
#include <uhd/device.hpp>
@@ -91,6 +92,7 @@ private:
std::vector<boost::weak_ptr<uhd::tx_streamer> > tx_streamers;
tx_dsp_core_200::sptr tx_dsp;
time64_core_200::sptr time64;
+ user_settings_core_200::sptr user;
std::vector<uhd::transport::zero_copy_if::sptr> rx_dsp_xports;
uhd::transport::zero_copy_if::sptr tx_dsp_xport;
uhd::usrp::dboard_manager::sptr dboard_manager;
diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp
index 179a930c6..e14798ecb 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.hpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2011 Ettus Research LLC
+// Copyright 2010-2012 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
@@ -39,7 +39,7 @@
#define SR_SIMTIMER 8 // 2
#define SR_TIME64 10 // 6
#define SR_BUF_POOL 16 // 4
-
+#define SR_USER_REGS 20 // 2
#define SR_RX_FRONT 24 // 5
#define SR_RX_CTRL0 32 // 9
#define SR_RX_DSP0 48 // 7
@@ -97,11 +97,11 @@
////////////////////////////////////////////////
#define U2_REG_STATUS READBACK_BASE + 4*8
#define U2_REG_GPIO_RB READBACK_BASE + 4*9
-#define U2_REG_TIME64_SECS_RB_IMM READBACK_BASE + 4*10
-#define U2_REG_TIME64_TICKS_RB_IMM READBACK_BASE + 4*11
+#define U2_REG_TIME64_HI_RB_IMM READBACK_BASE + 4*10
+#define U2_REG_TIME64_LO_RB_IMM READBACK_BASE + 4*11
#define U2_REG_COMPAT_NUM_RB READBACK_BASE + 4*12
#define U2_REG_IRQ_RB READBACK_BASE + 4*13
-#define U2_REG_TIME64_SECS_RB_PPS READBACK_BASE + 4*14
-#define U2_REG_TIME64_TICKS_RB_PPS READBACK_BASE + 4*15
+#define U2_REG_TIME64_HI_RB_PPS READBACK_BASE + 4*14
+#define U2_REG_TIME64_LO_RB_PPS READBACK_BASE + 4*15
#endif /* INCLUDED_USRP2_REGS_HPP */