[USRP-users] Synched TX/RX on B210 NOT POSSIBLE????

Marcus D. Leech mleech at ripnet.com
Tue Oct 28 19:34:11 EDT 2014


On 10/28/2014 06:01 PM, Eleftherios(Lef) Kampianakis via USRP-users wrote:
> Hello and thank you for your responses.
>
> I am sorry, sorry, I didnt realize that I wasnt clear enough.
>
> My goal is to "load" the B210 with the maximum number of samples (in 
> this case 2044) for transmission.  Followingly, I want to command the 
> usrp to start transmitting and receiving at the same time in such way 
> that all the transmitted samples have a known phase compared to the 
> received samples. That is, if the Nth sample is transmitted (i.e. on 
> the antenna) at time t_tx, and the Nth sample is received at time 
> t_rx, the t_tx - t_rx is known after every packet. I only need to do 
> this ONCE (i.e. transmit only ONE packet) so I am not interested in 
> streaming. However, since as you noted the TX and RX  synthesizers on 
> the ad9361 are not synched, I cannot proceed with the aforementioned 
> methodology.
I just want to re-emphasize.  The TX and RX synthesizers on the AD9361 
will be *coherent* to within the limits of the synthesizer phase-noise, 
but they
   won't have a predictable *phase offset* with respect to one another 
whenever you start a new session or re-tune.

Contrast this to the usual situation with a TX in one place, and an RX 
in another.  Unless special pains have been taken, the TX and RX will 
not have
   predictable phase-offset, and they won't "march together" (coherence).

An architecture in general-purpose transceivers (whether that's 
SDRs/USRPs/whatever) where the RX and TX LOs are exactly the same--that is,
   a single, shared, synthesizer, is not all that common, at least for 
general-purpose RF transceivers.  Having separate (but usually 
common-clocked)
   synthesizers is the norm.


>
> My next step is to utilize  a method proposed by Stefan Ereth with 
> which I will utilize a splitter at the transmitter with one output 
> going to the RX1 and the other to RX2. Supposing RX1 and RX2 are phase 
> synched (or have a fixed phase difference) I should be able to 
> compensate the phase difference between TX and RX in every session. I 
> have cited the failed code of my effort to synch transmit and receive 
> below, for archiving purposes. I have also corrected the mistake that 
> was pointed out by Michael which of course didnt solve the problem.
>
> #include <uhd/types/tune_request.hpp>
> #include <uhd/utils/thread_priority.hpp>
> #include <uhd/utils/safe_main.hpp>
> #include <uhd/usrp/multi_usrp.hpp>
> #include <boost/program_options.hpp>
> #include <boost/format.hpp>
> #include <boost/thread.hpp>
> #include <iostream>
> #include <fstream>
> #include <complex>
> #include <csignal>
>
> //------------------MACROS------------------
> #define DEB(x) std::cout << "DEB:" << x << std::endl
>
>
> //------------------SETUP------------------
>
> //Assign the namespace po from boost::program_options
> //This is done to work with the terminal inputs cause 
> boost::program_options
> // Question: why use namespace instead of .hpp
> namespace po = boost::program_options;
>
>
>
> #define CPU_FORMAT "fc32"
> #define WIRE_FORMAT "sc16"
> #define REF_CLOCK "internal"
> #define SAMP_RATE 200e3
> #define CENT_FREQ 915e6
> #define TX_GAIN  10 //dB
> #define RX_GAIN 10   //dB
> #define SAMPLES_PER_BUFFER 1000
> #define ARGS ""
> #define TX_FILENAME 
> "/Users/kampianakis/Desktop/SGCC/Demos/UHD/uhd/host/build/examples/data/sin_IQ_TX"
> #define RX_FILENAME 
> "/Users/kampianakis/Desktop/SGCC/Demos/UHD/uhd/host/build/examples/data/sin_IQ_RX"
> #define SN std::endl
> #define RX_BW SAMP_RATE/2;
> #define TX 1
> #define RX_CONT 0
> #define TOTAL_SAMPLES 1e6
> #define SYNCH_DELAY 2 //Seconds
> #define DEBUG 0
> #define RX_TIMEOUT 3
>
> //Stuff for tx asynch. Declare as global to avoid input in thread 
> (chicken)
> uhd::tx_streamer::sptr tx_stream;
> uhd::tx_metadata_t tx_md;                                             
>      //TX metadata structure for describing received IF data. Includes 
> time specification, and start and stop burst flags. The send routines 
> will convert the metadata to IF data headers.
> size_t samples_per_buff = SAMPLES_PER_BUFFER;
> size_t num_tx_samps = 0;
> std::vector<std::complex<float> > small_tx_buff(samples_per_buff);
>
>
>
> void thread_startTx(){
>     num_tx_samps = tx_stream->send(&small_tx_buff.front(), 
> small_tx_buff.size(), tx_md);
>     // num_tx_samps = tx_stream->send(&small_tx_buff.front(), 
> small_tx_buff.size(), tx_md);
> }
>
>
>
>
> typedef boost::function<uhd::sensor_value_t (const std::string&)> 
> get_sensor_fn_t;
> bool check_locked_sensor(std::vector<std::string> sensor_names, const 
> char* sensor_name, get_sensor_fn_t get_sensor_fn, double setup_time){
>     if (std::find(sensor_names.begin(), sensor_names.end(), 
> sensor_name) == sensor_names.end())
>         return false;
>
>     boost::system_time start = boost::get_system_time();
>     boost::system_time first_lock_time;
>
>     std::cout << boost::format("Waiting for \"%s\": ") % sensor_name;
>     std::cout.flush();
>
>     while (true){
>         if ((not first_lock_time.is_not_a_date_time()) and
>             (boost::get_system_time() > (first_lock_time + 
> boost::posix_time::seconds(setup_time))))
>         {
>             std::cout << " locked." << std::endl;
>             break;
>         }
>         if (get_sensor_fn(sensor_name).to_bool()){
>             if (first_lock_time.is_not_a_date_time())
>                 first_lock_time = boost::get_system_time();
>             std::cout << "+";
>             std::cout.flush();
>         }
>         else{
>             first_lock_time = boost::system_time(); //reset to 'not a 
> date time'
>
>             if (boost::get_system_time() > (start + 
> boost::posix_time::seconds(setup_time))){
>                 std::cout << std::endl;
>                 throw std::runtime_error(str(boost::format("timed out 
> waiting for consecutive locks on sensor \"%s\"") % sensor_name));
>             }
>             std::cout << "_";
>             std::cout.flush();
>         }
>         boost::this_thread::sleep(boost::posix_time::milliseconds(100));
>     }
>     std::cout << std::endl;
>     return true;
> }
>
>
>
> int UHD_SAFE_MAIN(int argc, char *argv[]){
>     uhd::set_thread_priority_safe();
>
>     std::string args, tx_file, rx_file, type, ref, wire_format, 
> cpu_format;
>     double rate, freq, tx_gain, rx_gain, rx_bw, delay, 
> lo_off,seconds_in_future, rx_timeout;
>
>     rx_bw = RX_BW;
>     rx_gain = RX_GAIN;
>     wire_format = WIRE_FORMAT;
>     cpu_format = CPU_FORMAT;
>     rate = SAMP_RATE;
>     args = ARGS;
>     ref = REF_CLOCK;
>     freq = CENT_FREQ;
>     tx_gain = TX_GAIN;
>     // samples_per_buff = SAMPLES_PER_BUFFER;
>     tx_file = TX_FILENAME;
>     rx_file = RX_FILENAME;
>     seconds_in_future = SYNCH_DELAY;
>     rx_timeout = RX_TIMEOUT;
>
>     //------------------INIT TX------------------
>                                         //Set the scheduling priority 
> on the current thread. Same as set_thread_priority but does not throw 
> on failure.
>     std::cout << boost::format("Creating the usrp device with: %s...") 
> % args << std::endl;
>     uhd::usrp::multi_usrp::sptr usrp = 
> uhd::usrp::multi_usrp::make(args);       //Make the usrp by calling 
> the constructor with param the args
>
>     usrp->set_clock_source(ref);                                       
>    //Set the clock source for the usrp device. This sets the source 
> for a 10 MHz reference clock. Typical options for source: internal, 
> external, MIMO.
>     std::cout << boost::format("Setting TX Rate: %f Msps...") % 
> (rate/1e6) << std::endl;
>     usrp->set_tx_rate(rate);                                           
>                                              //Set the sample rate
>     std::cout << boost::format("Actual TX Rate: %f Msps...") % 
> (usrp->get_tx_rate()/1e6) << std::endl << std::endl;
>
>     std::cout << boost::format("Setting TX Freq: %f MHz...") % 
> (freq/1e6) << std::endl;                              //Set up tuning 
> frequency
>     uhd::tune_request_t tune_request;
>     tune_request = uhd::tune_request_t(freq);                         
>                                                //Generate the tune request
>     usrp->set_tx_freq(tune_request);                                   
>                                              //Tune to CENT_FREQ
>     std::cout << boost::format("Actual TX Freq: %f MHz...") % 
> (usrp->get_tx_freq()/1e6) << std::endl << std::endl;  //PRINT Actual 
> CENT_FREQ
>
>     std::cout << boost::format("Setting TX Gain: %f dB...") % tx_gain 
> << std::endl;
>     usrp->set_tx_gain(tx_gain);                                       
>                                               //Set the tx_gain
>     std::cout << boost::format("Actual TX Gain: %f dB...") % 
> usrp->get_tx_gain() << std::endl << std::endl;
>     //------------------CHECK STUFF------------------
>     //Check Ref and LO Lock detect
>     std::vector<std::string> sensor_names;
>     sensor_names = usrp->get_tx_sensor_names(0);
>     if (std::find(sensor_names.begin(), sensor_names.end(), 
> "lo_locked") != sensor_names.end()) {
>         uhd::sensor_value_t lo_locked = 
> usrp->get_tx_sensor("lo_locked",0);
>         std::cout << boost::format("Checking TX: %s ...") % 
> lo_locked.to_pp_string() << std::endl;
>         UHD_ASSERT_THROW(lo_locked.to_bool());
>     }
>
>
>
>
>
>     //------------------INIT RX------------------
>
>     //IS THIS NECESSARY?
>     //always select the subdevice first, the channel mapping affects 
> the other settings
>     //usrp->set_rx_subdev_spec(subdev);
>
>     std::cout << boost::format("Setting RX Rate: %f Msps...") % 
> (rate/1e6) << std::endl;
>     usrp->set_rx_rate(rate);
>     std::cout << boost::format("Actual RX Rate: %f Msps...") % 
> (usrp->get_rx_rate()/1e6) << std::endl << std::endl;
>
>     //set the center frequency
>     std::cout << boost::format("Setting RX Freq: %f MHz...") % 
> (freq/1e6) << std::endl;
>     usrp->set_rx_freq(tune_request);
>     std::cout << boost::format("Actual RX Freq: %f MHz...") % 
> (usrp->get_rx_freq()/1e6) << std::endl << std::endl;
>     std::cout << boost::format("Setting RX Gain: %f dB...") % rx_gain 
> << std::endl;
>     usrp->set_rx_gain(rx_gain);
>     std::cout << boost::format("Actual RX Gain: %f dB...") % 
> usrp->get_rx_gain() << std::endl << std::endl;
>
>     boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow 
> 1sec  setup time
>     //------------------CHECK STUFF------------------
>     //Always check for locked sensor
>     check_locked_sensor(usrp->get_rx_sensor_names(0), "lo_locked", 
> boost::bind(&uhd::usrp::multi_usrp::get_rx_sensor, usrp, _1, 0), 1);
>
>     //------------------INIT FILES---------------
>
>     std::ofstream outfile;
>     outfile.open(rx_file.c_str(), std::ofstream::binary);
>     if(!outfile.good()){
>         std::cout << "OUT File error\n";
>         return 0;
>     }
>
>     std::ifstream infile(tx_file.c_str(), std::ifstream::binary);
>
>     if(!infile.good()){
>         std::cout << "IN File error\n";
>         return 0;
>     }
>
>     //------------------INIT STREAMS---------------
>
>     //Stream ARGS
>     uhd::stream_args_t stream_args(cpu_format, wire_format);           
>      //Call the constructor of the class stream_args_t and generate 
> the stream_args object with inputs the cpu_format and wire_format 
> (this is the format per sample)
>
>     tx_stream = usrp->get_tx_stream(stream_args);                     
>       //Generate a tx_streamer object named tx_stream using the 
> usrp->get_tx_stream(stream_args). Remember, usrp is already initialized
>     uhd::rx_streamer::sptr rx_stream = 
> usrp->get_rx_stream(stream_args);    //Generate a tx_streamer object 
> named tx_stream using the usrp->get_tx_stream(stream_args). Remember, 
> usrp is already initialized
>
>
>
>
>     //Setup metadata
>
>     //Setup tx_metadata
>
>     tx_md.start_of_burst = true;                                       
>        //Set start of burst to true for the first packet in the chain. ?
>     tx_md.end_of_burst =   false;
>
>     #define SYNCHED_TXRX 1
>     //For TX
>     if(SYNCHED_TXRX){
>         tx_md.has_time_spec = true;
>
>     }else{
>         tx_md.has_time_spec = false;
>     }
>
>     //Setup rx_metadata
>     uhd::rx_metadata_t rx_md;
>
>     //Setup stream command ONLY FOR RX
>     uhd::stream_cmd_t 
> stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
>     stream_cmd.num_samps = samples_per_buff;
>
>
>
>
>     //For RX
>     if(SYNCHED_TXRX){
>         stream_cmd.stream_now = false;
>         // tx_md.time_spec =   stream_cmd.time_spec;
>     }else{
>         stream_cmd.stream_now = true;
>         stream_cmd.time_spec = uhd::time_spec_t();
>     }
>
>
>     if(SYNCHED_TXRX){
>         //Cannt get any faster than this
>         tx_md.time_spec = stream_cmd.time_spec = 
> uhd::time_spec_t(seconds_in_future)+usrp->get_time_now();
>     }
>
>
>     //Create the  buffs
>     std::vector<std::complex<float> > small_rx_buff(samples_per_buff);
>
>     //Fill the  TX buffer
>     for (int i = 0; i < samples_per_buff; ++i){
>         infile.read((char*)&small_tx_buff.at 
> <http://small_tx_buff.at>(i), 
> small_tx_buff.size()*sizeof(std::complex<float>));
>
>     }
>     infile.close();                                                   
>      //Close the file pointer
>
>     //Issue the  stream command
>     rx_stream->issue_stream_cmd(stream_cmd);
>
>     //Print number of maximum buffer size
>     printf("MAX TX: %d\n", (int)tx_stream->get_max_num_samps());
>     printf("MAX RX %d\n", (int)rx_stream->get_max_num_samps());
>
>
>     size_t num_rx_samps = 0;
>
>
>     boost::thread txThread(thread_startTx);
>     //receivotrnsmit
>     txThread.join();                        //Strart the thread for tx 
>  (tx is f blocking)
>     num_rx_samps = rx_stream->recv(&small_rx_buff.front(), 
> small_rx_buff.size(), rx_md, rx_timeout, false);  // Receive buffers 
> containing samples described by the metadata.
>
>     // num_rx_samps = rx_stream->recv(&small_rx_buff.front(), 
> small_rx_buff.size(), rx_md, rx_timeout, false);  // Receive buffers 
> containing samples described by the metadata.
>
>
>     //Wait for everything to stop
>     boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
>
>
>     //Cleanup and print what happened
>     
> usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); // 
> Stop the stream (not really necessary here)
>
>     double rx_stamp = rx_md.time_spec.get_full_secs() + 
> rx_md.time_spec.get_frac_secs();
>     double tx_stamp = tx_md.time_spec.get_full_secs() + 
> tx_md.time_spec.get_frac_secs();
>     double t_diff = rx_stamp - tx_stamp;
>
>
>     printf("RX Time stamp: %.12lf\n ΤX Time stamp: %.12lf\n Diff: 
> %.12lf\n",rx_stamp, tx_stamp, t_diff);
>
>
>
>     switch ( rx_md.error_code ) {
>
>         case uhd::rx_metadata_t::ERROR_CODE_NONE:
>             printf("No error:)\n");
>             break;
>         case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
>             printf("MDError 2\n");
>             break;
>         case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
>             printf("MDError 3\n");
>             break;
>         case uhd::rx_metadata_t::ERROR_CODE_BROKEN_CHAIN:
>             printf("MDError 4\n");
>             break;
>         case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
>             printf("MDError 5\n");
>             break;
>         case uhd::rx_metadata_t::ERROR_CODE_ALIGNMENT:
>             printf("MDError 6\n");
>             break;
>         case uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET:
>             printf("MDError 7\n");
>             break;
>
>         default:
>             printf("WUT\n");
>             break;
>
>     }
>
>     //write the  samples
>     if (outfile.is_open()){
>         outfile.write((const char*)&small_rx_buff.front(), 
> num_rx_samps*sizeof(std::complex<float>));
>     }
>
>
>
>     outfile.close();                                                   
>      //Close the file pointer
>
>
>
>     //print
>     std::cout << "Transmitted samples: " << num_tx_samps << '\n';
>     std::cout << "Received samples: " << num_rx_samps << '\n';
>
>
>
>
>     return EXIT_SUCCESS;
> }
>
>
>
>
>
>
>
>
>
> On Mon, Oct 27, 2014 at 5:47 PM, Eleftherios(Lef) Kampianakis 
> <e.kampianakis.ee at ieee.org <mailto:e.kampianakis.ee at ieee.org>> wrote:
>
>     Hello forum,
>
>     I have a project for which it is crucial to have minimal or none
>     time delay between the transmitter and receiver. For my purposes I
>     utilize a B210 and use only the TX/RX for transmit and RX for receive.
>
>     I have developed (following the advice of Stephen Graham) the
>     following code that attaches a the transmit function to a thread
>     in order to execute tx and rx concurrently (tx is blocking). For
>     now, the TX/RX and RX channels are connected with coax cable to
>     avoid random phase introduction from the wireless channel. I
>     transmit and receive samples concurrently and calculate the time
>     difference using tx_metadata.time_spec and rx_metadata.time_spec.
>     However, when I apply a shift at the samples that I receive
>     according to this time delay (N_samples_to_shift = F_sampling *
>     T_delay) the signals still wont align and I still get a random
>     time delay everytime I execute the UHD code.
>
>     Could someone inform me if what I am trying to do here is even
>     remotely possible with the B210? Should I use another platform or
>     should I implement some kind of workaround?
>
>     Thank you in advance
>
>     CODE:
>     //Author Eleftherios(Lef) Kampianakis
>
>     //V0: Tx Rx wokrking but not synched
>     //V1: effort for synching (failed)
>     //V2: used threads to start tx asynch
>
>     #include <uhd/types/tune_request.hpp>
>     #include <uhd/utils/thread_priority.hpp>
>     #include <uhd/utils/safe_main.hpp>
>     #include <uhd/usrp/multi_usrp.hpp>
>     #include <boost/program_options.hpp>
>     #include <boost/format.hpp>
>     #include <boost/thread.hpp>
>     #include <iostream>
>     #include <fstream>
>     #include <complex>
>     #include <csignal>
>
>     //------------------MACROS------------------
>     #define DEB(x) std::cout << "DEB:" << x << std::endl
>
>
>     //------------------SETUP------------------
>
>     //Assign the namespace po from boost::program_options
>     //This is done to work with the terminal inputs cause
>     boost::program_options
>     // Question: why use namespace instead of .hpp
>     namespace po = boost::program_options;
>
>
>
>     #define CPU_FORMAT "fc32"
>     #define WIRE_FORMAT "sc16"
>     #define REF_CLOCK "internal"
>     #define SAMP_RATE 200e3
>     #define CENT_FREQ 915e6
>     #define TX_GAIN  10 //dB
>     #define RX_GAIN 10   //dB
>     #define SAMPLES_PER_BUFFER 1000
>     #define ARGS ""
>     #define TX_FILENAME
>     "/Users/kampianakis/Desktop/SGCC/Demos/UHD/uhd/host/build/examples/data/sin_IQ_TX"
>     #define RX_FILENAME
>     "/Users/kampianakis/Desktop/SGCC/Demos/UHD/uhd/host/build/examples/data/sin_IQ_RX"
>     #define SN std::endl
>     #define RX_BW SAMP_RATE/2;
>     #define TX 1
>     #define RX_CONT 0
>     #define TOTAL_SAMPLES 1e6
>     #define SYNCH_DELAY 2 //Seconds
>     #define DEBUG 0
>     #define RX_TIMEOUT 3
>
>     //Stuff for tx asynch. Declare as global to avoid input in thread
>     (chicken)
>     uhd::tx_streamer::sptr tx_stream;
>     uhd::tx_metadata_t tx_md;                                        
>              //TX metadata structure for describing received IF data.
>     Includes time specification, and start and stop burst flags. The
>     send routines will convert the metadata to IF data headers.
>     size_t samples_per_buff = SAMPLES_PER_BUFFER;
>     size_t num_tx_samps = 0;
>     std::vector<std::complex<float> > small_tx_buff(samples_per_buff);
>
>
>
>     void thread_startTx(){
>         num_tx_samps = tx_stream->send(&small_tx_buff.front(),
>     small_tx_buff.size(), tx_md);
>     }
>
>
>
>
>     typedef boost::function<uhd::sensor_value_t (const std::string&)>
>     get_sensor_fn_t;
>     bool check_locked_sensor(std::vector<std::string> sensor_names,
>     const char* sensor_name, get_sensor_fn_t get_sensor_fn, double
>     setup_time){
>         if (std::find(sensor_names.begin(), sensor_names.end(),
>     sensor_name) == sensor_names.end())
>             return false;
>
>         boost::system_time start = boost::get_system_time();
>         boost::system_time first_lock_time;
>
>         std::cout << boost::format("Waiting for \"%s\": ") % sensor_name;
>         std::cout.flush();
>
>         while (true){
>             if ((not first_lock_time.is_not_a_date_time()) and
>                 (boost::get_system_time() > (first_lock_time +
>     boost::posix_time::seconds(setup_time))))
>             {
>                 std::cout << " locked." << std::endl;
>                 break;
>             }
>             if (get_sensor_fn(sensor_name).to_bool()){
>                 if (first_lock_time.is_not_a_date_time())
>                     first_lock_time = boost::get_system_time();
>                 std::cout << "+";
>                 std::cout.flush();
>             }
>             else{
>                 first_lock_time = boost::system_time(); //reset to
>     'not a date time'
>
>                 if (boost::get_system_time() > (start +
>     boost::posix_time::seconds(setup_time))){
>                     std::cout << std::endl;
>                     throw std::runtime_error(str(boost::format("timed
>     out waiting for consecutive locks on sensor \"%s\"") % sensor_name));
>                 }
>                 std::cout << "_";
>                 std::cout.flush();
>             }
>            
>     boost::this_thread::sleep(boost::posix_time::milliseconds(100));
>         }
>         std::cout << std::endl;
>         return true;
>     }
>
>
>
>     int UHD_SAFE_MAIN(int argc, char *argv[]){
>         uhd::set_thread_priority_safe();
>
>         std::string args, tx_file, rx_file, type, ref, wire_format,
>     cpu_format;
>         double rate, freq, tx_gain, rx_gain, rx_bw, delay,
>     lo_off,seconds_in_future, rx_timeout;
>
>         rx_bw = RX_BW;
>         rx_gain = RX_GAIN;
>         wire_format = WIRE_FORMAT;
>         cpu_format = CPU_FORMAT;
>         rate = SAMP_RATE;
>         args = ARGS;
>         ref = REF_CLOCK;
>         freq = CENT_FREQ;
>         tx_gain = TX_GAIN;
>         // samples_per_buff = SAMPLES_PER_BUFFER;
>         tx_file = TX_FILENAME;
>         rx_file = RX_FILENAME;
>         seconds_in_future = SYNCH_DELAY;
>         rx_timeout = RX_TIMEOUT;
>
>         //------------------INIT TX------------------
>                                             //Set the scheduling
>     priority on the current thread. Same as set_thread_priority but
>     does not throw on failure.
>         std::cout << boost::format("Creating the usrp device with:
>     %s...") % args << std::endl;
>         uhd::usrp::multi_usrp::sptr usrp =
>     uhd::usrp::multi_usrp::make(args);       //Make the usrp by
>     calling the constructor with param the args
>
>         usrp->set_clock_source(ref);                                  
>            //Set the clock source for the usrp device. This sets the
>     source for a 10 MHz reference clock. Typical options for source:
>     internal, external, MIMO.
>         std::cout << boost::format("Setting TX Rate: %f Msps...") %
>     (rate/1e6) << std::endl;
>         usrp->set_tx_rate(rate);                                      
>                                                      //Set the sample rate
>         std::cout << boost::format("Actual TX Rate: %f Msps...") %
>     (usrp->get_tx_rate()/1e6) << std::endl << std::endl;
>
>         std::cout << boost::format("Setting TX Freq: %f MHz...") %
>     (freq/1e6) << std::endl;                              //Set up
>     tuning frequency
>         uhd::tune_request_t tune_request;
>         tune_request = uhd::tune_request_t(freq);                    
>                                                        //Generate the
>     tune request
>         usrp->set_tx_freq(tune_request);                              
>                                                      //Tune to CENT_FREQ
>         std::cout << boost::format("Actual TX Freq: %f MHz...") %
>     (usrp->get_tx_freq()/1e6) << std::endl << std::endl;  //PRINT
>     Actual CENT_FREQ
>
>         std::cout << boost::format("Setting TX Gain: %f dB...") %
>     tx_gain << std::endl;
>         usrp->set_tx_gain(tx_gain);                                  
>                                                       //Set the tx_gain
>         std::cout << boost::format("Actual TX Gain: %f dB...") %
>     usrp->get_tx_gain() << std::endl << std::endl;
>         //------------------CHECK STUFF------------------
>         //Check Ref and LO Lock detect
>         std::vector<std::string> sensor_names;
>         sensor_names = usrp->get_tx_sensor_names(0);
>         if (std::find(sensor_names.begin(), sensor_names.end(),
>     "lo_locked") != sensor_names.end()) {
>             uhd::sensor_value_t lo_locked =
>     usrp->get_tx_sensor("lo_locked",0);
>             std::cout << boost::format("Checking TX: %s ...") %
>     lo_locked.to_pp_string() << std::endl;
>             UHD_ASSERT_THROW(lo_locked.to_bool());
>         }
>
>
>
>
>
>         //------------------INIT RX------------------
>
>         //IS THIS NECESSARY?
>         //always select the subdevice first, the channel mapping
>     affects the other settings
>         //usrp->set_rx_subdev_spec(subdev);
>
>         std::cout << boost::format("Setting RX Rate: %f Msps...") %
>     (rate/1e6) << std::endl;
>         usrp->set_rx_rate(rate);
>         std::cout << boost::format("Actual RX Rate: %f Msps...") %
>     (usrp->get_rx_rate()/1e6) << std::endl << std::endl;
>
>         //set the center frequency
>         std::cout << boost::format("Setting RX Freq: %f MHz...") %
>     (freq/1e6) << std::endl;
>         usrp->set_rx_freq(tune_request);
>         std::cout << boost::format("Actual RX Freq: %f MHz...") %
>     (usrp->get_rx_freq()/1e6) << std::endl << std::endl;
>         std::cout << boost::format("Setting RX Gain: %f dB...") %
>     rx_gain << std::endl;
>         usrp->set_rx_gain(rx_gain);
>         std::cout << boost::format("Actual RX Gain: %f dB...") %
>     usrp->get_rx_gain() << std::endl << std::endl;
>
>         boost::this_thread::sleep(boost::posix_time::seconds(1));
>     //allow 1sec  setup time
>         //------------------CHECK STUFF------------------
>         //Always check for locked sensor
>         check_locked_sensor(usrp->get_rx_sensor_names(0), "lo_locked",
>     boost::bind(&uhd::usrp::multi_usrp::get_rx_sensor, usrp, _1, 0), 1);
>
>         //------------------INIT FILES---------------
>
>         std::ofstream outfile;
>         outfile.open(rx_file.c_str(), std::ofstream::binary);
>         if(!outfile.good()){
>             std::cout << "OUT File error\n";
>             return 0;
>         }
>
>         std::ifstream infile(tx_file.c_str(), std::ifstream::binary);
>
>         if(!infile.good()){
>             std::cout << "IN File error\n";
>             return 0;
>         }
>
>         //------------------INIT STREAMS---------------
>
>         //Stream ARGS
>         uhd::stream_args_t stream_args(cpu_format, wire_format);      
>              //Call the constructor of the class stream_args_t and
>     generate the stream_args object with inputs the cpu_format and
>     wire_format (this is the format per sample)
>
>         tx_stream = usrp->get_tx_stream(stream_args);                
>               //Generate a tx_streamer object named tx_stream using
>     the usrp->get_tx_stream(stream_args). Remember, usrp is already
>     initialized
>         uhd::rx_streamer::sptr rx_stream =
>     usrp->get_rx_stream(stream_args);    //Generate a tx_streamer
>     object named tx_stream using the usrp->get_tx_stream(stream_args).
>     Remember, usrp is already initialized
>
>
>
>
>         //Setup metadata
>
>         //Setup tx_metadata
>
>         tx_md.start_of_burst = true;                                  
>                //Set start of burst to true for the first packet in
>     the chain. ?
>         tx_md.end_of_burst =   false;
>
>         #define TIMED_TX 0
>         #define TIMED_RX 0
>         if(TIMED_TX){
>
>             tx_md.has_time_spec = true;
>             tx_md.time_spec =
>     uhd::time_spec_t(seconds_in_future)+usrp->get_time_now();
>
>         }else{
>             tx_md.has_time_spec = false;
>         }
>
>         //Setup rx_metadata
>         uhd::rx_metadata_t rx_md;
>
>         //Setup stream command ONLY FOR RX
>         uhd::stream_cmd_t
>     stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
>         stream_cmd.num_samps = samples_per_buff;
>
>         if(TIMED_RX){
>             stream_cmd.stream_now = false;
>             stream_cmd.time_spec =
>     uhd::time_spec_t(seconds_in_future)+usrp->get_time_now();
>         }else{
>             stream_cmd.stream_now = true;
>             stream_cmd.time_spec = uhd::time_spec_t();
>         }
>
>
>
>
>         //Create the  buffs
>         std::vector<std::complex<float> > small_rx_buff(samples_per_buff);
>
>         //Fill the  TX buffer
>         for (int i = 0; i < samples_per_buff; ++i){
>             infile.read((char*)&small_tx_buff.at
>     <http://small_tx_buff.at>(i),
>     small_tx_buff.size()*sizeof(std::complex<float>));
>
>         }
>         infile.close();                                              
>              //Close the file pointer
>
>         //Issue the  stream command
>         rx_stream->issue_stream_cmd(stream_cmd);
>
>         //Print number of maximum buffer size
>         printf("MAX TX: %d\n", (int)tx_stream->get_max_num_samps());
>         printf("MAX RX %d\n", (int)rx_stream->get_max_num_samps());
>
>
>         size_t num_rx_samps = 0;
>         size_t num_tx_samps = 0;
>
>
>         boost::thread txThread(thread_startTx);
>         //receivotrnsmit
>         num_rx_samps = rx_stream->recv(&small_rx_buff.front(),
>     small_rx_buff.size(), rx_md, rx_timeout, false);  // Receive
>     buffers containing samples described by the metadata.
>         txThread.join();                        //Strart the thread
>     for tx  (tx is f blocking)
>
>         double rx_stamp = rx_md.time_spec.get_full_secs() +
>     rx_md.time_spec.get_frac_secs();
>         double tx_stamp = tx_md.time_spec.get_full_secs() +
>     tx_md.time_spec.get_frac_secs();
>         double t_diff = rx_stamp - tx_stamp;
>
>
>         printf("RX Time stamp: %.12lf\n ΤX Time stamp: %.12lf\n Diff:
>     %.12lf\n",rx_stamp, tx_stamp, t_diff);
>
>
>
>         switch ( rx_md.error_code ) {
>
>             case uhd::rx_metadata_t::ERROR_CODE_NONE:
>                 printf("No error:)\n");
>                 break;
>             case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
>                 printf("MDError 2\n");
>                 break;
>             case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
>                 printf("MDError 3\n");
>                 break;
>             case uhd::rx_metadata_t::ERROR_CODE_BROKEN_CHAIN:
>                 printf("MDError 4\n");
>                 break;
>             case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
>                 printf("MDError 5\n");
>                 break;
>             case uhd::rx_metadata_t::ERROR_CODE_ALIGNMENT:
>                 printf("MDError 6\n");
>                 break;
>             case uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET:
>                 printf("MDError 7\n");
>                 break;
>
>             default:
>                 printf("WUT\n");
>                 break;
>
>         }
>
>
>
>
>
>         //write the  samples
>         if (outfile.is_open()){
>             outfile.write((const char*)&small_rx_buff.front(),
>     num_rx_samps*sizeof(std::complex<float>));
>         }
>
>
>
>         outfile.close();                                              
>              //Close the file pointer
>
>
>
>         //print
>         // std::cout << "Transmitted samples: " << num_tx_samps << '\n';
>         std::cout << "Received samples: " << num_rx_samps << '\n';
>
>
>
>
>         return EXIT_SUCCESS;
>     }
>
>
>     -- 
>     Eleftherios(Lef) Kampianakis
>     Electronics and Computer Engineer
>     PHD Candidate and Researcher at Sensing Computing Communications
>     Group (SGCC)
>     Department of Electrical Engineering
>     University of Washington
>     3927 Adams Lane, NE, Mercer Court D805B, 98105
>     website: http://users.isc.tuc.gr/~ekabianakis/
>     <http://users.isc.tuc.gr/%7Eekabianakis/>
>     mail:e.kampianakis.ee at ieee.org
>     <mailto:mail%3Ae.kampianakis.ee at ieee.org>
>
>
>
>
> -- 
> Eleftherios(Lef) Kampianakis
> Electronics and Computer Engineer
> PHD Candidate and Researcher at Sensing Computing Communications Group 
> (SGCC)
> Department of Electrical Engineering
> University of Washington
> 3927 Adams Lane, NE, Mercer Court D805B, 98105
> website: http://users.isc.tuc.gr/~ekabianakis/ 
> <http://users.isc.tuc.gr/%7Eekabianakis/>
> mail:e.kampianakis.ee at ieee.org <mailto:mail%3Ae.kampianakis.ee at ieee.org>
>
>
> _______________________________________________
> USRP-users mailing list
> USRP-users at lists.ettus.com
> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com


-- 
Marcus Leech
Principal Investigator
Shirleys Bay Radio Astronomy Consortium
http://www.sbrac.org

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20141028/9cdc815c/attachment-0002.html>


More information about the USRP-users mailing list