mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
Renamed the example to test_messages (not just async). Fixed bug in super recv packet handler related to messages. Basically, the sequence number for messages should be ignored. Fixed some quirks with usrp1 soft time control to get it work as well.
732 lines
28 KiB
C++
732 lines
28 KiB
C++
//
|
|
// Copyright 2011 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 <boost/test/unit_test.hpp>
|
|
#include "../lib/transport/super_recv_packet_handler.hpp"
|
|
#include <boost/shared_array.hpp>
|
|
#include <boost/bind.hpp>
|
|
#include <complex>
|
|
#include <vector>
|
|
#include <list>
|
|
|
|
#define BOOST_CHECK_TS_CLOSE(a, b) \
|
|
BOOST_CHECK_CLOSE((a).get_real_secs(), (b).get_real_secs(), 0.001)
|
|
|
|
/***********************************************************************
|
|
* A dummy overflow handler for testing
|
|
**********************************************************************/
|
|
struct overflow_handler_type{
|
|
overflow_handler_type(void){
|
|
num_overflow = 0;
|
|
}
|
|
void handle(void){
|
|
num_overflow++;
|
|
}
|
|
size_t num_overflow;
|
|
};
|
|
|
|
/***********************************************************************
|
|
* A dummy managed receive buffer for testing
|
|
**********************************************************************/
|
|
class dummy_mrb : public uhd::transport::managed_recv_buffer{
|
|
public:
|
|
void release(void){
|
|
//NOP
|
|
}
|
|
|
|
sptr get_new(boost::shared_array<char> mem, size_t len){
|
|
_mem = mem;
|
|
_len = len;
|
|
return make_managed_buffer(this);
|
|
}
|
|
|
|
private:
|
|
const void *get_buff(void) const{return _mem.get();}
|
|
size_t get_size(void) const{return _len;}
|
|
|
|
boost::shared_array<char> _mem;
|
|
size_t _len;
|
|
};
|
|
|
|
/***********************************************************************
|
|
* A dummy transport class to fill with fake data
|
|
**********************************************************************/
|
|
class dummy_recv_xport_class{
|
|
public:
|
|
dummy_recv_xport_class(const uhd::otw_type_t &otw_type){
|
|
_otw_type = otw_type;
|
|
}
|
|
|
|
void push_back_packet(
|
|
uhd::transport::vrt::if_packet_info_t &ifpi,
|
|
const boost::uint32_t optional_msg_word = 0
|
|
){
|
|
const size_t max_pkt_len = (ifpi.num_payload_words32 + uhd::transport::vrt::max_if_hdr_words32 + 1/*tlr*/)*sizeof(boost::uint32_t);
|
|
_mems.push_back(boost::shared_array<char>(new char[max_pkt_len]));
|
|
if (_otw_type.byteorder == uhd::otw_type_t::BO_BIG_ENDIAN){
|
|
uhd::transport::vrt::if_hdr_pack_be(reinterpret_cast<boost::uint32_t *>(_mems.back().get()), ifpi);
|
|
}
|
|
if (_otw_type.byteorder == uhd::otw_type_t::BO_LITTLE_ENDIAN){
|
|
uhd::transport::vrt::if_hdr_pack_le(reinterpret_cast<boost::uint32_t *>(_mems.back().get()), ifpi);
|
|
}
|
|
(reinterpret_cast<boost::uint32_t *>(_mems.back().get()) + ifpi.num_header_words32)[0] = optional_msg_word | uhd::byteswap(optional_msg_word);
|
|
_lens.push_back(ifpi.num_packet_words32*sizeof(boost::uint32_t));
|
|
}
|
|
|
|
uhd::transport::managed_recv_buffer::sptr get_recv_buff(double){
|
|
if (_mems.empty()) return uhd::transport::managed_recv_buffer::sptr(); //timeout
|
|
_mrbs.push_back(dummy_mrb());
|
|
uhd::transport::managed_recv_buffer::sptr mrb = _mrbs.back().get_new(_mems.front(), _lens.front());
|
|
_mems.pop_front();
|
|
_lens.pop_front();
|
|
return mrb;
|
|
}
|
|
|
|
private:
|
|
std::list<boost::shared_array<char> > _mems;
|
|
std::list<size_t> _lens;
|
|
std::list<dummy_mrb> _mrbs; //list means no-realloc
|
|
uhd::otw_type_t _otw_type;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){
|
|
////////////////////////////////////////////////////////////////////////
|
|
uhd::otw_type_t otw_type;
|
|
otw_type.width = 16;
|
|
otw_type.shift = 0;
|
|
otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
|
|
|
|
dummy_recv_xport_class dummy_recv_xport(otw_type);
|
|
uhd::transport::vrt::if_packet_info_t ifpi;
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 0;
|
|
ifpi.packet_count = 0;
|
|
ifpi.sob = true;
|
|
ifpi.eob = false;
|
|
ifpi.has_sid = false;
|
|
ifpi.has_cid = false;
|
|
ifpi.has_tsi = true;
|
|
ifpi.has_tsf = true;
|
|
ifpi.tsi = 0;
|
|
ifpi.tsf = 0;
|
|
ifpi.has_tlr = false;
|
|
|
|
static const double TICK_RATE = 100e6;
|
|
static const double SAMP_RATE = 10e6;
|
|
static const size_t NUM_PKTS_TO_TEST = 30;
|
|
|
|
//generate a bunch of packets
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
ifpi.num_payload_words32 = 10 + i%10;
|
|
dummy_recv_xport.push_back_packet(ifpi);
|
|
ifpi.packet_count++;
|
|
ifpi.tsf += ifpi.num_payload_words32*size_t(TICK_RATE/SAMP_RATE);
|
|
}
|
|
|
|
//create the super receive packet handler
|
|
uhd::transport::sph::recv_packet_handler handler(1);
|
|
handler.set_vrt_unpacker(&uhd::transport::vrt::if_hdr_unpack_be);
|
|
handler.set_tick_rate(TICK_RATE);
|
|
handler.set_samp_rate(SAMP_RATE);
|
|
handler.set_xport_chan_get_buff(0, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xport, _1));
|
|
handler.set_converter(otw_type);
|
|
|
|
//check the received packets
|
|
size_t num_accum_samps = 0;
|
|
std::vector<std::complex<float> > buff(20);
|
|
uhd::rx_metadata_t metadata;
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
std::cout << "data check " << i << std::endl;
|
|
size_t num_samps_ret = handler.recv(
|
|
&buff.front(), buff.size(), metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(not metadata.more_fragments);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10);
|
|
num_accum_samps += num_samps_ret;
|
|
}
|
|
|
|
//subsequent receives should be a timeout
|
|
for (size_t i = 0; i < 3; i++){
|
|
std::cout << "timeout check " << i << std::endl;
|
|
handler.recv(
|
|
&buff.front(), buff.size(), metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){
|
|
////////////////////////////////////////////////////////////////////////
|
|
uhd::otw_type_t otw_type;
|
|
otw_type.width = 16;
|
|
otw_type.shift = 0;
|
|
otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
|
|
|
|
dummy_recv_xport_class dummy_recv_xport(otw_type);
|
|
uhd::transport::vrt::if_packet_info_t ifpi;
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 0;
|
|
ifpi.packet_count = 0;
|
|
ifpi.sob = true;
|
|
ifpi.eob = false;
|
|
ifpi.has_sid = false;
|
|
ifpi.has_cid = false;
|
|
ifpi.has_tsi = true;
|
|
ifpi.has_tsf = true;
|
|
ifpi.tsi = 0;
|
|
ifpi.tsf = 0;
|
|
ifpi.has_tlr = false;
|
|
|
|
static const double TICK_RATE = 100e6;
|
|
static const double SAMP_RATE = 10e6;
|
|
static const size_t NUM_PKTS_TO_TEST = 30;
|
|
|
|
//generate a bunch of packets
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
ifpi.num_payload_words32 = 10 + i%10;
|
|
if (i != NUM_PKTS_TO_TEST/2){ //simulate a lost packet
|
|
dummy_recv_xport.push_back_packet(ifpi);
|
|
}
|
|
ifpi.packet_count++;
|
|
ifpi.tsf += ifpi.num_payload_words32*size_t(TICK_RATE/SAMP_RATE);
|
|
}
|
|
|
|
//create the super receive packet handler
|
|
uhd::transport::sph::recv_packet_handler handler(1);
|
|
handler.set_vrt_unpacker(&uhd::transport::vrt::if_hdr_unpack_be);
|
|
handler.set_tick_rate(TICK_RATE);
|
|
handler.set_samp_rate(SAMP_RATE);
|
|
handler.set_xport_chan_get_buff(0, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xport, _1));
|
|
handler.set_converter(otw_type);
|
|
|
|
//check the received packets
|
|
size_t num_accum_samps = 0;
|
|
std::vector<std::complex<float> > buff(20);
|
|
uhd::rx_metadata_t metadata;
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
std::cout << "data check " << i << std::endl;
|
|
size_t num_samps_ret = handler.recv(
|
|
&buff.front(), buff.size(), metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
if (i == NUM_PKTS_TO_TEST/2){
|
|
//must get the soft overflow here
|
|
BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
num_accum_samps += 10 + i%10;
|
|
}
|
|
else{
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(not metadata.more_fragments);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10);
|
|
num_accum_samps += num_samps_ret;
|
|
}
|
|
}
|
|
|
|
//subsequent receives should be a timeout
|
|
for (size_t i = 0; i < 3; i++){
|
|
std::cout << "timeout check " << i << std::endl;
|
|
handler.recv(
|
|
&buff.front(), buff.size(), metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){
|
|
////////////////////////////////////////////////////////////////////////
|
|
uhd::otw_type_t otw_type;
|
|
otw_type.width = 16;
|
|
otw_type.shift = 0;
|
|
otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
|
|
|
|
dummy_recv_xport_class dummy_recv_xport(otw_type);
|
|
uhd::transport::vrt::if_packet_info_t ifpi;
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 0;
|
|
ifpi.packet_count = 0;
|
|
ifpi.sob = true;
|
|
ifpi.eob = false;
|
|
ifpi.has_sid = false;
|
|
ifpi.has_cid = false;
|
|
ifpi.has_tsi = true;
|
|
ifpi.has_tsf = true;
|
|
ifpi.tsi = 0;
|
|
ifpi.tsf = 0;
|
|
ifpi.has_tlr = false;
|
|
|
|
static const double TICK_RATE = 100e6;
|
|
static const double SAMP_RATE = 10e6;
|
|
static const size_t NUM_PKTS_TO_TEST = 30;
|
|
|
|
//generate a bunch of packets
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 10 + i%10;
|
|
dummy_recv_xport.push_back_packet(ifpi);
|
|
ifpi.packet_count++;
|
|
ifpi.tsf += ifpi.num_payload_words32*size_t(TICK_RATE/SAMP_RATE);
|
|
|
|
//simulate overflow
|
|
if (i == NUM_PKTS_TO_TEST/2){
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_EXTENSION;
|
|
ifpi.num_payload_words32 = 1;
|
|
dummy_recv_xport.push_back_packet(ifpi, uhd::rx_metadata_t::ERROR_CODE_OVERFLOW);
|
|
}
|
|
}
|
|
|
|
//create the super receive packet handler
|
|
uhd::transport::sph::recv_packet_handler handler(1);
|
|
handler.set_vrt_unpacker(&uhd::transport::vrt::if_hdr_unpack_be);
|
|
handler.set_tick_rate(TICK_RATE);
|
|
handler.set_samp_rate(SAMP_RATE);
|
|
handler.set_xport_chan_get_buff(0, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xport, _1));
|
|
handler.set_converter(otw_type);
|
|
|
|
//create an overflow handler
|
|
overflow_handler_type overflow_handler;
|
|
handler.set_overflow_handler(0, boost::bind(&overflow_handler_type::handle, &overflow_handler));
|
|
|
|
//check the received packets
|
|
size_t num_accum_samps = 0;
|
|
std::vector<std::complex<float> > buff(20);
|
|
uhd::rx_metadata_t metadata;
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
std::cout << "data check " << i << std::endl;
|
|
size_t num_samps_ret = handler.recv(
|
|
&buff.front(), buff.size(), metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(not metadata.more_fragments);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10);
|
|
num_accum_samps += num_samps_ret;
|
|
if (i == NUM_PKTS_TO_TEST/2){
|
|
handler.recv(
|
|
&buff.front(), buff.size(), metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
std::cout << "metadata.error_code " << metadata.error_code << std::endl;
|
|
BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(overflow_handler.num_overflow, size_t(1));
|
|
}
|
|
}
|
|
|
|
//subsequent receives should be a timeout
|
|
for (size_t i = 0; i < 3; i++){
|
|
std::cout << "timeout check " << i << std::endl;
|
|
handler.recv(
|
|
&buff.front(), buff.size(), metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){
|
|
////////////////////////////////////////////////////////////////////////
|
|
uhd::otw_type_t otw_type;
|
|
otw_type.width = 16;
|
|
otw_type.shift = 0;
|
|
otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
|
|
|
|
uhd::transport::vrt::if_packet_info_t ifpi;
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 0;
|
|
ifpi.packet_count = 0;
|
|
ifpi.sob = true;
|
|
ifpi.eob = false;
|
|
ifpi.has_sid = false;
|
|
ifpi.has_cid = false;
|
|
ifpi.has_tsi = true;
|
|
ifpi.has_tsf = true;
|
|
ifpi.tsi = 0;
|
|
ifpi.tsf = 0;
|
|
ifpi.has_tlr = false;
|
|
|
|
static const double TICK_RATE = 100e6;
|
|
static const double SAMP_RATE = 10e6;
|
|
static const size_t NUM_PKTS_TO_TEST = 30;
|
|
static const size_t NUM_SAMPS_PER_BUFF = 20;
|
|
static const size_t NCHANNELS = 4;
|
|
|
|
std::vector<dummy_recv_xport_class> dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type));
|
|
|
|
//generate a bunch of packets
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
ifpi.num_payload_words32 = 10 + i%10;
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
dummy_recv_xports[ch].push_back_packet(ifpi);
|
|
}
|
|
ifpi.packet_count++;
|
|
ifpi.tsf += ifpi.num_payload_words32*size_t(TICK_RATE/SAMP_RATE);
|
|
}
|
|
|
|
//create the super receive packet handler
|
|
uhd::transport::sph::recv_packet_handler handler(NCHANNELS);
|
|
handler.set_vrt_unpacker(&uhd::transport::vrt::if_hdr_unpack_be);
|
|
handler.set_tick_rate(TICK_RATE);
|
|
handler.set_samp_rate(SAMP_RATE);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1));
|
|
}
|
|
handler.set_converter(otw_type);
|
|
|
|
//check the received packets
|
|
size_t num_accum_samps = 0;
|
|
std::vector<std::complex<float> > mem(NUM_SAMPS_PER_BUFF*NCHANNELS);
|
|
std::vector<std::complex<float> *> buffs(NCHANNELS);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
buffs[ch] = &mem[ch*NUM_SAMPS_PER_BUFF];
|
|
}
|
|
uhd::rx_metadata_t metadata;
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
std::cout << "data check " << i << std::endl;
|
|
size_t num_samps_ret = handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(not metadata.more_fragments);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10);
|
|
num_accum_samps += num_samps_ret;
|
|
}
|
|
|
|
//subsequent receives should be a timeout
|
|
for (size_t i = 0; i < 3; i++){
|
|
std::cout << "timeout check " << i << std::endl;
|
|
handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){
|
|
////////////////////////////////////////////////////////////////////////
|
|
uhd::otw_type_t otw_type;
|
|
otw_type.width = 16;
|
|
otw_type.shift = 0;
|
|
otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
|
|
|
|
uhd::transport::vrt::if_packet_info_t ifpi;
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 0;
|
|
ifpi.packet_count = 0;
|
|
ifpi.sob = true;
|
|
ifpi.eob = false;
|
|
ifpi.has_sid = false;
|
|
ifpi.has_cid = false;
|
|
ifpi.has_tsi = true;
|
|
ifpi.has_tsf = true;
|
|
ifpi.tsi = 0;
|
|
ifpi.tsf = 0;
|
|
ifpi.has_tlr = false;
|
|
|
|
static const double TICK_RATE = 100e6;
|
|
static const double SAMP_RATE = 10e6;
|
|
static const size_t NUM_PKTS_TO_TEST = 30;
|
|
static const size_t NUM_SAMPS_PER_BUFF = 20;
|
|
static const size_t NCHANNELS = 4;
|
|
|
|
std::vector<dummy_recv_xport_class> dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type));
|
|
|
|
//generate a bunch of packets
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
ifpi.num_payload_words32 = 10 + i%10;
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
if (i == NUM_PKTS_TO_TEST/2 and ch == 2){
|
|
continue; //simulates a lost packet
|
|
}
|
|
dummy_recv_xports[ch].push_back_packet(ifpi);
|
|
}
|
|
ifpi.packet_count++;
|
|
ifpi.tsf += ifpi.num_payload_words32*size_t(TICK_RATE/SAMP_RATE);
|
|
}
|
|
|
|
//create the super receive packet handler
|
|
uhd::transport::sph::recv_packet_handler handler(NCHANNELS);
|
|
handler.set_vrt_unpacker(&uhd::transport::vrt::if_hdr_unpack_be);
|
|
handler.set_tick_rate(TICK_RATE);
|
|
handler.set_samp_rate(SAMP_RATE);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1));
|
|
}
|
|
handler.set_converter(otw_type);
|
|
|
|
//check the received packets
|
|
size_t num_accum_samps = 0;
|
|
std::vector<std::complex<float> > mem(NUM_SAMPS_PER_BUFF*NCHANNELS);
|
|
std::vector<std::complex<float> *> buffs(NCHANNELS);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
buffs[ch] = &mem[ch*NUM_SAMPS_PER_BUFF];
|
|
}
|
|
uhd::rx_metadata_t metadata;
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
std::cout << "data check " << i << std::endl;
|
|
size_t num_samps_ret = handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
if (i == NUM_PKTS_TO_TEST/2){
|
|
//must get the soft overflow here
|
|
BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
num_accum_samps += 10 + i%10;
|
|
}
|
|
else{
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(not metadata.more_fragments);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10);
|
|
num_accum_samps += num_samps_ret;
|
|
}
|
|
}
|
|
|
|
//subsequent receives should be a timeout
|
|
for (size_t i = 0; i < 3; i++){
|
|
std::cout << "timeout check " << i << std::endl;
|
|
handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){
|
|
////////////////////////////////////////////////////////////////////////
|
|
uhd::otw_type_t otw_type;
|
|
otw_type.width = 16;
|
|
otw_type.shift = 0;
|
|
otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
|
|
|
|
uhd::transport::vrt::if_packet_info_t ifpi;
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 0;
|
|
ifpi.packet_count = 0;
|
|
ifpi.sob = true;
|
|
ifpi.eob = false;
|
|
ifpi.has_sid = false;
|
|
ifpi.has_cid = false;
|
|
ifpi.has_tsi = true;
|
|
ifpi.has_tsf = true;
|
|
ifpi.tsi = 0;
|
|
ifpi.tsf = 0;
|
|
ifpi.has_tlr = false;
|
|
|
|
static const double TICK_RATE = 100e6;
|
|
static const double SAMP_RATE = 10e6;
|
|
static const size_t NUM_PKTS_TO_TEST = 30;
|
|
static const size_t NUM_SAMPS_PER_BUFF = 20;
|
|
static const size_t NCHANNELS = 4;
|
|
|
|
std::vector<dummy_recv_xport_class> dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type));
|
|
|
|
//generate a bunch of packets
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
ifpi.num_payload_words32 = 10 + i%10;
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
dummy_recv_xports[ch].push_back_packet(ifpi);
|
|
}
|
|
ifpi.packet_count++;
|
|
ifpi.tsf += ifpi.num_payload_words32*size_t(TICK_RATE/SAMP_RATE);
|
|
if (i == NUM_PKTS_TO_TEST/2){
|
|
ifpi.tsf = 0; //simulate the user changing the time
|
|
}
|
|
}
|
|
|
|
//create the super receive packet handler
|
|
uhd::transport::sph::recv_packet_handler handler(NCHANNELS);
|
|
handler.set_vrt_unpacker(&uhd::transport::vrt::if_hdr_unpack_be);
|
|
handler.set_tick_rate(TICK_RATE);
|
|
handler.set_samp_rate(SAMP_RATE);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1));
|
|
}
|
|
handler.set_converter(otw_type);
|
|
|
|
//check the received packets
|
|
size_t num_accum_samps = 0;
|
|
std::vector<std::complex<float> > mem(NUM_SAMPS_PER_BUFF*NCHANNELS);
|
|
std::vector<std::complex<float> *> buffs(NCHANNELS);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
buffs[ch] = &mem[ch*NUM_SAMPS_PER_BUFF];
|
|
}
|
|
uhd::rx_metadata_t metadata;
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
std::cout << "data check " << i << std::endl;
|
|
size_t num_samps_ret = handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(not metadata.more_fragments);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, 10 + i%10);
|
|
num_accum_samps += num_samps_ret;
|
|
if (i == NUM_PKTS_TO_TEST/2){
|
|
num_accum_samps = 0; //simulate the user changing the time
|
|
}
|
|
}
|
|
|
|
//subsequent receives should be a timeout
|
|
for (size_t i = 0; i < 3; i++){
|
|
std::cout << "timeout check " << i << std::endl;
|
|
handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){
|
|
////////////////////////////////////////////////////////////////////////
|
|
uhd::otw_type_t otw_type;
|
|
otw_type.width = 16;
|
|
otw_type.shift = 0;
|
|
otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN;
|
|
|
|
uhd::transport::vrt::if_packet_info_t ifpi;
|
|
ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA;
|
|
ifpi.num_payload_words32 = 0;
|
|
ifpi.packet_count = 0;
|
|
ifpi.sob = true;
|
|
ifpi.eob = false;
|
|
ifpi.has_sid = false;
|
|
ifpi.has_cid = false;
|
|
ifpi.has_tsi = true;
|
|
ifpi.has_tsf = true;
|
|
ifpi.tsi = 0;
|
|
ifpi.tsf = 0;
|
|
ifpi.has_tlr = false;
|
|
|
|
static const double TICK_RATE = 100e6;
|
|
static const double SAMP_RATE = 10e6;
|
|
static const size_t NUM_PKTS_TO_TEST = 30;
|
|
static const size_t NUM_SAMPS_PER_BUFF = 10;
|
|
static const size_t NCHANNELS = 4;
|
|
|
|
std::vector<dummy_recv_xport_class> dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type));
|
|
|
|
//generate a bunch of packets
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
ifpi.num_payload_words32 = 10 + i%10;
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
dummy_recv_xports[ch].push_back_packet(ifpi);
|
|
}
|
|
ifpi.packet_count++;
|
|
ifpi.tsf += ifpi.num_payload_words32*size_t(TICK_RATE/SAMP_RATE);
|
|
}
|
|
|
|
//create the super receive packet handler
|
|
uhd::transport::sph::recv_packet_handler handler(NCHANNELS);
|
|
handler.set_vrt_unpacker(&uhd::transport::vrt::if_hdr_unpack_be);
|
|
handler.set_tick_rate(TICK_RATE);
|
|
handler.set_samp_rate(SAMP_RATE);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1));
|
|
}
|
|
handler.set_converter(otw_type);
|
|
|
|
//check the received packets
|
|
size_t num_accum_samps = 0;
|
|
std::vector<std::complex<float> > mem(NUM_SAMPS_PER_BUFF*NCHANNELS);
|
|
std::vector<std::complex<float> *> buffs(NCHANNELS);
|
|
for (size_t ch = 0; ch < NCHANNELS; ch++){
|
|
buffs[ch] = &mem[ch*NUM_SAMPS_PER_BUFF];
|
|
}
|
|
uhd::rx_metadata_t metadata;
|
|
for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){
|
|
std::cout << "data check " << i << std::endl;
|
|
size_t num_samps_ret = handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, 10);
|
|
num_accum_samps += num_samps_ret;
|
|
|
|
if (not metadata.more_fragments) continue;
|
|
|
|
num_samps_ret = handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE);
|
|
BOOST_CHECK(not metadata.more_fragments);
|
|
BOOST_CHECK_EQUAL(metadata.fragment_offset, 10);
|
|
BOOST_CHECK(metadata.has_time_spec);
|
|
BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t(0, num_accum_samps, SAMP_RATE));
|
|
BOOST_CHECK_EQUAL(num_samps_ret, i%10);
|
|
num_accum_samps += num_samps_ret;
|
|
}
|
|
|
|
//subsequent receives should be a timeout
|
|
for (size_t i = 0; i < 3; i++){
|
|
std::cout << "timeout check " << i << std::endl;
|
|
handler.recv(
|
|
buffs, NUM_SAMPS_PER_BUFF, metadata,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET, 1.0
|
|
);
|
|
BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT);
|
|
}
|
|
|
|
}
|