Commit 0bbd3649 authored by Raymond Knopp's avatar Raymond Knopp

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5481 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 11758458
USRP_OBJ += $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.o
USRP_FILE_OBJ += $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
USRP_CFLAGS += -I$(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/
/** usrp_lib.cpp
*
* Author: HongliangXU : hong-liang-xu@agilent.com
*/
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <uhd/utils/thread_priority.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <complex>
#include <fstream>
#include <cmath>
#include "usrp_lib.h"
typedef struct
{
// --------------------------------
// variables for USRP configuration
// --------------------------------
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;
uhd::tx_metadata_t tx_md;
uhd::rx_metadata_t rx_md;
uhd::time_spec_t tm_spec;
//setup variables and allocate buffer
uhd::async_metadata_t async_md;
double sample_rate;
// time offset between transmiter timestamp and receiver timestamp;
double tdiff;
// use usrp_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;
int64_t tx_count;
int64_t rx_count;
openair0_timestamp rx_timestamp;
} usrp_state_t;
static int trx_usrp_start(openair0_device *device)
{
usrp_state_t *s = (usrp_state_t*)device->priv;
// init recv and send streaming
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.01);
cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd);
s->tx_md.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate);
s->tx_md.has_time_spec = true;
s->tx_md.start_of_burst = true;
s->tx_md.end_of_burst = false;
s->rx_count = 0;
s->tx_count = 0;
s->rx_timestamp = 0;
}
static void trx_usrp_end(openair0_device *device)
{
usrp_state_t *s = (usrp_state_t*)device->priv;
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;
}
static void trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, const void *buff, int nsamps, 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);
if(flags)
s->tx_md.has_time_spec = true;
else
s->tx_md.has_time_spec = false;
s->tx_stream->send(buff, nsamps, s->tx_md);
s->tx_md.start_of_burst = false;
}
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps)
{
usrp_state_t *s = (usrp_state_t*)device->priv;
int samples_received;
//TODO: only one channel is supported now
samples_received = s->rx_stream->recv(buff, nsamps, s->rx_md);
//handle the error code
switch(s->rx_md.error_code){
case uhd::rx_metadata_t::ERROR_CODE_NONE:
break;
case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
printf("[recv] USRP RX OVERFLOW!\n");
s->num_overflows++;
break;
case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
printf("[recv] USRP RX TIMEOUT!\n");
break;
default:
printf("[recv] Unexpected error on RX, Error code: 0x%x\n",s->rx_md.error_code);
break;
}
s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
return samples_received;
}
static bool is_equal(double a, double b)
{
return std::fabs(a-b) < std::numeric_limits<double>::epsilon();
}
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg)
{
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
memset(s, 0, sizeof(usrp_state_t));
// Initialize USRP device
std::string args = "";
uhd::device_addrs_t device_adds = uhd::device::find(args);
if(device_adds.size() == 0)
{
std::cerr<<"No USRP Device Found. " << std::endl;
free(s);
return -1;
}
s->usrp = uhd::usrp::multi_usrp::make(args);
// lock mboard clocks
s->usrp->set_clock_source("internal");
// set master clock rate and sample rate for tx & rx for streaming
s->usrp->set_master_clock_rate(30.72e6);
s->usrp->set_rx_rate(openair0_cfg->sample_rate);
s->usrp->set_tx_rate(openair0_cfg->sample_rate);
s->usrp->set_tx_freq(openair0_cfg->tx_freq);
s->usrp->set_rx_freq(openair0_cfg->rx_freq);
s->usrp->set_tx_gain(openair0_cfg->tx_gain);
s->usrp->set_rx_gain(openair0_cfg->rx_gain);
s->usrp->set_tx_bandwidth(openair0_cfg->tx_bw);
s->usrp->set_rx_bandwidth(openair0_cfg->rx_bw);
// create tx & rx streamer
uhd::stream_args_t stream_args("sc16", "sc16");
s->tx_stream = s->usrp->get_tx_stream(stream_args);
s->rx_stream = s->usrp->get_rx_stream(stream_args);
s->usrp->set_time_now(uhd::time_spec_t(0.0));
// display USRP settings
std::cout << std::endl<<boost::format("Actual TX sample rate: %fMSps...") % (s->usrp->get_tx_rate()/1e6) << std::endl;
std::cout << boost::format("Actual RX sample rate: %fMSps...") % (s->usrp->get_rx_rate()/1e6) << std::endl;
std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->usrp->get_tx_freq()/1e9) << std::endl;
std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->usrp->get_rx_freq()/1e9) << std::endl;
std::cout << boost::format("Actual TX gain: %f...") % (s->usrp->get_tx_gain()) << std::endl;
std::cout << boost::format("Actual RX gain: %f...") % (s->usrp->get_rx_gain()) << std::endl;
std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->usrp->get_tx_bandwidth()/1e6) << std::endl;
std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->usrp->get_rx_bandwidth()/1e6) << std::endl;
std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna()) << std::endl;
std::cout << boost::format("Actual RX antenna: %s...") % (s->usrp->get_rx_antenna()) << std::endl;
std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl;
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;
s->sample_rate = openair0_cfg->sample_rate;
// TODO:
// init tx_forward_nsamps based usrp_time_offset ex
if(is_equal(s->sample_rate, (double)30.72e6))
s->tx_forward_nsamps = 176;
if(is_equal(s->sample_rate, (double)15.36e6))
s->tx_forward_nsamps = 90;
if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50;
return 0;
}
/** usrp_lib.h
*
* Author: HongliangXU : hong-liang-xu@agilent.com
*/
#ifndef USRP_LIB_H
#define USRP_LIB_H
typedef int64_t openair0_timestamp;
typedef struct openair0_device_t openair0_device;
/* structrue holds the parameters to configure USRP devices
*/
typedef struct {
/* the sample rate for both transmit and receive. */
double sample_rate;
/* number of RX channels (=RX antennas) */
int rx_num_channels;
/* number of TX channels (=TX antennas) */
int tx_num_channels;
/* center frequency in Hz for RX */
double rx_freq;
/* center frequency in Hz for TX */
double tx_freq;
/* gain for RX in dB */
double rx_gain;
/* gain for TX in dB */
double tx_gain;
/* RX bandwidth in Hz */
double rx_bw;
/* TX bandwidth in Hz */
double tx_bw;
} openair0_config_t;
struct openair0_device_t {
/* USRP RF frontend parameters set by application */
openair0_config_t openair0_cfg;
/* Can be used by driver to hold internal structure*/
void *priv;
/* Functions API, which are called by the application*/
/* Called to start the transceiver. Return 0 if OK, < 0 if error */
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, const void *buff, int nsamps, int flags);
/* Read 'nsamps' samples from each channel to buffers. buff[0] is the array for
* the first channel. *ptimestamp is the time at which the first sample
* was received.
* Return the number of sample read */
int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps);
/* Terminate operation of the transceiver -- free all associated resources */
void (*trx_end_func)(openair0_device *device);
};
#ifdef __cplusplus
extern "C"
{
/* return 0 if OK, < 0 if error */
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
}
#endif
#endif // USRP_LIB_H
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment