add multi-channel support for soapy

master
Andre Puschmann 6 years ago
parent beec489dd4
commit 3405a1bff6

@ -48,9 +48,6 @@
#define PRINT_RX_STATS 0 #define PRINT_RX_STATS 0
#define PRINT_TX_STATS 0 #define PRINT_TX_STATS 0
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
typedef struct { typedef struct {
char *devname; char *devname;
SoapySDRKwargs args; SoapySDRKwargs args;
@ -63,6 +60,8 @@ typedef struct {
srslte_rf_info_t info; srslte_rf_info_t info;
double tx_rate; double tx_rate;
size_t rx_mtu, tx_mtu; size_t rx_mtu, tx_mtu;
size_t num_rx_channels;
size_t num_tx_channels;
srslte_rf_error_handler_t soapy_error_handler; srslte_rf_error_handler_t soapy_error_handler;
@ -224,7 +223,7 @@ int rf_soapy_start_rx_stream(void *h, bool now)
if(SoapySDRDevice_activateStream(handler->device, handler->rxStream, SOAPY_SDR_HAS_TIME | SOAPY_SDR_END_BURST, 0, 0) != 0) if(SoapySDRDevice_activateStream(handler->device, handler->rxStream, SOAPY_SDR_HAS_TIME | SOAPY_SDR_END_BURST, 0, 0) != 0)
return SRSLTE_ERROR; return SRSLTE_ERROR;
handler->rx_stream_active = true; handler->rx_stream_active = true;
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -236,7 +235,7 @@ int rf_soapy_start_tx_stream(void *h)
if(SoapySDRDevice_activateStream(handler->device, handler->txStream, 0, 0, 0) != 0) if(SoapySDRDevice_activateStream(handler->device, handler->txStream, 0, 0, 0) != 0)
return SRSLTE_ERROR; return SRSLTE_ERROR;
handler->tx_stream_active = true; handler->tx_stream_active = true;
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -288,9 +287,7 @@ float rf_soapy_get_rssi(void *h)
return 0.0; return 0.0;
} }
int rf_soapy_open_multi(char* args, void** h, uint32_t num_requested_channels)
//TODO: add multi-channel support
int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
{ {
size_t length; size_t length;
const SoapySDRKwargs *soapy_args = SoapySDRDevice_enumerate(NULL, &length); const SoapySDRKwargs *soapy_args = SoapySDRDevice_enumerate(NULL, &length);
@ -328,38 +325,44 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
handler->rx_stream_active = false; handler->rx_stream_active = false;
handler->devname = devname; handler->devname = devname;
// init rx/tx rate to lowest LTE rate to avoid decimation warnings // Setup Rx streamer
rf_soapy_set_rx_srate(handler, 1.92e6); size_t num_available_channels = SoapySDRDevice_getNumChannels(handler->device, SOAPY_SDR_RX);
rf_soapy_set_tx_srate(handler, 1.92e6); if ((num_available_channels > 0) && (num_requested_channels > 0)) {
handler->num_rx_channels = SRSLTE_MIN(num_available_channels, num_requested_channels);
size_t channels = SoapySDRDevice_getNumChannels(handler->device, SOAPY_SDR_RX); size_t rx_channels[handler->num_rx_channels];
for (int i = 0; i < handler->num_rx_channels; i++) {
if((channels > 0) && (nof_rx_antennas > 0)){
printf("Setting up RX stream\n");
size_t numChannels = channels;
if (channels > nof_rx_antennas) {
numChannels = nof_rx_antennas;
}
size_t rx_channels[numChannels];
for(int i = 0 ; i < numChannels ; i++) {
rx_channels[i] = i; rx_channels[i] = i;
} }
if(SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, rx_channels, numChannels, NULL) != 0) { printf("Setting up Rx stream with %zd channel(s)\n", handler->num_rx_channels);
if (SoapySDRDevice_setupStream(handler->device, &handler->rxStream, SOAPY_SDR_RX, SOAPY_SDR_CF32, rx_channels,
handler->num_rx_channels, NULL) != 0) {
printf("Rx setupStream fail: %s\n", SoapySDRDevice_lastError()); printf("Rx setupStream fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
handler->rx_mtu = SoapySDRDevice_getStreamMTU(handler->device, handler->rxStream); handler->rx_mtu = SoapySDRDevice_getStreamMTU(handler->device, handler->rxStream);
} }
if(SoapySDRDevice_getNumChannels(handler->device, SOAPY_SDR_TX) > 0){ // Setup Tx streamer
printf("Setting up TX stream\n"); num_available_channels = SoapySDRDevice_getNumChannels(handler->device, SOAPY_SDR_TX);
if (SoapySDRDevice_setupStream(handler->device, &(handler->txStream), SOAPY_SDR_TX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) { if ((num_available_channels > 0) && (num_requested_channels > 0)) {
handler->num_tx_channels = SRSLTE_MIN(num_available_channels, num_requested_channels);
size_t tx_channels[handler->num_tx_channels];
for (int i = 0; i < handler->num_tx_channels; i++) {
tx_channels[i] = i;
}
printf("Setting up Tx stream with %zd channel(s)\n", handler->num_tx_channels);
if (SoapySDRDevice_setupStream(handler->device, &handler->txStream, SOAPY_SDR_TX, SOAPY_SDR_CF32, tx_channels,
handler->num_tx_channels, NULL) != 0) {
printf("Tx setupStream fail: %s\n", SoapySDRDevice_lastError()); printf("Tx setupStream fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
handler->tx_mtu = SoapySDRDevice_getStreamMTU(handler->device, handler->txStream); handler->tx_mtu = SoapySDRDevice_getStreamMTU(handler->device, handler->txStream);
} }
// init rx/tx rate to lowest LTE rate to avoid decimation warnings
rf_soapy_set_rx_srate(handler, 1.92e6);
rf_soapy_set_tx_srate(handler, 1.92e6);
// list device sensors // list device sensors
size_t list_length; size_t list_length;
char** list; char** list;
@ -370,10 +373,12 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
} }
// list channel sensors // list channel sensors
list = SoapySDRDevice_listChannelSensors(handler->device, SOAPY_SDR_RX, 0, &list_length); for (uint32_t i = 0; i < handler->num_rx_channels; ++i) {
printf("Available sensors for RX channel 0: \n"); list = SoapySDRDevice_listChannelSensors(handler->device, SOAPY_SDR_RX, i, &list_length);
for(int i = 0; i < list_length; i++) { printf("Available sensors for Rx channel %d: \n", i);
printf(" - %s\n", list[i]); for (int i = 0; i < list_length; i++) {
printf(" - %s\n", list[i]);
}
} }
// Set static radio info // Set static radio info
@ -444,8 +449,8 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
bool start_async_thread = true; bool start_async_thread = true;
if (args) { if (args) {
if (strstr(args, "silent")) { if (strstr(args, "silent")) {
REMOVE_SUBSTRING_WITHCOMAS(args, "silent"); REMOVE_SUBSTRING_WITHCOMAS(args, "silent");
start_async_thread = false; start_async_thread = false;
} }
} }
#endif #endif
@ -458,7 +463,9 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas)
cf_t dummy_buffer[1920]; cf_t dummy_buffer[1920];
cf_t *dummy_buffer_array[SRSLTE_MAX_PORTS]; cf_t *dummy_buffer_array[SRSLTE_MAX_PORTS];
dummy_buffer_array[0] = dummy_buffer; for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
dummy_buffer_array[i] = dummy_buffer;
}
rf_soapy_start_rx_stream(handler, true); rf_soapy_start_rx_stream(handler, true);
rf_soapy_recv_with_time_multi(handler, (void**)dummy_buffer_array, 1920, false, NULL, NULL); rf_soapy_recv_with_time_multi(handler, (void**)dummy_buffer_array, 1920, false, NULL, NULL);
rf_soapy_stop_rx_stream(handler); rf_soapy_stop_rx_stream(handler);
@ -570,31 +577,34 @@ double rf_soapy_set_rx_srate(void *h, double rate)
rf_soapy_stop_rx_stream(handler); rf_soapy_stop_rx_stream(handler);
} }
if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_RX, 0, rate) != 0) { for (uint32_t i = 0; i < handler->num_rx_channels; i++) {
printf("setSampleRate Rx fail: %s\n", SoapySDRDevice_lastError()); if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_RX, i, rate) != 0) {
return SRSLTE_ERROR; printf("setSampleRate Rx fail: %s\n", SoapySDRDevice_lastError());
} return SRSLTE_ERROR;
}
#if SET_RF_BW #if SET_RF_BW
// Set bandwidth close to current rate // Set bandwidth close to current rate
size_t bw_length; size_t bw_length;
SoapySDRRange *bw_range = SoapySDRDevice_getBandwidthRange(handler->device, SOAPY_SDR_RX, 0, &bw_length); SoapySDRRange* bw_range = SoapySDRDevice_getBandwidthRange(handler->device, SOAPY_SDR_RX, 0, &bw_length);
double bw = rate * 0.75; double bw = rate * 0.75;
bw = MIN(bw, bw_range->maximum); bw = SRSLTE_MIN(bw, bw_range->maximum);
bw = MAX(bw, bw_range->minimum); bw = SRSLTE_MAX(bw, bw_range->minimum);
bw = MAX(bw, 2.5e6); // For the Lime to avoid warnings bw = SRSLTE_MAX(bw, 2.5e6); // For the Lime to avoid warnings
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_RX, 0, bw) != 0) { if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_RX, i, bw) != 0) {
printf("setBandwidth fail: %s\n", SoapySDRDevice_lastError()); printf("setBandwidth fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
printf("Set Rx bandwidth to %.2f MHz\n", SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_RX, 0)/1e6); printf("Set Rx bandwidth to %.2f MHz\n", SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_RX, i) / 1e6);
#endif #endif
}
if (rx_stream_active) { if (rx_stream_active) {
rf_soapy_start_rx_stream(handler, true); rf_soapy_start_rx_stream(handler, true);
} }
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0); // retrun sample rate of first channel
return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX, 0);
} }
double rf_soapy_set_tx_srate(void *h, double rate) double rf_soapy_set_tx_srate(void *h, double rate)
@ -607,30 +617,33 @@ double rf_soapy_set_tx_srate(void *h, double rate)
rf_soapy_stop_rx_stream(handler); rf_soapy_stop_rx_stream(handler);
} }
if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_TX, 0, rate) != 0) { for (uint32_t i = 0; i < handler->num_tx_channels; i++) {
printf("setSampleRate Tx fail: %s\n", SoapySDRDevice_lastError()); if (SoapySDRDevice_setSampleRate(handler->device, SOAPY_SDR_TX, i, rate) != 0) {
return SRSLTE_ERROR; printf("setSampleRate Tx fail: %s\n", SoapySDRDevice_lastError());
} return SRSLTE_ERROR;
}
#if SET_RF_BW #if SET_RF_BW
size_t bw_length; size_t bw_length;
SoapySDRRange *bw_range = SoapySDRDevice_getBandwidthRange(handler->device, SOAPY_SDR_TX, 0, &bw_length); SoapySDRRange* bw_range = SoapySDRDevice_getBandwidthRange(handler->device, SOAPY_SDR_TX, i, &bw_length);
// try to set the BW a bit narrower than sampling rate to prevent aliasing but make sure to stay within device boundaries // try to set the BW a bit narrower than sampling rate to prevent aliasing but make sure to stay within device
double bw = rate * 0.75; // boundaries
bw = MAX(bw, bw_range->minimum); double bw = rate * 0.75;
bw = MIN(bw, bw_range->maximum); bw = SRSLTE_MAX(bw, bw_range->minimum);
if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_TX, 0, bw) != 0) { bw = SRSLTE_MIN(bw, bw_range->maximum);
printf("setBandwidth fail: %s\n", SoapySDRDevice_lastError()); if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_TX, i, bw) != 0) {
return SRSLTE_ERROR; printf("setBandwidth fail: %s\n", SoapySDRDevice_lastError());
} return SRSLTE_ERROR;
printf("Set Tx bandwidth to %.2f MHz\n", SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_TX, 0)/1e6); }
printf("Set Tx bandwidth to %.2f MHz\n", SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_TX, i) / 1e6);
#endif #endif
}
if (rx_stream_active) { if (rx_stream_active) {
rf_soapy_start_rx_stream(handler, true); rf_soapy_start_rx_stream(handler, true);
} }
handler->tx_rate = SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX, 0); handler->tx_rate = SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX, 0);
return handler->tx_rate; return handler->tx_rate;
} }
@ -638,10 +651,12 @@ double rf_soapy_set_tx_srate(void *h, double rate)
double rf_soapy_set_rx_gain(void *h, double gain) double rf_soapy_set_rx_gain(void *h, double gain)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
if (SoapySDRDevice_setGain(handler->device, SOAPY_SDR_RX, 0, gain) != 0)
{ for (uint32_t i = 0; i < handler->num_rx_channels; i++) {
printf("setGain fail: %s\n", SoapySDRDevice_lastError()); if (SoapySDRDevice_setGain(handler->device, SOAPY_SDR_RX, i, gain) != 0) {
return SRSLTE_ERROR; printf("setGain fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR;
}
} }
return rf_soapy_get_rx_gain(h); return rf_soapy_get_rx_gain(h);
} }
@ -650,22 +665,23 @@ double rf_soapy_set_rx_gain(void *h, double gain)
double rf_soapy_set_tx_gain(void *h, double gain) double rf_soapy_set_tx_gain(void *h, double gain)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
if (SoapySDRDevice_setGain(handler->device, SOAPY_SDR_TX, 0, gain) != 0) for (uint32_t i = 0; i < handler->num_tx_channels; i++) {
{ if (SoapySDRDevice_setGain(handler->device, SOAPY_SDR_TX, i, gain) != 0) {
printf("setGain fail: %s\n", SoapySDRDevice_lastError()); printf("setGain fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR; return SRSLTE_ERROR;
}
} }
return rf_soapy_get_tx_gain(h); return rf_soapy_get_tx_gain(h);
} }
// Return gain of first channel
double rf_soapy_get_rx_gain(void *h) double rf_soapy_get_rx_gain(void *h)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
return SoapySDRDevice_getGain(handler->device, SOAPY_SDR_RX, 0); return SoapySDRDevice_getGain(handler->device, SOAPY_SDR_RX, 0);
} }
// Return gain of first channel
double rf_soapy_get_tx_gain(void *h) double rf_soapy_get_tx_gain(void *h)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
@ -687,30 +703,30 @@ srslte_rf_info_t * rf_soapy_get_info(void *h)
double rf_soapy_set_rx_freq(void *h, double freq) double rf_soapy_set_rx_freq(void *h, double freq)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
if (SoapySDRDevice_setFrequency(handler->device, SOAPY_SDR_RX, 0, freq, NULL) != 0)
{ for (uint32_t i = 0; i < handler->num_rx_channels; i++) {
printf("setFrequency fail: %s\n", SoapySDRDevice_lastError()); if (SoapySDRDevice_setFrequency(handler->device, SOAPY_SDR_RX, i, freq, NULL) != 0) {
return SRSLTE_ERROR; printf("setFrequency fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR;
}
} }
printf("Tuned Rx to %.2f MHz\n", SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_RX, 0)/1e6);
// wait until LO is locked // wait until LO is locked
rf_soapy_rx_wait_lo_locked(handler); rf_soapy_rx_wait_lo_locked(handler);
// Return actual frequency for channel 0
return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_RX, 0); return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_RX, 0);
} }
double rf_soapy_set_tx_freq(void *h, double freq) double rf_soapy_set_tx_freq(void *h, double freq)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
if (SoapySDRDevice_setFrequency(handler->device, SOAPY_SDR_TX, 0, freq, NULL) != 0) for (uint32_t i = 0; i < handler->num_tx_channels; i++) {
{ if (SoapySDRDevice_setFrequency(handler->device, SOAPY_SDR_TX, i, freq, NULL) != 0) {
printf("setFrequency fail: %s\n", SoapySDRDevice_lastError()); printf("setFrequency fail: %s\n", SoapySDRDevice_lastError());
return SRSLTE_ERROR; return SRSLTE_ERROR;
}
} }
printf("Tuned Tx to %.2f MHz\n", SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_TX, 0)/1e6);
return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_TX, 0); return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_TX, 0);
} }
@ -730,8 +746,7 @@ int rf_soapy_recv_with_time_multi(void *h,
double *frac_secs) double *frac_secs)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
int flags; //flags set by receive operation int flags = 0; // flags set by receive operation
int num_channels = 1; // temp
const long timeoutUs = 400000; // arbitrarily chosen const long timeoutUs = 400000; // arbitrarily chosen
int trials = 0; int trials = 0;
@ -744,13 +759,13 @@ int rf_soapy_recv_with_time_multi(void *h,
#endif #endif
do { do {
size_t rx_samples = MIN(nsamples - n, handler->rx_mtu); size_t rx_samples = SRSLTE_MIN(nsamples - n, handler->rx_mtu);
#if PRINT_RX_STATS #if PRINT_RX_STATS
printf(" - rx_samples=%zd\n", rx_samples); printf(" - rx_samples=%zd\n", rx_samples);
#endif #endif
void *buffs_ptr[4]; void* buffs_ptr[SRSLTE_MAX_PORTS];
for (int i=0; i<num_channels; i++){ for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
cf_t *data_c = (cf_t*) data[i]; cf_t *data_c = (cf_t*) data[i];
buffs_ptr[i] = &data_c[n]; buffs_ptr[i] = &data_c[n];
} }
@ -799,16 +814,15 @@ int rf_soapy_recv_with_time(void *h,
return rf_soapy_recv_with_time_multi(h, &data, nsamples, blocking, secs, frac_secs); return rf_soapy_recv_with_time_multi(h, &data, nsamples, blocking, secs, frac_secs);
} }
int rf_soapy_send_timed(void* h,
int rf_soapy_send_timed(void *h, void* data,
void *data, int nsamples,
int nsamples, time_t secs,
time_t secs, double frac_secs,
double frac_secs, bool has_time_spec,
bool has_time_spec, bool blocking,
bool blocking, bool is_start_of_burst,
bool is_start_of_burst, bool is_end_of_burst)
bool is_end_of_burst)
{ {
void *_data[SRSLTE_MAX_PORTS]= {data, zero_mem, zero_mem, zero_mem}; void *_data[SRSLTE_MAX_PORTS]= {data, zero_mem, zero_mem, zero_mem};
return rf_soapy_send_timed_multi(h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst); return rf_soapy_send_timed_multi(h, _data, nsamples, secs, frac_secs, has_time_spec, blocking, is_start_of_burst, is_end_of_burst);
@ -816,15 +830,15 @@ int rf_soapy_send_timed(void *h,
// Todo: Check correct handling of flags, use RF metrics API, fix timed transmissions // Todo: Check correct handling of flags, use RF metrics API, fix timed transmissions
int rf_soapy_send_timed_multi(void *h, int rf_soapy_send_timed_multi(void* h,
void *data[SRSLTE_MAX_PORTS], void* data[SRSLTE_MAX_PORTS],
int nsamples, int nsamples,
time_t secs, time_t secs,
double frac_secs, double frac_secs,
bool has_time_spec, bool has_time_spec,
bool blocking, bool blocking,
bool is_start_of_burst, bool is_start_of_burst,
bool is_end_of_burst) bool is_end_of_burst)
{ {
rf_soapy_handler_t *handler = (rf_soapy_handler_t *) h; rf_soapy_handler_t *handler = (rf_soapy_handler_t *) h;
int flags = 0; int flags = 0;
@ -850,7 +864,7 @@ int rf_soapy_send_timed_multi(void *h,
do { do {
#if USE_TX_MTU #if USE_TX_MTU
size_t tx_samples = MIN(nsamples - n, handler->tx_mtu); size_t tx_samples = SRSLTE_MIN(nsamples - n, handler->tx_mtu);
#else #else
size_t tx_samples = nsamples; size_t tx_samples = nsamples;
if (tx_samples > nsamples - n) { if (tx_samples > nsamples - n) {

@ -35,9 +35,7 @@
SRSLTE_API int rf_soapy_open(char *args, SRSLTE_API int rf_soapy_open(char *args,
void **handler); void **handler);
SRSLTE_API int rf_soapy_open_multi(char *args, SRSLTE_API int rf_soapy_open_multi(char* args, void** handler, uint32_t num_requested_channels);
void **handler,
uint32_t nof_rx_antennas);
SRSLTE_API char* rf_soapy_devname(void *h); SRSLTE_API char* rf_soapy_devname(void *h);

Loading…
Cancel
Save