uhd_io.cpp 10.1 KB
Newer Older
M
manjaro 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright 2015 Ettus Research LLC
 * Copyright 2018 Ettus Research, a National Instruments Company
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

#include <uhd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <string>
#include <thread>
M
manjaro 已提交
15
static bool stop_signal_called = false;
M
manjaro 已提交
16 17
#define UHD_DO(X) \
{\
D
dev 已提交
18 19 20 21 22 23 24 25 26 27
    uhd_error e = (X);\
    char buf_errs[512];\
    if (e) { snprintf(buf_errs,sizeof(buf_errs),"Error in line %d, NO %d.",__LINE__,e);\
    std::string ev = __FILE__;\
    ev += ":";\
    ev += buf_errs;\
    return_code = 1;\
    throw ev;\
    }\
    };
M
manjaro 已提交
28
void sigint_handler(int code){
D
dev 已提交
29 30
    (void)code;
    stop_signal_called = true;
M
manjaro 已提交
31 32
}

D
dev 已提交
33
typedef short SPTYPE;
M
manjaro 已提交
34
int  main(int /*argc*/, char * /*argv*/[])
M
manjaro 已提交
35
{
D
dev 已提交
36 37 38
    int return_code = EXIT_SUCCESS;
    char dev_args[] = "";
    char error_string[512];
M
manjaro 已提交
39 40 41 42 43 44 45
    //通道,B210左侧为A:A,右侧为A:B
    const char subdev_rx[] = "A:A";
    uhd_subdev_spec_handle subdev_hrx;
    UHD_DO(uhd_subdev_spec_make(&subdev_hrx,subdev_rx))

	    //Sample rate in Hz
	    double sprate		=  61.44e6/2 ;
M
manjaro 已提交
46
    //接收频率
M
manjaro 已提交
47
    double rx_freq		= 107.7e6;
D
dev 已提交
48 49 50
    double rx_sprate	= sprate;
    double rx_gain		= 55.0;
    bool   rx_agc		= false;
M
manjaro 已提交
51
    double rx_bw		= 400000;
M
manjaro 已提交
52 53
    //接收信号。MIMO时,可以指定0,1
    size_t rx_channel[]	= {0};
M
manjaro 已提交
54
    //转发频率
M
manjaro 已提交
55 56 57 58 59 60
    const char subdev_tx[] = "A:B";
    uhd_subdev_spec_handle subdev_htx;
    UHD_DO(uhd_subdev_spec_make(&subdev_htx,subdev_tx))


	    double tx_freq		= 89.0e6;
D
dev 已提交
61
    double tx_sprate	= sprate;
M
manjaro 已提交
62
    double tx_gain		= 70;
M
manjaro 已提交
63
    double tx_bw		= 400000;
M
manjaro 已提交
64 65
    //发射信号。MIMO时,可以指定0,1
    size_t tx_channel[]	= {0};
D
dev 已提交
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

    //设备句柄
    uhd_usrp_handle usrp = 0;
    uhd_rx_streamer_handle rx_streamer = 0;
    uhd_rx_metadata_handle rx_meta = 0;
    uhd_tx_streamer_handle tx_streamer = 0;
    uhd_tx_metadata_handle tx_meta = 0;
    //ring buffer
    const size_t sz_buffer = 65536;
    SPTYPE * io_buff[sz_buffer];
    memset(io_buff,0,sizeof(io_buff));
    long long rx_pos = 0, tx_pos = 0;

    try{
	fprintf(stderr, "Creating USRP with args \"%s\"...\n", dev_args);
	UHD_DO(uhd_usrp_make(&usrp, dev_args));

	puts("Press Enter to start...");
	// Ctrl+C will exit loop
	signal(SIGINT, &sigint_handler);
	fprintf(stderr, "Press Ctrl+C to stop streaming...\n");

	getchar();

M
manjaro 已提交
90 91 92 93 94 95 96 97 98
	//设置接收通道,母板号为0(multi-usrp支持级联)
	UHD_DO(uhd_usrp_set_rx_subdev_spec(usrp,subdev_hrx,0));
	//设置发射通道,子板号为0(multi-usrp支持级联)
	UHD_DO(uhd_usrp_set_tx_subdev_spec(usrp,subdev_htx,0));

	//设置天线,子板号为0(multi-usrp支持级联)
	UHD_DO(uhd_usrp_set_rx_antenna(usrp,"RX2",0));
	UHD_DO(uhd_usrp_set_tx_antenna(usrp,"TX/RX",0));

D
dev 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112
	// Create RX streamer
	UHD_DO(uhd_rx_streamer_make(&rx_streamer));

	// Create TX streamer
	UHD_DO(uhd_tx_streamer_make(&tx_streamer));

	// Create RX metadata
	UHD_DO(uhd_rx_metadata_make(&rx_meta));

	// Create TX metadata
	UHD_DO(uhd_tx_metadata_make(&tx_meta, false, 0, 0.1, true, false));

	// Create other necessary structs
	uhd_tune_request_t rx_tune_request =
M
manjaro 已提交
113
	{
D
dev 已提交
114 115 116 117 118 119 120 121 122 123 124 125
	    .target_freq = rx_freq,
	    .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
	    .rf_freq = 0,
	    .dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
	    .dsp_freq = 0,
	    .args = 0
	};
	uhd_tune_result_t rx_tune_result;
	//char rx_cpu_format[] = "fc32";
	char rx_cpu_format[] = "sc16";
	char rx_otw_format[] = "sc16";
	char rx_args[] = "";
M
manjaro 已提交
126
	const size_t rx_channel_count = sizeof(rx_channel)/sizeof(rx_channel[0]);
D
dev 已提交
127 128 129 130
	uhd_stream_args_t rx_stream_args = {
	    .cpu_format = rx_cpu_format,
	    .otw_format = rx_otw_format,
	    .args = rx_args,
M
manjaro 已提交
131 132
	    .channel_list = rx_channel,
	    .n_channels = rx_channel_count
D
dev 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
	};

	uhd_stream_cmd_t rx_stream_cmd = {
	    .stream_mode = UHD_STREAM_MODE_START_CONTINUOUS,
	    .num_samps = 0,
	    .stream_now = true,
	    .time_spec_full_secs = 0,
	    .time_spec_frac_secs = 0
	};

	// Create other necessary structs for TX
	uhd_tune_request_t tx_tune_request = {
	    .target_freq = tx_freq,
	    .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
	    .rf_freq = 0,
	    .dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
	    .dsp_freq = 0,
	    .args = 0
	};
	uhd_tune_result_t tx_tune_result;
	//char tx_cpu_format[] = "fc32";
	char tx_cpu_format[] = "sc16";
	char tx_otw_format[] = "sc16";
	char tx_args[] = "";
M
manjaro 已提交
157 158
	const size_t tx_channel_count = sizeof(tx_channel)/sizeof(tx_channel[0]);

D
dev 已提交
159 160 161 162
	uhd_stream_args_t tx_stream_args = {
	    .cpu_format = tx_cpu_format,
	    .otw_format = tx_otw_format,
	    .args = tx_args,
M
manjaro 已提交
163 164
	    .channel_list = tx_channel,
	    .n_channels = tx_channel_count
D
dev 已提交
165 166 167 168 169 170
	};
	size_t rx_sps_buff = 0;
	size_t tx_sps_buff = 0;

	// Set rate
	fprintf(stderr, "Setting RX Rate: %f...\n", rx_sprate);
M
manjaro 已提交
171
	UHD_DO(uhd_usrp_set_rx_rate(usrp, rx_sprate, rx_channel[0]));
D
dev 已提交
172 173

	// See what rate actually is
M
manjaro 已提交
174
	UHD_DO(uhd_usrp_get_rx_rate(usrp, rx_channel[0], &rx_sprate));
D
dev 已提交
175 176 177 178
	fprintf(stderr, "Actual RX Rate: %f...\n", rx_sprate);

	// Set gain
	fprintf(stderr, "Setting RX Gain: %f dB...\n", rx_gain);
M
manjaro 已提交
179
	UHD_DO(uhd_usrp_set_rx_gain(usrp, rx_gain, rx_channel[0], ""));
D
dev 已提交
180 181

	// See what gain actually is
M
manjaro 已提交
182
	UHD_DO(uhd_usrp_get_rx_gain(usrp, rx_channel[0], "", &rx_gain));
D
dev 已提交
183 184 185 186
	fprintf(stderr, "Actual RX Gain: %f...\n", rx_gain);

	if (rx_agc)
	{
M
manjaro 已提交
187 188
	    uhd_usrp_set_rx_agc(usrp,true,rx_channel[0]);
	    uhd_usrp_set_rx_dc_offset_enabled(usrp,true,rx_channel[0]);
M
manjaro 已提交
189
	}
D
dev 已提交
190 191
	// Set frequency
	fprintf(stderr, "Setting RX frequency: %f MHz...\n", rx_freq/1e6);
M
manjaro 已提交
192
	UHD_DO(uhd_usrp_set_rx_freq(usrp, &rx_tune_request, rx_channel[0], &rx_tune_result));
D
dev 已提交
193 194

	// See what frequency actually is
M
manjaro 已提交
195
	UHD_DO(uhd_usrp_get_rx_freq(usrp, rx_channel[0], &rx_freq));
D
dev 已提交
196 197 198
	fprintf(stderr, "Actual RX frequency: %f MHz...\n", rx_freq / 1e6);

	fprintf(stderr, "Setting RX Bandwidth: %f MHz...\n", rx_bw/1e6);
M
manjaro 已提交
199
	UHD_DO(uhd_usrp_set_rx_bandwidth(usrp, rx_bw, rx_channel[0]));
M
manjaro 已提交
200

D
dev 已提交
201
	//Band
M
manjaro 已提交
202
	UHD_DO(uhd_usrp_get_rx_bandwidth(usrp, rx_channel[0], &rx_bw));
D
dev 已提交
203
	fprintf(stderr, "Actual RX Bandwidth: %f MHz...\n", rx_bw / 1e6);
M
manjaro 已提交
204 205


D
dev 已提交
206 207
	// Set rate
	fprintf(stderr, "Setting TX Rate: %f...\n", tx_sprate);
M
manjaro 已提交
208
	UHD_DO(uhd_usrp_set_tx_rate(usrp, tx_sprate, tx_channel[0]));
M
manjaro 已提交
209

D
dev 已提交
210
	// See what rate actually is
M
manjaro 已提交
211
	UHD_DO(uhd_usrp_get_tx_rate(usrp, tx_channel[0], &tx_sprate));
D
dev 已提交
212
	fprintf(stderr, "Actual TX Rate: %f...\n\n", tx_sprate);
M
manjaro 已提交
213

D
dev 已提交
214 215 216 217 218
	// Set gain
	fprintf(stderr, "Setting TX Gain: %f db...\n", tx_gain);
	UHD_DO(uhd_usrp_set_tx_gain(usrp, tx_gain, 0, ""));

	// See what gain actually is
M
manjaro 已提交
219
	UHD_DO(uhd_usrp_get_tx_gain(usrp, tx_channel[0], "", &tx_gain));
D
dev 已提交
220 221 222 223
	fprintf(stderr, "Actual TX Gain: %f...\n", tx_gain);

	// Set frequency
	fprintf(stderr, "Setting TX frequency: %f MHz...\n", tx_freq / 1e6);
M
manjaro 已提交
224
	UHD_DO(uhd_usrp_set_tx_freq(usrp, &tx_tune_request, tx_channel[0], &tx_tune_result));
D
dev 已提交
225 226

	// See what frequency actually is
M
manjaro 已提交
227
	UHD_DO(uhd_usrp_get_tx_freq(usrp, tx_channel[0], &tx_freq));
D
dev 已提交
228 229 230 231
	fprintf(stderr, "Actual TX frequency: %f MHz...\n", tx_freq / 1e6);

	//Band
	fprintf(stderr, "Setting TX Bandwidth: %f MHz...\n", tx_bw/1e6);
M
manjaro 已提交
232
	UHD_DO(uhd_usrp_set_tx_bandwidth(usrp, tx_bw,tx_channel[0]));
D
dev 已提交
233

M
manjaro 已提交
234
	UHD_DO(uhd_usrp_get_tx_bandwidth(usrp, tx_channel[0], &tx_bw));
D
dev 已提交
235 236 237
	fprintf(stderr, "Actual TX Bandwidth: %f MHz...\n", tx_bw / 1e6);

	// Set up streamer
M
manjaro 已提交
238
	rx_stream_args.channel_list = rx_channel;
D
dev 已提交
239 240 241 242 243 244 245
	UHD_DO(uhd_usrp_get_rx_stream(usrp, &rx_stream_args, rx_streamer));

	// Set up buffer
	UHD_DO(uhd_rx_streamer_max_num_samps(rx_streamer, &rx_sps_buff));
	fprintf(stderr, "Buffer size in samples: %zu\n", rx_sps_buff);

	// Set up streamer
M
manjaro 已提交
246
	tx_stream_args.channel_list = tx_channel;
D
dev 已提交
247 248 249 250 251 252 253 254
	UHD_DO(uhd_usrp_get_tx_stream(usrp, &tx_stream_args, tx_streamer));

	// Set up buffer
	UHD_DO(uhd_tx_streamer_max_num_samps(tx_streamer, &tx_sps_buff));
	fprintf(stderr, "Buffer size in samples: %zu\n", tx_sps_buff);

	if (rx_sps_buff!=tx_sps_buff)
	    throw ("RX buffer assumed equal to TX buffer. Stopped.");
M
manjaro 已提交
255
	for (size_t i=0;i<sz_buffer;++i)
D
dev 已提交
256 257 258 259 260 261
	    io_buff[i] = (SPTYPE *) malloc(rx_sps_buff * 2 * sizeof(SPTYPE));

	// Issue stream command
	fprintf(stderr, "Issuing stream command.\n");
	UHD_DO(uhd_rx_streamer_issue_stream_cmd(rx_streamer, &rx_stream_cmd));

M
manjaro 已提交
262
	//uhd_usrp_set_time_now(usrp,0,0,0);
D
dev 已提交
263 264 265 266
	size_t num_samps_sent = 0;
	// Actual streaming, TX Threading
	std::thread th_send([&]()->void
	{
M
manjaro 已提交
267

M
manjaro 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
	    try{
		while (!stop_signal_called) {
		    if (rx_pos<5)
			continue;
		    SPTYPE * tx_buff = io_buff[tx_pos % sz_buffer];
		    const void ** tx_buff_ptr = (const void **) &tx_buff;
		    UHD_DO(uhd_tx_streamer_send(tx_streamer, tx_buff_ptr, tx_sps_buff, &tx_meta, 1, &num_samps_sent));
		    if (tx_pos<rx_pos)
			++tx_pos;
		}
	    }
	    catch(std::string er)
	    {
		fputs(er.c_str(),stderr);
	    }
	}
	);
D
dev 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
	//Read, RX in Main Thread
	const int spn = (int(sprate)/rx_sps_buff)<1?1:(int(sprate)/rx_sps_buff);
	while (!stop_signal_called) {
	    size_t num_rx_samps = 0;
	    SPTYPE * rx_buff = (SPTYPE *)io_buff[rx_pos % sz_buffer];
	    void ** rx_buff_ptr = (void **)&rx_buff;
	    // Handle data
	    UHD_DO(uhd_rx_streamer_recv(rx_streamer, rx_buff_ptr, rx_sps_buff, &rx_meta, 1, false, &num_rx_samps));
	    ++rx_pos;

	    uhd_rx_metadata_error_code_t error_code;
	    UHD_DO(uhd_rx_metadata_error_code(rx_meta, &error_code));
	    if(error_code != UHD_RX_METADATA_ERROR_CODE_NONE){
		fprintf(stderr, "Warning: Error code 0x%x was returned during streaming.\n", error_code);
		puts(error_string);
	    }

	    if (rx_pos % spn==0) {
		time_t full_secs;
		double frac_secs;
		uhd_rx_metadata_time_spec(rx_meta, &full_secs, &frac_secs);
		fprintf(stderr, "%u samples x %lld cabs, %lf secs, %lf frac secs\r",
			num_rx_samps, rx_pos,
			difftime(full_secs, (int64_t) 0),
			frac_secs);
	    }
M
manjaro 已提交
311 312
	}

D
dev 已提交
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
	th_send.join();
    }
    catch(std::string s)
    {
	fputs(s.c_str(),stderr);
    }



    for (int i=0;i<sz_buffer;++i) {
	if (io_buff[i])
	    free(io_buff[i]);
    }
    if (tx_streamer) uhd_tx_streamer_free(&tx_streamer);
    if (rx_streamer) uhd_rx_streamer_free(&rx_streamer);
    if (tx_meta) uhd_tx_metadata_free(&tx_meta);
    if (rx_meta) uhd_rx_metadata_free(&rx_meta);

    if(return_code != EXIT_SUCCESS && usrp != NULL){
	uhd_usrp_last_error(usrp, error_string, 512);
	fprintf(stderr, "USRP reported the following error: %s\n", error_string);
    }
    uhd_usrp_free(&usrp);

    fprintf(stderr, (return_code ? "Failure\n" : "Success\n"));
    return return_code;
M
manjaro 已提交
339
}