BladeRF interface working at 5 MHz

master
ismagom 9 years ago
parent efdcda0784
commit a0a730b1de

@ -39,7 +39,8 @@
uint32_t nof_prb = 25;
uint32_t nof_frames = 20;
float tone_offset_hz = 0;
int time_adv_samples = 0;
float tone_offset_hz = 1e6;
float rf_rx_gain=40, rf_tx_gain=40, rf_freq=2.4e9;
char *rf_args="";
char *output_filename = NULL;
@ -52,13 +53,14 @@ void usage(char *prog) {
printf("\t-g RF RX gain [Default %.1f dB]\n", rf_rx_gain);
printf("\t-G RF TX gain [Default %.1f dB]\n", rf_tx_gain);
printf("\t-t Single tone offset (Hz) [Default %f]\n", tone_offset_hz);
printf("\t-T Time advance samples [Default %d]\n", time_adv_samples);
printf("\t-i File name to read signal from [Default single tone]\n");
printf("\t-p Number of UL RB [Default %d]\n", nof_prb);
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "ioafgpt")) != -1) {
while ((opt = getopt(argc, argv, "ioafgGptT")) != -1) {
switch (opt) {
case 'a':
rf_args = argv[optind];
@ -72,6 +74,9 @@ void parse_args(int argc, char **argv) {
case 't':
tone_offset_hz = atof(argv[optind]);
break;
case 'T':
time_adv_samples = atoi(argv[optind]);
break;
case 'f':
rf_freq = atof(argv[optind]);
break;
@ -97,13 +102,17 @@ void parse_args(int argc, char **argv) {
usage(argv[0]);
exit(-1);
}
if (time_adv_samples < 0) {
printf("Time advance must be positive\n");
usage(argv[0]);
exit(-1);
}
}
int main(int argc, char **argv) {
parse_args(argc, argv);
uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000;
uint32_t nsamples_adv = 3000;
cf_t *rx_buffer = malloc(sizeof(cf_t)*flen*nof_frames);
if (!rx_buffer) {
@ -111,12 +120,12 @@ int main(int argc, char **argv) {
exit(-1);
}
cf_t *tx_buffer = malloc(sizeof(cf_t)*(flen+nsamples_adv));
cf_t *tx_buffer = malloc(sizeof(cf_t)*(flen+time_adv_samples));
if (!tx_buffer) {
perror("malloc");
exit(-1);
}
bzero(tx_buffer, sizeof(cf_t)*(flen+nsamples_adv));
bzero(tx_buffer, sizeof(cf_t)*(flen+time_adv_samples));
cf_t *zeros = calloc(sizeof(cf_t),flen);
if (!zeros) {
@ -124,6 +133,8 @@ int main(int argc, char **argv) {
exit(-1);
}
float time_adv_sec = (float) time_adv_samples/srslte_sampling_freq_hz(nof_prb);
// Send through RF
rf_t rf;
printf("Opening RF device...\n");
@ -142,19 +153,22 @@ int main(int argc, char **argv) {
rf_set_rx_srate(&rf, (double) srate);
rf_set_tx_srate(&rf, (double) srate);
printf("Subframe len: %d samples\n", flen);
printf("Time advance: %f us\n",time_adv_sec*1e6);
printf("Set TX/RX rate: %.2f MHz\n", (float) srate / 1000000);
printf("Set RX gain: %.1f dB\n", rf_set_rx_gain(&rf, rf_rx_gain));
printf("Set TX gain: %.1f dB\n", rf_set_tx_gain(&rf, rf_tx_gain));
printf("Set TX/RX freq: %.2f MHz\n", rf_set_rx_freq(&rf, rf_freq) / 1000000);
rf_set_tx_freq(&rf, rf_freq);
sleep(1);
if (input_filename) {
srslte_vec_load_file(input_filename, &tx_buffer[nsamples_adv], flen*sizeof(cf_t));
srslte_vec_load_file(input_filename, &tx_buffer[time_adv_samples], flen*sizeof(cf_t));
} else {
for (int i=0;i<flen-nsamples_adv;i++) {
tx_buffer[i+nsamples_adv] = cexpf(_Complex_I*2*M_PI*tone_offset_hz*(float) i/(float) srate);
for (int i=0;i<flen-time_adv_samples;i++) {
tx_buffer[i+time_adv_samples] = 0.3*cexpf(_Complex_I*2*M_PI*tone_offset_hz*((float) i/(float) srate));
}
srslte_vec_save_file("rf_txrx_tone", tx_buffer, flen*sizeof(cf_t));
}
@ -164,24 +178,16 @@ int main(int argc, char **argv) {
rf_start_rx_stream(&rf);
uint32_t nframe=0;
float burst_settle_time = (float) nsamples_adv/srslte_sampling_freq_hz(nof_prb);
printf("timeadv=%f\n",burst_settle_time);
while(nframe<nof_frames) {
printf("Rx subframe %d\n", nframe);
rf_recv_with_time(&rf, &rx_buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
nframe++;
if (nframe==9 || nframe==8) {
srslte_timestamp_add(&tstamp, 0, 2e-3-burst_settle_time);
if (nframe==8) {
//rf_send_timed2(&rf, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
printf("Transmitting zeros\n");
} else {
rf_send_timed2(&rf, tx_buffer, flen+nsamples_adv, tstamp.full_secs, tstamp.frac_secs, true, true);
if (nframe==9) {
srslte_timestamp_add(&tstamp, 0, 2e-3-time_adv_sec);
rf_send_timed2(&rf, tx_buffer, flen+time_adv_samples, tstamp.full_secs, tstamp.frac_secs, true, true);
printf("Transmitting Signal\n");
}
}
}

@ -34,11 +34,20 @@
#include "rf_blade_imp.h"
#include "srslte/rf/rf.h"
#define CONVERT_BUFFER_SIZE 24*1024
typedef struct {
struct bladerf *dev;
uint32_t rx_rate;
uint32_t tx_rate;
int16_t rx_buffer[CONVERT_BUFFER_SIZE];
int16_t tx_buffer[CONVERT_BUFFER_SIZE];
bool stream_enabled;
} rf_blade_handler_t;
void rf_blade_suppress_stdout(void *h) {
bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_SILENT);
}
void rf_blade_register_msg_handler(void *notused, rf_msg_handler_t new_handler)
@ -48,86 +57,302 @@ void rf_blade_register_msg_handler(void *notused, rf_msg_handler_t new_handler)
bool rf_blade_rx_wait_lo_locked(void *h)
{
usleep(1000);
return true;
}
int rf_blade_start_rx_stream(void *h)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
const unsigned int num_buffers = 16;
const unsigned int buffer_size_rx = 4*1024;
const unsigned int buffer_size_tx = 1024;
const unsigned int num_transfers = 8;
const unsigned int timeout_ms = 4000;
/* Configure the device's RX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */
status = bladerf_sync_config(handler->dev,
BLADERF_MODULE_RX,
BLADERF_FORMAT_SC16_Q11_META,
num_buffers,
buffer_size_rx,
num_transfers,
timeout_ms);
if (status != 0) {
fprintf(stderr, "Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_sync_config(handler->dev,
BLADERF_MODULE_TX,
BLADERF_FORMAT_SC16_Q11_META,
num_buffers,
buffer_size_tx,
num_transfers,
timeout_ms);
if (status != 0) {
fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, true);
if (status != 0) {
fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, true);
if (status != 0) {
fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status));
return status;
}
handler->stream_enabled = true;
return 0;
}
int rf_blade_stop_rx_stream(void *h)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, false);
if (status != 0) {
fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, false);
if (status != 0) {
fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status));
return status;
}
handler->stream_enabled = false;
return 0;
}
void rf_blade_flush_buffer(void *h)
{
}
bool rf_blade_has_rssi(void *h) {
bool rf_blade_has_rssi(void *h)
{
return false;
}
float rf_blade_get_rssi(void *h) {
float rf_blade_get_rssi(void *h)
{
return 0;
}
double rf_blade_set_rx_gain_th(void *h, double gain)
{
return rf_blade_set_rx_gain(h, gain);
}
void rf_blade_set_tx_rx_gain_offset(void *h, double offset) {
}
/* This thread listens for set_rx_gain commands to the USRP */
static void* thread_gain_fcn(void *h) {
void rf_blade_set_tx_rx_gain_offset(void *h, double offset)
{
}
int rf_blade_open(char *args, void **h, bool create_thread_gain, bool tx_gain_same_rx)
{
*h = NULL;
rf_blade_handler_t *handler = (rf_blade_handler_t*) malloc(sizeof(rf_blade_handler_t));
if (!handler) {
perror("malloc");
return -1;
}
*h = handler;
printf("Opening bladeRF...\n");
int status = bladerf_open(&handler->dev, NULL);
if (status) {
fprintf(stderr, "Unable to open device: %s\n", bladerf_strerror(status));
return status;
}
//bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_VERBOSE);
/* Configure the gains of the RX LNA and RX VGA1*/
status = bladerf_set_lna_gain(handler->dev, BLADERF_LNA_GAIN_MAX);
if (status != 0) {
fprintf(stderr, "Failed to set RX LNA gain: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_set_rxvga1(handler->dev, 25);
if (status != 0) {
fprintf(stderr, "Failed to set RX VGA1 gain: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_set_txvga1(handler->dev, -10);
if (status != 0) {
fprintf(stderr, "Failed to set TX VGA1 gain: %s\n", bladerf_strerror(status));
return status;
}
handler->stream_enabled = false;
return 0;
}
int rf_blade_close(void *h)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
bladerf_close(handler->dev);
return 0;
}
void rf_blade_set_master_clock_rate(void *h, double rate) {
void rf_blade_set_master_clock_rate(void *h, double rate)
{
}
bool rf_blade_is_master_clock_dynamic(void *h) {
bool rf_blade_is_master_clock_dynamic(void *h)
{
return true;
}
double rf_blade_set_rx_srate(void *h, double freq)
{
uint32_t bw;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_set_sample_rate(handler->dev, BLADERF_MODULE_RX, (uint32_t) freq, &handler->rx_rate);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n", (uint32_t) freq, bladerf_strerror(status));
return -1;
}
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate, &bw);
if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status));
return -1;
}
return (double) handler->rx_rate;
}
double rf_blade_set_tx_srate(void *h, double freq)
{
uint32_t bw;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_set_sample_rate(handler->dev, BLADERF_MODULE_TX, (uint32_t) freq, &handler->tx_rate);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n", (uint32_t) freq, bladerf_strerror(status));
return -1;
}
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_TX, handler->tx_rate, &bw);
if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->tx_rate, bladerf_strerror(status));
return -1;
}
return (double) handler->tx_rate;
}
double rf_blade_set_rx_gain(void *h, double gain)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_set_rxvga2(handler->dev, (int) gain);
if (status != 0) {
fprintf(stderr, "Failed to set RX VGA2 gain: %s\n", bladerf_strerror(status));
return -1;
}
return rf_blade_get_rx_gain(h);
}
double rf_blade_set_tx_gain(void *h, double gain)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_set_txvga2(handler->dev, (int) gain);
if (status != 0) {
fprintf(stderr, "Failed to set TX VGA2 gain: %s\n", bladerf_strerror(status));
return -1;
}
return rf_blade_get_tx_gain(h);
}
double rf_blade_get_rx_gain(void *h)
{
int status;
int gain;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_get_rxvga2(handler->dev, &gain);
if (status != 0) {
fprintf(stderr, "Failed to get RX VGA2 gain: %s\n",
bladerf_strerror(status));
return -1;
}
return gain;
}
double rf_blade_get_tx_gain(void *h)
{
int status;
int gain;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_get_txvga2(handler->dev, &gain);
if (status != 0) {
fprintf(stderr, "Failed to get TX VGA2 gain: %s\n",
bladerf_strerror(status));
return -1;
}
return gain;
}
double rf_blade_set_rx_freq(void *h, double freq)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_set_frequency(handler->dev, BLADERF_MODULE_RX, (uint32_t) freq);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n",
(uint32_t) freq, bladerf_strerror(status));
return -1;
}
return freq;
}
double rf_blade_set_tx_freq(void *h, double freq)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_set_frequency(handler->dev, BLADERF_MODULE_TX, (uint32_t) freq);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n",
(uint32_t) freq, bladerf_strerror(status));
return -1;
}
/* Apply manual IQ correction for 2.5-2.6G */
if (freq > 2.5e9 && freq < 2.6e9) {
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_PHASE, 184);
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_GAIN, 20);
}
return freq;
}
static void timestamp_to_secs(uint32_t rate, uint64_t timestamp, time_t *secs, double *frac_secs) {
double totalsecs = (double) timestamp/rate;
time_t secs_i = (time_t) totalsecs;
if (secs) {
*secs = secs_i;
}
if (frac_secs) {
*frac_secs = totalsecs-secs_i;
}
}
static void secs_to_timestamps(uint32_t rate, time_t secs, double frac_secs, uint64_t *timestamp) {
double totalsecs = (double) secs + frac_secs;
if (timestamp) {
*timestamp = rate * totalsecs;
}
}
void rf_blade_get_time(void *h, time_t *secs, double *frac_secs)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
struct bladerf_metadata meta;
void rf_blade_get_time(void *h, time_t *secs, double *frac_secs) {
int status = bladerf_get_timestamp(handler->dev, BLADERF_MODULE_RX, &meta.timestamp);
if (status != 0) {
fprintf(stderr, "Failed to get current RX timestamp: %s\n",
bladerf_strerror(status));
}
timestamp_to_secs(handler->rx_rate, meta.timestamp, secs, frac_secs);
}
int rf_blade_recv_with_time(void *h,
@ -137,6 +362,35 @@ int rf_blade_recv_with_time(void *h,
time_t *secs,
double *frac_secs)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
struct bladerf_metadata meta;
int status;
memset(&meta, 0, sizeof(meta));
meta.flags = BLADERF_META_FLAG_RX_NOW;
if (2*nsamples > CONVERT_BUFFER_SIZE) {
fprintf(stderr, "RX failed: nsamples exceeds buffer size (%d>%d)\n", nsamples, CONVERT_BUFFER_SIZE);
return -1;
}
status = bladerf_sync_rx(handler->dev, handler->rx_buffer, nsamples, &meta, 0);
if (status) {
fprintf(stderr, "RX failed: %s\n\n", bladerf_strerror(status));
exit(-1);
return -1;
} else if (meta.status & BLADERF_META_STATUS_OVERRUN) {
fprintf(stderr, "Overrun detected in scheduled RX. "
"%u valid samples were read.\n\n", meta.actual_count);
}
timestamp_to_secs(handler->rx_rate, meta.timestamp, secs, frac_secs);
uint64_t rx_timestamp, rx_timestamp2, tx_timestamp;
bladerf_get_timestamp(handler->dev, BLADERF_MODULE_RX, &rx_timestamp);
bladerf_get_timestamp(handler->dev, BLADERF_MODULE_RX, &rx_timestamp2);
bladerf_get_timestamp(handler->dev, BLADERF_MODULE_TX, &tx_timestamp);
srslte_vec_convert_if(handler->rx_buffer, data, 2048, 2*nsamples);
return nsamples;
}
int rf_blade_send_timed(void *h,
@ -149,5 +403,40 @@ int rf_blade_send_timed(void *h,
bool is_start_of_burst,
bool is_end_of_burst)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
struct bladerf_metadata meta;
int status;
if (2*nsamples > CONVERT_BUFFER_SIZE) {
fprintf(stderr, "TX failed: nsamples exceeds buffer size (%d>%d)\n", nsamples, CONVERT_BUFFER_SIZE);
return -1;
}
srslte_vec_convert_fi(data, handler->tx_buffer, 2048, 2*nsamples);
memset(&meta, 0, sizeof(meta));
if (is_start_of_burst) {
if (has_time_spec) {
secs_to_timestamps(handler->tx_rate, secs, frac_secs, &meta.timestamp);
} else {
meta.flags |= BLADERF_META_FLAG_TX_NOW;
}
meta.flags |= BLADERF_META_FLAG_TX_BURST_START;
}
if (is_end_of_burst) {
meta.flags |= BLADERF_META_FLAG_TX_BURST_END;
}
uint64_t dev_timestamp;
status = bladerf_get_timestamp(handler->dev, BLADERF_MODULE_TX, &dev_timestamp);
if (status != 0) {
fprintf(stderr, "Failed to get current RX timestamp: %s\n",
bladerf_strerror(status));
}
status = bladerf_sync_tx(handler->dev, handler->tx_buffer, nsamples, &meta, 0);
if (status != 0) {
fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));
return status;
}
return nsamples;
}

@ -241,7 +241,7 @@ void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len) {
#ifndef HAVE_VOLK_CONVERT_IF_FUNCTION
int i;
for (i=0;i<len;i++) {
z[i] = ((float) x[i])*scale;
z[i] = ((float) x[i])/scale;
}
#else
volk_16i_s32f_convert_32f(z,x,scale,len);

@ -217,8 +217,8 @@ void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, uint32_t len)
__m128 ret1, ret2;
for(;number < eighthPoints; number++){
inputVal1 = _mm_load_ps(inputVectorPtr); inputVectorPtr += 4;
inputVal2 = _mm_load_ps(inputVectorPtr); inputVectorPtr += 4;
inputVal1 = _mm_loadu_ps(inputVectorPtr); inputVectorPtr += 4;
inputVal2 = _mm_loadu_ps(inputVectorPtr); inputVectorPtr += 4;
ret1 = _mm_mul_ps(inputVal1, vScalar);
ret2 = _mm_mul_ps(inputVal2, vScalar);
@ -228,7 +228,7 @@ void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, uint32_t len)
intInputVal1 = _mm_packs_epi32(intInputVal1, intInputVal2);
_mm_store_si128((__m128i*)outputVectorPtr, intInputVal1);
_mm_storeu_si128((__m128i*)outputVectorPtr, intInputVal1);
outputVectorPtr += 8;
}

Loading…
Cancel
Save