3 auto start = std::chrono::system_clock::now();
10 BOOST_LOG_TRIVIAL(info) <<
"Initializing hardware manager";
16 if(
sw_loop)BOOST_LOG_TRIVIAL(debug) <<
"Software loop enabled";
19 cudaSetDevice(settings->GPU_device_index);
21 cudaGetDeviceProperties(&props, settings->GPU_device_index);
30 dev_addrs = uhd::device::find(hint);
31 std::cout<<
"Looking for USRP x300 device number "<< usrp_number <<
" .." <<std::flush;
32 while(dev_addrs.size()< usrp_number + 1){
34 dev_addrs = uhd::device::find(hint);
35 std::cout<<
"."<<std::flush;
40 std::cout<<
"Device found and assigned to GPU "<< props.name <<
" ("<< settings->GPU_device_index <<
")"<<std::endl;
50 main_usrp = uhd::usrp::multi_usrp::make(args);
51 std::cout<<
"Creating device with arguments: "<<
device_arguments <<std::endl;
53 main_usrp = uhd::usrp::multi_usrp::make(dev_addrs[usrp_number]);
56 main_usrp->set_clock_source(settings->clock_reference);
59 A_sw_loop_queue =
new tx_queue(SW_LOOP_QUEUE_LENGTH);
60 B_sw_loop_queue =
new tx_queue(SW_LOOP_QUEUE_LENGTH);
71 A_tx_thread_operation =
false;
73 B_tx_thread_operation =
false;
76 std::this_thread::sleep_for(std::chrono::milliseconds(800));
84 A_tx_error_queue =
new error_queue(ERROR_QUEUE_LENGTH);
85 B_tx_error_queue =
new error_queue(ERROR_QUEUE_LENGTH);
87 A_rx_stream =
nullptr;
88 A_tx_stream =
nullptr;
89 B_rx_stream =
nullptr;
90 B_tx_stream =
nullptr;
92 if(not sw_loop)
main_usrp->set_time_now(0.);
94 BOOST_LOG_TRIVIAL(info) <<
"Hardware manager initilaized";
103 BOOST_LOG_TRIVIAL(info) <<
"Presetting USRP";
105 BOOST_LOG_TRIVIAL(info) <<
"Presetting sw loop queue";
108 apply(requested_config);
114 BOOST_LOG_TRIVIAL(info) <<
"Preset done";
120 std::this_thread::sleep_for(std::chrono::milliseconds(20));
127 std::this_thread::sleep_for(std::chrono::milliseconds(20));
134 std::this_thread::sleep_for(std::chrono::milliseconds(20));
141 std::this_thread::sleep_for(std::chrono::milliseconds(20));
142 bool op = B_tx_thread_operation or A_tx_thread_operation;
148 std::this_thread::sleep_for(std::chrono::milliseconds(20));
149 bool op = A_tx_thread_operation;
155 std::this_thread::sleep_for(std::chrono::milliseconds(20));
156 bool op = B_tx_thread_operation;
168 param *current_settings,
173 BOOST_LOG_TRIVIAL(debug) <<
"Starting tx threads";
174 bool tx_thread_operation;
177 tx_thread_operation = A_tx_thread_operation;
178 }
else if(front_end==
'B'){
179 tx_thread_operation = B_tx_thread_operation;
181 print_error(
"Front end code not recognised by hardware manager");
185 if(not tx_thread_operation){
190 A_tx_thread =
new boost::thread(boost::bind(&hardware_manager::single_tx_thread,
this,
201 }
else if(front_end==
'B'){
202 B_tx_thread =
new boost::thread(boost::bind(&hardware_manager::single_tx_thread,
this,
217 A_tx_thread =
new boost::thread(boost::bind(&hardware_manager::software_tx_thread,
this,current_settings,memory,
A_TX_queue,A_sw_loop_queue,
'A'));
219 }
else if(front_end==
'B'){
220 B_tx_thread =
new boost::thread(boost::bind(&hardware_manager::software_tx_thread,
this,current_settings,memory,
B_TX_queue,B_sw_loop_queue,
'B'));
225 std::stringstream ss;
226 ss <<
"Cannot start TX thread, a tx thread associated with USRP "<<
this_usrp_number <<
" is already running";
230 BOOST_LOG_TRIVIAL(debug) <<
"tx threads started";
239 param *current_settings,
243 BOOST_LOG_TRIVIAL(debug) <<
"Starting rx threads";
244 bool rx_thread_operation;
248 }
else if(front_end==
'B'){
251 print_error(
"Front end code not recognised by hardware manager");
255 if(not rx_thread_operation){
259 A_rx_thread =
new boost::thread(boost::bind(&hardware_manager::single_rx_thread,
this,
268 }
else if(front_end==
'B'){
269 B_rx_thread =
new boost::thread(boost::bind(&hardware_manager::single_rx_thread,
this,
281 A_rx_thread =
new boost::thread(boost::bind(&hardware_manager::software_rx_thread,
this,current_settings,memory,
A_RX_queue,A_sw_loop_queue,
'A'));
284 }
else if(front_end==
'B'){
285 B_rx_thread =
new boost::thread(boost::bind(&hardware_manager::software_rx_thread,
this,current_settings,memory,
B_RX_queue,B_sw_loop_queue,
'B'));
292 std::stringstream ss;
293 ss <<
"Cannot start RX thread, a rx threead associated with USRP "<<
this_usrp_number <<
" is already running";
296 BOOST_LOG_TRIVIAL(debug) <<
"rx threads started";
301 if(A_tx_thread_operation){
302 A_tx_thread->interrupt();
305 A_tx_thread =
nullptr;
306 A_tx_thread_operation =
false;
310 if(B_tx_thread_operation){
311 B_tx_thread->interrupt();
314 B_tx_thread =
nullptr;
315 B_tx_thread_operation =
false;
324 A_rx_thread->interrupt();
327 A_rx_thread =
nullptr;
333 B_rx_thread->interrupt();
336 B_rx_thread =
nullptr;
345 BOOST_LOG_TRIVIAL(info) <<
"Cleaning tx queue";
352 while(not TX_queue->empty() or TX_queue->pop(buffer)){
354 memory->
trash(buffer);
359 std::stringstream ss;
360 ss <<
"TX queue cleaned of "<< counter <<
"buffer(s)";
363 BOOST_LOG_TRIVIAL(info) <<
"tx queue cleaned of packets: "<< counter;
370 BOOST_LOG_TRIVIAL(info) <<
"Cleaning rx queue";
373 RX_wrapper warapped_buffer;
374 warapped_buffer.buffer =
nullptr;
379 while(not RX_queue->empty() and RX_queue->pop(warapped_buffer)){
380 memory->
trash(warapped_buffer.buffer);
385 std::stringstream ss;
386 ss <<
"RX queue cleaned of "<< counter <<
"buffer(s)";
389 BOOST_LOG_TRIVIAL(info) <<
"rx queue cleaned of packets: "<< counter;
394 void hardware_manager::apply(usrp_param* requested_config){
395 BOOST_LOG_TRIVIAL(info) <<
"Applying USRP configuration";
400 std::stringstream ss;
404 ss<<
"Hardware parameter subdevice A_TXRX: ";
405 switch(requested_config->A_TXRX.mode){
410 if(not sw_loop)
main_usrp->set_tx_antenna(
"TX/RX",0);
413 ss<<
"Channel is OFF";
417 ss<<apply_antenna_config(&(requested_config->A_TXRX), &config.A_TXRX,0);
419 ss<<
"Hardware parameter subdevice A_RX2: ";
420 switch(requested_config->A_RX2.mode){
425 if(not sw_loop)
main_usrp->set_tx_antenna(
"RX2",0);
428 ss<<
"Channel is OFF";
432 ss<<apply_antenna_config(&(requested_config->A_RX2), &config.A_RX2,0);
437 ss<<
"Hardware parameter subdevice B_TXRX: ";
438 switch(requested_config->B_TXRX.mode){
443 if(not sw_loop)
main_usrp->set_tx_antenna(
"TX/RX",1);
446 ss<<
"Channel is OFF";
450 ss<<apply_antenna_config(&(requested_config->B_TXRX), &config.B_TXRX,1);
452 ss<<
"Hardware parameter subdevice B_RX2: ";
453 switch(requested_config->B_RX2.mode){
458 if(not sw_loop)
main_usrp->set_tx_antenna(
"RX2",1);
461 ss<<
"Channel is OFF";
465 ss<<apply_antenna_config(&(requested_config->B_RX2), &config.B_RX2,1);
468 BOOST_LOG_TRIVIAL(info) <<
"USRP configuration applied";
471 bool hardware_manager::check_tuning(){
472 BOOST_LOG_TRIVIAL(info) <<
"Checking tuning";
477 size_t num_rx_channels =
main_usrp->get_rx_num_channels();
478 size_t num_tx_channels =
main_usrp->get_tx_num_channels();
480 for(
size_t chan = 0; chan<num_rx_channels; chan++){
482 std::vector<std::string> rx_sensor_names;
483 rx_sensor_names =
main_usrp->get_rx_sensor_names(chan);
487 if(check_global_mode_presence(RX,chan)){
488 std::cout<<
"Checking RX frontend tuning for channel "<< chan <<
" ... "<<std::endl;
489 if (std::find(rx_sensor_names.begin(), rx_sensor_names.end(),
"lo_locked") != rx_sensor_names.end()) {
490 uhd::sensor_value_t lo_locked =
main_usrp->get_rx_sensor(
"lo_locked",chan);
493 int timeout_counter = 0;
494 while (not
main_usrp->get_rx_sensor(
"lo_locked",chan).to_bool()){
497 std::this_thread::sleep_for(std::chrono::milliseconds(20));
498 if(timeout_counter>500){
499 std::stringstream ss;
500 ss<<
"Cannot tune the RX frontend of channel "<<chan;
505 lo_locked =
main_usrp->get_rx_sensor(
"lo_locked",chan);
507 rx = rx and
main_usrp->get_rx_sensor(
"lo_locked",chan).to_bool();
509 }
catch (uhd::lookup_error e){
510 std::cout<<
"None"<<std::endl;
514 for(
size_t chan = 0; chan<num_tx_channels; chan++){
516 std::vector<std::string> tx_sensor_names;
517 tx_sensor_names =
main_usrp->get_tx_sensor_names(chan);
520 if(check_global_mode_presence(TX,chan)){
521 std::cout<<
"Checking TX frontend tuning for channel "<< chan <<
" ... "<<std::endl;
522 if (std::find(tx_sensor_names.begin(), tx_sensor_names.end(),
"lo_locked") != tx_sensor_names.end()) {
523 uhd::sensor_value_t lo_locked =
main_usrp->get_tx_sensor(
"lo_locked",chan);
526 int timeout_counter = 0;
527 while (not
main_usrp->get_tx_sensor(
"lo_locked",chan).to_bool()){
530 std::this_thread::sleep_for(std::chrono::milliseconds(20));
531 if(timeout_counter>500){
532 std::stringstream ss;
533 ss<<
"Cannot tune the TX frontend of channel "<<chan;
538 lo_locked =
main_usrp->get_tx_sensor(
"lo_locked",chan);
540 tx = tx and
main_usrp->get_tx_sensor(
"lo_locked",chan).to_bool();
542 }
catch (uhd::lookup_error e){
543 std::cout<<
"None"<<std::endl;
547 BOOST_LOG_TRIVIAL(info) <<
"Tuning checked with results tx: "<< tx <<
" and rx: "<< rx ;
552 void hardware_manager::set_streams(){
554 BOOST_LOG_TRIVIAL(info) <<
"Presetting streams";
561 if(channel_num.size()!=1)channel_num.resize(1);
563 if (config.A_TXRX.mode == RX and config.A_RX2.mode == RX){
564 print_error(
"Currently only one receiver per front end is suppored");
568 if (config.A_TXRX.mode == TX and config.A_RX2.mode == TX){
569 print_error(
"Currently only one transmitter per front end is suppored");
577 if(config.A_TXRX.mode == RX){
578 BOOST_LOG_TRIVIAL(info) <<
"Config A_TXRX as RX";
579 uhd::stream_args_t stream_args(
"fc32");
580 front_end_code0 =
'A';
582 stream_args.channels = channel_num;
584 BOOST_LOG_TRIVIAL(info) <<
"Config done";
585 }
else if(config.A_RX2.mode == RX){
586 BOOST_LOG_TRIVIAL(info) <<
"Config A_RX2 as RX";
587 uhd::stream_args_t stream_args(
"fc32");
588 front_end_code0 =
'B';
590 stream_args.channels = channel_num;
592 BOOST_LOG_TRIVIAL(info) <<
"Config done";
595 if(config.B_TXRX.mode == RX){
596 BOOST_LOG_TRIVIAL(info) <<
"Config B_TXRX as RX";
597 uhd::stream_args_t stream_args(
"fc32");
599 front_end_code0 =
'C';
601 stream_args.channels = channel_num;
603 BOOST_LOG_TRIVIAL(info) <<
"Config done";
605 }
else if(config.B_RX2.mode == RX){
606 BOOST_LOG_TRIVIAL(info) <<
"Config B_RX2 as RX";
607 uhd::stream_args_t stream_args(
"fc32");
608 front_end_code0 =
'D';
610 stream_args.channels = channel_num;
612 BOOST_LOG_TRIVIAL(info) <<
"Config done";
616 if(config.A_RX2.mode == TX or config.A_TXRX.mode == TX){
617 BOOST_LOG_TRIVIAL(info) <<
"Config A_TXRX as TX";
618 uhd::stream_args_t stream_args(
"fc32");
620 stream_args.channels = channel_num;
622 BOOST_LOG_TRIVIAL(info) <<
"Config done";
625 if(config.B_RX2.mode == TX or config.B_TXRX.mode == TX){
626 BOOST_LOG_TRIVIAL(info) <<
"Config B_TXRX as TX";
627 uhd::stream_args_t stream_args(
"fc32");
630 stream_args.channels = channel_num;
632 BOOST_LOG_TRIVIAL(info) <<
"Config done";
635 BOOST_LOG_TRIVIAL(info) <<
"Stream presetting done";
638 void hardware_manager::clear_streams(){
639 BOOST_LOG_TRIVIAL(info) <<
"Resetting streams";
642 A_rx_stream =
nullptr;
646 A_tx_stream =
nullptr;
650 B_rx_stream =
nullptr;
654 B_tx_stream =
nullptr;
656 BOOST_LOG_TRIVIAL(info) <<
"Streams reset";
660 std::string hardware_manager::apply_antenna_config(param *parameters, param *old_parameters,
size_t chan){
662 BOOST_LOG_TRIVIAL(info) <<
"Configuring antenna...";
665 std::stringstream ss;
668 bool changed =
false;
670 if(parameters->mode!=OFF){
672 if(old_parameters->mode == OFF or old_parameters->rate != parameters->rate){
677 parameters->mode == RX ?
678 main_usrp->set_rx_rate(parameters->rate,chan):
679 main_usrp->set_tx_rate(parameters->rate,chan);
681 if(parameters->mode == RX){
683 old_parameters->rate =
main_usrp->get_rx_rate(chan);
684 }
else old_parameters->rate = parameters->rate;
685 ss << boost::format(
"\tSetting RX Rate: %f Msps. ") % (parameters->rate / 1e6) << std::flush;
688 old_parameters->rate =
main_usrp->get_tx_rate(chan);
689 }
else old_parameters->rate = parameters->rate;
690 ss << boost::format(
"\tSetting TX Rate: %f Msps. ") % (parameters->rate / 1e6) << std::flush;
692 old_parameters->rate == parameters->rate?
694 ss<<boost::format(
"Effective value: %f Msps. ") % (old_parameters->rate / 1e6)<<std::endl;
695 parameters->rate = old_parameters->rate;
698 if(old_parameters->mode == OFF or old_parameters->tone != parameters->tone or old_parameters->tuning_mode != parameters->tuning_mode){
702 if(parameters->mode == RX) {
705 main_usrp->get_rx_sensor(
"lo_locked",chan).to_bool();
706 if(not parameters->tuning_mode){
708 uhd::tune_request_t tune_request(parameters->tone);
709 tune_request.args = uhd::device_addr_t(
"mode_n=integer");
710 main_usrp->set_rx_freq(tune_request,chan);
712 uhd::tune_request_t tune_request(parameters->tone);
713 main_usrp->set_rx_freq(tune_request,chan);
716 old_parameters->tone =
main_usrp->get_rx_freq(chan);
717 }
else old_parameters->tone = parameters->tone;
718 old_parameters->tuning_mode = parameters->tuning_mode;
719 ss << boost::format(
"\tSetting RX central frequency: %f MHz. ") % (parameters->tone / 1e6);
720 if(parameters->tuning_mode){
721 ss<<
" (fractional) ";
731 main_usrp->get_tx_sensor(
"lo_locked",chan).to_bool();
732 if(not parameters->tuning_mode){
734 uhd::tune_request_t tune_request(parameters->tone);
735 tune_request.args = uhd::device_addr_t(
"mode_n=integer");
736 main_usrp->set_tx_freq(tune_request,chan);
738 uhd::tune_request_t tune_request(parameters->tone);
739 main_usrp->set_tx_freq(tune_request,chan);
741 old_parameters->tone =
main_usrp->get_tx_freq(chan);
743 old_parameters->tone = parameters->tone;
745 old_parameters->tuning_mode = parameters->tuning_mode;
747 ss << boost::format(
"\tSetting TX central frequency: %f MHz. ") % (parameters->tone / 1e6);
748 if(parameters->tuning_mode){
749 ss<<
" (fractional) ";
756 old_parameters->tone == parameters->tone?
758 ss<<boost::format(
"Effective value: %f MHz. ") % (old_parameters->tone / 1e6)<<std::endl;
759 parameters->tone = old_parameters->tone;
761 }
catch(uhd::lookup_error e){
762 ss << boost::format(
"\tNo mixer detected\n");
765 if(old_parameters->mode == OFF or old_parameters->gain != parameters->gain){
770 parameters->mode == RX ?
771 main_usrp->set_rx_gain(parameters->gain,chan):
772 main_usrp->set_tx_gain(parameters->gain,chan);
774 if(parameters->mode == RX){
775 old_parameters->gain =
main_usrp->get_rx_gain(chan);
776 ss << boost::format(
"\tSetting RX gain: %d dB. ") % (parameters->gain ) << std::flush;
778 old_parameters->gain =
main_usrp->get_tx_gain(chan);
779 ss << boost::format(
"\tSetting TX gain: %d dB. ") % (parameters->gain ) << std::flush;
781 old_parameters->gain == parameters->gain?
783 ss<<boost::format(
"Effective value: %d dB. ") % (old_parameters->gain )<<std::endl;
784 parameters->gain = old_parameters->gain;
785 }
else old_parameters->gain = parameters->gain;
787 if(old_parameters->mode == OFF or old_parameters->bw != parameters->bw){
791 parameters->mode == RX ?
792 main_usrp->set_rx_bandwidth(parameters->bw,chan):
793 main_usrp->set_tx_bandwidth(parameters->bw,chan);
795 if(parameters->mode == RX){
796 old_parameters->bw =
main_usrp->get_rx_bandwidth(chan);
797 ss << boost::format(
"\tSetting RX bandwidth: %f MHz. ") % (parameters->bw/ 1e6 ) << std::flush;
799 old_parameters->bw =
main_usrp->get_tx_bandwidth(chan);
800 ss << boost::format(
"\tSetting TX bandwidth: %f MHz. ") % (parameters->bw/ 1e6 ) << std::flush;
802 old_parameters->bw == parameters->bw?
804 ss<<boost::format(
"Effective value: %f MHz. ") % (old_parameters->gain/ 1e6 )<<std::endl;
805 parameters->bw = old_parameters->bw;
806 }
else old_parameters->bw = parameters->bw;
808 if(old_parameters->mode == OFF or old_parameters->delay != parameters->delay){
810 old_parameters->delay = parameters->delay;
811 ss << boost::format(
"\tSetting start streaming delay: %f msec. ") % (parameters->delay*1e3 ) << std::endl;
813 if((old_parameters->mode == OFF or old_parameters->burst_off != parameters->burst_off) and parameters->burst_off != 0){
815 old_parameters->burst_off = parameters->burst_off;
816 ss << boost::format(
"\tSetting interval between bursts: %f msec. ") % (parameters->burst_off*1e3 ) << std::endl;
818 if((old_parameters->mode == OFF or old_parameters->burst_on != parameters->burst_on) and parameters->burst_on != 0){
820 old_parameters->burst_on = parameters->burst_on;
821 ss << boost::format(
"\tSetting bursts duration: %f msec. ") % (parameters->burst_on*1e3 ) << std::endl;
823 if(old_parameters->mode == OFF or old_parameters->samples != parameters->samples){
825 old_parameters->samples = parameters->samples;
826 ss << boost::format(
"\tSetting total samples to %f Ms") % (parameters->samples /1e6 ) << std::endl;
828 if(old_parameters->mode == OFF or old_parameters->buffer_len != parameters->buffer_len){
830 old_parameters->buffer_len = parameters->buffer_len;
831 ss << boost::format(
"\tSetting buffer length to %f Ms") % (parameters->buffer_len /1e6 ) << std::endl;
833 if(old_parameters->mode == OFF or old_parameters->burst_off != parameters->burst_off){
835 old_parameters->burst_off = parameters->burst_off;
836 if(old_parameters->burst_off == 0){
837 ss << boost::format(
"\tSetting continuous acquisition mode (no bursts)")<< std::endl;
839 ss << boost::format(
"\tSetting samples between bursts to %f msec") % (parameters->burst_off *1e3 ) << std::endl;
842 if(old_parameters->mode == OFF or old_parameters->burst_on != parameters->burst_on){
844 old_parameters->burst_on = parameters->burst_on;
845 if(old_parameters->burst_on != 0){
846 ss << boost::format(
"\tSetting bursts length to %f msec") % (parameters->burst_on *1e3 ) << std::endl;
849 if(not changed) ss<<
"\tHardware parameters were identical to last setup"<<std::endl;
852 old_parameters->mode = parameters->mode;
854 BOOST_LOG_TRIVIAL(info) <<
"Antenna configured";
861 bool hardware_manager::check_double_txrx(ant_mode
TXRX){
863 if(A_TXRX_chk == TXRX)tx++;
864 if(A_RX2_chk == TXRX)tx++;
865 if(B_RX2_chk == TXRX)tx++;
866 if(B_TXRX_chk == TXRX)tx++;
873 bool hardware_manager::check_global_mode_presence(ant_mode mode,
size_t chan){
874 bool present =
false;
875 if(chan == 0)present = present or (config.A_TXRX.mode == mode);
876 if(chan == 1)present = present or (config.B_TXRX.mode == mode);
877 if(chan == 0)present = present or (config.A_RX2.mode == mode);
878 if(chan == 1)present = present or (config.B_RX2.mode == mode);
882 void hardware_manager::software_tx_thread(
883 param *current_settings,
886 tx_queue* sw_loop_queue,
889 std::stringstream thread_name;
890 thread_name <<
"Software tx thread "<<front_end;
892 BOOST_LOG_TRIVIAL(debug) <<
"Thread started";
894 if(front_end ==
'A'){
895 A_tx_thread_operation =
true;
896 }
else if(front_end ==
'B'){
897 B_tx_thread_operation =
true;
899 print_error(
"Frontend code not recognized in software tx thread");
903 size_t sent_samp = 0;
905 while(active and (sent_samp < current_settings->samples)){
907 boost::this_thread::interruption_point();
908 if(TX_queue->pop(tx_buffer)){
910 float2* tx_buffer_copy = (float2*)malloc(
sizeof(float2)*current_settings->buffer_len);
912 sent_samp += current_settings->buffer_len;
914 memcpy(tx_buffer_copy, tx_buffer,
sizeof(float2)*current_settings->buffer_len);
916 while(not sw_loop_queue->push(tx_buffer_copy))std::this_thread::sleep_for(std::chrono::microseconds(1));
918 if(memory)memory->
trash(tx_buffer);
921 std::this_thread::sleep_for(std::chrono::microseconds(200));
923 }
catch (boost::thread_interrupted &){
928 if(front_end ==
'A'){
929 A_tx_thread_operation =
false;
930 }
else if(front_end ==
'B'){
931 B_tx_thread_operation =
false;
933 BOOST_LOG_TRIVIAL(debug) <<
"Thread joined";
989 void hardware_manager::single_tx_thread(
990 param *current_settings,
993 uhd::tx_streamer::sptr &tx_stream,
998 std::stringstream thread_name;
999 thread_name <<
"Hardware tx thread "<<front_end;
1002 uhd::set_thread_priority_safe(1.);
1004 size_t sent_samp = 0;
1010 std::stringstream ss;
1011 ss<<
"TX worker " << front_end;
1014 if(front_end ==
'A'){
1015 A_tx_thread_operation =
true;
1016 }
else if(front_end ==
'B'){
1017 B_tx_thread_operation =
true;
1019 print_error(
"Frontend code not recognized in hardware tx thread");
1026 uhd::tx_metadata_t metadata_tx;
1028 BOOST_LOG_TRIVIAL(debug) <<
"Starting metadata thread";
1029 boost::thread* metadata_thread =
nullptr;
1030 if(front_end ==
'A'){
1031 metadata_thread =
new boost::thread(boost::bind(&hardware_manager::async_stream,
this,tx_stream,front_end));
1033 metadata_tx.start_of_burst =
true;
1034 metadata_tx.end_of_burst =
false;
1035 metadata_tx.has_time_spec =
true;
1036 metadata_tx.time_spec = uhd::time_spec_t(1.0+current_settings->delay);
1037 double timeout = 1.0+current_settings->delay + 0.1;
1039 size_t max_samples_tx = current_settings->samples;
1041 size_t buffer_len_tx = current_settings->buffer_len;
1045 std::future<float2*> handle;
1047 BOOST_LOG_TRIVIAL(info) <<
"Starting main loop";
1048 while(active and (sent_samp < current_settings->samples)){
1051 boost::this_thread::interruption_point();
1053 if(sent_samp + buffer_len_tx >= max_samples_tx) metadata_tx.end_of_burst =
true;
1059 while(not TX_queue->pop(tx_buffer))std::this_thread::sleep_for(std::chrono::nanoseconds(500));
1061 sent_samp += tx_stream->send(tx_buffer, buffer_len_tx, metadata_tx, timeout);
1063 metadata_tx.start_of_burst =
false;
1064 metadata_tx.has_time_spec =
false;
1068 if(memory)memory->
trash(tx_buffer);
1070 }
catch (boost::thread_interrupted &){
1072 BOOST_LOG_TRIVIAL(info) <<
"Interrupt received";
1077 while(not TX_queue->empty()){
1078 TX_queue->pop(tx_buffer);
1079 if(memory)memory->
trash(tx_buffer);
1082 if(not active and sent_samp < current_settings->samples){
1083 print_warning(
"TX thread was joined without transmitting the specified samples");
1084 std::cout<<
"Missing "<< current_settings->samples - sent_samp<<
" samples"<<std::endl;
1085 BOOST_LOG_TRIVIAL(info) <<
"Thread was joined without transmitting "<< current_settings->samples - sent_samp<<
" samples";
1087 if(front_end ==
'A'){
1088 metadata_thread->interrupt();
1089 metadata_thread->join();
1090 delete metadata_thread;
1091 metadata_thread =
nullptr;
1094 if(front_end ==
'A'){
1095 A_tx_thread_operation =
false;
1096 }
else if(front_end ==
'B'){
1097 B_tx_thread_operation =
false;
1101 BOOST_LOG_TRIVIAL(debug) <<
"Thread joined";
1105 void hardware_manager::async_stream(uhd::tx_streamer::sptr &tx_stream,
char fornt_end){
1106 bool parent_process_active =
false;
1108 uhd::async_metadata_t async_md;
1113 boost::this_thread::interruption_point();
1115 if (fornt_end ==
'A'){
1116 parent_process_active = A_tx_thread_operation;
1117 }
else if (fornt_end ==
'B'){
1118 parent_process_active = B_tx_thread_operation;
1121 if(parent_process_active){
1123 if(tx_stream->recv_async_msg(async_md)){
1126 if(errors>0 and parent_process_active){
1127 if (fornt_end ==
'A'){
1128 A_tx_error_queue->push(1);
1129 }
else if (fornt_end ==
'B'){
1130 B_tx_error_queue->push(1);
1134 }
else{ active =
false; }
1135 }
catch (boost::thread_interrupted &e){ active =
false; }
1136 std::this_thread::sleep_for(std::chrono::milliseconds(5));
1142 void hardware_manager::software_rx_thread(
1143 param *current_settings,
1146 tx_queue* sw_loop_queue,
1149 std::stringstream thread_name;
1150 thread_name <<
"Software rx thread "<<front_end;
1152 BOOST_LOG_TRIVIAL(debug) <<
"Thread started";
1154 if(front_end ==
'A'){
1157 }
else if(front_end ==
'B'){
1161 print_error(
"Frontend code not recognized in software rx thread");
1166 RX_wrapper warapped_buffer;
1168 float2 *rx_buffer_cpy;
1169 size_t acc_samp = 0;
1171 while(active and (acc_samp < current_settings->samples)){
1175 boost::this_thread::interruption_point();
1177 if(taken)rx_buffer_cpy = memory->
get();
1179 if(sw_loop_queue->pop(rx_buffer)){
1182 memcpy(rx_buffer_cpy, rx_buffer, current_settings->buffer_len *
sizeof(float2));
1184 warapped_buffer.buffer = rx_buffer_cpy;
1185 warapped_buffer.packet_number = counter;
1186 warapped_buffer.length = current_settings->buffer_len;
1187 warapped_buffer.errors = 0;
1188 warapped_buffer.front_end_code = front_end_c;
1189 while(not Rx_queue->push(warapped_buffer))std::this_thread::sleep_for(std::chrono::microseconds(1));
1190 acc_samp += current_settings->buffer_len;
1193 std::this_thread::sleep_for(std::chrono::milliseconds(5));
1197 }
catch (boost::thread_interrupted &){ active =
false;}
1200 if(front_end ==
'A'){
1202 }
else if(front_end ==
'B'){
1205 BOOST_LOG_TRIVIAL(debug) <<
"Thread joined";
1209 void hardware_manager::single_rx_thread(
1210 param *current_settings,
1214 uhd::rx_streamer::sptr &rx_stream ,
1219 std::stringstream thread_name;
1220 thread_name <<
"Hardware rx thread "<<front_end;
1222 BOOST_LOG_TRIVIAL(debug) <<
"Thread started";
1224 if(front_end ==
'A'){
1227 }
else if(front_end ==
'B'){
1231 print_error(
"Frontend code not recognized in hardware rx thread");
1234 if (not uhd::set_thread_priority_safe(+1)){
1235 std::stringstream ss;
1236 ss<<
"Cannot set thread priority from tx thread"<<front_end;
1242 size_t num_rx_samps = 0;
1243 size_t acc_samp = 0;
1244 size_t frag_count = 0;
1245 float timeout = 0.1f;
1248 size_t samples_remaining;
1249 size_t push_counter;
1250 size_t push_timer = 1;
1253 RX_wrapper warapped_buffer;
1259 uhd::rx_metadata_t metadata_rx;
1265 uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
1268 if(current_settings->burst_off == 0){
1269 stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS ;
1270 stream_cmd.num_samps = 0;
1272 stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE;
1273 stream_cmd.num_samps = current_settings->buffer_len;
1275 stream_cmd.stream_now = current_settings->delay == 0 ?
true:
false;
1277 stream_cmd.time_spec = uhd::time_spec_t(1.0+current_settings->delay);
1280 metadata_rx.end_of_burst = current_settings->samples <= current_settings->buffer_len ? true :
false;
1283 bool first_packet =
true;
1289 stream_cmd.stream_now =
false;
1290 stream_cmd.num_samps = current_settings->buffer_len;
1291 stream_cmd.time_spec = uhd::time_spec_t(1.0+current_settings->delay);
1292 timeout = 1.0+current_settings->delay;
1293 stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS ;
1294 rx_stream->issue_stream_cmd(stream_cmd);
1297 uhd::stream_cmd_t stop_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
1298 stop_cmd.stream_now =
false;
1300 uhd::set_thread_priority_safe(+1);
1301 while(active and acc_samp < current_settings->samples){
1305 boost::this_thread::interruption_point();
1308 rx_buffer = memory->
get();
1327 while(num_rx_samps<current_settings->buffer_len){
1330 samples_remaining = std::min(current_settings->buffer_len,current_settings->buffer_len-num_rx_samps);
1338 num_rx_samps += rx_stream->recv(rx_buffer + num_rx_samps, samples_remaining, metadata_rx,timeout);
1344 if(front_end ==
'A'){
1345 while(A_tx_error_queue->pop(tmp) and A_tx_thread_operation)errors++;
1346 }
else if(front_end ==
'B'){
1347 while(B_tx_error_queue->pop(tmp) and B_tx_thread_operation)errors++;
1352 metadata_rx.start_of_burst = current_settings->samples <= current_settings->buffer_len ? true :
false;
1353 metadata_rx.has_time_spec = current_settings->burst_off == 0?
false:
true;
1354 metadata_rx.time_spec = uhd::time_spec_t(current_settings->burst_off);
1355 first_packet =
false;
1358 std::cout<<
"F" << frag_count<<std::flush;
1362 std::stringstream ss;
1363 ss<<
"RX Fragmentation too high: "<< frag_count <<
" calls to recv to reach "<<num_rx_samps<<
" /"<< current_settings->buffer_len<<
" samples.";
1366 print_error(
"RX thread got stuck: USRP is not streaming any sample.");
1369 num_rx_samps = current_settings->buffer_len;
1376 acc_samp += num_rx_samps;
1379 if(current_settings->samples < acc_samp + current_settings->buffer_len) metadata_rx.end_of_burst =
true;
1383 warapped_buffer.buffer = rx_buffer;
1384 warapped_buffer.packet_number = counter;
1385 warapped_buffer.length = num_rx_samps;
1386 warapped_buffer.errors = errors;
1387 warapped_buffer.front_end_code = front_end_c;
1391 while(not Rx_queue->push(warapped_buffer)){
1392 std::this_thread::sleep_for(std::chrono::microseconds(push_timer));
1393 if(push_counter>1)
print_warning(
"RX queue is experencing some delay. This may cause troubles in real time acquisition.");
1395 if(push_timer * push_counter > 1e3*current_settings->buffer_len/current_settings->rate){
1396 print_warning(
"RX queue is experencing some delay. This may cause troubles in real time acquisition.");
1400 }
catch (boost::thread_interrupted &){ active =
false; }
1403 rx_stream->issue_stream_cmd(stop_cmd);
1405 flush_rx_streamer(rx_stream);
1410 print_warning(
"RX thread was taken down without receiving the specified samples");
1415 if(front_end ==
'A'){
1417 }
else if(front_end ==
'B'){
1421 BOOST_LOG_TRIVIAL(debug) <<
"Thread joined";
1424 void hardware_manager::flush_rx_streamer(uhd::rx_streamer::sptr &rx_streamer) {
1425 constexpr
double timeout { 0.010 };
1426 constexpr
size_t size { 1048576 };
1427 static float2 dummy_buffer[size];
1428 static uhd::rx_metadata_t dummy_meta { };
1429 while (rx_streamer->recv(dummy_buffer, size, dummy_meta, timeout)) {}
std::atomic< bool > B_rx_thread_operation
std::string device_arguments
void start_rx(int buffer_len, threading_condition *wait_condition, preallocator< float2 > *memory, int thread_op, param *current_settings, char front_end)
@ brief start a rx thread.
bool check_tx_status(bool verbose=false)
Check the status of every tx operations. Returns the status of A or B.
bool check_rx_status(bool verbose=false)
Check the status of every rx operations. Returns the status of A or B.
void trash(vector_type *trash_vector)
std::atomic< bool > A_rx_thread_operation
void SetThreadName(boost::thread *thread, const char *threadName)
bool check_A_rx_status(bool verbose=false)
Check the status of A rx operations.
void print_error(std::string text)
int clean_rx_queue(rx_queue *RX_queue, preallocator< float2 > *memory)
Release the memory associated with pointers holded by a rx queue using the respective memory allocato...
bool check_B_tx_status(bool verbose=false)
Check the status of B tx operations.
tx_queue * B_TX_queue
Queue accessed to stream data from B frontend.
void Thread_Prioriry(boost::thread &Thread, int priority, int affinity)
tx_queue * A_TX_queue
Queue accessed to stream data from A frontend.
hardware_manager(server_settings *settings, bool sw_loop_init, size_t usrp_number=0)
The initializer of the class can be used to select which usrp is controlled by the class Default call...
void set_this_thread_name(std::string thread_name)
Set the htread name reported in the logging.
int clean_tx_queue(tx_queue *TX_queue, preallocator< float2 > *memory)
Release the memory associated with pointers holded by a tx queue using the respective memory allocato...
bool preset_usrp(usrp_param *requested_config)
Set the USRP device with user parameters.
bool check_B_rx_status(bool verbose=false)
Check the status of B rx operations.
int get_rx_errors(uhd::rx_metadata_t *metadata, bool verbose)
void close_tx()
Close all the tx streamer threads.
void start_tx(threading_condition *wait_condition, int thread_op, param *current_settings, char front_end, preallocator< float2 > *memory=NULL)
Start a transmission thread. The threads started by this function do two things: pop a packet from th...
void close_rx()
Close all the rx streamer threads.
bool check_A_tx_status(bool verbose=false)
Check the status of A tx operations.
void print_debug(std::string text, double value)
void print_warning(std::string text)
rx_queue * A_RX_queue
Queue accessed to retrive data from A frontend.
int get_tx_error(uhd::async_metadata_t *async_md, bool verbose)
Interpret tx errors from the async usrp comunication.
uhd::usrp::multi_usrp::sptr main_usrp
rx_queue * B_RX_queue
Queue accessed to retrive data from B frontend.