UHD: Wait for `lo_locked` after frequency change (#635)

* UHD: clang-tidy rf_uhd_imp.c
* UHD: wait for LO_lock after frequency change
master
Merlin Chlosta 5 years ago committed by Ismael Gomez
parent c92c61d560
commit 2079c1324c

@ -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;
}

Loading…
Cancel
Save