Merge branch 'master' into feature-21-TM7

Conflicts:
	openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
	openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
	openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
	openair1/SCHED/phy_procedures_lte_ue.c
	openair1/SIMULATION/LTE_PHY/dlsim.c
	openair1/SIMULATION/LTE_PHY/mbmssim.c
	targets/RT/USER/Makefile
This commit is contained in:
Xiwen JIANG
2015-10-05 11:27:50 +02:00
1895 changed files with 226357 additions and 505447 deletions
+285 -218
View File
@@ -37,24 +37,299 @@
#include <stdlib.h>
#include <inttypes.h>
#include "bladerf_lib.h"
#include "common_lib.h"
#include "log.h"
#define SAMPLE_LEN samples_per_frame*sizeof(int32_t)
int num_devices=0;
/*These items configure the underlying asynch stream used by the the sync interface.
*/
unsigned int num_buffers;
unsigned int buffer_size;
unsigned int num_transfers;
unsigned int timeout_ms;
int trx_brf_init(openair0_device *openair0) {
}
openair0_timestamp trx_get_timestamp(openair0_device *device) {
int status;
struct bladerf_metadata meta;
brf_state_t *brf = (brf_state_t*)device->priv;
if ((status=bladerf_get_timestamp(brf->dev, BLADERF_MODULE_TX, &meta.timestamp)) != 0) {
fprintf(stderr,"Failed to get current RX timestamp: %s\n",bladerf_strerror(status));
} else {
printf("Current TX timestampe 0x%016"PRIx64"\n", meta.timestamp);
}
return meta.timestamp;
}
int trx_brf_start(openair0_device *openair0) {
return 0;
}
static void trx_brf_stats(openair0_device *device){
}
static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) {
int status, i;
brf_state_t *brf = (brf_state_t*)device->priv;
/* BRF has only 1 rx/tx chaine : is it correct? */
void *samples = (void*)buff[0];
//brf->meta_tx.flags &= ~BLADERF_META_FLAG_TX_NOW;
brf->meta_tx.flags = BLADERF_META_FLAG_TX_BURST_START |
BLADERF_META_FLAG_TX_NOW |
BLADERF_META_FLAG_TX_BURST_END;
brf->meta_tx.timestamp= (uint64_t) ptimestamp;
status = bladerf_sync_tx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_tx, 2*brf->tx_timeout_ms);
if (status != 0) {
fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status));
brf->num_tx_errors++;
brf_error(status);
} else if (brf->meta_tx.status & BLADERF_META_STATUS_UNDERRUN){
/* libbladeRF does not report this status. It is here for future use. */
fprintf(stderr, "TX Underrun detected. %u valid samples were read.\n", brf->meta_tx.actual_count);
brf->num_underflows++;
}
// printf("tx status %d \n",brf->meta_tx.status);
brf->tx_current_ts=brf->meta_tx.timestamp;
brf->tx_actual_nsamps+=brf->meta_tx.actual_count;
brf->tx_nsamps+=nsamps;
brf->tx_count++;
return(0);
}
static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
int status, ret;
unsigned int i;
brf_state_t *brf = (brf_state_t*)device->priv;
// BRF has only one rx/tx chain
void *samples = (void*)buff[0];
brf->meta_rx.flags |= BLADERF_META_FLAG_RX_NOW;
status = bladerf_sync_rx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_rx, 2*brf->rx_timeout_ms);
if (status != 0) {
fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status));
brf->num_rx_errors++;
} else if ( brf->meta_rx.status & BLADERF_META_STATUS_OVERRUN) {
brf->num_overflows++;
fprintf(stderr, "RX overrun (%d) is detected. t=0x%"PRIu64". Got %u samples. nsymps %d\n",
brf->num_overflows,brf->meta_rx.timestamp, brf->meta_rx.actual_count, nsamps);
//brf->meta_rx.timestamp=(unsigned int)(nsamps-brf->meta_rx.actual_count);
}
//printf("[BRF] (buff %p) ts=0x%"PRIu64" %s\n",samples, brf->meta_rx.timestamp,bladerf_strerror(status));
brf->rx_current_ts=brf->meta_rx.timestamp;
brf->rx_actual_nsamps+=brf->meta_rx.actual_count;
brf->rx_nsamps+=nsamps;
brf->rx_count++;
*ptimestamp = brf->meta_rx.timestamp;
return brf->meta_rx.actual_count;
}
int trx_brf_end(openair0_device *device) {
int status;
brf_state_t *brf = (brf_state_t*)device->priv;
// Disable RX module, shutting down our underlying RX stream
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false)) != 0) {
fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status));
}
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false)) != 0) {
fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status));
}
bladerf_close(brf->dev);
return 0;
}
int trx_brf_get_stats(openair0_device* device) {
return(0);
}
int trx_brf_reset_stats(openair0_device* device) {
return(0);
}
int trx_brf_stop(openair0_device* device) {
return(0);
}
int trx_brf_set_freq(openair0_device* device) {
return(0);
}
int trx_brf_set_gains(openair0_device* device) {
return(0);
}
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
int status;
int card=0;
brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t));
memset(brf, 0, sizeof(brf_state_t));
// init required params for BRF
brf->num_buffers = 128;
brf->buffer_size = (unsigned int) openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024
brf->num_transfers = 16;
brf->rx_timeout_ms = 0;
brf->tx_timeout_ms = 0;
brf->sample_rate=(unsigned int)openair0_cfg[card].sample_rate;
printf("\n[BRF] sampling_rate %d, num_buffers %d, buffer_size %d, num transfer %d, timeout_ms (rx %d, tx %d)\n",
brf->sample_rate, brf->num_buffers, brf->buffer_size,brf->num_transfers, brf->rx_timeout_ms, brf->tx_timeout_ms);
if ((status=bladerf_open(&brf->dev, "")) != 0 ) {
fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status));
brf_error(status);
}
printf("[BRF] init dev %p\n", brf->dev);
switch(bladerf_device_speed(brf->dev)){
case BLADERF_DEVICE_SPEED_SUPER:
printf("[BRF] Device operates at max speed\n");
break;
default:
printf("[BRF] Device does not operates at max speed, change the USB port\n");
brf_error(BLADERF_ERR_UNSUPPORTED);
}
// RX
// Example of CLI output: RX Frequency: 2539999999Hz
if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_freq[0])) != 0){
fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
brf_error(status);
} else
printf("[BRF] set RX frequency to %f\n",openair0_cfg[card].rx_freq[0]);
if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_RX, (unsigned int)openair0_cfg[card].sample_rate, NULL)) != 0){
fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] set RX sample rate to %f\n",openair0_cfg[card].sample_rate);
if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw, NULL)) != 0){
fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] set RX bandwidth to %f\n",openair0_cfg[card].rx_bw);
if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg[card].rx_gain[0])) != 0) {
fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status));
brf_error(status);
} else
printf("[BRF] set RX gain to %f\n",openair0_cfg[card].rx_gain[0]);
/* Configure the device's RX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */
if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->rx_timeout_ms)) != 0 ) {
fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] configured Rx for sync interface \n");
/* We must always enable the RX module after calling bladerf_sync_config(), and
* before attempting to RX samples via bladerf_sync_rx(). */
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) {
fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] RX module enabled \n");
// TX
if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].tx_freq[0])) != 0){
fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] set Tx Frequenct to %f \n", openair0_cfg[card].tx_freq[0]);
if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].sample_rate, NULL)) != 0){
fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] set Tx sampling rate to %f \n", openair0_cfg[card].sample_rate);
if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg[card].tx_bw, NULL)) != 0){
fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] set Tx sampling ratebandwidth to %f \n", openair0_cfg[card].tx_bw);
if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int)openair0_cfg[card].tx_gain[0])) != 0) {
fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] set the Tx gain to %f \n", openair0_cfg[card].tx_gain[0]);
/* Configure the device's TX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */
if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_TX,BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->tx_timeout_ms)) != 0 ) {
fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
brf_error(status);
}else
printf("[BRF] configured tx for sync interface \n");
/* We must always enable the TX module after calling bladerf_sync_config(), and
* before attempting to TX samples via bladerf_sync_tx(). */
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) {
fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
brf_error(status);
} else
printf("[BRF] TX module enabled \n");
bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level));
printf("BLADERF: Initializing openair0_device\n");
device->priv = brf;
device->Mod_id = num_devices++;
device->trx_start_func = trx_brf_start;
device->trx_end_func = trx_brf_end;
device->trx_read_func = trx_brf_read;
device->trx_write_func = trx_brf_write;
device->trx_get_stats_func = trx_brf_get_stats;
device->trx_reset_stats_func = trx_brf_reset_stats;
device->trx_stop_func = trx_brf_stop;
device->trx_set_freq_func = trx_brf_set_freq;
device->trx_set_gains_func = trx_brf_set_gains;
memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
return 0;
}
int brf_error(int status) {
//exit(-1);
//return 1; // or status error code
}
struct bladerf * open_bladerf_from_serial(const char *serial) {
int status;
@@ -81,218 +356,10 @@ struct bladerf * open_bladerf_from_serial(const char *serial) {
return dev;
}
}
int trx_brf_start(openair0_device *openair0) {
}
int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) {
int status;
struct bladerf_metadata meta;
int16_t zeros[] = { 0, 0, 0, 0 };
struct bladerf *dev = (struct bladerf*) device->priv;
openair0_timestamp current_timestamp;
/* BRF has only 1 rx/tx chaine : is it correct? */
void *sample = (void*)buff[0];
memset(&meta, 0, sizeof(meta));
/* Retrieve the current timestamp */
#ifdef BRF_TEST
if ((status=bladerf_get_timestamp(dev, BLADERF_MODULE_TX, &meta.timestamp)) != 0) {
fprintf(stderr,"Failed to get current RX timestamp: %s\n",bladerf_strerror(status));
} else {
current_timestamp = meta.timestamp;
printf("Current TX timestampe 0x%016"PRIx64" and current timestamp: 0x%016"PRIx64"\n", ptimestamp, meta.timestamp);
}
#endif
meta.timestamp= ptimestamp;
meta.flags |= BLADERF_META_FLAG_TX_NOW;
status = bladerf_sync_tx(dev, sample, nsamps, &meta, timeout_ms);
if (status != 0) {
fprintf(stderr, "Failed to TX sample: %s\n", bladerf_strerror(status));
brf_error(status);
}
}
int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
int status, ret;
struct bladerf_metadata meta;
unsigned int i;
struct bladerf *dev = (struct bladerf*) device->priv;
/* BRF has only onerx/tx chain: is it correct? */
void *sample = (void*)buff[0];
memset(&meta, 0, sizeof(meta));
/* Retrieve the current timestamp */
if ((status=bladerf_get_timestamp(dev, BLADERF_MODULE_RX, &meta.timestamp)) != 0) {
fprintf(stderr,"Failed to get current RX timestamp: %s\n",bladerf_strerror(status));
} else {
*ptimestamp = meta.timestamp;
printf("Current RX timestamp: 0x%016"PRIx64"\n", meta.timestamp);
}
meta.flags |= BLADERF_META_FLAG_RX_NOW;
//fflush(stdout);
status = bladerf_sync_rx(dev, sample, nsamps, &meta, timeout_ms);
/* if (meta.actual_count < nsamps ) {
printf("[BRF][RX] received %d samples out of %d\n", meta.actual_count, nsamps);
}
*/
if (status != 0) {
fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status));
} else if (meta.status & BLADERF_META_STATUS_OVERRUN) {
fprintf(stderr, "Overrun detected in RX. %u valid samples were read (nsymps %d)\n", meta.actual_count,nsamps);
} else if (meta.status & BLADERF_META_STATUS_UNDERRUN) {
fprintf(stderr, "Underrun detected in RX. %u valid samples were read (nsymps %d) \n", meta.actual_count,nsamps);
}else {
printf("Got %u samples at t=0x%016"PRIx64"\n", meta.actual_count, meta.timestamp);
}
return meta.actual_count;
}
int trx_brf_end(openair0_device *device) {
int status;
struct bladerf *dev = (struct bladerf*) device->priv;
// Disable RX module, shutting down our underlying RX stream
if ((status=bladerf_enable_module(device->priv, BLADERF_MODULE_RX, false)) != 0) {
fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status));
}
if ((status=bladerf_enable_module(device->priv, BLADERF_MODULE_TX, false)) != 0) {
fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status));
}
bladerf_close(dev);
return 0;
}
//int openair0_device_brf_init(openair0_device *device, openair0_config_t *openair0_cfg) {
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
int status;
int card=0;
//struct bladerf_version *version;
//printf("Opening the brf device (version %s)...\n", bladerf_version(version));
// opaque data struct
struct bladerf *dev;// = (struct bladerf*)malloc(sizeof(struct bladerf));
//memset(dev, 0, sizeof(struct bladerf));
// An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend)
// init required params for BRF
num_buffers = 16;
buffer_size = openair0_cfg[card]. samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024
num_transfers = 8; // ? device->openair0_cfg.samples_per_packets
timeout_ms = 1; // or 0/
printf("the buffer_size is set to %d\n", buffer_size);
if ((status=bladerf_open(&dev, "")) != 0 ) {
fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status));
brf_error(status);
}
printf("[BRF] device speed is %d\n",bladerf_device_speed(dev) );
// RX
// Example of CLI output: RX Frequency: 2539999999Hz
if ((status=bladerf_set_frequency(dev, BLADERF_MODULE_RX, openair0_cfg[card].rx_freq[0])) != 0){
fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
brf_error(status);
}
// RX sample rate: 7680000 0/1
if ((status=bladerf_set_sample_rate(dev, BLADERF_MODULE_RX, openair0_cfg[card].sample_rate, NULL)) != 0){
fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status));
brf_error(status);
}
// RX Bandwidth: 14000000Hz
if ((status=bladerf_set_bandwidth(dev, BLADERF_MODULE_RX, openair0_cfg[card].rx_bw, NULL)) != 0){
fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
brf_error(status);
}
// desired gain = 16
if ((status=bladerf_set_gain(dev, BLADERF_MODULE_RX, openair0_cfg[card].rx_gain[0])) != 0) {
fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status));
brf_error(status);
}
/* Configure the device's RX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */
if ((status=bladerf_sync_config(dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,num_buffers,buffer_size,num_transfers,timeout_ms)) != 0 ) {
fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
brf_error(status);
}
/* We must always enable the RX module after calling bladerf_sync_config(), and
* before attempting to RX samples via bladerf_sync_rx(). */
if ((status=bladerf_enable_module(dev, BLADERF_MODULE_RX, true)) != 0) {
fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
brf_error(status);
}
// TX
if ((status=bladerf_set_frequency(dev, BLADERF_MODULE_TX, openair0_cfg[card].tx_freq[0])) != 0){
fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status));
brf_error(status);
}
if ((status=bladerf_set_sample_rate(dev, BLADERF_MODULE_TX, openair0_cfg[card].sample_rate, NULL)) != 0){
fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status));
brf_error(status);
}
if ((status=bladerf_set_bandwidth(dev, BLADERF_MODULE_TX,openair0_cfg[card].tx_bw, NULL)) != 0){
fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
brf_error(status);
}
if ((status=bladerf_set_gain(dev, BLADERF_MODULE_TX, openair0_cfg[card].tx_gain[0])) != 0) {
fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status));
brf_error(status);
}
/* Configure the device's TX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */
if ((status=bladerf_sync_config(dev, BLADERF_MODULE_TX,BLADERF_FORMAT_SC16_Q11_META,num_buffers,buffer_size,num_transfers,timeout_ms)) != 0 ) {
fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
brf_error(status);
}
/* We must always enable the TX module after calling bladerf_sync_config(), and
* before attempting to TX samples via bladerf_sync_tx(). */
if ((status=bladerf_enable_module(dev, BLADERF_MODULE_TX, true)) != 0) {
fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
brf_error(status);
}
bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level));
printf("BLADERF: Initializing openair0_device\n");
device->priv = dev;
device->Mod_id = num_devices++;
device->trx_start_func = trx_brf_start;
device->trx_end_func = trx_brf_end;
device->trx_read_func = trx_brf_read;
device->trx_write_func = trx_brf_write;
memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
}
void brf_error(int status) {
exit(-1);
}
int get_brf_log_level(int log_level){
int level=BLADERF_LOG_LEVEL_INFO;
//return BLADERF_LOG_LEVEL_DEBUG;
switch(log_level) {
case LOG_DEBUG:
level=BLADERF_LOG_LEVEL_DEBUG;
@@ -33,46 +33,54 @@
*/
#include <libbladeRF.h>
/*
enum brf_err_num{
BLADERF_ERR_MIN=0,
BLADERF_ERR_UNEXPECTED=-1,
BLADERF_ERR_RANGE=-2,
BLADERF_ERR_INVAL=-3,
BLADERF_ERR_MEM=-4,
BLADERF_ERR_IO=-5,
BLADERF_ERR_TIMEOUT=-6,
BLADERF_ERR_NODEV=-7,
BLADERF_ERR_UNSUPPORTED=-8,
BLADERF_ERR_MISALIGNED=-9,
BLADERF_ERR_CHECKSUM=-10,
BLADERF_ERR_NO_FILE=-11,
BLADERF_ERR_UPDATE_FPGA=-12,
BLADERF_ERR_UPDATE_FW=-13,
BLADERF_ERR_TIME_PAST=-14,
BLADERF_ERR_MAX=-15,
}
mapping brf_err_names[] = {
{"BLADERF_OK", BLADERF_ERR_MIN},
{"BLADERF_ERR_UNEXPECTED",BLADERF_ERR_UNEXPECTED},
{"BLADERF_ERR_RANGE",BLADERF_ERR_RANGE},
{"BLADERF_ERR_INVAL",BLADERF_ERR_INVAL},
{"BLADERF_ERR_MEM",BLADERF_ERR_MEM},
{"BLADERF_ERR_IO",BLADERF_ERR_IO},
{"BLADERF_ERR_TIMEOUT",BLADERF_ERR_TIMEOUT},
{"BLADERF_ERR_NODEV",BLADERF_ERR_NODEV},
{"BLADERF_ERR_UNSUPPORTED",BLADERF_ERR_UNSUPPORTED},
{"BLADERF_ERR_MISALIGNED",BLADERF_ERR_MISALIGNED},
{"BLADERF_ERR_CHECKSUM",BLADERF_ERR_CHECKSUM},
{"BLADERF_ERR_NO_FILE",BLADERF_ERR_NO_FILE},
{"BLADERF_ERR_UPDATE_FPGA",BLADERF_ERR_UPDATE_FPGA},
{"BLADERF_ERR_UPDATE_FW",BLADERF_ERR_UPDATE_FW},
{"BLADERF_ERR_TIME_PAST",BLADERF_ERR_TIME_PAST},
{NULL, BLADERF_ERR_MAX}
};
*/
#include "common_lib.h"
#include "log.h"
typedef struct {
// opaque BRF data struct
struct bladerf *dev;
// An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend)
unsigned int num_buffers;
unsigned int buffer_size;
unsigned int num_transfers;
unsigned int rx_timeout_ms;
unsigned int tx_timeout_ms;
struct bladerf_metadata meta_rx;
struct bladerf_metadata meta_tx;
unsigned int sample_rate;
// time offset between transmiter timestamp and receiver timestamp;
double tdiff;
// use brf_time_offset to get this value
int tx_forward_nsamps; //166 for 20Mhz
// --------------------------------
// Debug and output control
// --------------------------------
int num_underflows;
int num_overflows;
int num_seq_errors;
int num_rx_errors;
int num_tx_errors;
uint64_t tx_current_ts;
uint64_t rx_current_ts;
uint64_t tx_actual_nsamps;
uint64_t rx_actual_nsamps;
uint64_t tx_nsamps;
uint64_t rx_nsamps;
uint64_t tx_count;
uint64_t rx_count;
openair0_timestamp rx_timestamp;
} brf_state_t;
/*
* func prototypes
*/
void brf_error(int status);
int brf_error(int status);
+64
View File
@@ -0,0 +1,64 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file common_lib.c
* \brief common APIs for different RF frontend device
* \author HongliangXU, Navid Nikaein
* \date 2015
* \version 0.2
* \company Eurecom
* \maintainer: navid.nikaein@eurecom.fr
* \note
* \warning
*/
#include <stdio.h>
#include "common_lib.h"
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
#ifdef ETHERNET
device->type=ETH_IF;
device->func_type = BBU_FUNC;
openair0_dev_init_eth(device, openair0_cfg);
printf(" openair0_dev_init_eth ...\n");
#elif EXMIMO
device->type=EXMIMO_IF;
openair0_dev_init_exmimo(device, openair0_cfg);
printf("openair0_dev_init_exmimo...\n");
#elif OAI_USRP
device->type=USRP_IF;
openair0_dev_init_usrp(device, openair0_cfg);
printf("openair0_dev_init_usrp ...\n");
#elif OAI_BLADERF
device->type=BLADERF_IF;
openair0_dev_init_bladerf(device, openair0_cfg);
printf(" openair0_dev_init_bladerf ...\n");
#endif
}
+163 -25
View File
@@ -26,40 +26,68 @@
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file common_lib.h
* \brief common APIs for different RF frontend device
* \author HongliangXU, Navid Nikaein
* \date 2015
* \version 0.2
* \company Eurecom
* \maintainer: navid.nikaein@eurecom.fr
* \note
* \warning
*/
/** common_lib.h
*
* Author: HongliangXU : hong-liang-xu@agilent.com
*/
#ifndef COMMON_LIB_H
#define COMMON_LIB_H
#include <stdint.h>
#include <sys/types.h>
typedef int64_t openair0_timestamp;
typedef volatile int64_t openair0_vtimestamp;
/* structrue holds the parameters to configure USRP devices*/
typedef struct openair0_device_t openair0_device;
/* structrue holds the parameters to configure USRP devices
*/
#ifndef EXMIMO
#define MAX_CARDS 1
#endif
#define USRP_GAIN_OFFSET (86.0) // 86 calibrated for USRP B210 @ 2.6 GHz to get equivalent RS EPRE in OAI to SMBV100 output
//#define USRP_GAIN_OFFSET (56.0) // 86 calibrated for USRP B210 @ 2.6 GHz to get equivalent RS EPRE in OAI to SMBV100 output
typedef enum {
max_gain=0,med_gain,byp_gain
} rx_gain_t;
/** @addtogroup _PHY_RF_INTERFACE_
* @{
*/
typedef struct {
//! Frequency for which RX chain was calibrated
double freq;
//! Offset to be applied to RX gain
double offset;
} rx_gain_calib_table_t;
typedef struct {
//! Module ID for this configuration
int Mod_id;
// device log level
int log_level;
//! number of downlink resource blocks
int num_rb_dl;
//! number of samples per frame
unsigned int samples_per_frame;
//! the sample rate for both transmit and receive.
double sample_rate;
//! number of samples per RX/TX packet (USRP + Ethernet)
int samples_per_packet;
// delay in sending samples (write) due to hardware access, softmodem processing and fronthaul delay if exist
int tx_delay;
//! adjust the position of the samples after delay when sending
unsigned int tx_forward_nsamps;
//! number of RX channels (=RX antennas)
int rx_num_channels;
//! number of TX channels (=TX antennas)
@@ -70,21 +98,31 @@ typedef struct {
//! \brief Center frequency in Hz for TX.
//! index: [0..rx_num_channels[ !!! see lte-ue.c:427 FIXME iterates over rx_num_channels
double tx_freq[4];
//! mode for rxgain (ExpressMIMO2)
//! mode for rxgain (ExpressMIMO2)
rx_gain_t rxg_mode[4];
//! \brief Gain for RX in dB.
//! index: [0..rx_num_channels]
double rx_gain[4];
//! \brief Gain offset (for calibration) in dB
//! index: [0..rx_num_channels]
double rx_gain_offset[4];
//! gain for TX in dB
double tx_gain[4];
//! RX bandwidth in Hz
double rx_bw;
//! TX bandwidth in Hz
double tx_bw;
//! Auto calibration flag
int autocal[4];
//! RRH IP addr for Ethernet interface
char *rrh_ip;
char *remote_ip;
//! RRH port number for Ethernet interface
int rrh_port;
int remote_port;
//! my IP addr for Ethernet interface (eNB/BBU, UE)
char *my_ip;
//! my port number for Ethernet interface (eNB/BBU, UE)
int my_port;
} openair0_config_t;
typedef struct {
@@ -96,9 +134,50 @@ typedef struct {
/*!\brief interface types that apply to modules (RRH_BBU/RRH_UE) created in RRH (rrh_gw.c)
and are defined with respect to the RF device that is present in RRH
-RRH_BBU modules have two devices, one is by default ETHERNET (will have ETH_IF) and the other one is a
RF device (EXMIMO,USRP,BLADERF) or no device (NONE_IF).
-RRH_UE modules have two devices one is by default ETHERNET (will have ETH_IF)
and the other one by default not present so it will have NONE_IF
*/
typedef enum {
MIN_DEV_TYPE = 0,
/*!\brief device is ETH */
ETH_IF,
/*!\brief device is ExpressMIMO */
EXMIMO_IF,
/*!\brief device is USRP*/
USRP_IF,
/*!\brief device is BLADE RF*/
BLADERF_IF,
/*!\brief device is NONE*/
NONE_IF,
MAX_DEV_TYPE
} dev_type_t;
/*!\brief openair0 device host type */
typedef enum {
MIN_FUNC_TYPE = 0,
/*!\brief device functions within a BBU */
BBU_FUNC,
/*!\brief device functions within a RRH */
RRH_FUNC,
MAX_FUNC_TYPE
}func_type_t;
struct openair0_device_t {
/* Module ID of this device */
int Mod_id;
/* Type of this device */
dev_type_t type;
/* Type of the device's host (BBU/RRH) */
func_type_t func_type;
/* RF frontend parameters set by application */
openair0_config_t openair0_cfg;
@@ -108,14 +187,34 @@ struct openair0_device_t {
/* Functions API, which are called by the application*/
/* Called to start the transceiver. Return 0 if OK, < 0 if error */
/*! \brief Called to start the transceiver. Return 0 if OK, < 0 if error
@param device pointer to the device structure specific to the RF hardware target
*/
int (*trx_start_func)(openair0_device *device);
/* Write 'nsamps' samples on each channel from buffers. buff[0] is the array for
* the first channel. timestamp if the time (in samples) at which the first sample
* MUST be sent
* use flags = 1 to send as timestamp specfied*/
void (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags);
/*! \brief Called to send a request message between BBU-RRH
@param device pointer to the device structure specific to the RF hardware target
@param msg pointer to the message structure passed between BBU-RRH
@param msg_len length of the message
*/
int (*trx_request_func)(openair0_device *device, void *msg, ssize_t msg_len);
/*! \brief Called to send a reply message between BBU-RRH
@param device pointer to the device structure specific to the RF hardware target
@param msg pointer to the message structure passed between BBU-RRH
@param msg_len length of the message
*/
int (*trx_reply_func)(openair0_device *openair0, void *msg, ssize_t msg_len);
/*! \brief Called to send samples to the RF target
@param device pointer to the device structure specific to the RF hardware target
@param timestamp The timestamp at whicch the first sample MUST be sent
@param buff Buffer which holds the samples
@param nsamps number of samples to be sent
@param antenna_id index of the antenna if the device has multiple anteannas
@param flags flags must be set to TRUE if timestamp parameter needs to be applied
*/
int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags);
/*! \brief Receive samples from hardware.
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
@@ -128,10 +227,40 @@ struct openair0_device_t {
* \param cc Number of channels. If cc == 1, only buff[0] is filled with samples.
* \returns the number of sample read
*/
int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int cc);
int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id);
/* Terminate operation of the transceiver -- free all associated resources */
/*! \brief print the device statistics
* \param device the hardware to use
* \returns 0 on success
*/
int (*trx_get_stats_func)(openair0_device *device);
/*! \brief Reset device statistics
* \param device the hardware to use
* \returns 0 in success
*/
int (*trx_reset_stats_func)(openair0_device *device);
/*! \brief Terminate operation of the transceiver -- free all associated resources */
void (*trx_end_func)(openair0_device *device);
/* Terminate operation */
int (*trx_stop_func)(int card);
/* Functions API related to UE*/
/*! \brief Set RX feaquencies
* \param
* \returns 0 in success
*/
int (*trx_set_freq_func)(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config);
/*! \brief Set gains
* \param
* \returns 0 in success
*/
int (*trx_set_gains_func)(openair0_device* device, openair0_config_t *openair0_cfg);
};
@@ -140,13 +269,22 @@ extern "C"
{
#endif
/* return 0 if OK, < 0 if error */
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
openair0_timestamp get_usrp_time(openair0_device *device);
int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
int openair0_set_gains(openair0_device* device, openair0_config_t *openair0_cfg);
/*! \brief Initialize Openair RF target. It returns 0 if OK */
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
//USRP
/*! \brief Get the current timestamp of USRP */
openair0_timestamp get_usrp_time(openair0_device *device);
/*! \brief Set the RX frequency of USRP RF TARGET */
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
//extern
/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg);
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg);
int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg);
int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg);
/*@}*/
#ifdef __cplusplus
}
+479 -177
View File
@@ -26,16 +26,16 @@
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/** ethernet_lib : API to stream I/Q samples over standard ethernet
*
* Authors: Pedro Dinis <pedrodinis20@gmail.com>
* Lucio Ferreira <lucio.ferreira@inov.pt>
* Raymond Knopp <raymond.knopp@eurecom.fr>
*
* Changelog:
* 06.10.2014: Initial version
*/
/*! \file ethernet_lib.c
* \brief API to stream I/Q samples over standard ethernet
* \author Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp
* \date 2015
* \version 0.2
* \company Eurecom
* \maintainer: navid.nikaein@eurecom.fr
* \note
* \warning
*/
#include <arpa/inet.h>
#include <linux/if_packet.h>
@@ -50,198 +50,500 @@
#include <errno.h>
#include "common_lib.h"
#include "ethernet_lib.h"
#define DEFAULT_IF "eth0"
#define BUF_SIZ 8960 /*Jumbo frame size*/
#define MAX_INST 4
//#define DEBUG 1
int sockfd[MAX_INST];
struct sockaddr_in dest_addr[MAX_INST];
int num_devices_eth = 0;
int dest_addr_len[MAX_INST];
int i;
int tx_len = 0;
char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/
/**PDF: Initialization of UDP Socket to communicate with one DEST */
int ethernet_socket_init(int Mod_id, char *dest_ip,int dest_port)
{
/*! \fn static int eth_socket_init(openair0_device *device)
* \brief initialization of UDP Socket to communicate with one destination
* \param[in] *device openair device for which the socket will be created
* \param[out]
* \return 0 on success, otherwise -1
* \note
* @ingroup _oai
*/
static int eth_socket_init(openair0_device *device);
/**PDF: To be passed by input argument*/
// DEST_port = 32000;
struct sockaddr_in *dest = &dest_addr[Mod_id];
/*! \fn static int eth_set_dev_conf(openair0_device *device)
* \brief
* \param[in] *device openair device
* \param[out]
* \return 0 on success, otherwise -1
* \note
* @ingroup _oai
*/
static int eth_set_dev_conf(openair0_device *device);
/*! \fn static int eth_get_dev_conf(openair0_device *device)
* \brief
* \param[in] *device openair device
* \param[out]
* \return 0 on success, otherwise -1
* \note
* @ingroup _oai
*/
static int eth_get_dev_conf(openair0_device *device);
int trx_eth_start(openair0_device *device) {
/* initialize socket */
if (eth_socket_init(device)!=0) {
return -1;
}
/* RRH gets openair0 device configuration BBU sets openair0 device configuration*/
if (device->func_type == BBU_FUNC) {
return eth_set_dev_conf(device);
} else {
return eth_get_dev_conf(device);
}
return 0;
}
int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
int n_written=0,i;
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
int sendto_flag =0;
sendto_flag|=MSG_DONTWAIT;
for (i=0;i<cc;i++) {
/* buff[i] points to the position in tx buffer where the payload to be sent is
buff2 points to the position in tx buffer where the packet header will be placed */
void *buff2 = (void*)(buff[i]-header_size);
/* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/
int32_t temp0 = *(int32_t *)buff2;
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
n_written = 0;
*(int16_t *)(buff2 + sizeof(int16_t))=1+(i<<1);
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp;
/* printf("[RRH]write mod_%d %d , len %d, buff %p antenna %d\n",
Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
while(n_written < nsamps) {
/* Send packet */
if ((n_written += sendto(eth->sockfd[Mod_id],
buff2,
(nsamps<<2)+header_size,
0,
(struct sockaddr*)&eth->dest_addr[Mod_id],
dest_addr_len[Mod_id])) < 0) {
perror("ETHERNET WRITE");
exit(-1);
}
}
#if DEBUG
printf("Buffer head TX: nu=%d an_id=%d ts%d samples_send=%d i=%d data=%x\n",
*(int16_t *)buff2,
*(int16_t *)(buff2 + sizeof(int16_t)),
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
n_written>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
#endif
/* tx buffer values restored */
*(int32_t *)buff2 = temp0;
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
}
return n_written;
}
int trx_eth_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
int bytes_received=0;
int block_cnt=0;
int ret=0,i;
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
for (i=0;i<cc;i++) {
/* buff[i] points to the position in rx buffer where the payload to be received will be placed
buff2 points to the position in rx buffer where the packet header will be placed */
void *buff2 = (void*)(buff[i]-header_size);
/* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/
int32_t temp0 = *(int32_t *)buff2;
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
bytes_received=0;
block_cnt=0;
ret=0;
/* printf("[RRH] read mod_%d %d,len %d, buff %p antenna %d\n",
Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
while(bytes_received < (int)((nsamps<<2))) {
ret=recvfrom(eth->sockfd[Mod_id],
buff2+bytes_received,
(nsamps<<2)+header_size-bytes_received,
0,//MSG_DONTWAIT,
(struct sockaddr *)&eth->dest_addr[Mod_id],
(socklen_t *)&dest_addr_len[Mod_id]);
if (ret==-1) {
if (errno == EAGAIN) {
perror("ETHERNET READ: ");
return((nsamps<<2) + header_size);
} else if (errno == EWOULDBLOCK) {
block_cnt++;
usleep(10);
if (block_cnt == 100) return(-1);
}
} else {
bytes_received+=ret;
}
}
#if DEBUG
printf("Buffer head RX: nu=%d an_id=%d ts%d samples_recv=%d i=%d data=%x\n",
*(int16_t *)buff2,
*(int16_t *)(buff2 + sizeof(int16_t)),
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
ret>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
#endif
/* store the timestamp value from packet's header */
*timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
/* tx buffer values restored */
*(int32_t *)buff2 = temp0;
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
}
return nsamps;
}
void trx_eth_end(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
/*destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
if ( close(eth->sockfd[Mod_id]) <0 ) {
perror("ETHERNET: Failed to close socket");
exit(0);
} else {
printf("[RRH] socket for mod_id %d has been successfully closed.\n",Mod_id);
}
}
int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) {
int Mod_id = device->Mod_id;
eth_state_t *eth = (eth_state_t*)device->priv;
/* BBU sends a message to RRH */
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&eth->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
perror("ETHERNET: ");
exit(0);
}
return 0;
}
int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
/* RRH receives from BBU a message */
if (recvfrom(eth->sockfd[Mod_id],
msg,
msg_len,
0,
(struct sockaddr *)&eth->dest_addr[Mod_id],
(socklen_t *)&dest_addr_len[Mod_id])==-1) {
perror("ETHERNET: ");
exit(0);
}
return 0;
}
static int eth_set_dev_conf(openair0_device *device) {
int Mod_id = device->Mod_id;
eth_state_t *eth = (eth_state_t*)device->priv;
void *msg;
ssize_t msg_len;
/* a BBU client sents to RRH a set of configuration parameters (openair0_config_t)
so that RF front end is configured appropriately and
frame/packet size etc. can be set */
msg=malloc(sizeof(openair0_config_t));
msg_len=sizeof(openair0_config_t);
memcpy(msg,(void*)&device->openair0_cfg,msg_len);
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&eth->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
perror("ETHERNET: ");
exit(0);
}
return 0;
}
static int eth_get_dev_conf(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
char str[INET_ADDRSTRLEN];
void *msg;
ssize_t msg_len;
msg=malloc(sizeof(openair0_config_t));
msg_len=sizeof(openair0_config_t);
/* RRH receives from BBU openair0_config_t */
if (recvfrom(eth->sockfd[Mod_id],
msg,
msg_len,
0,
(struct sockaddr *)&eth->dest_addr[Mod_id],
(socklen_t *)&dest_addr_len[Mod_id])==-1) {
perror("ETHERNET: ");
exit(0);
}
memcpy((void*)&device->openair0_cfg,msg,msg_len);
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port);
device->openair0_cfg.remote_ip=str;
/*apply additional configuration*/
//ethernet_tune (device, RING_PAR);
// printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port));
return 0;
}
int trx_eth_stop(int card) {
return(0);
}
int trx_eth_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
return(0);
}
int trx_eth_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
return(0);
}
int trx_eth_get_stats(openair0_device* device) {
return(0);
}
int trx_eth_reset_stats(openair0_device* device) {
return(0);
}
static int eth_socket_init(openair0_device *device) {
int i = 0;
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
char str[INET_ADDRSTRLEN];
const char *dest_ip;
int dest_port=0;
if (device->func_type == RRH_FUNC ) {
dest_ip = device->openair0_cfg.my_ip;
dest_port = device->openair0_cfg.my_port;
printf("[RRH] ip addr %s port %d\n",dest_ip, dest_port);
} else {
dest_ip = device->openair0_cfg.remote_ip;
dest_port = device->openair0_cfg.remote_port;
printf("[BBU] ip addr %s port %d\n",dest_ip, dest_port);
}
/* Open RAW socket to send on */
if ((sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
if ((eth->sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
perror("ETHERNET: Error opening socket");
exit(0);
}
bzero((void *)dest,sizeof(struct sockaddr));
dest->sin_family = AF_INET;
dest->sin_addr.s_addr=inet_addr(dest_ip);
dest->sin_port=htons(dest_port);
dest_addr_len[Mod_id] = sizeof(struct sockaddr);
inet_ntop(AF_INET, &(dest->sin_addr), str, INET_ADDRSTRLEN);
printf("Connecting to %s:%d\n",str,ntohs(dest->sin_port));
}
int ethernet_write_data(int Mod_id, openair0_timestamp timestamp, const void **buff, int antenna_id, int nsamps)
{
void *buff2 = (void*)buff[antenna_id]-sizeof(openair0_timestamp)-(sizeof(int16_t)*2);
int32_t temp0 = *(int32_t *)buff2;
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2+(sizeof(int16_t)*2));
int n_written;
n_written = 0;
((int16_t *)buff2)[0] = 1+(antenna_id<<1);
((int16_t *)buff2)[1] = nsamps;
*((openair0_timestamp *)(buff2+(sizeof(int16_t)*2))) = timestamp;
// printf("Timestamp TX sent : %d\n",timestamp);
// printf("buffer head : %d %d %d %d \n",((int16_t *)buff2)[0],((int16_t *)buff2)[1],((int16_t *)buff2)[2],((int16_t *)buff2)[3]);
while(n_written < nsamps) {
/* Send packet */
if ((n_written += sendto(sockfd[Mod_id],
buff2,
(nsamps<<2)+sizeof(openair0_timestamp)+(2*sizeof(int16_t)),
0,
(struct sockaddr*)&dest_addr[Mod_id],
dest_addr_len[Mod_id])) < 0) {
printf("Send failed for Mod_id %d\n",Mod_id);
perror("ETHERNET:");
exit(-1);
}
/* initialize destination address */
for (i=0; i< MAX_INST; i++) {
bzero((void *)&(eth->dest_addr[i]), sizeof(eth->dest_addr[i]));
}
*(int32_t *)buff2 = temp0;
*(openair0_timestamp *)(buff2+2*sizeof(int16_t)) = temp1;
return n_written;
}
int ethernet_read_data(int Mod_id,openair0_timestamp *timestamp,void **buff, int antenna_id, int nsamps)
{
void *buff2 = (void*)buff[antenna_id]-sizeof(openair0_timestamp);
int bytes_received;
int block_cnt;
int ret;
openair0_timestamp temp = *(openair0_timestamp*)(buff2);
int16_t mesg[2];
char str[INET_ADDRSTRLEN];
//mesg[0] = 0+(antenna_id<<1);
//mesg[1] = nsamps;
inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
// send command RX for nsamps samples
// printf("requesting %d samples from (%s:%d)\n",nsamps,str,ntohs(dest_addr[Mod_id].sin_port));
//sendto(sockfd[Mod_id],mesg,4,0,(struct sockaddr *)&dest_addr[Mod_id],dest_addr_len[Mod_id]);
bytes_received=0;
block_cnt=0;
while(bytes_received < (int)((nsamps<<2))) {
//printf("requesting %d bytes\n",(nsamps<<2));
ret=recvfrom(sockfd[Mod_id],
buff2+bytes_received,
(nsamps<<2)+sizeof(openair0_timestamp)-bytes_received,
0,//MSG_DONTWAIT,
(struct sockaddr *)&dest_addr[Mod_id],
&dest_addr_len[Mod_id]);
//printf("bytes_received %d (ret %d)\n",bytes_received+ret,ret);
if (ret==-1) {
if (errno == EAGAIN) {
perror("ETHERNET: ");
return((nsamps<<2)+sizeof(openair0_timestamp));
} else if (errno == EWOULDBLOCK) {
block_cnt++;
usleep(10);
if (block_cnt == 100) return(-1);
}
// bzero((void *)dest,sizeof(struct sockaddr_in));
eth->dest_addr[Mod_id].sin_family = AF_INET;
inet_pton(AF_INET,dest_ip,&(eth->dest_addr[Mod_id].sin_addr.s_addr));
eth->dest_addr[Mod_id].sin_port=htons(dest_port);
dest_addr_len[Mod_id] = sizeof(struct sockaddr_in);
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
/* if RRH, then I am the server, so bind */
if (device->func_type == RRH_FUNC ) {
if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&eth->dest_addr[Mod_id], dest_addr_len[Mod_id])<0) {
perror("ETHERNET: Cannot bind to socket");
exit(0);
} else {
bytes_received+=ret;
printf("[RRH] binding mod_%d to %s:%d\n",Mod_id,str,ntohs(eth->dest_addr[Mod_id].sin_port));
}
} else {
printf("[BBU] Connecting to %s:%d\n",str,ntohs(eth->dest_addr[Mod_id].sin_port));
}
return 0;
}
int ethernet_tune(openair0_device *device , eth_opt_t option) {
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id=device->Mod_id;
unsigned int sndbuf_size=0, rcvbuf_size=0;
struct timeval snd_timeout, rcv_timeout;
struct ifreq ifr;
char system_cmd[256];
char* if_name=DEFAULT_IF;
/****************** socket level options ************************/
if (option== SND_BUF_SIZE) { /* transmit socket buffer size */
if (setsockopt(eth->sockfd[Mod_id],
SOL_SOCKET,
SO_SNDBUF,
&sndbuf_size,sizeof(sndbuf_size))) {
perror("[ETHERNET] setsockopt()");
} else {
printf( "sndbuf_size= %d bytes\n", sndbuf_size);
}
} else if (option== RCV_BUF_SIZE) { /* receive socket buffer size */
if (setsockopt(eth->sockfd[Mod_id],
SOL_SOCKET,
SO_RCVBUF,
&rcvbuf_size,sizeof(rcvbuf_size))) {
perror("[ETHERNET] setsockopt()");
} else {
printf( "rcvbuf_size= %d bytes\n", rcvbuf_size);
}
} else if (option==RCV_TIMEOUT) {
rcv_timeout.tv_sec = 0;
rcv_timeout.tv_usec = 180;//less than rt_period
if (setsockopt(eth->sockfd[Mod_id],
SOL_SOCKET,
SO_RCVTIMEO,
(char *)&rcv_timeout,sizeof(rcv_timeout))) {
perror("[ETHERNET] setsockopt()");
} else {
printf( "rcv_timeout= %d usecs\n", rcv_timeout.tv_usec);
}
} else if (option==SND_TIMEOUT) {
snd_timeout.tv_sec = 0;
snd_timeout.tv_usec = 180;//less than rt_period
if (setsockopt(eth->sockfd[Mod_id],
SOL_SOCKET,
SO_SNDTIMEO,
(char *)&snd_timeout,sizeof(snd_timeout))) {
perror("[ETHERNET] setsockopt()");
} else {
printf( "snd_timeout= %d usecs\n", snd_timeout.tv_usec);
}
}
/******************* interface level options *************************/
else if (option==MTU_SIZE) { /* change MTU of the eth interface */
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
ifr.ifr_mtu =8960;
if (ioctl(eth->sockfd[Mod_id],SIOCSIFMTU,(caddr_t)&ifr) < 0 )
perror ("[ETHERNET] Can't set the MTU");
else
printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu);
} else if (option==TX_Q_LEN) { /* change TX queue length of eth interface */
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
ifr.ifr_qlen =3000 ;
if (ioctl(eth->sockfd[Mod_id],SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 )
perror ("[ETHERNET] Can't set the txqueuelen");
else
printf("[ETHERNET] %s txqueuelen size has changed to %d\n",DEFAULT_IF,ifr.ifr_qlen);
//printf("buffer head : %x %x %x %x \n",((int32_t *)buff2)[0],((int32_t *)buff2)[1],((int32_t *)buff2)[2],((int32_t *)buff2)[3]);
*timestamp = *(openair0_timestamp *)(buff2);
// printf("Received %d samples, timestamp = %d\n",bytes_received>>2,*(int32_t*)timestamp);
*(openair0_timestamp *)(buff2) = temp;
return nsamps;
/******************* device level options *************************/
} else if (option==COALESCE_PAR) {
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs 3",DEFAULT_IF) > 0) {
system(system_cmd);
printf("[ETHERNET] Coalesce parameters %s\n",system_cmd);
} else {
perror("[ETHERNET] Can't set coalesce parameters\n");
}
} else if (option==PAUSE_PAR ) {
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",DEFAULT_IF) > 0) {
system(system_cmd);
printf("[ETHERNET] Pause parameters %s\n",system_cmd);
} else {
perror("[ETHERNET] Can't set pause parameters\n");
}
} else if (option==RING_PAR ) {
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx 4096 tx 4096",DEFAULT_IF) > 0) {
system(system_cmd);
printf("[ETHERNET] Ring parameters %s\n",system_cmd);
} else {
perror("[ETHERNET] Can't set ring parameters\n");
}
}
return 0;
}
int trx_eth_start(openair0_device *openair0)
{
int16_t mesg[2];
int Mod_id;
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg) {
Mod_id = openair0->openair0_cfg.Mod_id;
ethernet_socket_init(openair0->openair0_cfg.Mod_id, openair0->openair0_cfg.rrh_ip,openair0->openair0_cfg.rrh_port);
eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t));
int card = 0;
memset(eth, 0, sizeof(eth_state_t));
eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024
eth->sample_rate = (unsigned int)openair0_cfg[card].sample_rate;
device->priv = eth;
mesg[0] = 1 + 0; //antenna index is 0, to be replaced by the number of active antennas
mesg[1] = openair0->openair0_cfg.samples_per_packet;
sendto(sockfd[Mod_id],mesg,4,0,(struct sockaddr *)&dest_addr[Mod_id],dest_addr_len[Mod_id]);
return(0);
}
void trx_eth_write(openair0_device *device, openair0_timestamp timestamp, const void **buff, int nsamps, int cc, int flags)
{
int i;
for (i=0; i<cc; i++)
ethernet_write_data(device->Mod_id,timestamp,buff,i,nsamps);
}
int trx_eth_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int cc)
{
int i;
for (i=0; i<cc; i++)
return(ethernet_read_data(device->Mod_id,ptimestamp,buff,i,nsamps));
}
void trx_eth_end(openair0_device *device)
{
}
int num_devices = 0;
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg)
{
printf("ETHERNET: Initializing openair0_device\n");
device->Mod_id = num_devices++;
device->trx_start_func = trx_eth_start;
device->trx_end_func = trx_eth_end;
device->trx_read_func = trx_eth_read;
device->trx_write_func = trx_eth_write;
printf("ETHERNET: Initializing openair0_device for %s ...\n", ((device->func_type == BBU_FUNC) ? "BBU": "RRH"));
device->Mod_id = num_devices_eth++;
device->trx_start_func = trx_eth_start;
device->trx_request_func = trx_eth_request;
device->trx_reply_func = trx_eth_reply;
device->trx_write_func = trx_eth_write;
device->trx_read_func = trx_eth_read;
device->trx_get_stats_func = trx_eth_get_stats;
device->trx_reset_stats_func = trx_eth_reset_stats;
device->trx_end_func = trx_eth_end;
device->trx_stop_func = trx_eth_stop;
device->trx_set_freq_func = trx_eth_set_freq;
device->trx_set_gains_func = trx_eth_set_gains;
memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
return 0;
}
@@ -1,3 +1,42 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file ethernet_lib.h
* \brief API to stream I/Q samples over standard ethernet
* \author Katerina Trilyraki, Navid Nikaein
* \date 2015
* \version 0.2
* \company Eurecom
* \maintainer: navid.nikaein@eurecom.fr
* \note
* \warning
*/
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
@@ -8,8 +47,107 @@
#include <net/if.h>
#include <netinet/ether.h>
int ethernet_socket_init(int Mod_id, char *dest_ip,int dest_port);
#define MAX_INST 4
#define DEFAULT_IF "lo"
#define BUF_SIZ 8960 /*Jumbo frame size*/
int ethernet_write_data(int Mod_id, const void *buff, int nsamps,int cc);
typedef struct {
int ethernet_read_data(int Mod_id,void *buff, int nsamps,int cc);
// opaque eth data struct
//struct eth_if *dev;
// An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend)
int sockfd[MAX_INST];
struct sockaddr_in dest_addr[MAX_INST];
unsigned int buffer_size;
unsigned int timeout_ns;
//struct eth_metadata meta_rx;
//struct eth_metadata meta_tx;
unsigned int sample_rate;
// time offset between transmiter timestamp and receiver timestamp;
double tdiff;
// use brf_time_offset to get this value
int tx_forward_nsamps; //166 for 20Mhz
// --------------------------------
// Debug and output control
// --------------------------------
int num_underflows;
int num_overflows;
int num_seq_errors;
int num_rx_errors;
int num_tx_errors;
uint64_t tx_actual_nsamps; // actual number of samples transmitted
uint64_t rx_actual_nsamps;
uint64_t tx_nsamps; // number of planned samples
uint64_t rx_nsamps;
uint64_t tx_count; // number pf packets
uint64_t rx_count;
//openair0_timestamp rx_timestamp;
} eth_state_t;
#define ETH_META_STATUS_OVERRUN (1 << 0)
#define ETH_META_STATUS_UNDERRUN (1 << 1)
struct eth_meta_data{
uint64_t timestamp;
uint32_t flags;
uint32_t status;
unsigned int actual_count;
};
/*!\brief packet header */
typedef struct {
/*!\brief packet's timestamp */
openair0_timestamp timestamp;
/*!\brief variable declared for alignment purposes (sample size=32 bit) */
int16_t not_used;
/*!\brief antenna port used to resynchronize */
int16_t antenna_id;
} header_t;
/*!\brief different options for ethernet tuning in socket and driver level */
typedef enum {
MIN_OPT = 0,
/*!\brief socket send buffer size in bytes */
SND_BUF_SIZE,
/*!\brief socket receive buffer size in bytes */
RCV_BUF_SIZE,
/*!\brief receiving timeout */
RCV_TIMEOUT,
/*!\brief sending timeout */
SND_TIMEOUT,
/*!\brief maximun transmission unit size in bytes */
MTU_SIZE,
/*!\brief TX queue length */
TX_Q_LEN,
/*!\brief RX/TX ring parameters of ethernet device */
RING_PAR,
/*!\brief interruptions coalesence mechanism of ethernet device */
COALESCE_PAR,
/*!\brief pause parameters of ethernet device */
PAUSE_PAR,
MAX_OPT
} eth_opt_t;
/*! \fn int ethernet_tune (openair0_device *device, eth_opt_t option)
* \brief this function allows you to configure certain ethernet parameters in socket or device level
* \param[in] openair0 device which bears the socket
* \param[in] name of parameter to configure
* \return 0 on success, otherwise -1
* \note
* @ingroup _oai
*/
int ethernet_tune (openair0_device *device, eth_opt_t option);
int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc) ;
int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int cc);
@@ -1,11 +1,11 @@
# PROMGEN: Xilinx Prom Generator P.49d
# Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved.
# PROMGEN: Xilinx Prom Generator P.20131013
# Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved.
SOFTWARE_VERSION P.49d
DATE 3/21/2014 - 17:31
SOURCE /homes/ghaddab/riadh/openair0/express-mimo2/grlib-gpl-1.1.0-b4113/designs/express-mimo2/exmimo2_prom.mcs
SOFTWARE_VERSION P.20131013
DATE 6/16/2015 - 16:10
SOURCE /homes/maatalla/openair/openair0/express-mimo2/backup_houssem/express-mimo2/grlib-gpl-1.1.0-b4113/designs/express-mimo2/exmimo2_prom.mcs
DEVICE 8192K
DATA_WIDTH 4
FILL_DATA 0xFF
SIGNATURE 0x41900D70
SIGNATURE 0x41521D58
START_ADDRESS 0x00000000 END_ADDRESS 0x00406577 DIRECTION_UP "express-mimo2.bit" 6slx150tfgg900
File diff suppressed because it is too large Load Diff
@@ -1,9 +1,9 @@
PROMGEN: Xilinx Prom Generator P.49d
Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved.
PROMGEN: Xilinx Prom Generator P.20131013
Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved.
promgen -w -p mcs -c FF -o /homes/ghaddab/riadh/openair0/express-mimo2/grlib-gpl-1.1.0-b4113/designs/express-mimo2//exmimo2_prom -s 8192 -u 0000 express-mimo2.bit -spi
promgen -w -p mcs -c FF -o /homes/maatalla/openair/openair0/express-mimo2/backup_houssem/express-mimo2/grlib-gpl-1.1.0-b4113/designs/express-mimo2//exmimo2_prom -s 8192 -u 0000 express-mimo2.bit -spi
PROM /homes/ghaddab/riadh/openair0/express-mimo2/grlib-gpl-1.1.0-b4113/designs/express-mimo2/exmimo2_prom.prm map: Fri Mar 21 17:31:05 2014
PROM /homes/maatalla/openair/openair0/express-mimo2/backup_houssem/express-mimo2/grlib-gpl-1.1.0-b4113/designs/express-mimo2/exmimo2_prom.prm map: Tue Jun 16 16:10:48 2015
Calculating PROM checksum with fill value ff
@@ -11,7 +11,7 @@ Format Mcs86 (32-bit)
Size 8192K
PROM start 0000:0000
PROM end 007f:ffff
PROM checksum 41900d70
PROM checksum 41521d58
Addr1 Addr2 Date File(s)
0000:0000 0040:6577 Mar 21 17:30:57 2014 express-mimo2.bit
0000:0000 0040:6577 Jun 16 16:10:43 2015 express-mimo2.bit
Binary file not shown.
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
setMode -bs
setCable -port auto
Identify
identifyMPM
assignFile -p 1 -file "express-mimo2.bit"
Program -p 1 -defaultVersion 0
quit
@@ -247,10 +247,10 @@ int openair0_stop_without_reset(int card)
#define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
#define RF_MODE_BASE (LNA1ON + RFBBNORM)
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg) {
// Initialize card
exmimo_config_t *p_exmimo_config;
// exmimo_config_t *p_exmimo_config;
exmimo_id_t *p_exmimo_id;
int ret;
@@ -276,7 +276,7 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf
printf ("Detected %d number of cards, %d number of antennas.\n", openair0_num_detected_cards, openair0_num_antennas[0]);
}
p_exmimo_config = openair0_exmimo_pci[0].exmimo_config_ptr;
// p_exmimo_config = openair0_exmimo_pci[0].exmimo_config_ptr;
p_exmimo_id = openair0_exmimo_pci[0].exmimo_id_ptr;
printf("Card %d: ExpressMIMO %d, HW Rev %d, SW Rev 0x%d\n", 0, p_exmimo_id->board_exmimoversion, p_exmimo_id->board_hwrev, p_exmimo_id->board_swrev);
@@ -356,14 +356,15 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
for (ant=0; ant<4; ant++) {
if (openair0_cfg[card].rx_freq[ant] || openair0_cfg[card].tx_freq[ant]) {
p_exmimo_config->rf.rf_mode[ant] = RF_MODE_BASE;
p_exmimo_config->rf.do_autocal[ant] = 1;
p_exmimo_config->rf.do_autocal[ant] = 1;//openair0_cfg[card].autocal[ant];
printf("card %d, antenna %d, autocal %d\n",card,ant,openair0_cfg[card].autocal[ant]);
}
if (openair0_cfg[card].tx_freq[ant]) {
p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX + TXLPFNORM + TXLPFEN + tx_filter);
p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant];
p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant];
printf("openair0 : programming card %d TX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
}
if (openair0_cfg[card].rx_freq[ant]) {
@@ -419,11 +420,11 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
int openair0_reconfig(openair0_config_t *openair0_cfg)
{
int ret;
int ant, card;
exmimo_config_t *p_exmimo_config;
exmimo_id_t *p_exmimo_id;
// exmimo_id_t *p_exmimo_id;
if (!openair0_cfg) {
printf("Error, openair0_cfg is null!!\n");
@@ -433,7 +434,7 @@ int openair0_reconfig(openair0_config_t *openair0_cfg)
for (card=0; card<openair0_num_detected_cards; card++) {
p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr;
p_exmimo_id = openair0_exmimo_pci[card].exmimo_id_ptr;
// p_exmimo_id = openair0_exmimo_pci[card].exmimo_id_ptr;
for (ant=0; ant<4; ant++) {
if (openair0_cfg[card].tx_freq[ant]) {
@@ -468,6 +469,22 @@ int openair0_reconfig(openair0_config_t *openair0_cfg)
return(0);
}
int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
if (exmimo_dump_config > 0) {
// do a full configuration
openair0_config(openair0_cfg,0);
}
else { // just change the frequencies in pci descriptor
openair0_reconfig(openair0_cfg);
}
return(0);
}
int openair0_set_gains(openair0_device* device, openair0_config_t *openair0_cfg){
return(0);
}
unsigned int *openair0_daq_cnt(void) {
@@ -95,4 +95,7 @@ int openair0_stop_without_reset(int card);
// return the DAQ block counter
unsigned int *openair0_daq_cnt(void);
// set the TX and RX frequencies (card 0 only for now, to retain USRP compatibility)
int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config);
#endif
@@ -0,0 +1,276 @@
close all
clear all
hold off
%gpib_card=0; % first GPIB PCI card in the computer
%gpib_device=28; % this is configured in the signal generator Utilities->System->GPIB->Address menu
smbv_ip_addr = "192.168.12.201";
command = [getenv("OPENAIR_TARGETS") "/TEST/ROHDE_SCHWARZ/EthernetRawCommand.out"];
fc = 1907600e3;
%fc = 2.6e9;
%fc=700e6;
fs = 7680e3;
fref = fc+fs/4;
power_dBm = [-70 -80 -90]; %needs to be adjusted based on carrier freq
cables_loss_dB = 11; % we need to account for the power loss between the signal generator and the card input (splitter, cables)
nb_meas = 10;
dual_tx = 0;
tdd = 1;
card = 0;
limeparms;
%rf_mode = (RXEN+TXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+DMAMODE_TX)*[1 1 1 1];
rf_mode = (RXEN+0+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNAMax+RFBBNORM+DMAMODE_RX+0)*[1 1 1 1];
freq_rx = fc*[1 1 1 1];
freq_tx = freq_rx;
tx_gain = 25*[1 1 1 1];
rx_gain = 15*[1 1 1 1];
%rf_local= [8254744 8255063 8257340 8257340]; %rf_local*[1 1 1 1];
rf_local = [8254813 8255016 8254813 8254813]; %exmimo2_2
%rf_rxdc = rf_rxdc*[1 1 1 1];
%rf_rxdc = ((128+rxdc_I) + (128+rxdc_Q)*(2^8))*[1 1 1 1];
rf_rxdc = [37059 35459 36300 36999]; %exmimo2_2
rf_vcocal=rf_vcocal_19G*[1 1 1 1];
eNBflag = 0;
tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX;
syncmode = SYNCMODE_FREE;
%syncmode = [SYNCMODE_MASTER SYNCMODE_SLAVE];
rffe_rxg_low = 63*[1 1 1 1];
rffe_rxg_final = 63*[1 1 1 1];
rffe_band = B19G_TDD*[1 1 1 1];
autocal = [1 1 1 1];
resampling_factor = [2 2 2 2];
system(sprintf('%s %s ''*RST;*CLS''',command, smbv_ip_addr)); % reset and configure the signal generator
%gpib_send(gpib_card,gpib_device,sprintf("POW %ddBm",power_dBm+cables_loss_dB));
%gpib_send(gpib_card,gpib_device,'POW -14dBm');
%gpib_send(gpib_card,gpib_device,'FREQ 1.91860GHz');
%gpib_send(gpib_card,gpib_device,'FREQ 1.919225GHz');
%gpib_send(gpib_card,gpib_device,'FREQ 1.909225GHz');
system(sprintf('%s %s ''FREQ %ldHz''',command,smbv_ip_addr,fref));
%for card=1:oarf_get_num_detected_cards
%oarf_config_exmimo(card-1,freq_rx,freq_tx,tdd_config,syncmode(card),rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
%end
autocal = [0 0 0 0];
ALL_rxrfmode = [LNAByp LNAMed LNAMax];
%ALL_rxrfmode = [LNAMax];
ALL_gain = 0:10:30;
num_chains = 4*oarf_get_num_detected_cards;
SpN0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
%SpN1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
N0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
%N1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
S0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
S0_lin = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
%S1 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
G0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
G1 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
NF0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
NF1 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
NF2 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
SNR0 = zeros(length(ALL_rxrfmode),length(ALL_gain),num_chains);
%SNR1 = zeros(length(ALL_rxrfmode),length(ALL_gain));
%keyboard
for mode_idx = 3
LNA=ALL_rxrfmode(mode_idx);
system(sprintf('%s %s ''POW %d dBm''',command,smbv_ip_addr,power_dBm(mode_idx)+cables_loss_dB));
idx_gain = 1;
for rx_gain=ALL_gain
rf_mode = (RXEN+TXLPFNORM+TXLPFEN+TXLPF25+RXLPFNORM+RXLPFEN+RXLPF25+LNA1ON+LNA+RFBBNORM+DMAMODE_RX)*[1 1 1 1];
rx_gain = rx_gain * [1 1 1 1];
for card=1:oarf_get_num_detected_cards
oarf_config_exmimo(card-1,freq_rx,freq_tx,tdd_config,syncmode(card),rx_gain,tx_gain,eNBflag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
end
sleep(1);
% signal measurement
system(sprintf('%s %s ''OUTP:STAT ON''',command,smbv_ip_addr)); % activate output
sleep(.5);
%f1 = (7.68*(0:length(s(:,2))-1)/(length(s(:,2))))-3.84;
f1 = (7.68*(0:307200-1)/307200)-3.84;
%nidx = find(f1>=0.5 & f1<=1.5); %1MHz
nidx = find(f1>=1.5 & f1<=2.5); %1MHz
sidx = find(f1>=1.87 & f1<=1.97); %100kHz
SpN0_temp = 0;
spn0_temp = 0;
for k=1:nb_meas
s=oarf_get_frame(0);
sleep(.5);
s = s - repmat(mean(s,1),size(s,1),1);
SpN0_temp = SpN0_temp + mean(abs(s).^2,1) - abs(mean(s,1)).^2;
sf = fftshift(fft(s),1)/sqrt(length(s));
%np = 10*log10(sum(abs(sf(nidx,:)).^2));
%sp_temp = sp_temp + 10*log10(sum(abs(sf(sidx,:)).^2));
spn0_temp = spn0_temp + sum(abs(sf).^2);
end
%SpN0(mode_idx,idx_gain,:) = mean(abs(s).^2,1) - abs(mean(s,1)).^2;
%SpN1(mode_idx,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
SpN0(mode_idx,idx_gain,:) = SpN0_temp/nb_meas;
spn0 = spn0_temp/nb_meas;
%keyboard;
sf = fftshift(fft(s),1)/sqrt(length(s));
figure(1);
hold off
plot(f1,20*log10(abs((sf(:,3)))),'r');
hold on
plot(f1(nidx),20*log10(abs(sf(nidx,3))),'b');
plot(f1(sidx),20*log10(abs(sf(sidx,3))),'g');
title("Signal");
ylim([0 200]);
% noise measurement
system(sprintf('%s %s ''OUTP:STAT OFF''',command,smbv_ip_addr)); % deactivate output
sleep(.5);
N0_temp = 0;
np_temp = 0;
np_temp_unit = 0;
for k=1:nb_meas
s=oarf_get_frame(0); %oarf_get_frame
sleep(.5);
s = s - repmat(mean(s,1),size(s,1),1);
N0_temp = N0_temp + mean(abs(s).^2,1) - abs(mean(s,1)).^2;
%N1(idx_power,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
sf = fftshift(fft(s),1)/sqrt(length(s));
np_temp = np_temp + sum(abs(sf).^2);
np_temp_unit = np_temp_unit + sum(abs(sf(nidx,:)).^2);
end
N0(mode_idx,idx_gain,:) = N0_temp/nb_meas;
%N0(mode_idx,idx_gain,:) = mean(abs(s).^2,1) - abs(mean(s,1)).^2;
%N1(mode_idx,idx_gain) = mean(abs(s(:,2)).^2) - abs(mean(s(:,2))).^2;
%G1(mode_idx,idx_gain,:) = sp - power_dBm(mode_idx);
np = np_temp/nb_meas;
snr = 10*log10((spn0-np)./np); %measured snr
snr_real = power_dBm(mode_idx) - (-174 + 10*log10(7.68e6)); %signal over thermal noise
np_unit = np_temp_unit/nb_meas;
snr_output_unit = 10*log10((spn0-np_unit)./np_unit); %measured snr
snr_input_unit = power_dBm(mode_idx) - (-174 + 10*log10(1e6)); %signal over thermal noise
NF1(mode_idx,idx_gain,:) = snr_real - snr;
NF2(mode_idx,idx_gain,:) = snr_input_unit - snr_output_unit;
sf = fftshift(fft(s),1)/sqrt(length(s));
figure(2);
hold off
plot(f1,20*log10(abs((sf(:,3)))),'r');
title("Noise");
ylim([0 200]);
% do some plausibility checks
% if ((N0(mode_idx,idx_gain) > SpN0(mode_idx,idx_gain)) ||
% (N1(mode_idx,idx_gain) > SpN1(mode_idx,idx_gain)))
% error("something is wrong");
% end
S0_lin(mode_idx,idx_gain,:) = SpN0(mode_idx,idx_gain,:)-N0(mode_idx,idx_gain,:);
S0_lin(mode_idx,idx_gain,S0_lin(mode_idx,idx_gain,:)<0) = 0;
S0(mode_idx,idx_gain,:) = 10*log10(S0_lin(mode_idx,idx_gain,:));
%S1(mode_idx,idx_gain) = 10*log10(SpN1(mode_idx,idx_gain)-N1(mode_idx,idx_gain));
G0(mode_idx,idx_gain,:) = S0(mode_idx,idx_gain,:) - power_dBm(mode_idx);
%G1(mode_idx,idx_gain) = S1(mode_idx,idx_gain) - power_dBm;
NF0(mode_idx,idx_gain,:) = 10*log10(N0(mode_idx,idx_gain,:)) - G0(mode_idx,idx_gain,:) + 105; % 108 is the thermal noise
%NF1(mode_idx,idx_gain) = 10*log10(N1(mode_idx,idx_gain)) - G1(mode_idx,idx_gain) + 105;
SNR0(mode_idx,idx_gain,:) = S0(mode_idx,idx_gain,:)-10*log10(N0(mode_idx,idx_gain,:));
%SNR1(mode_idx,idx_gain) = S1(mode_idx,idx_gain)-10*log10(N1(mode_idx,idx_gain));
%printf(' %d: Signal strength (%f,%f), Gain (%f %f), N (%f %f) SNR (%f %f) NF (%f %f)\n',
% rx_gain(1), S0(mode_idx,idx_gain),S1(mode_idx,idx_gain),
% G0(mode_idx,idx_gain),G1(mode_idx,idx_gain),
% 10*log10(N0(mode_idx,idx_gain)),10*log10(N1(mode_idx,idx_gain)),
% SNR0(mode_idx,idx_gain),SNR1(mode_idx,idx_gain),
% NF0(mode_idx,idx_gain),NF1(mode_idx,idx_gain));
%fflush(stdout);
%fprintf(fid,'%d, %d, %d, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n',
%power_dBm,gain2391,gain9862, S0,S1,G0,G1,10*log10(N0),10*log10(N1),SNR0,SNR1,NF0,NF1);
%keyboard
figure(3)
hold off
plot(ALL_gain,G0(:,:,1),'o-','markersize',10)
hold on
plot(ALL_gain,G0(:,:,2),'x-','markersize',10)
plot(ALL_gain,G0(:,:,3),'s-','markersize',10)
plot(ALL_gain,G0(:,:,4),'d-','markersize',10)
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
title('Gains')
xlabel('rx gains (dB)')
ylabel('NF (dB)')
figure(4)
hold off
plot(ALL_gain,NF0(:,:,1),'o-','markersize',10)
hold on
plot(ALL_gain,NF0(:,:,2),'x-','markersize',10)
plot(ALL_gain,NF0(:,:,3),'s-','markersize',10)
plot(ALL_gain,NF0(:,:,4),'d-','markersize',10)
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
title('Averaged Noise Figure measured in time domain')
xlabel('rx gains (dB)')
ylabel('NF (dB)')
figure(5)
hold off
plot(ALL_gain,NF1(:,:,1),'o-','markersize',10)
hold on
plot(ALL_gain,NF1(:,:,2),'x-','markersize',10)
plot(ALL_gain,NF1(:,:,3),'s-','markersize',10)
plot(ALL_gain,NF1(:,:,4),'d-','markersize',10)
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
title('Averaged Noise Figure measured in frequency domain')
xlabel('rx gains (dB)')
ylabel('NF (dB)')
figure(6)
hold off
plot(ALL_gain,NF2(:,:,1),'o-','markersize',10)
hold on
plot(ALL_gain,NF2(:,:,2),'x-','markersize',10)
plot(ALL_gain,NF2(:,:,3),'s-','markersize',10)
plot(ALL_gain,NF2(:,:,4),'d-','markersize',10)
%legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1');
legend('Byp RX0','Med RX0','Max RX0','Byp RX1','Med RX1','Max RX1','Byp RX2','Med RX2','Max RX2','Byp RX3','Med RX3','Max RX3');
title('Unit Bandwidth Noise Figure measured in frequency domain')
xlabel('rx gains (dB)')
ylabel('NF (dB)')
idx_gain = idx_gain + 1;
end
end
%gpib_send(gpib_card,gpib_device,'OUTP:STAT OFF'); % deactivate output
%l0 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G0;
%l1 = [ALL_gain2391; ones(size(ALL_gain2391))].'\G1;
+132 -19
View File
@@ -44,7 +44,15 @@
#include <complex>
#include <fstream>
#include <cmath>
#include "common_lib.h"
#ifdef __SSE4_1__
# include <smmintrin.h>
#endif
#ifdef __AVX2__
# include <immintrin.h>
#endif
typedef struct
{
@@ -54,7 +62,7 @@ typedef struct
// --------------------------------
uhd::usrp::multi_usrp::sptr usrp;
//uhd::usrp::multi_usrp::sptr rx_usrp;
//create a send streamer and a receive streamer
uhd::tx_streamer::sptr tx_stream;
uhd::rx_streamer::sptr rx_stream;
@@ -116,12 +124,14 @@ static void trx_usrp_end(openair0_device *device)
s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
//send a mini EOB packet
s->tx_md.end_of_burst = true;
s->tx_stream->send("", 0, s->tx_md);
s->tx_md.end_of_burst = false;
//send a mini EOB packet
s->tx_md.end_of_burst = true;
s->tx_stream->send("", 0, s->tx_md);
s->tx_md.end_of_burst = false;
}
static void trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
{
usrp_state_t *s = (usrp_state_t*)device->priv;
s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate);
@@ -138,29 +148,59 @@ static void trx_usrp_write(openair0_device *device, openair0_timestamp timestamp
else
s->tx_stream->send(buff[0], nsamps, s->tx_md);
s->tx_md.start_of_burst = false;
return 0;
}
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
{
usrp_state_t *s = (usrp_state_t*)device->priv;
int samples_received=0,i,j;
int nsamps2; // aligned to upper 32 or 16 byte boundary
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
__m256i buff_tmp[2][nsamps>>3];
nsamps2 = (nsamps+7)>>3;
#else
__m128i buff_tmp[2][nsamps>>2];
nsamps2 = (nsamps+3)>>2;
#endif
#elif defined(__arm__)
int16x8_t buff_tmp[2][nsamps>>2];
nsamps2 = (nsamps+3)>>2;
#endif
usrp_state_t *s = (usrp_state_t*)device->priv;
int samples_received=0,i;
if (cc>1) {
// receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs;
for (int i=0;i<cc;i++) buff_ptrs.push_back(buff[i]);
for (int i=0;i<cc;i++) buff_ptrs.push_back(buff_tmp[i]);
samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
} else {
// receive a single channel (e.g. from connector RF A)
samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md);
samples_received = s->rx_stream->recv(buff_tmp[0], nsamps, s->rx_md);
}
// bring RX data into 12 LSBs for softmodem RX
for (int i=0;i<cc;i++) {
for (int j=0; j<nsamps2; j++) {
#if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
#else
((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
#endif
#elif defined(__arm__)
((int16x8_t*)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4);
#endif
}
}
if (samples_received < nsamps) {
printf("[recv] received %d samples out of %d\n",samples_received,nsamps);
}
//handle the error code
switch(s->rx_md.error_code){
case uhd::rx_metadata_t::ERROR_CODE_NONE:
@@ -179,6 +219,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
return samples_received;
}
@@ -195,7 +236,7 @@ static bool is_equal(double a, double b)
return std::fabs(a-b) < std::numeric_limits<double>::epsilon();
}
int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) {
int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) {
usrp_state_t *s = (usrp_state_t*)device->priv;
@@ -223,16 +264,72 @@ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *open
}
int openair0_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
int trx_usrp_set_gains(openair0_device* device,
openair0_config_t *openair0_cfg) {
usrp_state_t *s = (usrp_state_t*)device->priv;
s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]);
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]);
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0);
// limit to maximum gain
if (openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] > gain_range.stop()) {
printf("RX Gain 0 too high, reduce by %f dB\n",
openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] - gain_range.stop());
exit(-1);
}
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]);
printf("Setting USRP RX gain to %f\n", openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]);
return(0);
}
int trx_usrp_stop(int card) {
return(0);
}
rx_gain_calib_table_t calib_table[] = {
{3500000000.0,46.0},
{2660000000.0,53.0},
{2300000000.0,54.0},
{1880000000.0,55.0},
{816000000.0,62.0},
{-1,0}};
void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) {
int i=0;
// loop through calibration table to find best adjustment factor for RX frequency
double min_diff = 6e9,diff;
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg)
while (calib_table[i].freq>0) {
diff = fabs(openair0_cfg->rx_freq[chain_index] - calib_table[i].freq);
printf("cal %d: freq %f, offset %f, diff %f\n",
i,calib_table[i].freq,calib_table[i].offset,diff);
if (min_diff > diff) {
min_diff = diff;
openair0_cfg->rx_gain_offset[chain_index] = calib_table[i].offset;
}
i++;
}
}
int trx_usrp_get_stats(openair0_device* device) {
return(0);
}
int trx_usrp_reset_stats(openair0_device* device) {
return(0);
}
int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg)
{
uhd::set_thread_priority_safe(1.0);
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
@@ -300,7 +397,19 @@ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cf
s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i);
printf("Setting rx freq/gain on channel %lu/%lu\n",i,s->usrp->get_rx_num_channels());
s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i);
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i],i);
set_rx_gain_offset(&openair0_cfg[0],i);
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i);
// limit to maximum gain
if (openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] > gain_range.stop()) {
printf("RX Gain %lu too high, lower by %f dB\n",i,openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop());
exit(-1);
}
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i);
printf("RX Gain %lu %f (%f) => %f (max %f)\n",i,
openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i],
openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop());
}
}
for(i=0;i<s->usrp->get_tx_num_channels();i++) {
@@ -367,10 +476,15 @@ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cf
device->priv = s;
device->trx_start_func = trx_usrp_start;
device->trx_end_func = trx_usrp_end;
device->trx_read_func = trx_usrp_read;
device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read;
device->trx_get_stats_func = trx_usrp_get_stats;
device->trx_reset_stats_func = trx_usrp_reset_stats;
device->trx_end_func = trx_usrp_end;
device->trx_stop_func = trx_usrp_stop;
device->trx_set_freq_func = trx_usrp_set_freq;
device->trx_set_gains_func = trx_usrp_set_gains;
s->sample_rate = openair0_cfg[0].sample_rate;
// TODO:
// init tx_forward_nsamps based usrp_time_offset ex
@@ -380,6 +494,5 @@ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cf
s->tx_forward_nsamps = 90;
if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50;
return 0;
}