Statistics
| Branch: | Tag: | Revision:

root / host / examples / tx_timed_samples.cpp @ 0f705316

History | View | Annotate | Download (4.91 KB)

1
//
2
// Copyright 2010-2011 Ettus Research LLC
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

    
18
#include <uhd/utils/thread_priority.hpp>
19
#include <uhd/utils/safe_main.hpp>
20
#include <uhd/usrp/multi_usrp.hpp>
21
#include <boost/program_options.hpp>
22
#include <boost/thread/thread.hpp>
23
#include <boost/format.hpp>
24
#include <iostream>
25
#include <complex>
26

    
27
namespace po = boost::program_options;
28

    
29
int UHD_SAFE_MAIN(int argc, char *argv[]){
30
    uhd::set_thread_priority_safe();
31

    
32
    //variables to be set by po
33
    std::string args;
34
    double seconds_in_future;
35
    size_t total_num_samps;
36
    double rate;
37
    float ampl;
38

    
39
    //setup the program options
40
    po::options_description desc("Allowed options");
41
    desc.add_options()
42
        ("help", "help message")
43
        ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
44
        ("secs", po::value<double>(&seconds_in_future)->default_value(1.5), "number of seconds in the future to transmit")
45
        ("nsamps", po::value<size_t>(&total_num_samps)->default_value(10000), "total number of samples to transmit")
46
        ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of outgoing samples")
47
        ("ampl", po::value<float>(&ampl)->default_value(float(0.3)), "amplitude of each sample")
48
        ("dilv", "specify to disable inner-loop verbose")
49
    ;
50
    po::variables_map vm;
51
    po::store(po::parse_command_line(argc, argv, desc), vm);
52
    po::notify(vm);
53

    
54
    //print the help message
55
    if (vm.count("help")){
56
        std::cout << boost::format("UHD TX Timed Samples %s") % desc << std::endl;
57
        return ~0;
58
    }
59

    
60
    bool verbose = vm.count("dilv") == 0;
61

    
62
    //create a usrp device
63
    std::cout << std::endl;
64
    std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
65
    uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
66
    std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
67

    
68
    //set the tx sample rate
69
    std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl;
70
    usrp->set_tx_rate(rate);
71
    std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl;
72

    
73
    std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
74
    usrp->set_time_now(uhd::time_spec_t(0.0));
75

    
76
    //allocate buffer with data to send
77
    std::vector<std::complex<float> > buff(usrp->get_device()->get_max_send_samps_per_packet(), std::complex<float>(ampl, ampl));
78

    
79
    //setup metadata for the first packet
80
    uhd::tx_metadata_t md;
81
    md.start_of_burst = false;
82
    md.end_of_burst = false;
83
    md.has_time_spec = true;
84
    md.time_spec = uhd::time_spec_t(seconds_in_future);
85

    
86
    //the first call to send() will block this many seconds before sending:
87
    double timeout = seconds_in_future + 0.1; //timeout (delay before transmit + padding)
88

    
89
    size_t num_acc_samps = 0; //number of accumulated samples
90
    while(num_acc_samps < total_num_samps){
91
        size_t samps_to_send = std::min(total_num_samps - num_acc_samps, buff.size());
92

    
93
        //ensure the the last packet has EOB set
94
        md.end_of_burst = samps_to_send <= buff.size();
95

    
96
        //send a single packet
97
        size_t num_tx_samps = usrp->get_device()->send(
98
            &buff.front(), samps_to_send, md,
99
            uhd::io_type_t::COMPLEX_FLOAT32,
100
            uhd::device::SEND_MODE_ONE_PACKET, timeout
101
        );
102

    
103
        //do not use time spec for subsequent packets
104
        md.has_time_spec = false;
105

    
106
        if (num_tx_samps < samps_to_send) std::cerr << "Send timeout..." << std::endl;
107
        if(verbose) std::cout << boost::format("Sent packet: %u samples") % num_tx_samps << std::endl;
108

    
109
        num_acc_samps += num_tx_samps;
110
    }
111

    
112
    std::cout << std::endl << "Waiting for async burst ACK... " << std::flush;
113
    uhd::async_metadata_t async_md;
114
    bool got_async_burst_ack = false;
115
    //loop through all messages for the ACK packet (may have underflow messages in queue)
116
    while (not got_async_burst_ack and usrp->get_device()->recv_async_msg(async_md, seconds_in_future)){
117
        got_async_burst_ack = (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK);
118
    }
119
    std::cout << (got_async_burst_ack? "success" : "fail") << std::endl;
120

    
121
    //finished
122
    std::cout << std::endl << "Done!" << std::endl << std::endl;
123

    
124
    return 0;
125
}