|
|
|
@ -19,17 +19,18 @@
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <uhd.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <uhd.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
|
|
|
|
|
#include "srslte/srslte.h"
|
|
|
|
|
#include "rf_uhd_imp.h"
|
|
|
|
|
#include "rf_helper.h"
|
|
|
|
|
#include "srslte/srslte.h"
|
|
|
|
|
#include "uhd_c_api.h"
|
|
|
|
|
|
|
|
|
|
#include "rf_uhd_imp.h"
|
|
|
|
|
|
|
|
|
|
#define HAVE_ASYNC_THREAD 1
|
|
|
|
|
|
|
|
|
|
#if UHD_VERSION < 3130000
|
|
|
|
@ -71,7 +72,8 @@ void suppress_handler(const char *x)
|
|
|
|
|
|
|
|
|
|
cf_t zero_mem[64 * 1024];
|
|
|
|
|
|
|
|
|
|
static void log_overflow(rf_uhd_handler_t *h) {
|
|
|
|
|
static void log_overflow(rf_uhd_handler_t* h)
|
|
|
|
|
{
|
|
|
|
|
if (h->uhd_error_handler) {
|
|
|
|
|
srslte_rf_error_t error;
|
|
|
|
|
bzero(&error, sizeof(srslte_rf_error_t));
|
|
|
|
@ -80,7 +82,8 @@ static void log_overflow(rf_uhd_handler_t *h) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void log_late(rf_uhd_handler_t *h, bool is_rx) {
|
|
|
|
|
static void log_late(rf_uhd_handler_t* h, bool is_rx)
|
|
|
|
|
{
|
|
|
|
|
if (h->uhd_error_handler) {
|
|
|
|
|
srslte_rf_error_t error;
|
|
|
|
|
bzero(&error, sizeof(srslte_rf_error_t));
|
|
|
|
@ -91,7 +94,8 @@ static void log_late(rf_uhd_handler_t *h, bool is_rx) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if HAVE_ASYNC_THREAD
|
|
|
|
|
static void log_underflow(rf_uhd_handler_t *h) {
|
|
|
|
|
static void log_underflow(rf_uhd_handler_t* h)
|
|
|
|
|
{
|
|
|
|
|
if (h->uhd_error_handler) {
|
|
|
|
|
srslte_rf_error_t error;
|
|
|
|
|
bzero(&error, sizeof(srslte_rf_error_t));
|
|
|
|
@ -101,7 +105,8 @@ static void log_underflow(rf_uhd_handler_t *h) {
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void log_rx_error(rf_uhd_handler_t *h) {
|
|
|
|
|
static void log_rx_error(rf_uhd_handler_t* h)
|
|
|
|
|
{
|
|
|
|
|
if (h->uhd_error_handler) {
|
|
|
|
|
char error_string[512];
|
|
|
|
|
uhd_usrp_last_error(h->usrp, error_string, 512);
|
|
|
|
@ -115,7 +120,8 @@ static void log_rx_error(rf_uhd_handler_t *h) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if HAVE_ASYNC_THREAD
|
|
|
|
|
static void* async_thread(void *h) {
|
|
|
|
|
static void* async_thread(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
uhd_async_metadata_handle md;
|
|
|
|
|
uhd_async_metadata_make(&md);
|
|
|
|
@ -143,7 +149,8 @@ static void* async_thread(void *h) {
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void rf_uhd_suppress_stdout(void *h) {
|
|
|
|
|
void rf_uhd_suppress_stdout(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_register_msg_handler_c(suppress_handler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -167,23 +174,56 @@ static bool find_string(uhd_string_vector_handle h, char *str)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isLocked(rf_uhd_handler_t *handler, char *sensor_name, bool is_rx, uhd_sensor_value_handle *value_h)
|
|
|
|
|
// timeout in ms
|
|
|
|
|
static uhd_error
|
|
|
|
|
wait_sensor_locked(rf_uhd_handler_t* handler, char* sensor_name, bool is_mboard, int timeout, bool* is_locked)
|
|
|
|
|
{
|
|
|
|
|
bool val_out = false;
|
|
|
|
|
uhd_error error;
|
|
|
|
|
*is_locked = false;
|
|
|
|
|
|
|
|
|
|
uhd_sensor_value_handle value_h;
|
|
|
|
|
uhd_string_vector_handle sensors;
|
|
|
|
|
|
|
|
|
|
if (sensor_name) {
|
|
|
|
|
if (is_rx) {
|
|
|
|
|
uhd_usrp_get_rx_sensor(handler->usrp, sensor_name, 0, value_h);
|
|
|
|
|
uhd_string_vector_make(&sensors);
|
|
|
|
|
uhd_sensor_value_make_from_bool(&value_h, "", true, "True", "False");
|
|
|
|
|
if (is_mboard) {
|
|
|
|
|
// motherboard sensor
|
|
|
|
|
error = uhd_usrp_get_mboard_sensor_names(handler->usrp, 0, &sensors);
|
|
|
|
|
} else {
|
|
|
|
|
uhd_usrp_get_mboard_sensor(handler->usrp, sensor_name, 0, value_h);
|
|
|
|
|
// daughterboard sensor
|
|
|
|
|
error = uhd_usrp_get_rx_sensor_names(handler->usrp, 0, &sensors);
|
|
|
|
|
}
|
|
|
|
|
uhd_sensor_value_to_bool(*value_h, &val_out);
|
|
|
|
|
|
|
|
|
|
if (error == UHD_ERROR_NONE && find_string(sensors, sensor_name)) {
|
|
|
|
|
do {
|
|
|
|
|
if (is_mboard) {
|
|
|
|
|
error = uhd_usrp_get_mboard_sensor(handler->usrp, sensor_name, 0, &value_h);
|
|
|
|
|
} else {
|
|
|
|
|
usleep(500);
|
|
|
|
|
val_out = true;
|
|
|
|
|
error = uhd_usrp_get_rx_sensor(handler->usrp, sensor_name, 0, &value_h);
|
|
|
|
|
}
|
|
|
|
|
if (error != UHD_ERROR_NONE) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
uhd_sensor_value_to_bool(value_h, is_locked);
|
|
|
|
|
usleep(1000); // 1ms
|
|
|
|
|
timeout -= 1; // 1ms
|
|
|
|
|
} while (*is_locked == false && timeout > 0);
|
|
|
|
|
}
|
|
|
|
|
if (error != UHD_ERROR_NONE) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"%s has no sensor \"%s\", or reading failed. UHD error: %i\n",
|
|
|
|
|
is_mboard ? "Motherboard" : "Daugherboard",
|
|
|
|
|
sensor_name,
|
|
|
|
|
error);
|
|
|
|
|
// board doesn't have this sensor, sleep for timeout
|
|
|
|
|
*is_locked = true;
|
|
|
|
|
usleep(timeout * 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return val_out;
|
|
|
|
|
uhd_string_vector_free(&sensors);
|
|
|
|
|
uhd_sensor_value_free(&value_h);
|
|
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* rf_uhd_devname(void* h)
|
|
|
|
@ -196,47 +236,29 @@ bool rf_uhd_rx_wait_lo_locked(void *h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
|
|
|
|
|
uhd_string_vector_handle mb_sensors;
|
|
|
|
|
uhd_string_vector_handle rx_sensors;
|
|
|
|
|
char *sensor_name;
|
|
|
|
|
uhd_sensor_value_handle value_h;
|
|
|
|
|
uhd_string_vector_make(&mb_sensors);
|
|
|
|
|
uhd_string_vector_make(&rx_sensors);
|
|
|
|
|
uhd_sensor_value_make_from_bool(&value_h, "", true, "True", "False");
|
|
|
|
|
uhd_usrp_get_mboard_sensor_names(handler->usrp, 0, &mb_sensors);
|
|
|
|
|
uhd_usrp_get_rx_sensor_names(handler->usrp, 0, &rx_sensors);
|
|
|
|
|
// wait for clock source to lock
|
|
|
|
|
char* sensor_name = "lo_locked";
|
|
|
|
|
bool is_locked = false;
|
|
|
|
|
|
|
|
|
|
/*if (find_string(rx_sensors, "lo_locked")) {
|
|
|
|
|
sensor_name = "lo_locked";
|
|
|
|
|
} else */if (find_string(mb_sensors, "ref_locked")) {
|
|
|
|
|
sensor_name = "ref_locked";
|
|
|
|
|
} else {
|
|
|
|
|
sensor_name = NULL;
|
|
|
|
|
}
|
|
|
|
|
// blocks until sensor is blocked
|
|
|
|
|
uhd_error error = wait_sensor_locked(handler, sensor_name, false, 300, &is_locked);
|
|
|
|
|
|
|
|
|
|
double report = 0.0;
|
|
|
|
|
while (!isLocked(handler, sensor_name, false, &value_h) && report < 30.0) {
|
|
|
|
|
report += 0.1;
|
|
|
|
|
usleep(1000);
|
|
|
|
|
if (!is_locked || error != UHD_ERROR_NONE) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"Could not lock reference clock source. Sensor: %s=%s, UHD error: %i\n",
|
|
|
|
|
sensor_name,
|
|
|
|
|
is_locked ? "true" : "false",
|
|
|
|
|
error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool val = isLocked(handler, sensor_name, false, &value_h);
|
|
|
|
|
|
|
|
|
|
uhd_string_vector_free(&mb_sensors);
|
|
|
|
|
uhd_string_vector_free(&rx_sensors);
|
|
|
|
|
uhd_sensor_value_free(&value_h);
|
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
return is_locked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rf_uhd_start_rx_stream(void* h, bool now)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
|
|
|
|
|
uhd_stream_cmd_t stream_cmd = {
|
|
|
|
|
.stream_mode = UHD_STREAM_MODE_START_CONTINUOUS,
|
|
|
|
|
.stream_now = now
|
|
|
|
|
};
|
|
|
|
|
uhd_stream_cmd_t stream_cmd = {.stream_mode = UHD_STREAM_MODE_START_CONTINUOUS, .stream_now = now};
|
|
|
|
|
if (!now) {
|
|
|
|
|
uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs);
|
|
|
|
|
stream_cmd.time_spec_frac_secs += 0.2;
|
|
|
|
@ -252,10 +274,7 @@ int rf_uhd_start_rx_stream(void *h, bool now)
|
|
|
|
|
int rf_uhd_stop_rx_stream(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
uhd_stream_cmd_t stream_cmd = {
|
|
|
|
|
.stream_mode = UHD_STREAM_MODE_STOP_CONTINUOUS,
|
|
|
|
|
.stream_now = true
|
|
|
|
|
};
|
|
|
|
|
uhd_stream_cmd_t stream_cmd = {.stream_mode = UHD_STREAM_MODE_STOP_CONTINUOUS, .stream_now = true};
|
|
|
|
|
uhd_rx_streamer_issue_stream_cmd(handler->rx_stream, &stream_cmd);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -271,12 +290,14 @@ void rf_uhd_flush_buffer(void *h)
|
|
|
|
|
} while (n > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rf_uhd_has_rssi(void *h) {
|
|
|
|
|
bool rf_uhd_has_rssi(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
return handler->has_rssi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool get_has_rssi(void *h) {
|
|
|
|
|
bool get_has_rssi(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
uhd_string_vector_handle rx_sensors;
|
|
|
|
|
uhd_string_vector_make(&rx_sensors);
|
|
|
|
@ -286,7 +307,8 @@ bool get_has_rssi(void *h) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float rf_uhd_get_rssi(void *h) {
|
|
|
|
|
float rf_uhd_get_rssi(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
if (handler->has_rssi) {
|
|
|
|
|
double val_out;
|
|
|
|
@ -509,13 +531,31 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
|
|
|
|
|
handler->devname = "uhd_unknown";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool is_locked = false;
|
|
|
|
|
char* sensor_name = "";
|
|
|
|
|
|
|
|
|
|
// Set external clock reference
|
|
|
|
|
if (clock_src == EXTERNAL) {
|
|
|
|
|
uhd_usrp_set_clock_source(handler->usrp, "external", 0);
|
|
|
|
|
uhd_usrp_set_time_source(handler->usrp, "external", 0);
|
|
|
|
|
sensor_name = "ref_locked";
|
|
|
|
|
} else if (clock_src == GPSDO) {
|
|
|
|
|
uhd_usrp_set_clock_source(handler->usrp, "gpsdo", 0);
|
|
|
|
|
uhd_usrp_set_time_source(handler->usrp, "gpsdo", 0);
|
|
|
|
|
sensor_name = "gps_locked";
|
|
|
|
|
}
|
|
|
|
|
// wait until external reference / GPS is locked
|
|
|
|
|
if (clock_src != DEFAULT) {
|
|
|
|
|
// blocks until clock source is locked
|
|
|
|
|
error = wait_sensor_locked(handler, sensor_name, true, 300, &is_locked);
|
|
|
|
|
|
|
|
|
|
if (!is_locked || error != UHD_ERROR_NONE) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"Could not lock reference clock source. Sensor: %s=%s, UHD error: %i\n",
|
|
|
|
|
sensor_name,
|
|
|
|
|
is_locked ? "true" : "false",
|
|
|
|
|
error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handler->has_rssi = get_has_rssi(handler);
|
|
|
|
@ -600,7 +640,6 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int rf_uhd_close(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_stop_rx_stream(h);
|
|
|
|
@ -628,7 +667,8 @@ int rf_uhd_close(void *h)
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rf_uhd_set_master_clock_rate(void *h, double rate) {
|
|
|
|
|
void rf_uhd_set_master_clock_rate(void* h, double rate)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
if (fmod(handler->current_master_clock, rate)) {
|
|
|
|
|
if (handler->dynamic_rate) {
|
|
|
|
@ -638,7 +678,8 @@ void rf_uhd_set_master_clock_rate(void *h, double rate) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rf_uhd_is_master_clock_dynamic(void *h) {
|
|
|
|
|
bool rf_uhd_is_master_clock_dynamic(void* h)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
return handler->dynamic_rate;
|
|
|
|
|
}
|
|
|
|
@ -652,7 +693,10 @@ double rf_uhd_set_rx_srate(void *h, double freq)
|
|
|
|
|
double frac;
|
|
|
|
|
uhd_usrp_get_time_now(handler->usrp, 0, &full, &frac);
|
|
|
|
|
frac += 0.100;
|
|
|
|
|
if (frac >= 1.0) { full++; frac -= 1.0; };
|
|
|
|
|
if (frac >= 1.0) {
|
|
|
|
|
full++;
|
|
|
|
|
frac -= 1.0;
|
|
|
|
|
};
|
|
|
|
|
uhd_usrp_set_command_time(handler->usrp, full, frac, 0);
|
|
|
|
|
#endif /* UHD_SUPPORTS_COMMAND_TIME */
|
|
|
|
|
for (int i = 0; i < handler->nof_rx_channels; i++) {
|
|
|
|
@ -676,7 +720,10 @@ double rf_uhd_set_tx_srate(void *h, double freq)
|
|
|
|
|
double frac;
|
|
|
|
|
uhd_usrp_get_time_now(handler->usrp, 0, &full, &frac);
|
|
|
|
|
frac += 0.100;
|
|
|
|
|
if (frac >= 1.0) { full++; frac -= 1.0; };
|
|
|
|
|
if (frac >= 1.0) {
|
|
|
|
|
full++;
|
|
|
|
|
frac -= 1.0;
|
|
|
|
|
};
|
|
|
|
|
uhd_usrp_set_command_time(handler->usrp, full, frac, 0);
|
|
|
|
|
#endif /* UHD_SUPPORTS_COMMAND_TIME */
|
|
|
|
|
for (int i = 0; i < handler->nof_tx_channels; i++) {
|
|
|
|
@ -774,8 +821,8 @@ double rf_uhd_set_tx_freq(void* h, uint32_t ch, double freq)
|
|
|
|
|
return freq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void rf_uhd_get_time(void *h, time_t *secs, double *frac_secs) {
|
|
|
|
|
void rf_uhd_get_time(void* h, time_t* secs, double* frac_secs)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
uhd_usrp_get_time_now(handler->usrp, 0, secs, frac_secs);
|
|
|
|
|
}
|
|
|
|
@ -788,22 +835,13 @@ void rf_uhd_sync_pps(void* h)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rf_uhd_recv_with_time(void *h,
|
|
|
|
|
void *data,
|
|
|
|
|
uint32_t nsamples,
|
|
|
|
|
bool blocking,
|
|
|
|
|
time_t *secs,
|
|
|
|
|
double *frac_secs)
|
|
|
|
|
int rf_uhd_recv_with_time(void* h, void* data, uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs)
|
|
|
|
|
{
|
|
|
|
|
return rf_uhd_recv_with_time_multi(h, &data, nsamples, blocking, secs, frac_secs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rf_uhd_recv_with_time_multi(void *h,
|
|
|
|
|
void *data[SRSLTE_MAX_PORTS],
|
|
|
|
|
uint32_t nsamples,
|
|
|
|
|
bool blocking,
|
|
|
|
|
time_t *secs,
|
|
|
|
|
double *frac_secs)
|
|
|
|
|
int rf_uhd_recv_with_time_multi(
|
|
|
|
|
void* h, void* data[SRSLTE_MAX_PORTS], uint32_t nsamples, bool blocking, time_t* secs, double* frac_secs)
|
|
|
|
|
{
|
|
|
|
|
rf_uhd_handler_t* handler = (rf_uhd_handler_t*)h;
|
|
|
|
|
uhd_rx_metadata_handle* md = &handler->rx_md_first;
|
|
|
|
@ -822,8 +860,8 @@ int rf_uhd_recv_with_time_multi(void *h,
|
|
|
|
|
size_t num_rx_samples = (num_samps_left > handler->rx_nof_samples) ? handler->rx_nof_samples : num_samps_left;
|
|
|
|
|
|
|
|
|
|
rxd_samples = 0;
|
|
|
|
|
uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, buffs_ptr,
|
|
|
|
|
num_rx_samples, md, 1.0, false, &rxd_samples);
|
|
|
|
|
uhd_error error =
|
|
|
|
|
uhd_rx_streamer_recv(handler->rx_stream, buffs_ptr, num_rx_samples, md, 1.0, false, &rxd_samples);
|
|
|
|
|
if (error) {
|
|
|
|
|
ERROR("Error receiving from UHD: %d\n", error);
|
|
|
|
|
log_rx_error(handler);
|
|
|
|
@ -876,7 +914,8 @@ int rf_uhd_send_timed(void *h,
|
|
|
|
|
{
|
|
|
|
|
void* _data[SRSLTE_MAX_PORTS] = {data, zero_mem, zero_mem, zero_mem};
|
|
|
|
|
|
|
|
|
|
return rf_uhd_send_timed_multi(h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst);
|
|
|
|
|
return rf_uhd_send_timed_multi(
|
|
|
|
|
h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rf_uhd_send_timed_multi(void* h,
|
|
|
|
@ -934,8 +973,8 @@ int rf_uhd_send_timed_multi(void *h,
|
|
|
|
|
void* buff = (void*)&data_c[i][n];
|
|
|
|
|
buffs_ptr[i] = buff;
|
|
|
|
|
}
|
|
|
|
|
uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr,
|
|
|
|
|
tx_samples, &handler->tx_md, 1.0, &txd_samples);
|
|
|
|
|
uhd_error error =
|
|
|
|
|
uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, tx_samples, &handler->tx_md, 1.0, &txd_samples);
|
|
|
|
|
if (error) {
|
|
|
|
|
ERROR("Error sending to UHD: %d\n", error);
|
|
|
|
|
goto unlock;
|
|
|
|
@ -964,10 +1003,8 @@ int rf_uhd_send_timed_multi(void *h,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = txd_samples;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
unlock:
|
|
|
|
|
pthread_mutex_unlock(&handler->tx_mutex);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|