aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/stream.hpp9
-rw-r--r--host/lib/convert/convert_common.hpp48
-rw-r--r--host/lib/convert/convert_with_tables.cpp21
-rw-r--r--host/lib/convert/gen_convert_general.py16
-rw-r--r--[-rwxr-xr-x]host/lib/transport/gen_vrt_if_packet.py0
-rw-r--r--host/lib/transport/super_send_packet_handler.hpp2
-rw-r--r--host/lib/usrp/b100/io_impl.cpp1
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_200.cpp17
-rw-r--r--host/lib/usrp/cores/tx_dsp_core_200.cpp25
-rw-r--r--host/lib/usrp/e100/io_impl.cpp1
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp1
11 files changed, 110 insertions, 31 deletions
diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp
index 0c9282545..cec2eee79 100644
--- a/host/include/uhd/stream.hpp
+++ b/host/include/uhd/stream.hpp
@@ -79,10 +79,11 @@ struct UHD_API stream_args_t{
* The args parameter is used to pass arbitrary key/value pairs.
* Possible keys used by args (depends on implementation):
*
- * - scalar: an integer scaling factor used with the sc8 wire format.
- * Use scalar=1 to harvest the lower 8-bits.
- * Use scalar=256 to harvest the upper 8-bits.
- * Any scalar in-between is also a possibility.
+ * - peak: specifies a fractional sample level to calculate scaling with the sc8 wire format.
+ * When using sc8 samples over the wire, the device must scale samples
+ * (both on the host and in the device) to satisfy the dynamic range needs.
+ * The peak value specifies a fraction of the maximum sample level (1.0 = 100%).
+ * Set peak to max_sample_level/full_scale_level to ensure optimum dynamic range.
*
* - underflow_policy: how the TX DSP should recover from underflow.
* Possible options are "next_burst" or "next_packet".
diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp
index 699d6301b..aab59de4b 100644
--- a/host/lib/convert/convert_common.hpp
+++ b/host/lib/convert/convert_common.hpp
@@ -190,4 +190,52 @@ static UHD_INLINE void item32_sc8_to_fc64(item32_t item, fc64_t &out0, fc64_t &o
);
}
+/***********************************************************************
+ * Convert complex char to items32 sc8 buffer
+ **********************************************************************/
+static UHD_INLINE item32_t sc8_to_item32_sc8(sc8_t in0, sc8_t in1, double){
+ return
+ (item32_t(boost::uint8_t(in0.real())) << 8) |
+ (item32_t(boost::uint8_t(in0.imag())) << 0) |
+ (item32_t(boost::uint8_t(in1.real())) << 24) |
+ (item32_t(boost::uint8_t(in1.imag())) << 16)
+ ;
+}
+
+/***********************************************************************
+ * Convert complex short to items32 sc8 buffer
+ **********************************************************************/
+static UHD_INLINE item32_t sc16_to_item32_sc8(sc16_t in0, sc16_t in1, double){
+ return
+ (item32_t(boost::uint8_t(in0.real())) << 8) |
+ (item32_t(boost::uint8_t(in0.imag())) << 0) |
+ (item32_t(boost::uint8_t(in1.real())) << 24) |
+ (item32_t(boost::uint8_t(in1.imag())) << 16)
+ ;
+}
+
+/***********************************************************************
+ * Convert complex float to items32 sc8 buffer
+ **********************************************************************/
+static UHD_INLINE item32_t fc32_to_item32_sc8(fc32_t in0, fc32_t in1, double scale_factor){
+ return
+ (item32_t(boost::uint8_t(in0.real()*float(scale_factor))) << 8) |
+ (item32_t(boost::uint8_t(in0.imag()*float(scale_factor))) << 0) |
+ (item32_t(boost::uint8_t(in1.real()*float(scale_factor))) << 24) |
+ (item32_t(boost::uint8_t(in1.imag()*float(scale_factor))) << 16)
+ ;
+}
+
+/***********************************************************************
+ * Convert complex double to items32 sc8 buffer
+ **********************************************************************/
+static UHD_INLINE item32_t fc64_to_item32_sc8(fc64_t in0, fc64_t in1, double scale_factor){
+ return
+ (item32_t(boost::uint8_t(in0.real()*(scale_factor))) << 8) |
+ (item32_t(boost::uint8_t(in0.imag()*(scale_factor))) << 0) |
+ (item32_t(boost::uint8_t(in1.real()*(scale_factor))) << 24) |
+ (item32_t(boost::uint8_t(in1.imag()*(scale_factor))) << 16)
+ ;
+}
+
#endif /* INCLUDED_LIBUHD_CONVERT_COMMON_HPP */
diff --git a/host/lib/convert/convert_with_tables.cpp b/host/lib/convert/convert_with_tables.cpp
index c033a2959..2379739a7 100644
--- a/host/lib/convert/convert_with_tables.cpp
+++ b/host/lib/convert/convert_with_tables.cpp
@@ -68,24 +68,19 @@ class convert_sc8_item32_1_to_fcxx_1 : public converter{
public:
convert_sc8_item32_1_to_fcxx_1(void): _table(sc16_table_len){}
- void set_scalar(const double scalar){
-
- //special case, this is converts sc8 to sc16,
- //use the scale-factor but no normalization
+ //special case for sc16 type, 32767 undoes float normalization
+ static type conv(const boost::int8_t &num, const double scalar){
if (sizeof(type) == sizeof(s16_t)){
- for (size_t i = 0; i < sc16_table_len; i++){
- const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff));
- const type real = type(boost::math::iround(boost::int8_t(val >> 8)*scalar*32767));
- const type imag = type(boost::math::iround(boost::int8_t(val >> 0)*scalar*32767));
- _table[i] = std::complex<type>(real, imag);
- }
- return;
+ return type(boost::math::iround(num*scalar*32767));
}
+ return type(num*scalar);
+ }
+ void set_scalar(const double scalar){
for (size_t i = 0; i < sc16_table_len; i++){
const boost::uint16_t val = tohost(boost::uint16_t(i & 0xffff));
- const type real = type(boost::int8_t(val >> 8)*scalar);
- const type imag = type(boost::int8_t(val >> 0)*scalar);
+ const type real = conv(boost::int8_t(val >> 8), scalar);
+ const type imag = conv(boost::int8_t(val >> 0), scalar);
_table[i] = std::complex<type>(real, imag);
}
}
diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py
index b8d64aa4b..a6ae3f810 100644
--- a/host/lib/convert/gen_convert_general.py
+++ b/host/lib/convert/gen_convert_general.py
@@ -92,6 +92,22 @@ DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){
item32_sc8_to_$(cpu_type)(item_n, output[num_samps-1], dummy, scale_factor);
}
}
+
+DECLARE_CONVERTER($(cpu_type), 1, sc8_item32_$(end), 1, PRIORITY_GENERAL){
+ const $(cpu_type)_t *input = reinterpret_cast<const $(cpu_type)_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ const size_t num_pairs = nsamps/2;
+ for (size_t i = 0, j = 0; i < num_pairs; i++, j+=2){
+ const item32_t item = $(cpu_type)_to_item32_sc8(input[j], input[j+1], scale_factor);
+ output[i] = $(to_wire)(item);
+ }
+
+ if (nsamps != num_pairs*2){
+ const item32_t item = $(cpu_type)_to_item32_sc8(input[nsamps-1], 0, scale_factor);
+ output[num_pairs] = $(to_wire)(item);
+ }
+}
"""
TMPL_CONV_USRP1_COMPLEX = """
diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py
index 245a7ddbd..245a7ddbd 100755..100644
--- a/host/lib/transport/gen_vrt_if_packet.py
+++ b/host/lib/transport/gen_vrt_if_packet.py
diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp
index 5ed8e0143..57304a7d4 100644
--- a/host/lib/transport/super_send_packet_handler.hpp
+++ b/host/lib/transport/super_send_packet_handler.hpp
@@ -134,7 +134,7 @@ public:
vrt::if_packet_info_t if_packet_info;
if_packet_info.has_sid = false;
if_packet_info.has_cid = false;
- if_packet_info.has_tlr = false;
+ if_packet_info.has_tlr = true;
if_packet_info.has_tsi = metadata.has_time_spec;
if_packet_info.has_tsf = metadata.has_time_spec;
if_packet_info.tsi = boost::uint32_t(metadata.time_spec.get_full_secs());
diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp
index 6e9e017aa..9474268ef 100644
--- a/host/lib/usrp/b100/io_impl.cpp
+++ b/host/lib/usrp/b100/io_impl.cpp
@@ -263,6 +263,7 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){
//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
;
static const size_t bpp = 2048 - hdr_size;
diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp
index b2bf934bc..7b35daa42 100644
--- a/host/lib/usrp/cores/rx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp
@@ -63,8 +63,7 @@ public:
{
//init to something so update method has reasonable defaults
_scaling_adjustment = 1.0;
- _extra_scaling = 1.0;
- _fxpt_scalar_correction = 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
@@ -187,14 +186,14 @@ public:
}
void update_scalar(void){
- const double target_scalar = (1 << 16)*_scaling_adjustment/_extra_scaling;
+ 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 _fxpt_scalar_correction*_extra_scaling/32767.;
+ return _fxpt_scalar_correction*_host_extra_scaling/32767.;
}
double set_freq(const double freq_){
@@ -230,11 +229,15 @@ public:
unsigned format_word = 0;
if (stream_args.otw_format == "sc16"){
format_word = 0;
- _extra_scaling = 1.0;
+ _dsp_extra_scaling = 1.0;
+ _host_extra_scaling = 1.0;
}
else if (stream_args.otw_format == "sc8"){
format_word = (1 << 0);
- _extra_scaling = stream_args.args.cast<double>("scalar", 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: " + stream_args.otw_format);
@@ -248,7 +251,7 @@ private:
const size_t _dsp_base, _ctrl_base;
double _tick_rate, _link_rate;
bool _continuous_streaming;
- double _scaling_adjustment, _extra_scaling, _fxpt_scalar_correction;
+ 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.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp
index 2c5b86bfc..15358e184 100644
--- a/host/lib/usrp/cores/tx_dsp_core_200.cpp
+++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp
@@ -18,6 +18,7 @@
#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>
@@ -35,6 +36,7 @@
#define REG_TX_CTRL_POLICY _ctrl_base + 12
#define REG_TX_CTRL_CYCLES_PER_UP _ctrl_base + 16
#define REG_TX_CTRL_PACKETS_PER_UP _ctrl_base + 20
+#define REG_TX_CTRL_FORMAT _ctrl_base + 24
#define FLAG_TX_CTRL_POLICY_WAIT (0x1 << 0)
#define FLAG_TX_CTRL_POLICY_NEXT_PACKET (0x1 << 1)
@@ -60,8 +62,7 @@ public:
{
//init to something so update method has reasonable defaults
_scaling_adjustment = 1.0;
- _extra_scaling = 1.0;
- _fxpt_scalar_correction = 1.0;
+ _dsp_extra_scaling = 1.0;
//init the tx control registers
this->clear();
@@ -134,14 +135,14 @@ public:
}
void update_scalar(void){
- const double target_scalar = (1 << 17)*_scaling_adjustment/_extra_scaling;
+ 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*_extra_scaling*32767.;
+ return _fxpt_scalar_correction*_host_extra_scaling*32767.;
}
double set_freq(const double freq_){
@@ -175,13 +176,25 @@ public:
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"){
- _extra_scaling = 1.0;
+ 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"]);
}
@@ -191,7 +204,7 @@ private:
wb_iface::sptr _iface;
const size_t _dsp_base, _ctrl_base;
double _tick_rate, _link_rate;
- double _scaling_adjustment, _extra_scaling, _fxpt_scalar_correction;
+ double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction;
const boost::uint32_t _sid;
};
diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp
index 89a4ed00b..53f783a3f 100644
--- a/host/lib/usrp/e100/io_impl.cpp
+++ b/host/lib/usrp/e100/io_impl.cpp
@@ -339,6 +339,7 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){
//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
;
static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size;
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 58a5df2a5..6dcec6f1f 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -450,6 +450,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){
//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
+ vrt_send_header_offset_words32*sizeof(boost::uint32_t)
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
;