From 6e8473e6eef84875e2c3babb35732f8c3b2a0247 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Mon, 1 Mar 2010 11:50:14 -0800
Subject: Recv noise with uhd.

---
 host/lib/usrp/usrp2/dsp_impl.cpp   | 12 +++++-
 host/lib/usrp/usrp2/fw_common.h    |  1 +
 host/lib/usrp/usrp2/io_impl.cpp    | 86 +++++++++++++++++++++++++-------------
 host/lib/usrp/usrp2/usrp2_impl.hpp |  3 ++
 4 files changed, 73 insertions(+), 29 deletions(-)

(limited to 'host/lib/usrp/usrp2')

diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 22c00d99a..e5c4a4245 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -36,6 +36,10 @@ static uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t
     return freq_word;
 }
 
+static uint32_t calculate_iq_scale_word(int16_t i, int16_t q){
+    return ((i & 0xffff) << 16) | ((q & 0xffff) << 0);
+}
+
 void usrp2_impl::init_ddc_config(void){
     //create the ddc in the rx dsp dict
     _rx_dsps["ddc0"] = wax_obj_proxy(
@@ -61,6 +65,10 @@ void usrp2_impl::update_ddc_config(void){
         calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq())
     );
     out_data.data.ddc_args.decim = htonl(_ddc_decim);
+    static const uint32_t default_rx_scale_iq = 1024;
+    out_data.data.ddc_args.scale_iq = htonl(
+        calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq)
+    );
 
     //send and recv
     usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
@@ -209,7 +217,9 @@ void usrp2_impl::update_duc_config(void){
         calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq())
     );
     out_data.data.duc_args.interp = htonl(_duc_interp);
-    out_data.data.duc_args.scale_iq = htonl(scale);
+    out_data.data.duc_args.scale_iq = htonl(
+        calculate_iq_scale_word(scale, scale)
+    );
 
     //send and recv
     usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 3def8ddaa..aca0abb28 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -168,6 +168,7 @@ typedef struct{
         struct {
             uint32_t freq_word;
             uint32_t decim;
+            uint32_t scale_iq;
         } ddc_args;
         struct {
             uint8_t enabled;
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index c9a7b5fa4..9c7a41e49 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -22,6 +22,7 @@
 
 using namespace uhd;
 using namespace uhd::usrp;
+namespace asio = boost::asio;
 
 /***********************************************************************
  * Constants
@@ -38,28 +39,28 @@ static const size_t max_vrt_header_words = 5;
  * Helper Functions
  **********************************************************************/
 static inline void host_floats_to_usrp2_shorts(
-    int16_t *usrp2_shorts,
+    short *usrp2_shorts,
     const float *host_floats,
     size_t num_samps
 ){
     for(size_t i = 0; i < num_samps; i++){
-        usrp2_shorts[i] = htons(int16_t(host_floats[i]*float_scale_factor));
+        usrp2_shorts[i] = htons(short(host_floats[i]*float_scale_factor));
     }
 }
 
 static inline void usrp2_shorts_to_host_floats(
     float *host_floats,
-    const int16_t *usrp2_shorts,
+    const short *usrp2_shorts,
     size_t num_samps
 ){
     for(size_t i = 0; i < num_samps; i++){
-        host_floats[i] = float(ntohs(usrp2_shorts[i])/float_scale_factor);
+        host_floats[i] = float(short(ntohs(usrp2_shorts[i])))/float_scale_factor;
     }
 }
 
 static inline void host_shorts_to_usrp2_shorts(
-    int16_t *usrp2_shorts,
-    const int16_t *host_shorts,
+    short *usrp2_shorts,
+    const short *host_shorts,
     size_t num_samps
 ){
     for(size_t i = 0; i < num_samps; i++){
@@ -68,8 +69,8 @@ static inline void host_shorts_to_usrp2_shorts(
 }
 
 static inline void usrp2_shorts_to_host_shorts(
-    int16_t *host_shorts,
-    const int16_t *usrp2_shorts,
+    short *host_shorts,
+    const short *usrp2_shorts,
     size_t num_samps
 ){
     for(size_t i = 0; i < num_samps; i++){
@@ -102,16 +103,17 @@ size_t usrp2_impl::send_raw(
     }
     vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0;
     vrt_hdr_flags |= (metadata.end_of_burst)?   (0x1 << 24) : 0;
+    num_vrt_hdr_words += asio::buffer_size(buff)/sizeof(uint32_t);
 
     //fill in complete header word
     vrt_hdr[0] = htonl(vrt_hdr_flags |
         ((_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) |
-        ((boost::asio::buffer_size(buff)/sizeof(uint32_t)) & 0xffff)
+        (num_vrt_hdr_words & 0xffff)
     );
 
     //load the buffer vector
     size_t vrt_hdr_size = num_vrt_hdr_words*sizeof(uint32_t);
-    buffs[0] = boost::asio::buffer(&vrt_hdr, vrt_hdr_size);
+    buffs[0] = asio::buffer(&vrt_hdr, vrt_hdr_size);
     buffs[1] = buff;
 
     //send and return number of samples
@@ -125,11 +127,33 @@ size_t usrp2_impl::recv_raw(
     const boost::asio::mutable_buffer &buff,
     uhd::metadata_t &metadata
 ){
+    //handle the case where there is spillover
+    if (asio::buffer_size(_splillover_buff) != 0){
+        size_t bytes_to_copy = std::min(
+            asio::buffer_size(_splillover_buff),
+            asio::buffer_size(buff)
+        );
+        std::memcpy(
+            asio::buffer_cast<void*>(buff),
+            asio::buffer_cast<const void*>(_splillover_buff),
+            bytes_to_copy
+        );
+        _splillover_buff = asio::buffer(
+            asio::buffer_cast<uint8_t*>(_splillover_buff)+bytes_to_copy,
+            asio::buffer_size(_splillover_buff)-bytes_to_copy
+        );
+        //std::cout << boost::format("Copied spillover %d samples") % (bytes_to_copy/sizeof(sc16_t)) << std::endl;
+        return bytes_to_copy/sizeof(sc16_t);
+    }
+
     //load the buffer vector
-    std::vector<boost::asio::mutable_buffer> buffs(2);
+    std::vector<boost::asio::mutable_buffer> buffs(3);
     uint32_t vrt_hdr[max_vrt_header_words];
-    buffs[0] = boost::asio::buffer(vrt_hdr, max_vrt_header_words);
-    buffs[1] = buff;
+    buffs[0] = asio::buffer(vrt_hdr, max_vrt_header_words*sizeof(uint32_t));
+    buffs[1] = asio::buffer(//make sure its on a word boundary
+        buff, asio::buffer_size(buff) & ~(sizeof(uint32_t) - 1)
+    );
+    buffs[2] = asio::buffer(_spillover_mem, _mtu);
 
     //receive into the buffers
     size_t bytes_recvd = _data_transport->recv(buffs);
@@ -146,9 +170,15 @@ size_t usrp2_impl::recv_raw(
     metadata.time_spec.secs = ntohl(vrt_hdr[2]);
     metadata.time_spec.ticks = ntohl(vrt_hdr[3]);
 
-    //return the number of samples received
-    size_t num_words = vrt_header & 0xffff;
-    return (num_words*sizeof(uint32_t))/sizeof(sc16_t);
+    //extract the number of bytes received
+    size_t num_words = (vrt_header & 0xffff) - max_vrt_header_words;
+    size_t num_bytes = num_words*sizeof(uint32_t);
+
+    //handle the case where spillover memory was used
+    size_t spillover_size = num_bytes - std::min(num_bytes, asio::buffer_size(buff));
+    _splillover_buff = asio::buffer(_spillover_mem, spillover_size);
+
+    return (num_bytes - spillover_size)/sizeof(sc16_t);
 }
 
 /***********************************************************************
@@ -160,13 +190,13 @@ size_t usrp2_impl::send(
     const std::string &type
 ){
     if (type == "32fc"){
-        size_t num_samps = boost::asio::buffer_size(buff)/sizeof(fc32_t);
+        size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t);
         boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
         boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
 
         host_floats_to_usrp2_shorts(
-            boost::asio::buffer_cast<int16_t*>(raw_buff),
-            boost::asio::buffer_cast<const float*>(buff),
+            asio::buffer_cast<short*>(raw_buff),
+            asio::buffer_cast<const float*>(buff),
             num_samps*2 //double for complex
         );
 
@@ -177,13 +207,13 @@ size_t usrp2_impl::send(
         #ifdef HAVE_BIG_ENDIAN
         return send_raw(buff, metadata);
         #else
-        size_t num_samps = boost::asio::buffer_size(buff)/sizeof(sc16_t);
+        size_t num_samps = asio::buffer_size(buff)/sizeof(sc16_t);
         boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
         boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
 
         host_shorts_to_usrp2_shorts(
-            boost::asio::buffer_cast<int16_t*>(raw_buff),
-            boost::asio::buffer_cast<const int16_t*>(buff),
+            asio::buffer_cast<short*>(raw_buff),
+            asio::buffer_cast<const short*>(buff),
             num_samps*2 //double for complex
         );
 
@@ -203,15 +233,15 @@ size_t usrp2_impl::recv(
     const std::string &type
 ){
     if (type == "32fc"){
-        size_t num_samps = boost::asio::buffer_size(buff)/sizeof(fc32_t);
+        size_t num_samps = asio::buffer_size(buff)/sizeof(fc32_t);
         boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
         boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
 
         num_samps = recv_raw(raw_buff, metadata);
 
         usrp2_shorts_to_host_floats(
-            boost::asio::buffer_cast<float*>(buff),
-            boost::asio::buffer_cast<const int16_t*>(raw_buff),
+            asio::buffer_cast<float*>(buff),
+            asio::buffer_cast<const short*>(raw_buff),
             num_samps*2 //double for complex
         );
 
@@ -222,15 +252,15 @@ size_t usrp2_impl::recv(
         #ifdef HAVE_BIG_ENDIAN
         return recv_raw(buff, metadata);
         #else
-        size_t num_samps = boost::asio::buffer_size(buff)/sizeof(sc16_t);
+        size_t num_samps = asio::buffer_size(buff)/sizeof(sc16_t);
         boost::shared_array<sc16_t> raw_mem(new sc16_t[num_samps]);
         boost::asio::mutable_buffer raw_buff(raw_mem.get(), num_samps*sizeof(sc16_t));
 
         num_samps = recv_raw(raw_buff, metadata);
 
         usrp2_shorts_to_host_shorts(
-            boost::asio::buffer_cast<int16_t*>(buff),
-            boost::asio::buffer_cast<const int16_t*>(raw_buff),
+            asio::buffer_cast<short*>(buff),
+            asio::buffer_cast<const short*>(raw_buff),
             num_samps*2 //double for complex
         );
 
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 9a4c42d42..47b01d1b1 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -106,6 +106,9 @@ private:
     size_t send_raw(const boost::asio::const_buffer &, const uhd::metadata_t &);
     size_t recv_raw(const boost::asio::mutable_buffer &, uhd::metadata_t &);
     uhd::dict<uint32_t, size_t> _stream_id_to_packet_seq;
+    static const size_t _mtu = 1500;
+    uint8_t _spillover_mem[_mtu];
+    boost::asio::mutable_buffer _splillover_buff;
 
     //udp transports for control and data
     uhd::transport::udp::sptr _ctrl_transport;
-- 
cgit v1.2.3