diff options
| -rw-r--r-- | firmware/microblaze/apps/txrx.c | 45 | ||||
| -rw-r--r-- | host/include/uhd/props.hpp | 5 | ||||
| -rw-r--r-- | host/include/uhd/utils.hpp | 5 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 16 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 5 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 153 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 11 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 15 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 11 | 
9 files changed, 152 insertions, 114 deletions
| diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index dccb2bdc9..e4e40e7e0 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -457,6 +457,8 @@ void handle_udp_ctrl_packet(      case USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO:          time_secs =  ctrl_data_in->data.streaming.secs;          time_ticks = ctrl_data_in->data.streaming.ticks; +        streaming_items_per_frame = ctrl_data_in->data.streaming.samples; +          if (ctrl_data_in->data.streaming.enabled == 0){              stop_rx_cmd();          } @@ -518,8 +520,15 @@ eth_pkt_inspector(dbsm_t *sm, int bufno)  //------------------------------------------------------------------ -#define VRT_HEADER_WORDS 5 -#define VRT_TRAILER_WORDS 0 +static uint16_t get_vrt_packet_words(void){ +    return streaming_items_per_frame + \ +        USRP2_HOST_RX_VRT_HEADER_WORDS32 + \ +        USRP2_HOST_RX_VRT_TRAILER_WORDS32; +} + +static bool vrt_has_trailer(void){ +    return USRP2_HOST_RX_VRT_TRAILER_WORDS32 > 0; +}  void  restart_streaming(void) @@ -530,10 +539,10 @@ restart_streaming(void)    sr_rx_ctrl->clear_overrun = 1;			// reset    sr_rx_ctrl->vrt_header = (0       | VRTH_PT_IF_DATA_WITH_SID -     | ((VRT_TRAILER_WORDS)? VRTH_HAS_TRAILER : 0) +     | (vrt_has_trailer()? VRTH_HAS_TRAILER : 0)       | VRTH_TSI_OTHER       | VRTH_TSF_SAMPLE_CNT -     | (VRT_HEADER_WORDS+streaming_items_per_frame+VRT_TRAILER_WORDS)); +  );    sr_rx_ctrl->vrt_stream_id = 0;    sr_rx_ctrl->vrt_trailer = 0; @@ -595,8 +604,9 @@ start_rx_streaming_cmd(void)    } mem _AL4;    memset(&mem, 0, sizeof(mem)); -  streaming_items_per_frame = (1500)/sizeof(uint32_t) - (DSP_TX_FIRST_LINE + VRT_HEADER_WORDS + VRT_TRAILER_WORDS); //FIXME -  mem.ctrl_word = (VRT_HEADER_WORDS+streaming_items_per_frame+VRT_TRAILER_WORDS)*sizeof(uint32_t) | 1 << 16; +  printf("samples per frame: %d\n", streaming_items_per_frame); +  printf("words in a vrt packet %d\n", get_vrt_packet_words()); +  mem.ctrl_word = get_vrt_packet_words()*sizeof(uint32_t) | 1 << 16;    memcpy_wa(buffer_ram(DSP_RX_BUF_0), &mem, sizeof(mem));    memcpy_wa(buffer_ram(DSP_RX_BUF_1), &mem, sizeof(mem)); @@ -653,25 +663,6 @@ stop_rx_cmd(void)  } - -/*static void -setup_tx() -{ -  sr_tx_ctrl->clear_state = 1; -  bp_clear_buf(DSP_TX_BUF_0); -  bp_clear_buf(DSP_TX_BUF_1); - -  int tx_scale = 256; -  int interp = 32; - -  // setup some defaults - -  dsp_tx_regs->freq = 0; -  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; -  dsp_tx_regs->interp_rate = interp; -}*/ - -  #if (FW_SETS_SEQNO)  /*   * Debugging ONLY.  This will be handled by the tx_protocol_engine. @@ -760,10 +751,6 @@ main(void)    // tell app_common that this dbsm could be sending to the ethernet    ac_could_be_sending_to_eth = &dsp_rx_sm; - -  // program tx registers -  //setup_tx(); -    // kick off the state machine    dbsm_start(&dsp_tx_sm); diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index 2b6daf6c5..cf301d4bd 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -65,7 +65,9 @@ namespace uhd{      enum device_prop_t{          DEVICE_PROP_NAME,              //ro, std::string          DEVICE_PROP_MBOARD,            //ro, wax::obj -        DEVICE_PROP_MBOARD_NAMES       //ro, prop_names_t +        DEVICE_PROP_MBOARD_NAMES,      //ro, prop_names_t +        DEVICE_PROP_MAX_RX_SAMPLES,    //ro, size_t +        DEVICE_PROP_MAX_TX_SAMPLES     //ro, size_t      };      /*! @@ -77,7 +79,6 @@ namespace uhd{      enum mboard_prop_t{          MBOARD_PROP_NAME,              //ro, std::string          MBOARD_PROP_OTHERS,            //ro, prop_names_t -        MBOARD_PROP_MTU,               //ro, size_t          MBOARD_PROP_CLOCK_RATE,        //ro, freq_t          MBOARD_PROP_RX_DSP,            //ro, wax::obj          MBOARD_PROP_RX_DSP_NAMES,      //ro, prop_names_t diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 4331aba7e..9bbdc83c9 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -57,6 +57,11 @@ namespace std{          return last != std::find(first, last, elem);      } +    template<class T, class V> +    bool has(const V &vector, const T &elem){ +        return has(vector.begin(), vector.end(), elem); +    } +      template<class T>      T sum(const T &a, const T &b){          return a + b; diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index e5c4a4245..a57f5ff2d 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -48,7 +48,7 @@ void usrp2_impl::init_ddc_config(void){      );      //initial config and update -    _ddc_decim = 16; +    _ddc_decim = 64;      _ddc_freq = 0;      update_ddc_config(); @@ -82,6 +82,12 @@ void usrp2_impl::update_ddc_enabled(void){      out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0;      out_data.data.streaming.secs =  htonl(_ddc_stream_at.secs);      out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks); +    out_data.data.streaming.samples = htonl( +        _mtu/sizeof(uint32_t) - +        USRP2_HOST_RX_VRT_HEADER_WORDS32 - +        USRP2_HOST_RX_VRT_TRAILER_WORDS32 - +        ((2 + 14 + 20 + 8)/sizeof(uint32_t)) //size of headers (pad, eth, ip, udp) +    );      //send and recv      usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -151,8 +157,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){      if (key_name == "decim"){          size_t new_decim = wax::cast<size_t>(val);          ASSERT_THROW(std::has( -            _allowed_decim_and_interp_rates.begin(), -            _allowed_decim_and_interp_rates.end(), +            _allowed_decim_and_interp_rates,              new_decim          ));          _ddc_decim = new_decim; //shadow @@ -196,7 +201,7 @@ void usrp2_impl::init_duc_config(void){      );      //initial config and update -    _duc_interp = 16; +    _duc_interp = 64;      _duc_freq = 0;      update_duc_config();  } @@ -280,8 +285,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){      if (key_name == "interp"){          size_t new_interp = wax::cast<size_t>(val);          ASSERT_THROW(std::has( -            _allowed_decim_and_interp_rates.begin(), -            _allowed_decim_and_interp_rates.end(), +            _allowed_decim_and_interp_rates,              new_interp          ));          _duc_interp = new_interp; //shadow diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index aca0abb28..8e4b2ba35 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -27,6 +27,10 @@  extern "C" {  #endif +// size of the vrt header and trailer to the host +#define USRP2_HOST_RX_VRT_HEADER_WORDS32 5 +#define USRP2_HOST_RX_VRT_TRAILER_WORDS32 1 //FIXME fpga sets wrong header size when no trailer present +  // udp ports for the usrp2 communication  // Dynamic and/or private ports: 49152-65535  #define USRP2_UDP_CTRL_PORT 49152 @@ -175,6 +179,7 @@ typedef struct{              uint8_t _pad[3];              uint32_t secs;              uint32_t ticks; +            uint32_t samples;          } streaming;          struct {              uint32_t freq_word; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 9c7a41e49..8b45a708a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -16,7 +16,6 @@  //  #include <complex> -#include <boost/shared_array.hpp>  #include <boost/format.hpp>  #include "usrp2_impl.hpp" @@ -27,55 +26,80 @@ namespace asio = boost::asio;  /***********************************************************************   * Constants   **********************************************************************/ -typedef std::complex<float> fc32_t; -typedef std::complex<short> sc16_t; +typedef std::complex<float>   fc32_t; +typedef std::complex<int16_t> sc16_t; -static const float float_scale_factor = pow(2.0, 15); - -//max length with header, stream id, seconds, fractional seconds -static const size_t max_vrt_header_words = 5; +static const float shorts_per_float = pow(2.0, 15); +static const float floats_per_short = 1.0/shorts_per_float;  /***********************************************************************   * Helper Functions   **********************************************************************/ -static inline void host_floats_to_usrp2_shorts( -    short *usrp2_shorts, -    const float *host_floats, +void usrp2_impl::io_init(void){ +    //initially empty spillover buffer +    _splillover_buff = asio::buffer(_spillover_mem, 0); + +    //send a small data packet so the usrp2 knows the udp source port +    uint32_t zero_data = 0; +    _data_transport->send(boost::asio::buffer(&zero_data, sizeof(zero_data))); +} + +#define unrolled_loop(__i, __len, __inst) {\ +    size_t __i = 0; \ +    while(__i < (__len & ~0x7)){ \ +        __inst; __i++; __inst; __i++; \ +        __inst; __i++; __inst; __i++; \ +        __inst; __i++; __inst; __i++; \ +        __inst; __i++; __inst; __i++; \ +    } \ +    while(__i < __len){ \ +        __inst; __i++;\ +    } \ +} + +static inline void host_floats_to_usrp2_items( +    uint32_t *usrp2_items, +    const fc32_t *host_floats,      size_t num_samps  ){ -    for(size_t i = 0; i < num_samps; i++){ -        usrp2_shorts[i] = htons(short(host_floats[i]*float_scale_factor)); -    } +    unrolled_loop(i, num_samps,{ +        int16_t real = host_floats[i].real()*shorts_per_float; +        int16_t imag = host_floats[i].imag()*shorts_per_float; +        usrp2_items[i] = htonl(((real << 16) & 0xffff) | ((imag << 0) & 0xffff)); +    });  } -static inline void usrp2_shorts_to_host_floats( -    float *host_floats, -    const short *usrp2_shorts, +static inline void usrp2_items_to_host_floats( +    fc32_t *host_floats, +    const uint32_t *usrp2_items,      size_t num_samps  ){ -    for(size_t i = 0; i < num_samps; i++){ -        host_floats[i] = float(short(ntohs(usrp2_shorts[i])))/float_scale_factor; -    } +    unrolled_loop(i, num_samps,{ +        uint32_t item = ntohl(usrp2_items[i]); +        int16_t real = (item >> 16) & 0xffff; +        int16_t imag = (item >> 0)  & 0xffff; +        host_floats[i] = fc32_t(real*floats_per_short, imag*floats_per_short); +    });  } -static inline void host_shorts_to_usrp2_shorts( -    short *usrp2_shorts, -    const short *host_shorts, +static inline void host_items_to_usrp2_items( +    uint32_t *usrp2_items, +    const uint32_t *host_items,      size_t num_samps  ){ -    for(size_t i = 0; i < num_samps; i++){ -        usrp2_shorts[i] = htons(host_shorts[i]); -    } +    unrolled_loop(i, num_samps, +        usrp2_items[i] = htonl(host_items[i]) +    );  } -static inline void usrp2_shorts_to_host_shorts( -    short *host_shorts, -    const short *usrp2_shorts, +static inline void usrp2_items_to_host_items( +    uint32_t *host_items, +    const uint32_t *usrp2_items,      size_t num_samps  ){ -    for(size_t i = 0; i < num_samps; i++){ -        host_shorts[i] = ntohs(usrp2_shorts[i]); -    } +    unrolled_loop(i, num_samps, +        host_items[i] = ntohl(usrp2_items[i]) +    );  }  /*********************************************************************** @@ -86,7 +110,7 @@ size_t usrp2_impl::send_raw(      const uhd::metadata_t &metadata  ){      std::vector<boost::asio::const_buffer> buffs(2); -    uint32_t vrt_hdr[max_vrt_header_words]; +    uint32_t vrt_hdr[7]; //max size      uint32_t vrt_hdr_flags = 0;      size_t num_vrt_hdr_words = 1; @@ -107,7 +131,7 @@ size_t usrp2_impl::send_raw(      //fill in complete header word      vrt_hdr[0] = htonl(vrt_hdr_flags | -        ((_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) | +        ((_tx_stream_id_to_packet_seq[metadata.stream_id]++ & 0xf) << 16) |          (num_vrt_hdr_words & 0xffff)      ); @@ -148,18 +172,16 @@ size_t usrp2_impl::recv_raw(      //load the buffer vector      std::vector<boost::asio::mutable_buffer> buffs(3); -    uint32_t vrt_hdr[max_vrt_header_words]; -    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) -    ); +    uint32_t vrt_hdr[USRP2_HOST_RX_VRT_HEADER_WORDS32]; +    buffs[0] = asio::buffer(vrt_hdr, sizeof(vrt_hdr)); +    buffs[1] = buff;      buffs[2] = asio::buffer(_spillover_mem, _mtu);      //receive into the buffers      size_t bytes_recvd = _data_transport->recv(buffs);      //failure case -    if (bytes_recvd < max_vrt_header_words*sizeof(uint32_t)) return 0; +    if (bytes_recvd < sizeof(vrt_hdr)) return 0;      //unpack the vrt header      metadata = uhd::metadata_t(); @@ -170,8 +192,15 @@ size_t usrp2_impl::recv_raw(      metadata.time_spec.secs = ntohl(vrt_hdr[2]);      metadata.time_spec.ticks = ntohl(vrt_hdr[3]); +    size_t my_seq = (vrt_header >> 16) & 0xf; +    //std::cout << "seq " << my_seq << std::endl; +    if (my_seq != ((_rx_stream_id_to_packet_seq[metadata.stream_id]+1) & 0xf)) std::cout << "bad seq " << my_seq << std::endl; +    _rx_stream_id_to_packet_seq[metadata.stream_id] = my_seq; +      //extract the number of bytes received -    size_t num_words = (vrt_header & 0xffff) - max_vrt_header_words; +    size_t num_words = (vrt_header & 0xffff); +    num_words -= USRP2_HOST_RX_VRT_HEADER_WORDS32; +    num_words -= USRP2_HOST_RX_VRT_TRAILER_WORDS32;      size_t num_bytes = num_words*sizeof(uint32_t);      //handle the case where spillover memory was used @@ -191,13 +220,12 @@ size_t usrp2_impl::send(  ){      if (type == "32fc"){          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)); +        boost::asio::mutable_buffer raw_buff(_tmp_send_mem, num_samps*sizeof(sc16_t)); -        host_floats_to_usrp2_shorts( -            asio::buffer_cast<short*>(raw_buff), -            asio::buffer_cast<const float*>(buff), -            num_samps*2 //double for complex +        host_floats_to_usrp2_items( +            asio::buffer_cast<uint32_t*>(raw_buff), +            asio::buffer_cast<const fc32_t*>(buff), +            num_samps          );          return send_raw(raw_buff, metadata); @@ -208,13 +236,12 @@ size_t usrp2_impl::send(          return send_raw(buff, metadata);          #else          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)); +        boost::asio::mutable_buffer raw_buff(_tmp_send_mem, num_samps*sizeof(sc16_t)); -        host_shorts_to_usrp2_shorts( -            asio::buffer_cast<short*>(raw_buff), -            asio::buffer_cast<const short*>(buff), -            num_samps*2 //double for complex +        host_items_to_usrp2_items( +            asio::buffer_cast<uint32_t*>(raw_buff), +            asio::buffer_cast<const uint32_t*>(buff), +            num_samps          );          return send_raw(raw_buff, metadata); @@ -234,15 +261,14 @@ size_t usrp2_impl::recv(  ){      if (type == "32fc"){          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)); +        boost::asio::mutable_buffer raw_buff(_tmp_recv_mem, num_samps*sizeof(sc16_t));          num_samps = recv_raw(raw_buff, metadata); -        usrp2_shorts_to_host_floats( -            asio::buffer_cast<float*>(buff), -            asio::buffer_cast<const short*>(raw_buff), -            num_samps*2 //double for complex +        usrp2_items_to_host_floats( +            asio::buffer_cast<fc32_t*>(buff), +            asio::buffer_cast<const uint32_t*>(raw_buff), +            num_samps          );          return num_samps; @@ -253,15 +279,14 @@ size_t usrp2_impl::recv(          return recv_raw(buff, metadata);          #else          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)); +        boost::asio::mutable_buffer raw_buff(_tmp_recv_mem, num_samps*sizeof(sc16_t));          num_samps = recv_raw(raw_buff, metadata); -        usrp2_shorts_to_host_shorts( -            asio::buffer_cast<short*>(buff), -            asio::buffer_cast<const short*>(raw_buff), -            num_samps*2 //double for complex +        usrp2_items_to_host_items( +            asio::buffer_cast<uint32_t*>(buff), +            asio::buffer_cast<const uint32_t*>(raw_buff), +            num_samps          );          return num_samps; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index cc73b229c..8e682a675 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -82,6 +82,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_RX_DBOARD: +        ASSERT_THROW(_rx_dboards.has_key(name));          val = _rx_dboards[name].get_link();          return; @@ -90,6 +91,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_TX_DBOARD: +        ASSERT_THROW(_tx_dboards.has_key(name));          val = _tx_dboards[name].get_link();          return; @@ -97,17 +99,12 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){          val = prop_names_t(_tx_dboards.get_keys());          return; -    case MBOARD_PROP_MTU: -        // FIXME we dont know the real MTU... -        // give them something to fragment about -        val = size_t(1500); -        return; -      case MBOARD_PROP_CLOCK_RATE:          val = freq_t(get_master_clock_freq());          return;      case MBOARD_PROP_RX_DSP: +        ASSERT_THROW(_rx_dsps.has_key(name));          val = _rx_dsps[name].get_link();          return; @@ -116,6 +113,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_TX_DSP: +        ASSERT_THROW(_tx_dsps.has_key(name));          val = _tx_dsps[name].get_link();          return; @@ -183,7 +181,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){      case MBOARD_PROP_NAME:      case MBOARD_PROP_OTHERS: -    case MBOARD_PROP_MTU:      case MBOARD_PROP_CLOCK_RATE:      case MBOARD_PROP_RX_DSP:      case MBOARD_PROP_RX_DSP_NAMES: diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 06876d241..700f94ae1 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -133,9 +133,8 @@ usrp2_impl::usrp2_impl(      //init the tx and rx dboards (do last)      dboard_init(); -    //send a small data packet so the usrp2 knows the udp source port -    uint32_t zero_data = 0; -    _data_transport->send(boost::asio::buffer(&zero_data, sizeof(zero_data))); +    //init the send and recv io +    io_init();  } @@ -197,12 +196,22 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){          return;      case DEVICE_PROP_MBOARD: +        ASSERT_THROW(_mboards.has_key(name));          val = _mboards[name].get_link();          return;      case DEVICE_PROP_MBOARD_NAMES:          val = prop_names_t(_mboards.get_keys());          return; + +    case DEVICE_PROP_MAX_RX_SAMPLES: +        val = size_t(_max_samples_per_packet); +        return; + +    case DEVICE_PROP_MAX_TX_SAMPLES: +        val = size_t(_max_samples_per_packet); +        return; +      }  } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 47b01d1b1..43f32c6e6 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -105,10 +105,15 @@ private:      //the raw io interface (samples are in the usrp2 native format)      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]; +    uhd::dict<uint32_t, size_t> _tx_stream_id_to_packet_seq; +    uhd::dict<uint32_t, size_t> _rx_stream_id_to_packet_seq; +    static const size_t _mtu = 1500; //FIXME we have no idea +    static const size_t _max_samples_per_packet = _mtu/sizeof(uint32_t); +    uint32_t _tmp_send_mem[_mtu/sizeof(uint32_t)]; +    uint32_t _tmp_recv_mem[_mtu/sizeof(uint32_t)]; +    uint32_t _spillover_mem[_mtu/sizeof(uint32_t)];      boost::asio::mutable_buffer _splillover_buff; +    void io_init(void);      //udp transports for control and data      uhd::transport::udp::sptr _ctrl_transport; | 
