Commit 1d850ee8 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge remote-tracking branch 'origin/352-support-for-n300' into develop_integration_2018_w40

parents 341b33f1 1942d267
...@@ -50,10 +50,6 @@ ...@@ -50,10 +50,6 @@
#include "targets/RT/USER/rt_wrapper.h" #include "targets/RT/USER/rt_wrapper.h"
// RU OFDM Modulator, used in IF4p5 RRU, RCC/RAU with IF5, eNodeB
extern openair0_config_t openair0_cfg[MAX_CARDS];
extern int oai_exit; extern int oai_exit;
......
...@@ -146,7 +146,7 @@ typedef enum { ...@@ -146,7 +146,7 @@ typedef enum {
{CONFIG_STRING_RU_ATT_TX, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_ATT_TX, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_ATT_RX, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_ATT_RX, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_NBIOTRRC_LIST, NULL, 0, uptr:NULL, defintarrayval:DEFENBS, TYPE_INTARRAY, 1}, \ {CONFIG_STRING_RU_NBIOTRRC_LIST, NULL, 0, uptr:NULL, defintarrayval:DEFENBS, TYPE_INTARRAY, 1}, \
{CONFIG_STRING_RU_SDR_ADDRS, NULL, 0, strptr:NULL, defstrval:"0.0.0.0", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SDR_ADDRS, NULL, 0, strptr:NULL, defstrval:"type=b200", TYPE_STRING, 0}, \
{CONFIG_STRING_RU_SDR_CLK_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SDR_CLK_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \
} }
......
...@@ -65,211 +65,191 @@ ...@@ -65,211 +65,191 @@
/*! \brief USRP Configuration */ /*! \brief USRP Configuration */
typedef struct { typedef struct {
// -------------------------------- // --------------------------------
// variables for USRP configuration // variables for USRP configuration
// -------------------------------- // --------------------------------
//! USRP device pointer //! USRP device pointer
uhd::usrp::multi_usrp::sptr usrp; uhd::usrp::multi_usrp::sptr usrp;
//create a send streamer and a receive streamer //create a send streamer and a receive streamer
//! USRP TX Stream //! USRP TX Stream
uhd::tx_streamer::sptr tx_stream; uhd::tx_streamer::sptr tx_stream;
//! USRP RX Stream //! USRP RX Stream
uhd::rx_streamer::sptr rx_stream; uhd::rx_streamer::sptr rx_stream;
//! USRP TX Metadata //! USRP TX Metadata
uhd::tx_metadata_t tx_md; uhd::tx_metadata_t tx_md;
//! USRP RX Metadata //! USRP RX Metadata
uhd::rx_metadata_t rx_md; uhd::rx_metadata_t rx_md;
//! Sampling rate //! Sampling rate
double sample_rate; double sample_rate;
//! TX forward samples. We use usrp_time_offset to get this value //! TX forward samples. We use usrp_time_offset to get this value
int tx_forward_nsamps; //166 for 20Mhz int tx_forward_nsamps; //166 for 20Mhz
// -------------------------------- // --------------------------------
// Debug and output control // Debug and output control
// -------------------------------- // --------------------------------
int num_underflows; int num_underflows;
int num_overflows; int num_overflows;
int num_seq_errors; int num_seq_errors;
int64_t tx_count; int64_t tx_count;
int64_t rx_count; int64_t rx_count;
int wait_for_first_pps; int wait_for_first_pps;
int use_gps; int use_gps;
//! timestamp of RX packet //! timestamp of RX packet
openair0_timestamp rx_timestamp; openair0_timestamp rx_timestamp;
} usrp_state_t; } usrp_state_t;
//void print_notes(void) //void print_notes(void)
//{ //{
// Helpful notes // Helpful notes
// std::cout << boost::format("**************************************Helpful Notes on Clock/PPS Selection**************************************\n"); // std::cout << boost::format("**************************************Helpful Notes on Clock/PPS Selection**************************************\n");
// std::cout << boost::format("As you can see, the default 10 MHz Reference and 1 PPS signals are now from the GPSDO.\n"); // std::cout << boost::format("As you can see, the default 10 MHz Reference and 1 PPS signals are now from the GPSDO.\n");
// std::cout << boost::format("If you would like to use the internal reference(TCXO) in other applications, you must configure that explicitly.\n"); // std::cout << boost::format("If you would like to use the internal reference(TCXO) in other applications, you must configure that explicitly.\n");
// std::cout << boost::format("You can no longer select the external SMAs for 10 MHz or 1 PPS signaling.\n"); // std::cout << boost::format("You can no longer select the external SMAs for 10 MHz or 1 PPS signaling.\n");
// std::cout << boost::format("****************************************************************************************************************\n"); // std::cout << boost::format("****************************************************************************************************************\n");
//} //}
static int sync_to_gps(openair0_device *device) static int sync_to_gps(openair0_device *device) {
{ uhd::set_thread_priority_safe();
uhd::set_thread_priority_safe(); //std::string args;
//Set up program options
//std::string args; //po::options_description desc("Allowed options");
//desc.add_options()
//Set up program options //("help", "help message")
//po::options_description desc("Allowed options"); //("args", po::value<std::string>(&args)->default_value(""), "USRP device arguments")
//desc.add_options() //;
//("help", "help message") //po::variables_map vm;
//("args", po::value<std::string>(&args)->default_value(""), "USRP device arguments") //po::store(po::parse_command_line(argc, argv, desc), vm);
//; //po::notify(vm);
//po::variables_map vm; //Print the help message
//po::store(po::parse_command_line(argc, argv, desc), vm); //if (vm.count("help"))
//po::notify(vm); //{
// std::cout << boost::format("Synchronize USRP to GPS %s") % desc << std::endl;
//Print the help message // return EXIT_FAILURE;
//if (vm.count("help")) //}
//{ //Create a USRP device
// std::cout << boost::format("Synchronize USRP to GPS %s") % desc << std::endl; //std::cout << boost::format("\nCreating the USRP device with: %s...\n") % args;
// return EXIT_FAILURE; //uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
//} //std::cout << boost::format("Using Device: %s\n") % usrp->get_pp_string();
usrp_state_t *s = (usrp_state_t *)device->priv;
//Create a USRP device
//std::cout << boost::format("\nCreating the USRP device with: %s...\n") % args; try {
//uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); size_t num_mboards = s->usrp->get_num_mboards();
//std::cout << boost::format("Using Device: %s\n") % usrp->get_pp_string(); size_t num_gps_locked = 0;
usrp_state_t *s = (usrp_state_t*)device->priv; for (size_t mboard = 0; mboard < num_mboards; mboard++) {
std::cout << "Synchronizing mboard " << mboard << ": " << s->usrp->get_mboard_name(mboard) << std::endl;
try //Set references to GPSDO
{ s->usrp->set_clock_source("gpsdo", mboard);
size_t num_mboards = s->usrp->get_num_mboards(); s->usrp->set_time_source("gpsdo", mboard);
size_t num_gps_locked = 0; //std::cout << std::endl;
for (size_t mboard = 0; mboard < num_mboards; mboard++) //print_notes();
{ //std::cout << std::endl;
std::cout << "Synchronizing mboard " << mboard << ": " << s->usrp->get_mboard_name(mboard) << std::endl; //Check for 10 MHz lock
std::vector<std::string> sensor_names = s->usrp->get_mboard_sensor_names(mboard);
//Set references to GPSDO
s->usrp->set_clock_source("gpsdo", mboard); if(std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end()) {
s->usrp->set_time_source("gpsdo", mboard); std::cout << "Waiting for reference lock..." << std::flush;
bool ref_locked = false;
//std::cout << std::endl;
//print_notes(); for (int i = 0; i < 30 and not ref_locked; i++) {
//std::cout << std::endl; ref_locked = s->usrp->get_mboard_sensor("ref_locked", mboard).to_bool();
//Check for 10 MHz lock if (not ref_locked) {
std::vector<std::string> sensor_names = s->usrp->get_mboard_sensor_names(mboard); std::cout << "." << std::flush;
if(std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end()) boost::this_thread::sleep(boost::posix_time::seconds(1));
{ }
std::cout << "Waiting for reference lock..." << std::flush; }
bool ref_locked = false;
for (int i = 0; i < 30 and not ref_locked; i++)
{
ref_locked = s->usrp->get_mboard_sensor("ref_locked", mboard).to_bool();
if (not ref_locked)
{
std::cout << "." << std::flush;
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
}
if(ref_locked)
{
std::cout << "LOCKED" << std::endl;
} else {
std::cout << "FAILED" << std::endl;
std::cout << "Failed to lock to GPSDO 10 MHz Reference. Exiting." << std::endl;
exit(EXIT_FAILURE);
}
}
else
{
std::cout << boost::format("ref_locked sensor not present on this board.\n");
}
//Wait for GPS lock
bool gps_locked = s->usrp->get_mboard_sensor("gps_locked", mboard).to_bool();
if(gps_locked)
{
num_gps_locked++;
std::cout << boost::format("GPS Locked\n");
}
else
{
std::cerr << "WARNING: GPS not locked - time will not be accurate until locked" << std::endl;
}
//Set to GPS time if(ref_locked) {
uhd::time_spec_t gps_time = uhd::time_spec_t(time_t(s->usrp->get_mboard_sensor("gps_time", mboard).to_int())); std::cout << "LOCKED" << std::endl;
//s->usrp->set_time_next_pps(gps_time+1.0, mboard); } else {
s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); std::cout << "FAILED" << std::endl;
std::cout << "Failed to lock to GPSDO 10 MHz Reference. Exiting." << std::endl;
//Wait for it to apply exit(EXIT_FAILURE);
//The wait is 2 seconds because N-Series has a known issue where
//the time at the last PPS does not properly update at the PPS edge
//when the time is actually set.
boost::this_thread::sleep(boost::posix_time::seconds(2));
//Check times
gps_time = uhd::time_spec_t(time_t(s->usrp->get_mboard_sensor("gps_time", mboard).to_int()));
uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps(mboard);
std::cout << "USRP time: " << (boost::format("%0.9f") % time_last_pps.get_real_secs()) << std::endl;
std::cout << "GPSDO time: " << (boost::format("%0.9f") % gps_time.get_real_secs()) << std::endl;
//if (gps_time.get_real_secs() == time_last_pps.get_real_secs())
// std::cout << std::endl << "SUCCESS: USRP time synchronized to GPS time" << std::endl << std::endl;
//else
// std::cerr << std::endl << "ERROR: Failed to synchronize USRP time to GPS time" << std::endl << std::endl;
} }
} else {
std::cout << boost::format("ref_locked sensor not present on this board.\n");
}
if (num_gps_locked == num_mboards and num_mboards > 1) //Wait for GPS lock
{ bool gps_locked = s->usrp->get_mboard_sensor("gps_locked", mboard).to_bool();
//Check to see if all USRP times are aligned
//First, wait for PPS.
uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps();
while (time_last_pps == s->usrp->get_time_last_pps())
{
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
//Sleep a little to make sure all devices have seen a PPS edge if(gps_locked) {
boost::this_thread::sleep(boost::posix_time::milliseconds(200)); num_gps_locked++;
std::cout << boost::format("GPS Locked\n");
//Compare times across all mboards } else {
bool all_matched = true; std::cerr << "WARNING: GPS not locked - time will not be accurate until locked" << std::endl;
uhd::time_spec_t mboard0_time = s->usrp->get_time_last_pps(0); }
for (size_t mboard = 1; mboard < num_mboards; mboard++)
{ //Set to GPS time
uhd::time_spec_t mboard_time = s->usrp->get_time_last_pps(mboard); uhd::time_spec_t gps_time = uhd::time_spec_t(time_t(s->usrp->get_mboard_sensor("gps_time", mboard).to_int()));
if (mboard_time != mboard0_time) //s->usrp->set_time_next_pps(gps_time+1.0, mboard);
{ s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
all_matched = false; //Wait for it to apply
std::cerr << (boost::format("ERROR: Times are not aligned: USRP 0=%0.9f, USRP %d=%0.9f") //The wait is 2 seconds because N-Series has a known issue where
% mboard0_time.get_real_secs() //the time at the last PPS does not properly update at the PPS edge
% mboard //when the time is actually set.
% mboard_time.get_real_secs()) << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(2));
} //Check times
} gps_time = uhd::time_spec_t(time_t(s->usrp->get_mboard_sensor("gps_time", mboard).to_int()));
if (all_matched) uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps(mboard);
{ std::cout << "USRP time: " << (boost::format("%0.9f") % time_last_pps.get_real_secs()) << std::endl;
std::cout << "SUCCESS: USRP times aligned" << std::endl << std::endl; std::cout << "GPSDO time: " << (boost::format("%0.9f") % gps_time.get_real_secs()) << std::endl;
} else { //if (gps_time.get_real_secs() == time_last_pps.get_real_secs())
std::cout << "ERROR: USRP times are not aligned" << std::endl << std::endl; // std::cout << std::endl << "SUCCESS: USRP time synchronized to GPS time" << std::endl << std::endl;
} //else
} // std::cerr << std::endl << "ERROR: Failed to synchronize USRP time to GPS time" << std::endl << std::endl;
} }
catch (std::exception& e)
{ if (num_gps_locked == num_mboards and num_mboards > 1) {
std::cout << boost::format("\nError: %s") % e.what(); //Check to see if all USRP times are aligned
std::cout << boost::format("This could mean that you have not installed the GPSDO correctly.\n\n"); //First, wait for PPS.
std::cout << boost::format("Visit one of these pages if the problem persists:\n"); uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps();
std::cout << boost::format(" * N2X0/E1X0: http://files.ettus.com/manual/page_gpsdo.html");
std::cout << boost::format(" * X3X0: http://files.ettus.com/manual/page_gpsdo_x3x0.html\n\n"); while (time_last_pps == s->usrp->get_time_last_pps()) {
std::cout << boost::format(" * E3X0: http://files.ettus.com/manual/page_usrp_e3x0.html#e3x0_hw_gps\n\n"); boost::this_thread::sleep(boost::posix_time::milliseconds(1));
exit(EXIT_FAILURE); }
//Sleep a little to make sure all devices have seen a PPS edge
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
//Compare times across all mboards
bool all_matched = true;
uhd::time_spec_t mboard0_time = s->usrp->get_time_last_pps(0);
for (size_t mboard = 1; mboard < num_mboards; mboard++) {
uhd::time_spec_t mboard_time = s->usrp->get_time_last_pps(mboard);
if (mboard_time != mboard0_time) {
all_matched = false;
std::cerr << (boost::format("ERROR: Times are not aligned: USRP 0=%0.9f, USRP %d=%0.9f")
% mboard0_time.get_real_secs()
% mboard
% mboard_time.get_real_secs()) << std::endl;
}
}
if (all_matched) {
std::cout << "SUCCESS: USRP times aligned" << std::endl << std::endl;
} else {
std::cout << "ERROR: USRP times are not aligned" << std::endl << std::endl;
}
} }
} catch (std::exception &e) {
std::cout << boost::format("\nError: %s") % e.what();
std::cout << boost::format("This could mean that you have not installed the GPSDO correctly.\n\n");
std::cout << boost::format("Visit one of these pages if the problem persists:\n");
std::cout << boost::format(" * N2X0/E1X0: http://files.ettus.com/manual/page_gpsdo.html");
std::cout << boost::format(" * X3X0: http://files.ettus.com/manual/page_gpsdo_x3x0.html\n\n");
std::cout << boost::format(" * E3X0: http://files.ettus.com/manual/page_usrp_e3x0.html#e3x0_hw_gps\n\n");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
...@@ -315,24 +295,18 @@ char config_hlp_sf_wdelay[] = CONFIG_HLP_SF_WDELAY; ...@@ -315,24 +295,18 @@ char config_hlp_sf_wdelay[] = CONFIG_HLP_SF_WDELAY;
@param device pointer to the device structure specific to the RF hardware target @param device pointer to the device structure specific to the RF hardware target
*/ */
static int trx_usrp_start(openair0_device *device) { static int trx_usrp_start(openair0_device *device) {
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
if (u_sf_mode != 2) { // not replay mode
#endif
usrp_state_t *s = (usrp_state_t*)device->priv;
if (u_sf_mode != 2) { // not replay mode
// setup GPIO for TDD, GPIO(4) = ATR_RX #endif
//set data direction register (DDR) to output usrp_state_t *s = (usrp_state_t *)device->priv;
// setup GPIO for TDD, GPIO(4) = ATR_RX
//set data direction register (DDR) to output
s->usrp->set_gpio_attr("FP0", "DDR", 0x1f, 0x1f); s->usrp->set_gpio_attr("FP0", "DDR", 0x1f, 0x1f);
//set control register to ATR
//set control register to ATR
s->usrp->set_gpio_attr("FP0", "CTRL", 0x1f,0x1f); s->usrp->set_gpio_attr("FP0", "CTRL", 0x1f,0x1f);
//set ATR register
//set ATR register
s->usrp->set_gpio_attr("FP0", "ATR_RX", 1<<4, 0x1f); s->usrp->set_gpio_attr("FP0", "ATR_RX", 1<<4, 0x1f);
// init recv and send streaming // init recv and send streaming
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
LOG_I(PHY,"Time in secs now: %llu \n", s->usrp->get_time_now().to_ticks(s->sample_rate)); LOG_I(PHY,"Time in secs now: %llu \n", s->usrp->get_time_now().to_ticks(s->sample_rate));
...@@ -340,28 +314,26 @@ static int trx_usrp_start(openair0_device *device) { ...@@ -340,28 +314,26 @@ static int trx_usrp_start(openair0_device *device) {
if (s->use_gps == 1) { if (s->use_gps == 1) {
s->wait_for_first_pps = 1; s->wait_for_first_pps = 1;
cmd.time_spec = s->usrp->get_time_last_pps() + uhd::time_spec_t(1.0); cmd.time_spec = s->usrp->get_time_last_pps() + uhd::time_spec_t(1.0);
} } else {
else { s->wait_for_first_pps = 0;
s->wait_for_first_pps = 0;
cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.05); cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.05);
} }
cmd.stream_now = false; // start at constant delay cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd); s->rx_stream->issue_stream_cmd(cmd);
s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate); s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate);
s->tx_md.has_time_spec = true; s->tx_md.has_time_spec = true;
s->tx_md.start_of_burst = true; s->tx_md.start_of_burst = true;
s->tx_md.end_of_burst = false; s->tx_md.end_of_burst = false;
s->rx_count = 0; s->rx_count = 0;
s->tx_count = 0; s->tx_count = 0;
s->rx_timestamp = 0; s->rx_timestamp = 0;
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
} }
#endif
return 0; #endif
return 0;
} }
/*! \brief Terminate operation of the USRP transceiver -- free all associated resources /*! \brief Terminate operation of the USRP transceiver -- free all associated resources
* \param device the hardware to use * \param device the hardware to use
...@@ -369,12 +341,14 @@ static int trx_usrp_start(openair0_device *device) { ...@@ -369,12 +341,14 @@ static int trx_usrp_start(openair0_device *device) {
static void trx_usrp_end(openair0_device *device) { static void trx_usrp_end(openair0_device *device) {
#if defined(USRP_REC_PLAY) // For some ugly reason, this can be called several times... #if defined(USRP_REC_PLAY) // For some ugly reason, this can be called several times...
static int done = 0; static int done = 0;
if (done == 1) return; if (done == 1) return;
done = 1; done = 1;
if (u_sf_mode != 2) { // not subframes replay
#endif
usrp_state_t *s = (usrp_state_t*)device->priv;
if (u_sf_mode != 2) { // not subframes replay
#endif
usrp_state_t *s = (usrp_state_t *)device->priv;
s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
//send a mini EOB packet //send a mini EOB packet
s->tx_md.end_of_burst = true; s->tx_md.end_of_burst = true;
...@@ -382,55 +356,67 @@ static void trx_usrp_end(openair0_device *device) { ...@@ -382,55 +356,67 @@ static void trx_usrp_end(openair0_device *device) {
s->tx_md.end_of_burst = false; s->tx_md.end_of_burst = false;
sleep(1); sleep(1);
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
} }
#endif #endif
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
if (u_sf_mode == 1) { // subframes store
pFile = fopen (u_sf_filename,"wb+"); if (u_sf_mode == 1) { // subframes store
if (pFile == NULL) { pFile = fopen (u_sf_filename,"wb+");
std::cerr << "Cannot open " << u_sf_filename << std::endl;
} else { if (pFile == NULL) {
unsigned int i = 0; std::cerr << "Cannot open " << u_sf_filename << std::endl;
unsigned int modu = 0; } else {
if ((modu = nb_samples % 10) != 0) { unsigned int i = 0;
nb_samples -= modu; // store entire number of frames unsigned int modu = 0;
}
std::cerr << "Writing " << nb_samples << " subframes to " << u_sf_filename << " ..." << std::endl; if ((modu = nb_samples % 10) != 0) {
for (i = 0; i < nb_samples; i++) { nb_samples -= modu; // store entire number of frames
fwrite(ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), pFile);
}
fclose (pFile);
std::cerr << "File " << u_sf_filename << " closed." << std::endl;
} }
std::cerr << "Writing " << nb_samples << " subframes to " << u_sf_filename << " ..." << std::endl;
for (i = 0; i < nb_samples; i++) {
fwrite(ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), pFile);
}
fclose (pFile);
std::cerr << "File " << u_sf_filename << " closed." << std::endl;
} }
if (u_sf_mode == 1) { // record }
if (u_sf_mode == 1) { // record
if (ms_sample != NULL) {
free((void *)ms_sample);
ms_sample = NULL;
}
}
if (u_sf_mode == 2) { // replay
if (use_mmap) {
if (ms_sample != MAP_FAILED) {
munmap(ms_sample, sb.st_size);
ms_sample = NULL;
}
if (mmapfd != 0) {
close(mmapfd);
mmapfd = 0;
}
} else {
if (ms_sample != NULL) { if (ms_sample != NULL) {
free((void*)ms_sample); free(ms_sample);
ms_sample = NULL; ms_sample = NULL;
} }
}
if (u_sf_mode == 2) { // replay if (iqfd != 0) {
if (use_mmap) { close(iqfd);
if (ms_sample != MAP_FAILED) { iqfd = 0;
munmap(ms_sample, sb.st_size);
ms_sample = NULL;
}
if (mmapfd != 0) {
close(mmapfd);
mmapfd = 0;
}
} else {
if (ms_sample != NULL) {
free(ms_sample);
ms_sample = NULL;
}
if (iqfd != 0) {
close(iqfd);
iqfd = 0;
}
} }
} }
#endif }
#endif
} }
/*! \brief Called to send samples to the USRP RF target /*! \brief Called to send samples to the USRP RF target
...@@ -444,78 +430,80 @@ static void trx_usrp_end(openair0_device *device) { ...@@ -444,78 +430,80 @@ static void trx_usrp_end(openair0_device *device) {
static int 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) {
int ret=0; int ret=0;
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
if (u_sf_mode != 2) { // not replay mode if (u_sf_mode != 2) { // not replay mode
#endif #endif
usrp_state_t *s = (usrp_state_t*)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
int nsamps2; // aligned to upper 32 or 16 byte boundary
int nsamps2; // aligned to upper 32 or 16 byte boundary
#if defined(__x86_64) || defined(__i386__) #if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
nsamps2 = (nsamps+7)>>3; nsamps2 = (nsamps+7)>>3;
__m256i buff_tx[2][nsamps2]; __m256i buff_tx[2][nsamps2];
#else #else
nsamps2 = (nsamps+3)>>2; nsamps2 = (nsamps+3)>>2;
__m128i buff_tx[2][nsamps2]; __m128i buff_tx[2][nsamps2];
#endif #endif
#elif defined(__arm__) #elif defined(__arm__)
nsamps2 = (nsamps+3)>>2; nsamps2 = (nsamps+3)>>2;
int16x8_t buff_tx[2][nsamps2]; int16x8_t buff_tx[2][nsamps2];
#endif #endif
// bring RX data into 12 LSBs for softmodem RX // bring RX data into 12 LSBs for softmodem RX
for (int i=0; i<cc; i++) { for (int i=0; i<cc; i++) {
for (int j=0; j<nsamps2; j++) { for (int j=0; j<nsamps2; j++) {
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
buff_tx[i][j] = _mm256_slli_epi16(((__m256i*)buff[i])[j],4); buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
#else #else
buff_tx[i][j] = _mm_slli_epi16(((__m128i*)buff[i])[j],4); buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
#endif #endif
#elif defined(__arm__) #elif defined(__arm__)
buff_tx[i][j] = vshlq_n_s16(((int16x8_t*)buff[i])[j],4); buff_tx[i][j] = vshlq_n_s16(((int16x8_t *)buff[i])[j],4);
#endif #endif
}
} }
}
s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate);
s->tx_md.has_time_spec = flags; s->tx_md.has_time_spec = flags;
if(flags>0)
if(flags>0) s->tx_md.has_time_spec = true;
s->tx_md.has_time_spec = true; else
else s->tx_md.has_time_spec = false;
s->tx_md.has_time_spec = false;
if (flags == 2) { // start of burst
if (flags == 2) { // start of burst s->tx_md.start_of_burst = true;
s->tx_md.start_of_burst = true; s->tx_md.end_of_burst = false;
s->tx_md.end_of_burst = false; } else if (flags == 3) { // end of burst
} else if (flags == 3) { // end of burst s->tx_md.start_of_burst = false;
s->tx_md.start_of_burst = false; s->tx_md.end_of_burst = true;
s->tx_md.end_of_burst = true; } else if (flags == 4) { // start and end
} else if (flags == 4) { // start and end s->tx_md.start_of_burst = true;
s->tx_md.start_of_burst = true; s->tx_md.end_of_burst = true;
s->tx_md.end_of_burst = true; } else if (flags==1) { // middle of burst
} else if (flags==1) { // middle of burst s->tx_md.start_of_burst = false;
s->tx_md.start_of_burst = false; s->tx_md.end_of_burst = false;
s->tx_md.end_of_burst = false; }
}
if(flags==10){ // fail safe mode if(flags==10) { // fail safe mode
s->tx_md.has_time_spec = false; s->tx_md.has_time_spec = false;
s->tx_md.start_of_burst = false; s->tx_md.start_of_burst = false;
s->tx_md.end_of_burst = true; s->tx_md.end_of_burst = true;
} }
if (cc>1) {
std::vector<void *> buff_ptrs; if (cc>1) {
for (int i=0; i<cc; i++) std::vector<void *> buff_ptrs;
buff_ptrs.push_back(buff_tx[i]);
ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3); for (int i=0; i<cc; i++)
} else buff_ptrs.push_back(buff_tx[i]);
ret = (int)s->tx_stream->send(buff_tx[0], nsamps, s->tx_md,1e-3);
ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3);
} else
ret = (int)s->tx_stream->send(buff_tx[0], nsamps, s->tx_md,1e-3);
if (ret != nsamps)
LOG_E(PHY,"[xmit] tx samples %d != %d\n",ret,nsamps); if (ret != nsamps)
LOG_E(PHY,"[xmit] tx samples %d != %d\n",ret,nsamps);
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
} else { } else {
struct timespec req; struct timespec req;
...@@ -524,8 +512,8 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, ...@@ -524,8 +512,8 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
nanosleep(&req, NULL); nanosleep(&req, NULL);
ret = nsamps; ret = nsamps;
} }
#endif
#endif
return ret; return ret;
} }
...@@ -541,12 +529,13 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, ...@@ -541,12 +529,13 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
* \returns the number of sample read * \returns the number of sample read
*/ */
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { 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; usrp_state_t *s = (usrp_state_t *)device->priv;
int samples_received=0,i,j; int samples_received=0,i,j;
int nsamps2; // aligned to upper 32 or 16 byte boundary int nsamps2; // aligned to upper 32 or 16 byte boundary
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
if (u_sf_mode != 2) { // not replay mode if (u_sf_mode != 2) { // not replay mode
#endif #endif
#if defined(__x86_64) || defined(__i386__) #if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
nsamps2 = (nsamps+7)>>3; nsamps2 = (nsamps+7)>>3;
...@@ -561,66 +550,79 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -561,66 +550,79 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
#endif #endif
if (device->type == USRP_B200_DEV) { if (device->type == USRP_B200_DEV) {
if (cc>1) { if (cc>1) {
// receive multiple channels (e.g. RF A and RF B) // receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs; std::vector<void *> buff_ptrs;
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); for (int i=0; i<cc; i++) buff_ptrs.push_back(buff_tmp[i]);
} else {
// receive a single channel (e.g. from connector RF A) samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
samples_received=0; } else {
while (samples_received != nsamps) { // receive a single channel (e.g. from connector RF A)
samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received, samples_received=0;
nsamps-samples_received, s->rx_md);
if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)) while (samples_received != nsamps) {
break; samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received,
if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) { printf("sleep...\n");} //usleep(100); nsamps-samples_received, s->rx_md);
}
if (samples_received == nsamps) s->wait_for_first_pps=0; if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE))
break;
if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) {
printf("sleep...\n"); //usleep(100);
}
} }
// bring RX data into 12 LSBs for softmodem RX
for (int i=0; i<cc; i++) { if (samples_received == nsamps) s->wait_for_first_pps=0;
for (int j=0; j<nsamps2; j++) { }
// 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__) #if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4); ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
#else #else
((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4); ((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
#endif #endif
#elif defined(__arm__) #elif defined(__arm__)
((int16x8_t*)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4); ((int16x8_t *)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4);
#endif #endif
}
} }
}
} else if (device->type == USRP_X300_DEV) { } else if (device->type == USRP_X300_DEV) {
if (cc>1) { if (cc>1) {
// receive multiple channels (e.g. RF A and RF B) // receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs; 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[i]);
samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
} else { samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
// receive a single channel (e.g. from connector RF A) } else {
samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md); // receive a single channel (e.g. from connector RF A)
} samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md);
}
} }
if (samples_received < nsamps) if (samples_received < nsamps)
LOG_E(PHY,"[recv] received %d samples out of %d\n",samples_received,nsamps); LOG_E(PHY,"[recv] received %d samples out of %d\n",samples_received,nsamps);
if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
LOG_E(PHY, "%s\n", s->rx_md.to_pp_string(true).c_str()); LOG_E(PHY, "%s\n", s->rx_md.to_pp_string(true).c_str());
s->rx_count += nsamps; s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp; *ptimestamp = s->rx_timestamp;
#if defined (USRP_REC_PLAY) #if defined (USRP_REC_PLAY)
} }
#endif
#endif
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
if (u_sf_mode == 1) { // record mode if (u_sf_mode == 1) { // record mode
// Copy subframes to memory (later dump on a file) // Copy subframes to memory (later dump on a file)
if (nb_samples < u_sf_max) { if (nb_samples < u_sf_max) {
(ms_sample+nb_samples)->header = BELL_LABS_IQ_HEADER; (ms_sample+nb_samples)->header = BELL_LABS_IQ_HEADER;
(ms_sample+nb_samples)->ts = *ptimestamp; (ms_sample+nb_samples)->ts = *ptimestamp;
memcpy((ms_sample+nb_samples)->samples, buff[0], nsamps*4); memcpy((ms_sample+nb_samples)->samples, buff[0], nsamps*4);
nb_samples++; nb_samples++;
...@@ -629,62 +631,78 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -629,62 +631,78 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
if (cur_samples == nb_samples) { if (cur_samples == nb_samples) {
cur_samples = 0; cur_samples = 0;
wrap_count++; wrap_count++;
if (wrap_count == u_sf_loops) { if (wrap_count == u_sf_loops) {
std::cerr << "USRP device terminating subframes replay mode after " << u_sf_loops << " loops." << std::endl; std::cerr << "USRP device terminating subframes replay mode after " << u_sf_loops << " loops." << std::endl;
return 0; // should make calling process exit return 0; // should make calling process exit
} }
wrap_ts = wrap_count * (nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)); wrap_ts = wrap_count * (nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000));
if (!use_mmap) { if (!use_mmap) {
if (lseek(iqfd, 0, SEEK_SET) == 0) { if (lseek(iqfd, 0, SEEK_SET) == 0) {
std::cerr << "Seeking at the beginning of IQ file" << std::endl; std::cerr << "Seeking at the beginning of IQ file" << std::endl;
} else { } else {
std::cerr << "Problem seeking at the beginning of IQ file" << std::endl; std::cerr << "Problem seeking at the beginning of IQ file" << std::endl;
} }
} }
} }
if (use_mmap) { if (use_mmap) {
if (cur_samples < nb_samples) { if (cur_samples < nb_samples) {
*ptimestamp = (ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts; *ptimestamp = (ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts if (cur_samples == 0) {
<< " ts=" << *ptimestamp << std::endl; std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
} << " ts=" << *ptimestamp << std::endl;
memcpy(buff[0], &ms_sample[cur_samples].samples[0], nsamps*4); }
cur_samples++;
memcpy(buff[0], &ms_sample[cur_samples].samples[0], nsamps*4);
cur_samples++;
} }
} else { } else {
// read sample from file // read sample from file
if (read(iqfd, ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) { if (read(iqfd, ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
std::cerr << "pb reading iqfile at index " << sizeof(iqrec_t)*cur_samples << std::endl; std::cerr << "pb reading iqfile at index " << sizeof(iqrec_t)*cur_samples << std::endl;
close(iqfd); close(iqfd);
free(ms_sample); free(ms_sample);
ms_sample = NULL; ms_sample = NULL;
iqfd = 0; iqfd = 0;
exit(-1); exit(-1);
} }
if (cur_samples < nb_samples) { if (cur_samples < nb_samples) {
static int64_t ts0 = 0; static int64_t ts0 = 0;
if ((cur_samples == 0) && (wrap_count == 0)) {
ts0 = ms_sample->ts; if ((cur_samples == 0) && (wrap_count == 0)) {
} ts0 = ms_sample->ts;
*ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts; }
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts *ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
<< " ts=" << *ptimestamp << std::endl;
} if (cur_samples == 0) {
memcpy(buff[0], &ms_sample->samples[0], nsamps*4); std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
cur_samples++; << " ts=" << *ptimestamp << std::endl;
// Prepare for next read }
off_t where = lseek(iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET);
memcpy(buff[0], &ms_sample->samples[0], nsamps*4);
cur_samples++;
// Prepare for next read
off_t where = lseek(iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET);
} }
} }
struct timespec req; struct timespec req;
req.tv_sec = 0; req.tv_sec = 0;
req.tv_nsec = u_sf_read_delay * 1000; req.tv_nsec = u_sf_read_delay * 1000;
nanosleep(&req, NULL); nanosleep(&req, NULL);
return nsamps; return nsamps;
} }
#endif #endif
return samples_received; return samples_received;
} }
...@@ -694,16 +712,14 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -694,16 +712,14 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
* \param b second variable * \param b second variable
*/ */
static bool is_equal(double a, double b) { static bool is_equal(double a, double b) {
return std::fabs(a-b) < std::numeric_limits<double>::epsilon(); return std::fabs(a-b) < std::numeric_limits<double>::epsilon();
} }
void *freq_thread(void *arg) { void *freq_thread(void *arg) {
openair0_device *device=(openair0_device *)arg;
openair0_device *device=(openair0_device *)arg; usrp_state_t *s = (usrp_state_t *)device->priv;
usrp_state_t *s = (usrp_state_t*)device->priv; s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]);
s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]);
s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]);
s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]);
} }
/*! \brief Set frequencies (TX/RX). Spawns a thread to handle the frequency change to not block the calling thread /*! \brief Set frequencies (TX/RX). Spawns a thread to handle the frequency change to not block the calling thread
* \param device the hardware to use * \param device the hardware to use
...@@ -711,23 +727,20 @@ void *freq_thread(void *arg) { ...@@ -711,23 +727,20 @@ void *freq_thread(void *arg) {
* \param dummy dummy variable not used * \param dummy dummy variable not used
* \returns 0 in success * \returns 0 in success
*/ */
int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dont_block) { int trx_usrp_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dont_block) {
usrp_state_t *s = (usrp_state_t *)device->priv;
usrp_state_t *s = (usrp_state_t*)device->priv; pthread_t f_thread;
pthread_t f_thread; printf("Setting USRP TX Freq %f, RX Freq %f\n",openair0_cfg[0].tx_freq[0],openair0_cfg[0].rx_freq[0]);
printf("Setting USRP TX Freq %f, RX Freq %f\n",openair0_cfg[0].tx_freq[0],openair0_cfg[0].rx_freq[0]); // spawn a thread to handle the frequency change to not block the calling thread
if (dont_block == 1)
// spawn a thread to handle the frequency change to not block the calling thread pthread_create(&f_thread,NULL,freq_thread,(void *)device);
if (dont_block == 1) else {
pthread_create(&f_thread,NULL,freq_thread,(void*)device); s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]);
else { s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]);
s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]); }
s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]);
}
return(0);
return(0);
} }
/*! \brief Set RX frequencies /*! \brief Set RX frequencies
...@@ -735,21 +748,16 @@ int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, ...@@ -735,21 +748,16 @@ int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
* \returns 0 in success * \returns 0 in success
*/ */
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) { int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *openair0_cfg) {
usrp_state_t *s = (usrp_state_t *)device->priv;
usrp_state_t *s = (usrp_state_t*)device->priv; static int first_call=1;
static int first_call=1; static double rf_freq,diff;
static double rf_freq,diff; uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]);
rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL;
uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]); rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0];
rf_freq=openair0_cfg[0].rx_freq[0];
rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL; s->usrp->set_rx_freq(rx_tune_req);
rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0]; return(0);
rf_freq=openair0_cfg[0].rx_freq[0];
s->usrp->set_rx_freq(rx_tune_req);
return(0);
} }
/*! \brief Set Gains (TX/RX) /*! \brief Set Gains (TX/RX)
...@@ -757,62 +765,62 @@ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *open ...@@ -757,62 +765,62 @@ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *open
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
* \returns 0 in success * \returns 0 in success
*/ */
int trx_usrp_set_gains(openair0_device* device, int trx_usrp_set_gains(openair0_device *device,
openair0_config_t *openair0_cfg) { openair0_config_t *openair0_cfg) {
usrp_state_t *s = (usrp_state_t *)device->priv;
::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(0);
s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_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()) {
LOG_E(PHY,"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);
}
usrp_state_t *s = (usrp_state_t*)device->priv; s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]);
::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(0); LOG_I(PHY,"Setting USRP RX gain to %f (rx_gain %f,gain_range.stop() %f)\n",
s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[0]); openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0],
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0); openair0_cfg[0].rx_gain[0],gain_range.stop());
// limit to maximum gain return(0);
if (openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] > gain_range.stop()) {
LOG_E(PHY,"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]);
LOG_I(PHY,"Setting USRP RX gain to %f (rx_gain %f,gain_range.stop() %f)\n",
openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0],
openair0_cfg[0].rx_gain[0],gain_range.stop());
return(0);
} }
/*! \brief Stop USRP /*! \brief Stop USRP
* \param card refers to the hardware index to use * \param card refers to the hardware index to use
*/ */
int trx_usrp_stop(openair0_device* device) { int trx_usrp_stop(openair0_device *device) {
return(0); return(0);
} }
/*! \brief USRPB210 RX calibration table */ /*! \brief USRPB210 RX calibration table */
rx_gain_calib_table_t calib_table_b210[] = { rx_gain_calib_table_t calib_table_b210[] = {
{3500000000.0,44.0}, {3500000000.0,44.0},
{2660000000.0,49.0}, {2660000000.0,49.0},
{2300000000.0,50.0}, {2300000000.0,50.0},
{1880000000.0,53.0}, {1880000000.0,53.0},
{816000000.0,58.0}, {816000000.0,58.0},
{-1,0} {-1,0}
}; };
/*! \brief USRPB210 RX calibration table */ /*! \brief USRPB210 RX calibration table */
rx_gain_calib_table_t calib_table_b210_38[] = { rx_gain_calib_table_t calib_table_b210_38[] = {
{3500000000.0,44.0}, {3500000000.0,44.0},
{2660000000.0,49.8}, {2660000000.0,49.8},
{2300000000.0,51.0}, {2300000000.0,51.0},
{1880000000.0,53.0}, {1880000000.0,53.0},
{816000000.0,57.0}, {816000000.0,57.0},
{-1,0} {-1,0}
}; };
/*! \brief USRPx310 RX calibration table */ /*! \brief USRPx310 RX calibration table */
rx_gain_calib_table_t calib_table_x310[] = { rx_gain_calib_table_t calib_table_x310[] = {
{3500000000.0,77.0}, {3500000000.0,77.0},
{2660000000.0,81.0}, {2660000000.0,81.0},
{2300000000.0,81.0}, {2300000000.0,81.0},
{1880000000.0,82.0}, {1880000000.0,82.0},
{816000000.0,85.0}, {816000000.0,85.0},
{-1,0} {-1,0}
}; };
/*! \brief Set RX gain offset /*! \brief Set RX gain offset
...@@ -821,72 +829,81 @@ rx_gain_calib_table_t calib_table_x310[] = { ...@@ -821,72 +829,81 @@ rx_gain_calib_table_t calib_table_x310[] = {
* \returns 0 in success * \returns 0 in success
*/ */
void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) { void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) {
int i=0;
// loop through calibration table to find best adjustment factor for RX frequency
double min_diff = 6e9,diff,gain_adj=0.0;
int i=0; if (bw_gain_adjust==1) {
// loop through calibration table to find best adjustment factor for RX frequency switch ((int)openair0_cfg[0].sample_rate) {
double min_diff = 6e9,diff,gain_adj=0.0; case 30720000:
if (bw_gain_adjust==1) { break;
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000: case 23040000:
break; gain_adj=1.25;
case 23040000: break;
gain_adj=1.25;
break; case 15360000:
case 15360000: gain_adj=3.0;
gain_adj=3.0; break;
break;
case 7680000: case 7680000:
gain_adj=6.0; gain_adj=6.0;
break; break;
case 3840000:
gain_adj=9.0; case 3840000:
break; gain_adj=9.0;
case 1920000: break;
gain_adj=12.0;
break; case 1920000:
default: gain_adj=12.0;
LOG_E(PHY,"unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate); break;
exit(-1);
break; default:
} LOG_E(PHY,"unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate);
exit(-1);
break;
} }
while (openair0_cfg->rx_gain_calib_table[i].freq>0) { }
diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq);
LOG_I(PHY,"cal %d: freq %f, offset %f, diff %f\n", while (openair0_cfg->rx_gain_calib_table[i].freq>0) {
i, diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq);
openair0_cfg->rx_gain_calib_table[i].freq, LOG_I(PHY,"cal %d: freq %f, offset %f, diff %f\n",
openair0_cfg->rx_gain_calib_table[i].offset,diff); i,
if (min_diff > diff) { openair0_cfg->rx_gain_calib_table[i].freq,
min_diff = diff; openair0_cfg->rx_gain_calib_table[i].offset,diff);
openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj;
} if (min_diff > diff) {
i++; min_diff = diff;
openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj;
} }
i++;
}
} }
/*! \brief print the USRP statistics /*! \brief print the USRP statistics
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
*/ */
int trx_usrp_get_stats(openair0_device* device) { int trx_usrp_get_stats(openair0_device *device) {
return(0); return(0);
} }
/*! \brief Reset the USRP statistics /*! \brief Reset the USRP statistics
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
*/ */
int trx_usrp_reset_stats(openair0_device* device) { int trx_usrp_reset_stats(openair0_device *device) {
return(0); return(0);
} }
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
extern "C" { extern "C" {
/*! \brief Initializer for USRP record/playback config /*! \brief Initializer for USRP record/playback config
* \param parameter array description * \param parameter array description
* \returns 0 on success * \returns 0 on success
*/ */
int trx_usrp_recplay_config_init(paramdef_t *usrp_recplay_params) { int trx_usrp_recplay_config_init(paramdef_t *usrp_recplay_params) {
// --subframes-file // --subframes-file
memcpy(usrp_recplay_params[0].optname, config_opt_sf_file, strlen(config_opt_sf_file)); memcpy(usrp_recplay_params[0].optname, config_opt_sf_file, strlen(config_opt_sf_file));
usrp_recplay_params[0].helpstr = config_hlp_sf_file; usrp_recplay_params[0].helpstr = config_hlp_sf_file;
...@@ -943,9 +960,8 @@ int trx_usrp_recplay_config_init(paramdef_t *usrp_recplay_params) { ...@@ -943,9 +960,8 @@ int trx_usrp_recplay_config_init(paramdef_t *usrp_recplay_params) {
usrp_recplay_params[6].defuintval=DEF_SF_DELAY_WRITE; usrp_recplay_params[6].defuintval=DEF_SF_DELAY_WRITE;
usrp_recplay_params[6].type=TYPE_UINT; usrp_recplay_params[6].type=TYPE_UINT;
usrp_recplay_params[6].numelt=0; usrp_recplay_params[6].numelt=0;
return 0; // always ok return 0; // always ok
} }
} }
#endif #endif
...@@ -954,478 +970,473 @@ extern "C" { ...@@ -954,478 +970,473 @@ extern "C" {
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
*/ */
int device_init(openair0_device* device, openair0_config_t *openair0_cfg) { int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
LOG_D(PHY, "openair0_cfg[0].sdr_addrs == '%s'\n", openair0_cfg[0].sdr_addrs); LOG_D(PHY, "openair0_cfg[0].sdr_addrs == '%s'\n", openair0_cfg[0].sdr_addrs);
LOG_D(PHY, "openair0_cfg[0].clock_source == '%d'\n", openair0_cfg[0].clock_source); LOG_D(PHY, "openair0_cfg[0].clock_source == '%d'\n", openair0_cfg[0].clock_source);
#if defined(USRP_REC_PLAY)
paramdef_t usrp_recplay_params[7];
struct sysinfo systeminfo;
// to check
static int done = 0;
if (done == 1) {
return 0;
} // prevent from multiple init
done = 1;
// end to check
// Use mmap for IQ files for systems with less than 6GB total RAM
sysinfo(&systeminfo);
if (systeminfo.totalram < 6144000000) {
use_mmap = 0;
}
memset(usrp_recplay_params, 0, 7*sizeof(paramdef_t));
memset(&u_sf_filename[0], 0, 1024);
if (trx_usrp_recplay_config_init(usrp_recplay_params) != 0) {
std::cerr << "USRP device record/replay mode configuration error exiting" << std::endl;
return -1;
}
config_process_cmdline(usrp_recplay_params,sizeof(usrp_recplay_params)/sizeof(paramdef_t),NULL);
if (strlen(u_sf_filename) == 0) {
(void) strcpy(u_sf_filename, DEF_SF_FILE);
}
if (u_sf_replay == 1) u_sf_mode = 2;
if (u_sf_record == 1) u_sf_mode = 1;
if (u_sf_mode == 2) {
// Replay subframes from from file
int bw_gain_adjust=0;
device->openair0_cfg = openair0_cfg;
device->type = USRP_B200_DEV;
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
openair0_cfg[0].tx_sample_advance = 80;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
set_rx_gain_offset(&openair0_cfg[0],0,bw_gain_adjust);
device->priv = NULL;
device->trx_start_func = trx_usrp_start;
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;
device->openair0_cfg = openair0_cfg;
std::cerr << "USRP device initialized in subframes replay mode for " << u_sf_loops << " loops. Use mmap="
<< use_mmap << std::endl;
} else {
#endif
uhd::set_thread_priority_safe(1.0);
usrp_state_t *s = (usrp_state_t *)calloc(sizeof(usrp_state_t),1);
if (openair0_cfg[0].clock_source==gpsdo)
s->use_gps =1;
// Initialize USRP device
device->openair0_cfg = openair0_cfg;
int vers=0,subvers=0,subsubvers=0;
int bw_gain_adjust=0;
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
paramdef_t usrp_recplay_params[7];
struct sysinfo systeminfo;
// to check
static int done = 0;
if (done == 1) {
return 0;
} // prevent from multiple init
done = 1;
// end to check
// Use mmap for IQ files for systems with less than 6GB total RAM
sysinfo(&systeminfo);
if (systeminfo.totalram < 6144000000) {
use_mmap = 0;
}
memset(usrp_recplay_params, 0, 7*sizeof(paramdef_t));
memset(&u_sf_filename[0], 0, 1024);
if (trx_usrp_recplay_config_init(usrp_recplay_params) != 0) {
std::cerr << "USRP device record/replay mode configuration error exiting" << std::endl;
return -1;
}
config_process_cmdline(usrp_recplay_params,sizeof(usrp_recplay_params)/sizeof(paramdef_t),NULL);
if (strlen(u_sf_filename) == 0) { if (u_sf_mode == 1) {
(void) strcpy(u_sf_filename, DEF_SF_FILE); std::cerr << "USRP device initialized in subframes record mode" << std::endl;
} }
if (u_sf_replay == 1) u_sf_mode = 2;
if (u_sf_record == 1) u_sf_mode = 1;
if (u_sf_mode == 2) {
// Replay subframes from from file
int bw_gain_adjust=0;
device->openair0_cfg = openair0_cfg;
device->type = USRP_B200_DEV;
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
openair0_cfg[0].tx_sample_advance = 80;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
set_rx_gain_offset(&openair0_cfg[0],0,bw_gain_adjust);
device->priv = NULL;
device->trx_start_func = trx_usrp_start;
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;
device->openair0_cfg = openair0_cfg;
std::cerr << "USRP device initialized in subframes replay mode for " << u_sf_loops << " loops. Use mmap="
<< use_mmap << std::endl;
} else {
#endif #endif
uhd::set_thread_priority_safe(1.0); sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
usrp_state_t *s = (usrp_state_t*)calloc(sizeof(usrp_state_t),1); LOG_I(PHY,"Checking for USRPs : UHD %s (%d.%d.%d)\n",
uhd::get_version_string().c_str(),vers,subvers,subsubvers);
if (openair0_cfg[0].clock_source==gpsdo)
s->use_gps =1; std::string args;
if (openair0_cfg[0].sdr_addrs == NULL) {
// Initialize USRP device args = "type=b200";
device->openair0_cfg = openair0_cfg; } else {
args = openair0_cfg[0].sdr_addrs;
std::string args = "type=b200";
char *addr_args = NULL;
// Check whether sdr_addrs is set in the config or not
if (openair0_cfg[0].sdr_addrs != NULL) {
if (strcmp(openair0_cfg[0].sdr_addrs, "0.0.0.0") != 0) {
// Check whether sdr_addrs contains multiple IP addresses
// and split and add them to addr_args
if (strstr(openair0_cfg[0].sdr_addrs, ",") != NULL) {
char *addr0 = openair0_cfg[0].sdr_addrs;
// Replace , with \0
strsep(&openair0_cfg[0].sdr_addrs, ",");
char *addr1 = openair0_cfg[0].sdr_addrs;
// Allocate memory for ",addr0=,addr1=\0" and the addresses
size_t addr_args_len = sizeof(char)*(15 + strlen(addr0) + strlen(addr1));
addr_args = (char *)malloc(addr_args_len);
snprintf(addr_args, addr_args_len, ",addr0=%s,addr1=%s", addr0, addr1);
args += addr_args;
LOG_D(PHY, "addr_args == '%s'\n", addr_args);
}
}
} }
uhd::device_addrs_t device_adds = uhd::device::find(args); uhd::device_addrs_t device_adds = uhd::device::find(args);
int vers=0,subvers=0,subsubvers=0; if (device_adds.size() == 0) {
int bw_gain_adjust=0; std::cerr<<"No USRP Device Found. " << std::endl;
free(s);
return -1;
} else if (device_adds.size() > 1) {
std::cerr<<"More than one USRP Device Found. Please specify device more precisely in config file." << std::endl;
free(s);
return -1;
}
#if defined(USRP_REC_PLAY) std::cerr << "Found USRP " << device_adds[0].get("type") << "\n";
if (u_sf_mode == 1) { double usrp_master_clock;
std::cerr << "USRP device initialized in subframes record mode" << std::endl;
} if (device_adds[0].get("type") == "b200") {
#endif printf("Found USRP b200\n");
sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); device->type = USRP_B200_DEV;
LOG_I(PHY,"Checking for USRPs : UHD %s (%d.%d.%d)\n", usrp_master_clock = 30.72e6;
uhd::get_version_string().c_str(),vers,subvers,subsubvers); args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=15360, recv_frame_size=15360" ;
if(device_adds.size() == 0) { }
double usrp_master_clock = 184.32e6; if (device_adds[0].get("type") == "n3xx") {
std::string args = "type=x300"; printf("Found USRP n300\n");
device->type=USRP_X300_DEV; //treat it as X300 for now
if (addr_args) { usrp_master_clock = 122.88e6;
args += addr_args; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
} }
// workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate if (device_adds[0].get("type") == "x300") {
printf("Found USRP x300\n");
device->type=USRP_X300_DEV;
usrp_master_clock = 184.32e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
}
// args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096"; s->usrp = uhd::usrp::multi_usrp::make(args);
uhd::device_addrs_t device_adds = uhd::device::find(args);
if(device_adds.size() == 0) { // lock mboard clocks
args += ",addr=192.168.30.2"; if (openair0_cfg[0].clock_source == internal)
s->usrp->set_clock_source("internal");
else
s->usrp->set_clock_source("external");
uhd::device_addrs_t device_adds = uhd::device::find(args); if (device->type==USRP_X300_DEV) {
openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
#if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info
#endif
LOG_I(PHY,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
if(device_adds.size() == 0) { switch ((int)openair0_cfg[0].sample_rate) {
case 122880000:
std::cerr<<"No USRP Device Found. " << std::endl; // from usrp_time_offset
free(s); //openair0_cfg[0].samples_per_packet = 2048;
return -1; openair0_cfg[0].tx_sample_advance = 15; //to be checked
} openair0_cfg[0].tx_bw = 80e6;
} openair0_cfg[0].rx_bw = 80e6;
LOG_I(PHY,"Found USRP X300\n"); break;
s->usrp = uhd::usrp::multi_usrp::make(args);
// lock mboard clocks case 61440000:
if (openair0_cfg[0].clock_source == internal) // from usrp_time_offset
s->usrp->set_clock_source("internal"); //openair0_cfg[0].samples_per_packet = 2048;
else openair0_cfg[0].tx_sample_advance = 15;
s->usrp->set_clock_source("external"); openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;
break;
case 30720000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
//Setting device type to USRP X300/X310 case 15360000:
device->type=USRP_X300_DEV; //openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
openair0_cfg[0].tx_bw = 10e6;
openair0_cfg[0].rx_bw = 10e6;
break;
// this is not working yet, master clock has to be set via constructor case 7680000:
// set master clock rate and sample rate for tx & rx for streaming //openair0_cfg[0].samples_per_packet = 2048;
//s->usrp->set_master_clock_rate(usrp_master_clock); openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 5e6;
openair0_cfg[0].rx_bw = 5e6;
break;
case 1920000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 1.25e6;
openair0_cfg[0].rx_bw = 1.25e6;
break;
openair0_cfg[0].rx_gain_calib_table = calib_table_x310; default:
LOG_E(PHY,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
}
if (device->type == USRP_B200_DEV) {
if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
bw_gain_adjust=0;
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info
#endif #endif
} else {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
#if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info
#endif
}
LOG_I(PHY,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate); switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
switch ((int)openair0_cfg[0].sample_rate) { s->usrp->set_master_clock_rate(30.72e6);
case 122880000: //openair0_cfg[0].samples_per_packet = 1024;
// from usrp_time_offset openair0_cfg[0].tx_sample_advance = 115;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].tx_sample_advance = 15; //to be checked openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_bw = 80e6; break;
openair0_cfg[0].rx_bw = 80e6;
break;
case 61440000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;
break;
case 30720000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 15360000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
openair0_cfg[0].tx_bw = 10e6;
openair0_cfg[0].rx_bw = 10e6;
break;
case 7680000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 5e6;
openair0_cfg[0].rx_bw = 5e6;
break;
case 1920000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 1.25e6;
openair0_cfg[0].rx_bw = 1.25e6;
break;
default:
LOG_E(PHY,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
} else { case 23040000:
LOG_I(PHY,"Found USRP B200\n"); s->usrp->set_master_clock_rate(23.04e6); //to be checked
args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=15360, recv_frame_size=15360" ; //openair0_cfg[0].samples_per_packet = 1024;
s->usrp = uhd::usrp::multi_usrp::make(args); openair0_cfg[0].tx_sample_advance = 113;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
// s->usrp->set_rx_subdev_spec(rx_subdev); case 15360000:
// s->usrp->set_tx_subdev_spec(tx_subdev); s->usrp->set_master_clock_rate(30.72e06);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 103;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
// do not explicitly set the clock to "internal", because this will disable the gpsdo case 7680000:
// // lock mboard clocks s->usrp->set_master_clock_rate(30.72e6);
// s->usrp->set_clock_source("internal"); //openair0_cfg[0].samples_per_packet = 1024;
// set master clock rate and sample rate for tx & rx for streaming openair0_cfg[0].tx_sample_advance = 80;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
// lock mboard clocks case 1920000:
if (openair0_cfg[0].clock_source == internal){ s->usrp->set_master_clock_rate(30.72e6);
s->usrp->set_clock_source("internal"); //openair0_cfg[0].samples_per_packet = 1024;
} openair0_cfg[0].tx_sample_advance = 40;
else{ openair0_cfg[0].tx_bw = 20e6;
s->usrp->set_clock_source("external"); openair0_cfg[0].rx_bw = 20e6;
s->usrp->set_time_source("external"); break;
}
device->type = USRP_B200_DEV;
if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
bw_gain_adjust=0;
#if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info
#endif
} else {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
#if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info
#endif
}
switch ((int)openair0_cfg[0].sample_rate) { default:
case 30720000: LOG_E(PHY,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
s->usrp->set_master_clock_rate(30.72e6); exit(-1);
//openair0_cfg[0].samples_per_packet = 1024; break;
openair0_cfg[0].tx_sample_advance = 115;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 23040000:
s->usrp->set_master_clock_rate(23.04e6); //to be checked
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 113;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 15360000:
s->usrp->set_master_clock_rate(30.72e06);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 103;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 7680000:
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 80;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 1920000:
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 40;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
default:
LOG_E(PHY,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
} }
}
/* device specific */ /* device specific */
//openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered //openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered
//openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered //openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
openair0_cfg[0].iq_txshift = 4;//shift openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
for(int i=0; i<s->usrp->get_rx_num_channels(); i++) { for(int i=0; i<s->usrp->get_rx_num_channels(); i++) {
if (i<openair0_cfg[0].rx_num_channels) { if (i<openair0_cfg[0].rx_num_channels) {
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i); s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i);
s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i);
set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust);
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i);
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); // limit to maximum gain
// limit to maximum gain AssertFatal( openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] <= gain_range.stop(),
AssertFatal( openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] <= gain_range.stop(), "RX Gain too high, lower by %f dB\n",
"RX Gain too high, lower by %f dB\n", openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop());
openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop()); s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i);
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i); LOG_I(PHY,"RX Gain %d %f (%f) => %f (max %f)\n",i,
LOG_I(PHY,"RX Gain %d %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], openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop());
openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop());
}
} }
}
LOG_D(PHY, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels()); LOG_D(PHY, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels());
LOG_D(PHY, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels); LOG_D(PHY, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels);
for(int i=0; i<s->usrp->get_tx_num_channels(); i++) { for(int i=0; i<s->usrp->get_tx_num_channels(); i++) {
::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i); ::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i);
if (i<openair0_cfg[0].tx_num_channels) { if (i<openair0_cfg[0].tx_num_channels) {
s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i); s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i);
s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i); s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i);
s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[i],i); s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[i],i);
LOG_I(PHY,"USRP TX_GAIN:%3.2lf gain_range:%3.2lf tx_gain:%3.2lf\n", gain_range_tx.stop()-openair0_cfg[0].tx_gain[i], gain_range_tx.stop(), openair0_cfg[0].tx_gain[i]);
LOG_I(PHY,"USRP TX_GAIN:%3.2lf gain_range:%3.2lf tx_gain:%3.2lf\n", gain_range_tx.stop()-openair0_cfg[0].tx_gain[i], gain_range_tx.stop(), openair0_cfg[0].tx_gain[i]);
}
} }
}
//s->usrp->set_clock_source("external"); //s->usrp->set_clock_source("external");
//s->usrp->set_time_source("external"); //s->usrp->set_time_source("external");
// display USRP settings
// display USRP settings LOG_I(PHY,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6);
LOG_I(PHY,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6); sleep(1);
sleep(1); // create tx & rx streamer
uhd::stream_args_t stream_args_rx("sc16", "sc16");
// create tx & rx streamer int samples=openair0_cfg[0].sample_rate;
uhd::stream_args_t stream_args_rx("sc16", "sc16"); int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps();
int samples=openair0_cfg[0].sample_rate; samples/=10000;
int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps(); LOG_I(PHY,"RF board max packet size %u, size for 100µs jitter %d \n", max, samples);
samples/=10000;
LOG_I(PHY,"RF board max packet size %u, size for 100µs jitter %d \n", max, samples); if ( samples < max )
if ( samples < max ) stream_args_rx.args["spp"] = str(boost::format("%d") % samples );
stream_args_rx.args["spp"] = str(boost::format("%d") % samples );
LOG_I(PHY,"rx_max_num_samps %zu\n", LOG_I(PHY,"rx_max_num_samps %zu\n",
s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps()); s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps());
for (int i = 0; i<openair0_cfg[0].rx_num_channels; i++) for (int i = 0; i<openair0_cfg[0].rx_num_channels; i++)
stream_args_rx.channels.push_back(i); stream_args_rx.channels.push_back(i);
s->rx_stream = s->usrp->get_rx_stream(stream_args_rx);
s->rx_stream = s->usrp->get_rx_stream(stream_args_rx);
uhd::stream_args_t stream_args_tx("sc16", "sc16"); uhd::stream_args_t stream_args_tx("sc16", "sc16");
for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++)
stream_args_tx.channels.push_back(i); for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++)
s->tx_stream = s->usrp->get_tx_stream(stream_args_tx); stream_args_tx.channels.push_back(i);
/* Setting TX/RX BW after streamers are created due to USRP calibration issue */ s->tx_stream = s->usrp->get_tx_stream(stream_args_tx);
for(int i=0; i<s->usrp->get_tx_num_channels() && i<openair0_cfg[0].tx_num_channels; i++)
s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); /* Setting TX/RX BW after streamers are created due to USRP calibration issue */
for(int i=0; i<s->usrp->get_tx_num_channels() && i<openair0_cfg[0].tx_num_channels; i++)
for(int i=0; i<s->usrp->get_rx_num_channels() && i<openair0_cfg[0].rx_num_channels; i++) s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i);
s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i);
for(int i=0; i<s->usrp->get_rx_num_channels() && i<openair0_cfg[0].rx_num_channels; i++)
for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) { s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i);
LOG_I(PHY,"RX Channel %d\n",i);
LOG_I(PHY," Actual RX sample rate: %fMSps...\n",s->usrp->get_rx_rate(i)/1e6); for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) {
LOG_I(PHY," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i)/1e9); LOG_I(PHY,"RX Channel %d\n",i);
LOG_I(PHY," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i)); LOG_I(PHY," Actual RX sample rate: %fMSps...\n",s->usrp->get_rx_rate(i)/1e6);
LOG_I(PHY," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i)/1e6); LOG_I(PHY," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i)/1e9);
LOG_I(PHY," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i).c_str()); LOG_I(PHY," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i));
} LOG_I(PHY," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i)/1e6);
LOG_I(PHY," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i).c_str());
}
for (int i=0; i<openair0_cfg[0].tx_num_channels; i++) { for (int i=0; i<openair0_cfg[0].tx_num_channels; i++) {
LOG_I(PHY,"TX Channel %d\n",i); LOG_I(PHY,"TX Channel %d\n",i);
LOG_I(PHY," Actual TX sample rate: %fMSps...\n", s->usrp->get_tx_rate(i)/1e6); LOG_I(PHY," Actual TX sample rate: %fMSps...\n", s->usrp->get_tx_rate(i)/1e6);
LOG_I(PHY," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i)/1e9); LOG_I(PHY," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i)/1e9);
LOG_I(PHY," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i)); LOG_I(PHY," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i));
LOG_I(PHY," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6); LOG_I(PHY," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6);
LOG_I(PHY," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str()); LOG_I(PHY," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str());
} }
LOG_I(PHY,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs()); LOG_I(PHY,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
device->priv = s;
device->priv = s; device->trx_start_func = trx_usrp_start;
device->trx_start_func = trx_usrp_start; device->trx_write_func = trx_usrp_write;
device->trx_write_func = trx_usrp_write; device->trx_read_func = trx_usrp_read;
device->trx_read_func = trx_usrp_read; device->trx_get_stats_func = trx_usrp_get_stats;
device->trx_get_stats_func = trx_usrp_get_stats; device->trx_reset_stats_func = trx_usrp_reset_stats;
device->trx_reset_stats_func = trx_usrp_reset_stats; device->trx_end_func = trx_usrp_end;
device->trx_end_func = trx_usrp_end; device->trx_stop_func = trx_usrp_stop;
device->trx_stop_func = trx_usrp_stop; device->trx_set_freq_func = trx_usrp_set_freq;
device->trx_set_freq_func = trx_usrp_set_freq; device->trx_set_gains_func = trx_usrp_set_gains;
device->trx_set_gains_func = trx_usrp_set_gains; device->openair0_cfg = openair0_cfg;
device->openair0_cfg = openair0_cfg; s->sample_rate = openair0_cfg[0].sample_rate;
s->sample_rate = openair0_cfg[0].sample_rate; // TODO:
// TODO: // init tx_forward_nsamps based usrp_time_offset ex
// init tx_forward_nsamps based usrp_time_offset ex if(is_equal(s->sample_rate, (double)30.72e6))
if(is_equal(s->sample_rate, (double)30.72e6)) s->tx_forward_nsamps = 176;
s->tx_forward_nsamps = 176;
if(is_equal(s->sample_rate, (double)15.36e6)) if(is_equal(s->sample_rate, (double)15.36e6))
s->tx_forward_nsamps = 90; s->tx_forward_nsamps = 90;
if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50; if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50;
if (s->use_gps == 1) {
if (sync_to_gps(device)) { if (s->use_gps == 1) {
LOG_I(PHY,"USRP fails to sync with GPS...\n"); if (sync_to_gps(device)) {
exit(0); LOG_I(PHY,"USRP fails to sync with GPS...\n");
} exit(0);
} }
#if defined(USRP_REC_PLAY)
} }
#if defined(USRP_REC_PLAY)
}
#endif #endif
#if defined(USRP_REC_PLAY) #if defined(USRP_REC_PLAY)
if (u_sf_mode == 1) { // record mode
ms_sample = (iqrec_t*) malloc(u_sf_max * sizeof(iqrec_t)); if (u_sf_mode == 1) { // record mode
if (ms_sample == NULL) { ms_sample = (iqrec_t *) malloc(u_sf_max * sizeof(iqrec_t));
std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl;
exit(-1); if (ms_sample == NULL) {
} std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl;
memset(ms_sample, 0, u_sf_max * BELL_LABS_IQ_BYTES_PER_SF); exit(-1);
} }
if (u_sf_mode == 2) {
if (use_mmap) { memset(ms_sample, 0, u_sf_max * BELL_LABS_IQ_BYTES_PER_SF);
// use mmap }
mmapfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE);
if (mmapfd != 0) { if (u_sf_mode == 2) {
fstat(mmapfd, &sb); if (use_mmap) {
std::cerr << "Loading subframes using mmap() from " << u_sf_filename << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl; // use mmap
ms_sample = (iqrec_t*) mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, mmapfd, 0); mmapfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE);
if (ms_sample != MAP_FAILED) {
nb_samples = (sb.st_size / sizeof(iqrec_t)); if (mmapfd != 0) {
int aligned = (((unsigned long)ms_sample & 31) == 0)? 1:0; fstat(mmapfd, &sb);
std::cerr<< "Loaded "<< nb_samples << " subframes." << std::endl; std::cerr << "Loading subframes using mmap() from " << u_sf_filename << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl;
if (aligned == 0) { ms_sample = (iqrec_t *) mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, mmapfd, 0);
std::cerr<< "mmap address is not 32 bytes aligned, exiting." << std::endl;
close(mmapfd); if (ms_sample != MAP_FAILED) {
exit(-1); nb_samples = (sb.st_size / sizeof(iqrec_t));
} int aligned = (((unsigned long)ms_sample & 31) == 0)? 1:0;
} else { std::cerr<< "Loaded "<< nb_samples << " subframes." << std::endl;
std::cerr << "Cannot mmap file, exiting." << std::endl;
close(mmapfd); if (aligned == 0) {
exit(-1); std::cerr<< "mmap address is not 32 bytes aligned, exiting." << std::endl;
} close(mmapfd);
} else { exit(-1);
std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl; }
exit(-1); } else {
} std::cerr << "Cannot mmap file, exiting." << std::endl;
} else { close(mmapfd);
iqfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE); exit(-1);
if (iqfd != 0) { }
fstat(iqfd, &sb); } else {
nb_samples = (sb.st_size / sizeof(iqrec_t)); std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl;
std::cerr << "Loading " << nb_samples << " subframes from " << u_sf_filename exit(-1);
<< " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl; }
// allocate buffer for 1 sample at a time } else {
ms_sample = (iqrec_t*) malloc(sizeof(iqrec_t)); iqfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE);
if (ms_sample == NULL) {
std::cerr<< "Memory allocation failed for individual subframe replay mode." << std::endl; if (iqfd != 0) {
close(iqfd); fstat(iqfd, &sb);
exit(-1); nb_samples = (sb.st_size / sizeof(iqrec_t));
} std::cerr << "Loading " << nb_samples << " subframes from " << u_sf_filename
memset(ms_sample, 0, sizeof(iqrec_t)); << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl;
// point at beginning of file // allocate buffer for 1 sample at a time
if (lseek(iqfd, 0, SEEK_SET) == 0) { ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t));
std::cerr << "Initial seek at beginning of the file" << std::endl;
} else { if (ms_sample == NULL) {
std::cerr << "Problem initial seek at beginning of the file" << std::endl; std::cerr<< "Memory allocation failed for individual subframe replay mode." << std::endl;
} close(iqfd);
} else { exit(-1);
std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl; }
exit(-1);
} memset(ms_sample, 0, sizeof(iqrec_t));
}
// point at beginning of file
if (lseek(iqfd, 0, SEEK_SET) == 0) {
std::cerr << "Initial seek at beginning of the file" << std::endl;
} else {
std::cerr << "Problem initial seek at beginning of the file" << std::endl;
}
} else {
std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl;
exit(-1);
}
} }
#endif
return 0;
} }
#endif
return 0;
}
} }
/*@}*/ /*@}*/
...@@ -111,8 +111,6 @@ extern volatile int start_UE; ...@@ -111,8 +111,6 @@ extern volatile int start_UE;
#endif #endif
extern volatile int oai_exit; extern volatile int oai_exit;
extern openair0_config_t openair0_cfg[MAX_CARDS];
extern int transmission_mode; extern int transmission_mode;
extern int oaisim_flag; extern int oaisim_flag;
......
...@@ -171,8 +171,6 @@ double rx_gain_off = 0.0; ...@@ -171,8 +171,6 @@ double rx_gain_off = 0.0;
double sample_rate=30.72e6; double sample_rate=30.72e6;
double bw = 10.0e6; double bw = 10.0e6;
static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
char rf_config_file[1024]; char rf_config_file[1024];
int chain_offset=0; int chain_offset=0;
...@@ -199,7 +197,6 @@ int otg_enabled; ...@@ -199,7 +197,6 @@ int otg_enabled;
//int number_of_cards = 1; //int number_of_cards = 1;
static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
uint32_t target_dl_mcs = 28; //maximum allowed mcs uint32_t target_dl_mcs = 28; //maximum allowed mcs
uint32_t target_ul_mcs = 20; uint32_t target_ul_mcs = 20;
uint32_t timing_advance = 0; uint32_t timing_advance = 0;
...@@ -250,8 +247,6 @@ WORKER_CONF_t get_thread_worker_conf(void) ...@@ -250,8 +247,6 @@ WORKER_CONF_t get_thread_worker_conf(void)
/* struct for ethernet specific parameters given in eNB conf file */ /* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params; eth_params_t *eth_params;
openair0_config_t openair0_cfg[MAX_CARDS];
double cpuf; double cpuf;
extern char uecap_xer[1024]; extern char uecap_xer[1024];
...@@ -632,112 +627,6 @@ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { ...@@ -632,112 +627,6 @@ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
} }
void init_openair0(void) {
int card;
int i;
for (card=0; card<MAX_CARDS; card++) {
openair0_cfg[card].mmapped_dma=mmapped_dma;
openair0_cfg[card].configFilename = NULL;
if(frame_parms[0]->N_RB_DL == 100) {
if(numerology == 0)
{
if (frame_parms[0]->threequarter_fs) {
openair0_cfg[card].sample_rate=23.04e6;
openair0_cfg[card].samples_per_frame = 230400;
openair0_cfg[card].tx_bw = 10e6;
openair0_cfg[card].rx_bw = 10e6;
} else {
openair0_cfg[card].sample_rate=30.72e6;
openair0_cfg[card].samples_per_frame = 307200;
openair0_cfg[card].tx_bw = 10e6;
openair0_cfg[card].rx_bw = 10e6;
}
}else if(numerology == 1)
{
openair0_cfg[card].sample_rate=61.44e6;
openair0_cfg[card].samples_per_frame = 307200;
openair0_cfg[card].tx_bw = 20e6;
openair0_cfg[card].rx_bw = 20e6;
}else if(numerology == 2)
{
openair0_cfg[card].sample_rate=122.88e6;
openair0_cfg[card].samples_per_frame = 307200;
openair0_cfg[card].tx_bw = 20e6;
openair0_cfg[card].rx_bw = 20e6;
}else
{
printf("Un supported numerology\n");
}
} else if(frame_parms[0]->N_RB_DL == 50) {
openair0_cfg[card].sample_rate=15.36e6;
openair0_cfg[card].samples_per_frame = 153600;
openair0_cfg[card].tx_bw = 5e6;
openair0_cfg[card].rx_bw = 5e6;
} else if (frame_parms[0]->N_RB_DL == 25) {
openair0_cfg[card].sample_rate=7.68e6;
openair0_cfg[card].samples_per_frame = 76800;
openair0_cfg[card].tx_bw = 2.5e6;
openair0_cfg[card].rx_bw = 2.5e6;
} else if (frame_parms[0]->N_RB_DL == 6) {
openair0_cfg[card].sample_rate=1.92e6;
openair0_cfg[card].samples_per_frame = 19200;
openair0_cfg[card].tx_bw = 1.5e6;
openair0_cfg[card].rx_bw = 1.5e6;
}
if (frame_parms[0]->frame_type==TDD)
openair0_cfg[card].duplex_mode = duplex_mode_TDD;
else //FDD
openair0_cfg[card].duplex_mode = duplex_mode_FDD;
printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
RC.eNB[0][0]->frame_parms.nb_antennas_tx ,
RC.eNB[0][0]->frame_parms.nb_antennas_rx );
openair0_cfg[card].Mod_id = 0;
openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
openair0_cfg[card].clock_source = clock_source;
openair0_cfg[card].tx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_tx );
openair0_cfg[card].rx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_rx );
for (i=0; i<4; i++) {
if (i<openair0_cfg[card].tx_num_channels)
openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i] ;
else
openair0_cfg[card].tx_freq[i]=0.0;
if (i<openair0_cfg[card].rx_num_channels)
openair0_cfg[card].rx_freq[i] =downlink_frequency[0][i] + uplink_frequency_offset[0][i] ;
else
openair0_cfg[card].rx_freq[i]=0.0;
openair0_cfg[card].autocal[i] = 1;
openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;
openair0_cfg[card].configFilename = rf_config_file;
printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
card,i, openair0_cfg[card].tx_gain[i],
openair0_cfg[card].rx_gain[i],
openair0_cfg[card].tx_freq[i],
openair0_cfg[card].rx_freq[i]);
}
} /* for loop on cards */
}
void wait_RUs(void) { void wait_RUs(void) {
LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask); LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
...@@ -922,9 +811,6 @@ int main( int argc, char **argv ) ...@@ -922,9 +811,6 @@ int main( int argc, char **argv )
mode = normal_txrx; mode = normal_txrx;
memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
set_latency_target(); set_latency_target();
...@@ -1283,8 +1169,6 @@ int main( int argc, char **argv ) ...@@ -1283,8 +1169,6 @@ int main( int argc, char **argv )
pthread_mutex_destroy(&ue_pf_po_mutex); pthread_mutex_destroy(&ue_pf_po_mutex);
// *** Handle per CC_id openair0
for(ru_id=0; ru_id<RC.nb_RU; ru_id++) { for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
if (RC.ru[ru_id]->rfdevice.trx_end_func) { if (RC.ru[ru_id]->rfdevice.trx_end_func) {
......
...@@ -98,6 +98,9 @@ ...@@ -98,6 +98,9 @@
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" #define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n"
#define CONFIG_HLP_USRP_CLK_SRC "USRP clock source: 'internal' or 'external'\n"
/***************************************************************************************************************************************/ /***************************************************************************************************************************************/
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
when calling config_get or config_getlist functions */ when calling config_get or config_getlist functions */
...@@ -147,7 +150,9 @@ ...@@ -147,7 +150,9 @@
{"num-ues", NULL, 0, u8ptr:&(NB_UE_INST), defuintval:1, TYPE_UINT8, 0}, \ {"num-ues", NULL, 0, u8ptr:&(NB_UE_INST), defuintval:1, TYPE_UINT8, 0}, \
{"r" , CONFIG_HLP_PRB, 0, u8ptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT8, 0}, \ {"r" , CONFIG_HLP_PRB, 0, u8ptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT8, 0}, \
{"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
} {"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200", TYPE_STRING, 0}, \
{"usrp-clksrc", CONFIG_HLP_USRP_CLK_SRC,0, strptr:(char **)&usrp_clksrc, defstrval:"internal", TYPE_STRING, 0} \
}
#define DEFAULT_DLF 2680000000 #define DEFAULT_DLF 2680000000
......
...@@ -223,6 +223,9 @@ int numerology = 0; ...@@ -223,6 +223,9 @@ int numerology = 0;
char *parallel_config = NULL; char *parallel_config = NULL;
char *worker_config = NULL; char *worker_config = NULL;
char* usrp_args=NULL;
char* usrp_clksrc=NULL;
static THREAD_STRUCT thread_struct; static THREAD_STRUCT thread_struct;
void set_parallel_conf(char *parallel_conf) void set_parallel_conf(char *parallel_conf)
{ {
...@@ -739,6 +742,26 @@ void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) { ...@@ -739,6 +742,26 @@ void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
openair0_cfg[card].tx_freq[i], openair0_cfg[card].tx_freq[i],
openair0_cfg[card].rx_freq[i]); openair0_cfg[card].rx_freq[i]);
} }
if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
if (usrp_clksrc) {
if (strcmp(usrp_clksrc, "internal") == 0) {
openair0_cfg[card].clock_source = internal;
LOG_D(PHY, "USRP clock source set as internal\n");
} else if (strcmp(usrp_clksrc, "external") == 0) {
openair0_cfg[card].clock_source = external;
LOG_D(PHY, "USRP clock source set as external\n");
} else if (strcmp(usrp_clksrc, "gpsdo") == 0) {
openair0_cfg[card].clock_source = gpsdo;
LOG_D(PHY, "USRP clock source set as gpsdo\n");
} else {
openair0_cfg[card].clock_source = internal;
LOG_I(PHY, "USRP clock source unknown ('%s'). defaulting to internal\n", usrp_clksrc);
}
} else {
openair0_cfg[card].clock_source = internal;
LOG_I(PHY, "USRP clock source not specified. defaulting to internal\n");
}
} }
} }
......
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