git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7885 818b1a75-f10b-46b9-bf7c-635c3b92a50f
1612 lines
51 KiB
C
1612 lines
51 KiB
C
/*******************************************************************************
|
|
OpenAirInterface
|
|
Copyright(c) 1999 - 2014 Eurecom
|
|
|
|
OpenAirInterface is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
|
|
OpenAirInterface is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenAirInterface.The full GNU General Public License is
|
|
included in this distribution in the file called "COPYING". If not,
|
|
see <http://www.gnu.org/licenses/>.
|
|
|
|
Contact Information
|
|
OpenAirInterface Admin: openair_admin@eurecom.fr
|
|
OpenAirInterface Tech : openair_tech@eurecom.fr
|
|
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
|
|
|
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
|
|
|
*******************************************************************************/
|
|
|
|
/*! \file lte-softmodem.c
|
|
* \brief main program to control HW and scheduling
|
|
* \author R. Knopp, F. Kaltenberger
|
|
* \date 2012
|
|
* \version 0.1
|
|
* \company Eurecom
|
|
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
|
|
* \note
|
|
* \warning
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <sched.h>
|
|
#include <signal.h>
|
|
#include <execinfo.h>
|
|
#include <getopt.h>
|
|
|
|
#include "rt_wrapper.h"
|
|
|
|
#include "PHY/types.h"
|
|
#include "PHY/TOOLS/defs.h"
|
|
#include "openair0_lib.h"
|
|
|
|
#include "UTIL/LOG/log.h"
|
|
#include "UTIL/LOG/vcd_signal_dumper.h"
|
|
|
|
#include "gain_control.h"
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
# include "intertask_interface_init.h"
|
|
# include "timer.h"
|
|
# if defined(ENABLE_USE_MME)
|
|
# include "s1ap_eNB.h"
|
|
# include "sctp_eNB_task.h"
|
|
# endif
|
|
#endif
|
|
|
|
#define OPENAIR_THREAD_PRIORITY 255
|
|
#define OPENAIR_THREAD_STACK_SIZE 8192
|
|
|
|
#ifdef XFORMS
|
|
/*
|
|
#include "PHY/TOOLS/lte_phy_scope.h"
|
|
#include "stats.h"
|
|
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
|
|
// at eNB 0, an UL scope for every UE
|
|
FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX];
|
|
FD_lte_phy_scope_enb *form_enb[NUMBER_OF_UE_MAX];
|
|
FD_stats_form *form_stats=NULL;
|
|
char title[255];
|
|
unsigned char scope_enb_num_ue = 1;
|
|
*/
|
|
#include "lte_scope.h"
|
|
FD_lte_scope *form_lte;
|
|
char title[255];
|
|
#endif //XFORMS
|
|
|
|
#ifdef EMOS
|
|
#include <gps.h>
|
|
struct gps_fix_t dummy_gps_data;
|
|
#ifdef RTAI
|
|
#include <rtai_fifos.h>
|
|
#endif
|
|
|
|
//#define CHANSOUNDER_FIFO_SIZE 10485760 // 10 Mbytes FIFO
|
|
//#define CHANSOUNDER_FIFO_SIZE 20971520 // 20 Mbytes FIFO
|
|
#define CHANSOUNDER_FIFO_SIZE 52428800 // 50 Mbytes FIFO
|
|
//#define CHANSOUNDER_FIFO_SIZE 104857600 // 100 Mbytes FIFO
|
|
//#define CHANSOUNDER_FIFO_SIZE 1073741824 // 1Gbyte FIFO
|
|
#define CHANSOUNDER_FIFO_MINOR 4 // minor of the FIFO device - this is /dev/rtf3
|
|
#define CHANSOUNDER_FIFO_DEV "/dev/rtf4"
|
|
#endif
|
|
|
|
#define FRAME_PERIOD 100000000ULL
|
|
#define DAQ_PERIOD 66667ULL
|
|
#define LTE_SLOTS_PER_FRAME 20
|
|
//#define RESAMPLING_FACTOR 0
|
|
#define SAMPLES_PER_SLOT 15360
|
|
#define FRAME_LENGTH_COMPLEX_SAMPLES (SAMPLES_PER_SLOT*LTE_SLOTS_PER_FRAME)
|
|
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
|
|
|
|
#ifdef RTAI
|
|
static SEM *mutex;
|
|
//static CND *cond;
|
|
|
|
static long int thread0;
|
|
//static long int thread1;
|
|
//static long int sync_thread;
|
|
#else
|
|
pthread_t thread0;
|
|
//pthread_t thread1;
|
|
pthread_attr_t attr_dlsch_threads;
|
|
struct sched_param sched_param_dlsch;
|
|
#endif
|
|
|
|
pthread_t thread2; //xforms
|
|
pthread_t thread3; //emos
|
|
pthread_t thread4; //GPS
|
|
pthread_t thread5; //log
|
|
|
|
/*
|
|
static int instance_cnt=-1; //0 means worker is busy, -1 means its free
|
|
int instance_cnt_ptr_kern,*instance_cnt_ptr_user;
|
|
int pci_interface_ptr_kern;
|
|
*/
|
|
//extern unsigned int bigphys_top;
|
|
//extern unsigned int mem_base;
|
|
|
|
int number_of_cards = 1;
|
|
exmimo_config_t *p_exmimo_config;
|
|
exmimo_id_t *p_exmimo_id;
|
|
volatile unsigned int *DAQ_MBOX;
|
|
|
|
int oai_exit = 0;
|
|
|
|
//int time_offset[4] = {-138,-138,-138,-138};
|
|
//int time_offset[4] = {-145,-145,-145,-145};
|
|
int time_offset[4] = {0,0,0,0};
|
|
|
|
int fs4_test=0;
|
|
char UE_flag=0;
|
|
uint8_t eNB_id=0,UE_id=0;
|
|
|
|
// this array sets the bandwidth used for each card (and applies to all chains on one card).
|
|
exmimo_bw_t bandwidth[MAX_CARDS] = {BW5,BW5,BW5,BW5};
|
|
// the array carrier_freq sets the frequency for each chain of each card. A 0 means that the chain is disabled.
|
|
// Please make sure that the total number of channels enabled per card is in accordance with the following rules:
|
|
// BW20: one channel, BW10: 2 channels, BW5: 4 channels
|
|
//uint32_t carrier_freq[MAX_CARDS][4] = {{2590000000,0,0,0},{2590000000,0,0,0},{2605000000,2605000000,0,0},{0,0,0,0}};
|
|
//uint32_t carrier_freq[MAX_CARDS][4] = {{2590000000,0,0,0},{2605000000,2605000000,0,0},{0,0,0,0},{0,0,0,0}};
|
|
uint32_t carrier_freq[MAX_CARDS][4] = {{771500000,771500000,771500000,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};
|
|
|
|
// the following paramters set the aquisition time and period. These parameters have to be set in accordance with the write speed of your harddisk and the required throughput according to the setting above (see also channel_buffer_size which is computed later).
|
|
#define AQU_LENGTH_FRAMES 100 //Aquisition time in frames
|
|
#define AQU_PERIOD_FRAMES 100 //Repetition time of aquisition in frames
|
|
#define AQU_LENGTH_SLOTS (AQU_LENGTH_FRAMES*LTE_SLOTS_PER_FRAME) //Aquisition time in slots
|
|
#define AQU_PERIOD_SLOTS (AQU_PERIOD_FRAMES*LTE_SLOTS_PER_FRAME) //Repetition time of aquisition in slots
|
|
|
|
int32_t rx_total_gain_dB[3] = {-112, -124, -136};
|
|
|
|
/*
|
|
// this array sets the bandwidth used for each card (and applies to all chains on one card).
|
|
exmimo_bw_t bandwidth[MAX_CARDS] = {BW20,BW20,BW10,BW5};
|
|
// the array carrier_freq sets the frequency for each chain of each card. A 0 means that the chain is disabled.
|
|
// Please make sure that the total number of channels enabled per card is in accordance with the following rules:
|
|
// BW20: one channel, BW10: 2 channels, BW5: 4 channels
|
|
uint32_t carrier_freq[MAX_CARDS][4] = {{2590000000,0,0,0},{2590000000,0,0,0},{2605000000,2605000000,0,0},{0,0,0,0}};
|
|
//uint32_t carrier_freq[MAX_CARDS][4] = {{2590000000,0,0,0},{2605000000,2605000000,0,0},{0,0,0,0},{0,0,0,0}};
|
|
//uint32_t carrier_freq[MAX_CARDS][4] = {{2590000000,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};
|
|
|
|
// the following paramters set the aquisition time and period. These parameters have to be set in accordance with the write speed of your harddisk and the required throughput according to the setting above (see also channel_buffer_size which is computed later).
|
|
#define AQU_LENGTH_FRAMES 100 //Aquisition time in frames
|
|
#define AQU_PERIOD_FRAMES 200 //Repetition time of aquisition in frames
|
|
#define AQU_LENGTH_SLOTS (AQU_LENGTH_FRAMES*LTE_SLOTS_PER_FRAME) //Aquisition time in slots
|
|
#define AQU_PERIOD_SLOTS (AQU_PERIOD_FRAMES*LTE_SLOTS_PER_FRAME) //Repetition time of aquisition in slots
|
|
|
|
int32_t rx_total_gain_dB[3] = {-105, -110, -115};
|
|
*/
|
|
|
|
char dumpfile_dir[256] = "/mnt/emos";
|
|
|
|
char *conf_config_file_name = NULL;
|
|
|
|
unsigned int lost_bytes=0;
|
|
unsigned int rssi_lin[MAX_CARDS][4],rssi_lin_max[MAX_CARDS],rssi_lin_avg[MAX_CARDS];
|
|
uint8_t rssi_avg_dB[MAX_CARDS];
|
|
long long unsigned int total_bytes=0;
|
|
|
|
struct timing_info_t {
|
|
//unsigned int frame, hw_slot, last_slot, next_slot;
|
|
RTIME time_min, time_max, time_avg, time_last, time_now;
|
|
//unsigned int mbox0, mbox1, mbox2, mbox_target;
|
|
unsigned int n_samples;
|
|
} timing_info;
|
|
|
|
extern int16_t* sync_corr_ue0;
|
|
extern int16_t prach_ifft[4][1024*2];
|
|
|
|
unsigned int frame;
|
|
int rx_input_level_dBm;
|
|
#ifdef XFORMS
|
|
extern int otg_enabled;
|
|
#else
|
|
int otg_enabled;
|
|
#endif
|
|
|
|
int mbox_bounds[20] = {8,16,24,30,38,46,54,60,68,76,84,90,98,106,114,120,128,136,144, 0}; ///boundaries of slots in terms ob mbox counter rounded up to even numbers
|
|
//int mbox_bounds[20] = {6,14,22,28,36,44,52,58,66,74,82,88,96,104,112,118,126,134,142, 148}; ///boundaries of slots in terms ob mbox counter rounded up to even numbers
|
|
|
|
//void setup_ue_buffers(PHY_VARS_UE *phy_vars_ue, LTE_DL_FRAME_PARMS *frame_parms, int carrier);
|
|
//void setup_eNB_buffers(PHY_VARS_eNB *phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms, int carrier);
|
|
void test_config(int card, int ant, unsigned int rf_mode, int UE_flag);
|
|
|
|
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
|
|
{
|
|
return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
|
|
}
|
|
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
|
|
{
|
|
return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
|
|
}
|
|
|
|
void signal_handler(int sig)
|
|
{
|
|
void *array[10];
|
|
size_t size;
|
|
|
|
if (sig==SIGSEGV) {
|
|
// get void*'s for all entries on the stack
|
|
size = backtrace(array, 10);
|
|
|
|
// print out all the frames to stderr
|
|
fprintf(stderr, "Error: signal %d:\n", sig);
|
|
backtrace_symbols_fd(array, size, 2);
|
|
exit(-1);
|
|
} else {
|
|
oai_exit=1;
|
|
}
|
|
}
|
|
|
|
void exit_fun(const char* s)
|
|
{
|
|
void *array[10];
|
|
size_t size;
|
|
|
|
printf("Exiting: %s\n",s);
|
|
|
|
oai_exit=1;
|
|
//rt_sleep_ns(FRAME_PERIOD);
|
|
|
|
//exit (-1);
|
|
}
|
|
|
|
#ifdef XFORMS
|
|
extern void ia_receiver_on_off( FL_OBJECT * form, long arg) {}
|
|
|
|
|
|
void *scope_thread(void *arg)
|
|
{
|
|
int16_t prach_corr[1024];
|
|
char stats_buffer[16384];
|
|
//FILE *UE_stats, *eNB_stats;
|
|
int i,len=0;
|
|
float rxsig_t_dB[4][FRAME_LENGTH_COMPLEX_SAMPLES];
|
|
float time[FRAME_LENGTH_COMPLEX_SAMPLES];
|
|
struct sched_param sched_param;
|
|
int card,ant,idx;
|
|
|
|
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
|
|
sched_setscheduler(0, SCHED_FIFO,&sched_param);
|
|
|
|
printf("Scope thread has priority %d\n",sched_param.sched_priority);
|
|
|
|
/*
|
|
if (UE_flag==1)
|
|
UE_stats = fopen("UE_stats.txt", "w");
|
|
else
|
|
eNB_stats = fopen("eNB_stats.txt", "w");
|
|
*/
|
|
|
|
while (!oai_exit) {
|
|
/*
|
|
if (UE_flag==1) {
|
|
len = dump_ue_stats (PHY_vars_UE_g[0], stats_buffer, 0, mode,rx_input_level_dBm);
|
|
fl_set_object_label(form_stats->stats_text, stats_buffer);
|
|
//rewind (UE_stats);
|
|
//fwrite (stats_buffer, 1, len, UE_stats);
|
|
|
|
phy_scope_UE(form_ue[UE_id],
|
|
PHY_vars_UE_g[UE_id],
|
|
eNB_id,
|
|
UE_id,7);
|
|
|
|
} else {
|
|
len = dump_eNB_stats (PHY_vars_eNB_g[0], stats_buffer, 0);
|
|
fl_set_object_label(form_stats->stats_text, stats_buffer);
|
|
//rewind (eNB_stats);
|
|
//fwrite (stats_buffer, 1, len, eNB_stats);
|
|
for(UE_id=0;UE_id<scope_enb_num_ue;UE_id++) {
|
|
phy_scope_eNB(form_enb[UE_id],
|
|
PHY_vars_eNB_g[eNB_id],
|
|
UE_id);
|
|
}
|
|
|
|
}
|
|
*/
|
|
|
|
idx = 0;
|
|
|
|
for (card=0; card<number_of_cards; card++) {
|
|
for (ant=0; ant<4; ant++) {
|
|
if ((carrier_freq[card][ant] != 0) && (idx<4)) {
|
|
len = FRAME_LENGTH_COMPLEX_SAMPLES/(1<<openair0_exmimo_pci[card].exmimo_config_ptr->framing.resampling_factor[ant]);
|
|
|
|
for (i=0; i<len; i++) {
|
|
//rxsig_t_dB[0][i] = 10*log10(1.0+(float) ((((int16_t*) openair0_exmimo_pci[card].adc_head[0])[2*i])*(((int16_t*) openair0_exmimo_pci[card].adc_head[0])[2*i])+(((int16_t*) openair0_exmimo_pci[card].adc_head[0])[2*i+1])*(((int16_t*) openair0_exmimo_pci[card].adc_head[0])[2*i+1])));
|
|
rxsig_t_dB[0][i] = (float) ((((int16_t*) openair0_exmimo_pci[card].adc_head[ant])[2*i]));
|
|
rxsig_t_dB[1][i] = (float) ((((int16_t*) openair0_exmimo_pci[card].adc_head[ant])[2*i+1]));
|
|
time[i] = (float) i;
|
|
}
|
|
|
|
fl_set_xyplot_data(form_lte->channel_t_re[idx],time,rxsig_t_dB[0],len,"","","");
|
|
fl_set_xyplot_data(form_lte->channel_t_im[idx],time,rxsig_t_dB[1],len,"","","");
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//printf("doing forms\n");
|
|
usleep(100000);
|
|
}
|
|
|
|
//fclose (UE_stats);
|
|
//fclose (eNB_stats);
|
|
|
|
pthread_exit((void*)arg);
|
|
}
|
|
#endif
|
|
|
|
int dummy_tx_buffer[3840*4] __attribute__((aligned(16)));
|
|
|
|
|
|
#ifdef EMOS
|
|
void* gps_thread (void *arg)
|
|
{
|
|
|
|
struct gps_data_t gps_data;
|
|
struct gps_data_t *gps_data_ptr = &gps_data;
|
|
struct sched_param sched_param;
|
|
int ret;
|
|
|
|
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
|
|
sched_setscheduler(0, SCHED_FIFO,&sched_param);
|
|
|
|
printf("GPS thread has priority %d\n",sched_param.sched_priority);
|
|
|
|
memset(&dummy_gps_data,0,sizeof(struct gps_fix_t));
|
|
|
|
#if GPSD_API_MAJOR_VERSION>=5
|
|
ret = gps_open("127.0.0.1","2947",gps_data_ptr);
|
|
|
|
if (ret!=0)
|
|
#else
|
|
gps_data_ptr = gps_open("127.0.0.1","2947");
|
|
|
|
if (gps_data_ptr == NULL)
|
|
#endif
|
|
{
|
|
printf("[EMOS] Could not open GPS\n");
|
|
pthread_exit((void*)arg);
|
|
}
|
|
|
|
#if GPSD_API_MAJOR_VERSION>=4
|
|
else if (gps_stream(gps_data_ptr, WATCH_ENABLE,NULL) != 0)
|
|
#else
|
|
else if (gps_query(gps_data_ptr, "w+x") != 0)
|
|
#endif
|
|
{
|
|
printf("[EMOS] Error sending command to GPS\n");
|
|
pthread_exit((void*) arg);
|
|
} else
|
|
printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data_ptr);
|
|
|
|
|
|
while (!oai_exit) {
|
|
printf("[EMOS] polling data from gps\n");
|
|
#if GPSD_API_MAJOR_VERSION>=5
|
|
|
|
if (gps_waiting(gps_data_ptr,500)) {
|
|
if (gps_read(gps_data_ptr) <= 0) {
|
|
#else
|
|
|
|
if (gps_waiting(gps_data_ptr)) {
|
|
if (gps_poll(gps_data_ptr) != 0) {
|
|
#endif
|
|
printf("[EMOS] problem polling data from gps\n");
|
|
} else {
|
|
memcpy(&dummy_gps_data,&(gps_data_ptr->fix),sizeof(struct gps_fix_t));
|
|
printf("[EMOS] lat %g, lon %g\n",gps_data_ptr->fix.latitude,gps_data_ptr->fix.longitude);
|
|
}
|
|
} //gps_waiting
|
|
else {
|
|
printf("[EMOS] WARNING: No GPS data available, storing dummy packet\n");
|
|
}
|
|
|
|
//rt_sleep_ns(1000000000LL);
|
|
sleep(1);
|
|
} //oai_exit
|
|
|
|
pthread_exit((void*) arg);
|
|
|
|
}
|
|
|
|
void *log_thread (void *arg)
|
|
{
|
|
//struct tm now_sec;
|
|
struct timeval now;
|
|
int card;
|
|
FILE *logfile_id;
|
|
char logfile_name[1024];
|
|
time_t starttime_tmp;
|
|
struct tm starttime;
|
|
|
|
//open file
|
|
time(&starttime_tmp);
|
|
localtime_r(&starttime_tmp,&starttime);
|
|
snprintf(logfile_name,1024,"%s/%s_data_%d%02d%02d_%02d%02d%02d.log",
|
|
dumpfile_dir,
|
|
(UE_flag==0) ? "eNB" : "UE",
|
|
1900+starttime.tm_year, starttime.tm_mon+1, starttime.tm_mday, starttime.tm_hour, starttime.tm_min, starttime.tm_sec);
|
|
logfile_id = fopen(logfile_name,"w");
|
|
|
|
if ((logfile_id == NULL)) {
|
|
fprintf(stderr, "[EMOS] Error opening logfile %s\n",logfile_name);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
fprintf(logfile_id,
|
|
"#time, frame, total bytes wrote, total bytes lost, GPS time, GPS mode, lat, lon, alt, speed, rssi_lin_max[0], rssi_lin_avg[0], rssi_avg_dBm[0], rssi_avg_dB[0], rx_gain[0], LNA[0], ...\n");
|
|
|
|
while (!oai_exit) {
|
|
gettimeofday(&now,NULL);
|
|
//localtime_r(&(now.tv_sec),&now_sec);
|
|
fprintf(logfile_id,"%d.%06d, %d, %llu, %u, %e, %d, %e, %e, %e, %e, ",
|
|
(int) now.tv_sec, (int)now.tv_usec,
|
|
frame, total_bytes,lost_bytes,
|
|
dummy_gps_data.time, dummy_gps_data.mode, dummy_gps_data.latitude, dummy_gps_data.longitude, dummy_gps_data.altitude, dummy_gps_data.speed);
|
|
|
|
for (card=0; card<number_of_cards; card++)
|
|
if (carrier_freq[card][0] != 0)
|
|
fprintf(logfile_id,"%d, %d, %d, %d, %d, %d, ", rssi_lin_max[card], rssi_lin_avg[card],
|
|
rssi_avg_dB[card] + rx_total_gain_dB[((openair0_exmimo_pci[card].exmimo_config_ptr->rf.rf_mode[0] & LNAGAINMASK) >> 14)-1] - openair0_exmimo_pci[card].exmimo_config_ptr->rf.rx_gain[0][0],
|
|
rssi_avg_dB[card], openair0_exmimo_pci[card].exmimo_config_ptr->rf.rx_gain[0][0], (openair0_exmimo_pci[card].exmimo_config_ptr->rf.rf_mode[0] & LNAGAINMASK) >> 14);
|
|
|
|
fprintf(logfile_id,"\n");
|
|
usleep(10000);
|
|
}
|
|
|
|
//close file
|
|
fclose(logfile_id);
|
|
|
|
pthread_exit((void*) arg);
|
|
|
|
}
|
|
|
|
void *emos_thread (void *arg)
|
|
{
|
|
char c;
|
|
char *fifo2file_buffer, *fifo2file_ptr;
|
|
|
|
int fifo, counter=0, bytes;
|
|
|
|
FILE *dumpfile_id;
|
|
char dumpfile_name[1024];
|
|
time_t starttime_tmp;
|
|
struct tm starttime;
|
|
|
|
//time_t timer;
|
|
struct tm now_sec;
|
|
struct timeval now;
|
|
|
|
struct sched_param sched_param;
|
|
int ret;
|
|
|
|
int card, ant;
|
|
int channel_buffer_size=0; //in bytes
|
|
|
|
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
|
|
|
|
sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
|
|
sched_setscheduler(0, SCHED_FIFO,&sched_param);
|
|
|
|
printf("EMOS thread has priority %d\n",sched_param.sched_priority);
|
|
|
|
//timer = time(NULL);
|
|
//now = localtime(&timer);
|
|
|
|
for (card=0; card<number_of_cards; card++)
|
|
for (ant=0; ant<4; ant++)
|
|
if (carrier_freq[card][ant] != 0) {
|
|
printf("card %d, ant %d: freq %u, BW %d\n",card,ant,carrier_freq[card][ant],bandwidth[card]);
|
|
channel_buffer_size += SAMPLES_PER_SLOT/(1<<openair0_exmimo_pci[card].exmimo_config_ptr->framing.resampling_factor[ant]);
|
|
}
|
|
|
|
channel_buffer_size *= 4; //4 bytes per sample
|
|
|
|
// allocate memory for NO_FRAMES_DISK channes estimations
|
|
fifo2file_buffer = malloc(AQU_LENGTH_SLOTS*channel_buffer_size);
|
|
fifo2file_ptr = fifo2file_buffer;
|
|
|
|
if (fifo2file_buffer == NULL) {
|
|
printf("[EMOS] Cound not allocate memory for fifo2file_buffer\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if ((fifo = open(CHANSOUNDER_FIFO_DEV, O_RDONLY)) < 0) {
|
|
fprintf(stderr, "[EMOS] Error opening the fifo\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
|
|
time(&starttime_tmp);
|
|
localtime_r(&starttime_tmp,&starttime);
|
|
snprintf(dumpfile_name,1024,"%s/%s_data_%d%02d%02d_%02d%02d%02d.EMOS",
|
|
dumpfile_dir,
|
|
(UE_flag==0) ? "eNB" : "UE",
|
|
1900+starttime.tm_year, starttime.tm_mon+1, starttime.tm_mday, starttime.tm_hour, starttime.tm_min, starttime.tm_sec);
|
|
|
|
dumpfile_id = fopen(dumpfile_name,"w");
|
|
|
|
if ((dumpfile_id == NULL)) {
|
|
fprintf(stderr, "[EMOS] Error opening dumpfile %s\n",dumpfile_name);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
printf("[EMOS] starting dump, channel_buffer_size=%d ...\n",channel_buffer_size);
|
|
|
|
while (!oai_exit) {
|
|
//bytes = rtf_read_timed(fifo, fifo2file_ptr, channel_buffer_size,100);
|
|
bytes = rtf_read_all_at_once(fifo, fifo2file_ptr, channel_buffer_size);
|
|
|
|
if (bytes<=0) {
|
|
usleep(100);
|
|
continue;
|
|
}
|
|
|
|
if (bytes != channel_buffer_size) {
|
|
printf("[EMOS] Frame %d: ERROR! Only got %d bytes instead of %d!\n",frame,bytes,channel_buffer_size);
|
|
}
|
|
|
|
/*
|
|
if (UE_flag==0)
|
|
printf("eNB: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx,bytes);
|
|
else
|
|
printf("UE: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_UE*)fifo2file_ptr)->frame_rx,bytes);
|
|
*/
|
|
|
|
fifo2file_ptr += channel_buffer_size;
|
|
counter ++;
|
|
total_bytes += bytes;
|
|
|
|
if ((counter%AQU_LENGTH_SLOTS)==0) {
|
|
//reset stuff
|
|
fifo2file_ptr = fifo2file_buffer;
|
|
//counter = 0;
|
|
|
|
printf("[EMOS] Frame %d: start writing %d bytes to disk\n",frame,AQU_LENGTH_SLOTS*channel_buffer_size);
|
|
|
|
//flush buffer to disk
|
|
if (fwrite(fifo2file_buffer, sizeof(char), AQU_LENGTH_SLOTS*channel_buffer_size, dumpfile_id) != AQU_LENGTH_SLOTS*channel_buffer_size) {
|
|
fprintf(stderr, "[EMOS] Error writing to dumpfile\n");
|
|
exit(EXIT_FAILURE);
|
|
} else
|
|
printf("[EMOS] Frame %d: wrote %d bytes to disk\n",frame,AQU_LENGTH_SLOTS*channel_buffer_size);
|
|
|
|
}
|
|
|
|
if ((counter%AQU_LENGTH_SLOTS)==0) {
|
|
//time(&starttime_tmp);
|
|
gettimeofday(&now,NULL);
|
|
localtime_r(&(now.tv_sec),&now_sec);
|
|
printf("[EMOS] %02d:%02d:%02d.%03d, frame %d, total bytes wrote %llu, bytes lost %u\n",
|
|
now_sec.tm_hour, now_sec.tm_min, now_sec.tm_sec, (int)(now.tv_usec/1000), frame, total_bytes,lost_bytes);
|
|
|
|
for (card=0; card<number_of_cards; card++)
|
|
if (carrier_freq[card][0] != 0)
|
|
printf("[EMOS] %02d:%02d:%02d.%03d, card %d, rssi_lin_max %d, rssi_lin_avg %d, rssi_avg_dBm %d (rssi_avg_dB %d, rx_gain %d, LNA %d)\n",
|
|
now_sec.tm_hour, now_sec.tm_min, now_sec.tm_sec, (int)(now.tv_usec/1000), card, rssi_lin_max[card], rssi_lin_avg[card],
|
|
rssi_avg_dB[card] + rx_total_gain_dB[((openair0_exmimo_pci[card].exmimo_config_ptr->rf.rf_mode[0] & LNAGAINMASK) >> 14)-1] - openair0_exmimo_pci[card].exmimo_config_ptr->rf.rx_gain[0][0],
|
|
rssi_avg_dB[card], openair0_exmimo_pci[card].exmimo_config_ptr->rf.rx_gain[0][0], (openair0_exmimo_pci[card].exmimo_config_ptr->rf.rf_mode[0] & LNAGAINMASK) >> 14);
|
|
|
|
//printf("[EMOS] %02d:%02d:%02d, frame %d, GPS time %e, GPS mode %d, lat %e, lon %e, alt %e, speed %e\n", starttime.tm_hour, starttime.tm_min, starttime.tm_sec, counter/20, dummy_gps_data.time, dummy_gps_data.mode, dummy_gps_data.latitude, dummy_gps_data.longitude, dummy_gps_data.altitude, dummy_gps_data.speed);
|
|
}
|
|
}
|
|
|
|
free(fifo2file_buffer);
|
|
fclose(dumpfile_id);
|
|
close(fifo);
|
|
|
|
pthread_exit((void*) arg);
|
|
|
|
}
|
|
#endif
|
|
|
|
/* This is the main eNB thread. It gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */
|
|
static void *eNB_thread(void *arg)
|
|
{
|
|
#ifdef RTAI
|
|
RT_TASK *task;
|
|
#endif
|
|
unsigned char slot=0,last_slot, next_slot, hw_slot;
|
|
unsigned int msg1;
|
|
unsigned int aa,slot_offset, slot_offset_F;
|
|
int diff;
|
|
int delay_cnt;
|
|
RTIME time_in, time_diff;
|
|
int mbox_target=0,mbox_current=0;
|
|
int i,ret;
|
|
int tx_offset;
|
|
int bytes, bytes_tot=0, bytes_len;
|
|
long long int k1=1000;
|
|
long long int k2=1024-k1;
|
|
int ant,len,card = 0;
|
|
|
|
#ifdef RTAI
|
|
task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF);
|
|
LOG_D(HW,"Started eNB thread (id %p)\n",task);
|
|
#endif
|
|
|
|
#ifdef HARD_RT
|
|
rt_make_hard_real_time();
|
|
#endif
|
|
|
|
mlockall(MCL_CURRENT | MCL_FUTURE);
|
|
|
|
timing_info.time_min = 100000000ULL;
|
|
timing_info.time_max = 0;
|
|
timing_info.time_avg = 0;
|
|
timing_info.n_samples = 0;
|
|
|
|
while (!oai_exit) {
|
|
hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
|
|
//LOG_D(HW,"eNB frame %d, time %llu: slot %d, hw_slot %d (mbox %d)\n",frame,rt_get_time_ns(),slot,hw_slot,((unsigned int *)DAQ_MBOX)[0]);
|
|
//this is the mbox counter where we should be
|
|
//mbox_target = ((((slot+1)%20)*15+1)>>1)%150;
|
|
mbox_target = mbox_bounds[slot];
|
|
//this is the mbox counter where we are
|
|
mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
|
|
|
|
//this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD)
|
|
if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
|
|
diff = 150-mbox_current+mbox_target;
|
|
else if ((mbox_current<15) && (mbox_target>=135))
|
|
diff = -150+mbox_target-mbox_current;
|
|
else
|
|
diff = mbox_target - mbox_current;
|
|
|
|
if (diff < (-7)) {
|
|
// at the eNB, even slots have double as much time since most of the processing is done here and almost nothing in odd slots
|
|
LOG_D(HW,"eNB Frame %d, time %llu: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, diff);
|
|
slot++;
|
|
|
|
//if (frame>0)
|
|
//oai_exit=1;
|
|
if (slot==20) {
|
|
slot=0;
|
|
frame++;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (diff>8)
|
|
LOG_D(HW,"eNB Frame %d, time %llu: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, mbox_current,
|
|
mbox_target, diff);
|
|
|
|
delay_cnt = 0;
|
|
|
|
while ((diff>0) && (!oai_exit)) {
|
|
time_in = rt_get_time_ns();
|
|
//LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d, (slot+1)*15=%d, diff %d, time %llu\n",frame,delay_cnt,hw_slot,((unsigned int *)DAQ_MBOX)[0],slot,(((slot+1)*15)>>1),diff,time_in);
|
|
//LOG_D(HW,"eNB Frame %d, time %llu: sleeping for %llu (slot %d, hw_slot %d, diff %d, mbox %d, delay_cnt %d)\n", frame, time_in, diff*DAQ_PERIOD,slot,hw_slot,diff,((volatile unsigned int *)DAQ_MBOX)[0],delay_cnt);
|
|
ret = rt_sleep_ns(diff*DAQ_PERIOD);
|
|
|
|
if (ret)
|
|
LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
|
|
|
|
hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
|
|
//LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns());
|
|
delay_cnt++;
|
|
|
|
if (delay_cnt == 10) {
|
|
oai_exit = 1;
|
|
LOG_D(HW,"eNB Frame %d: HW stopped ... \n",frame);
|
|
}
|
|
|
|
mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
|
|
|
|
if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
|
|
diff = 150-mbox_current+mbox_target;
|
|
else if ((mbox_current<15) && (mbox_target>=135))
|
|
diff = -150+mbox_target-mbox_current;
|
|
else
|
|
diff = mbox_target - mbox_current;
|
|
}
|
|
|
|
last_slot = (slot)%LTE_SLOTS_PER_FRAME;
|
|
|
|
if (last_slot <0)
|
|
last_slot+=20;
|
|
|
|
next_slot = (slot+3)%LTE_SLOTS_PER_FRAME;
|
|
|
|
if (frame>=AQU_LENGTH_FRAMES) {
|
|
timing_info.time_last = timing_info.time_now;
|
|
timing_info.time_now = rt_get_time_ns();
|
|
|
|
if (timing_info.n_samples>0) {
|
|
time_diff = timing_info.time_now - timing_info.time_last;
|
|
|
|
if (time_diff < timing_info.time_min)
|
|
timing_info.time_min = time_diff;
|
|
|
|
if (time_diff > timing_info.time_max)
|
|
timing_info.time_max = time_diff;
|
|
|
|
timing_info.time_avg += time_diff;
|
|
}
|
|
|
|
timing_info.n_samples++;
|
|
|
|
// do measurements for rssi
|
|
if (last_slot==0) {
|
|
for (card=0; card<number_of_cards; card++) {
|
|
len = SAMPLES_PER_SLOT/(1<<openair0_exmimo_pci[card].exmimo_config_ptr->framing.resampling_factor[0]);
|
|
rssi_lin_max[card] = 0;
|
|
|
|
for (ant=0; ant<4; ant++) {
|
|
if (carrier_freq[card][ant] != 0) {
|
|
rssi_lin[card][ant] = signal_energy(&(((int32_t*) openair0_exmimo_pci[card].adc_head[ant])[last_slot*len]), len);
|
|
rssi_lin_max[card] = max(rssi_lin_max[card],rssi_lin[card][ant]);
|
|
}
|
|
}
|
|
|
|
rssi_lin_avg[card] = (int) ((k1*((long long int)(rssi_lin_avg[card])) + (k2*((long long int)(rssi_lin_max[card]))))>>10);
|
|
rssi_avg_dB[card] = dB_fixed(rssi_lin_avg[card]);
|
|
|
|
if (frame%100==0) {
|
|
gain_control_all(rssi_avg_dB[card],card);
|
|
//printf("AGC for card %d: rx_power_fil_dB=%d, rx_gain=%d, LNA=%d (1=Byp,2=Med,3=Max)\n",card,rssi_avg_dB,openair0_exmimo_pci[card].exmimo_config_ptr->rf.rx_gain[0][0],(openair0_exmimo_pci[card].exmimo_config_ptr->rf.rf_mode[0]&LNAGAINMASK)>>14);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef EMOS
|
|
|
|
// save raw samples here
|
|
if ((last_slot==0) && ((frame%AQU_PERIOD_FRAMES)==0)) {
|
|
printf("[EMOS] Frame %d: start writing to FIFO\n",frame);
|
|
bytes_tot=0;
|
|
}
|
|
|
|
if ((frame%AQU_PERIOD_FRAMES)<AQU_LENGTH_FRAMES) {
|
|
for (card=0; card<number_of_cards; card++) {
|
|
for (ant=0; ant<4; ant++) {
|
|
if (carrier_freq[card][ant] != 0) {
|
|
len = SAMPLES_PER_SLOT/(1<<openair0_exmimo_pci[card].exmimo_config_ptr->framing.resampling_factor[ant]);
|
|
bytes_len = len*4;
|
|
bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &(((int32_t*) openair0_exmimo_pci[card].adc_head[ant])[last_slot*len]), bytes_len);
|
|
bytes_tot += bytes;
|
|
|
|
if (bytes!=bytes_len) {
|
|
lost_bytes += bytes_len - bytes;
|
|
LOG_W(PHY,"Frame %d, slot %d: Problem writing EMOS data to FIFO (bytes=%d, size=%d)\n",
|
|
frame, last_slot, bytes, bytes_len);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((last_slot==19) && ((frame%AQU_PERIOD_FRAMES)==99))
|
|
printf("[EMOS] Frame %d: sent %d bytes to FIFO\n",frame,bytes_tot);
|
|
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
slot++;
|
|
|
|
if (slot==20) {
|
|
slot=0;
|
|
frame++;
|
|
}
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
itti_update_lte_time(frame, slot);
|
|
#endif
|
|
}
|
|
|
|
LOG_D(HW,"eNB_thread: finished, ran %d times.\n",frame);
|
|
|
|
#ifdef HARD_RT
|
|
rt_make_soft_real_time();
|
|
#endif
|
|
|
|
// clean task
|
|
#ifdef RTAI
|
|
rt_task_delete(task);
|
|
#endif
|
|
LOG_D(HW,"Task deleted. returning\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
|
|
#ifdef RTAI
|
|
RT_TASK *task;
|
|
#endif
|
|
int i,j,aa;
|
|
void *status;
|
|
int card = 0;
|
|
|
|
uint32_t rf_mode_base = TXLPFNORM + TXLPFEN + RXLPFNORM + RXLPFEN + LNA1ON +LNAMax + RFBBNORM;
|
|
uint32_t rf_local[4] = {8255000,8255000,8255000,8255000}; // UE zepto
|
|
//{8254617, 8254617, 8254617, 8254617}; //eNB khalifa
|
|
//{8255067,8254810,8257340,8257340}; // eNB PETRONAS
|
|
uint32_t rf_vcocal[4] = {910,910,910,910};
|
|
uint32_t rf_vcocal_850[4] = {2015, 2015, 2015, 2015};
|
|
uint32_t rf_rxdc[4] = {32896,32896,32896,32896};
|
|
uint32_t rxgain[4] = {30,30,30,30};
|
|
uint32_t txgain[4] = {0,0,0,0};
|
|
|
|
uint16_t Nid_cell = 0;
|
|
uint8_t cooperation_flag=0, transmission_mode=1, abstraction_flag=0;
|
|
uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
|
|
|
|
int c;
|
|
char do_forms=0;
|
|
unsigned int fd;
|
|
unsigned int tcxo = 114;
|
|
|
|
int amp;
|
|
uint8_t prach_fmt;
|
|
int N_ZC;
|
|
|
|
char rxg_fname[100];
|
|
char txg_fname[100];
|
|
char rflo_fname[100];
|
|
char rfdc_fname[100];
|
|
FILE *rxg_fd=NULL;
|
|
FILE *txg_fd=NULL;
|
|
FILE *rflo_fd=NULL;
|
|
FILE *rfdc_fd=NULL;
|
|
unsigned int rxg_max[4]= {133,133,133,133}, rxg_med[4]= {127,127,127,127}, rxg_byp[4]= {120,120,120,120};
|
|
int tx_max_power=0;
|
|
|
|
char line[1000];
|
|
int l;
|
|
int ret, ant;
|
|
int ant_offset=0;
|
|
|
|
int error_code;
|
|
char *itti_dump_file = NULL;
|
|
|
|
const struct option long_options[] = {
|
|
{"calib-ue-rx", required_argument, NULL, 256},
|
|
{"calib-ue-rx-med", required_argument, NULL, 257},
|
|
{"calib-ue-rx-byp", required_argument, NULL, 258},
|
|
{"debug-ue-prach", no_argument, NULL, 259},
|
|
{"no-L2-connect", no_argument, NULL, 260},
|
|
{NULL, 0, NULL, 0}
|
|
};
|
|
|
|
//mode = normal_txrx;
|
|
|
|
|
|
while ((c = getopt_long (argc, argv, "C:K:O:ST:UdF:V",long_options,NULL)) != -1) {
|
|
switch (c) {
|
|
case 'V':
|
|
ouput_vcd = 1;
|
|
break;
|
|
|
|
case 'd':
|
|
do_forms=1;
|
|
break;
|
|
|
|
case 'U':
|
|
UE_flag = 1;
|
|
break;
|
|
|
|
case 'C':
|
|
for (card=0; card<MAX_CARDS; card++) {
|
|
carrier_freq[card][0] = atof(optarg);
|
|
carrier_freq[card][1] = atof(optarg);
|
|
carrier_freq[card][2] = atof(optarg);
|
|
carrier_freq[card][3] = atof(optarg);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'S':
|
|
fs4_test=1;
|
|
break;
|
|
|
|
case 'T':
|
|
tcxo=atoi(optarg);
|
|
break;
|
|
|
|
case 'K':
|
|
#if defined(ENABLE_ITTI)
|
|
itti_dump_file = strdup(optarg);
|
|
#else
|
|
printf("-K option is disabled when ENABLE_ITTI is not defined\n");
|
|
#endif
|
|
break;
|
|
|
|
case 'O':
|
|
conf_config_file_name = optarg;
|
|
break;
|
|
|
|
case 'F':
|
|
sprintf(rxg_fname,"%srxg.lime",optarg);
|
|
rxg_fd = fopen(rxg_fname,"r");
|
|
|
|
if (rxg_fd) {
|
|
printf("Loading RX Gain parameters from %s\n",rxg_fname);
|
|
l=0;
|
|
|
|
while (fgets(line, sizeof(line), rxg_fd)) {
|
|
if ((strlen(line)==0) || (*line == '#')) continue; //ignore empty or comment lines
|
|
else {
|
|
if (l==0) sscanf(line,"%d %d %d %d",&rxg_max[0],&rxg_max[1],&rxg_max[2],&rxg_max[3]);
|
|
|
|
if (l==1) sscanf(line,"%d %d %d %d",&rxg_med[0],&rxg_med[1],&rxg_med[2],&rxg_med[3]);
|
|
|
|
if (l==2) sscanf(line,"%d %d %d %d",&rxg_byp[0],&rxg_byp[1],&rxg_byp[2],&rxg_byp[3]);
|
|
|
|
l++;
|
|
}
|
|
}
|
|
} else
|
|
printf("%s not found, running with defaults\n",rxg_fname);
|
|
|
|
sprintf(txg_fname,"%stxg.lime",optarg);
|
|
txg_fd = fopen(txg_fname,"r");
|
|
|
|
if (txg_fd) {
|
|
printf("Loading TX Gain parameters from %s\n",txg_fname);
|
|
l=0;
|
|
|
|
while (fgets(line, sizeof(line), txg_fd)) {
|
|
if ((strlen(line)==0) || (*line == '#')) {
|
|
continue; //ignore empty or comment lines
|
|
} else {
|
|
if (l==0) sscanf(line,"%d %d %d %d",&txgain[0],&txgain[1],&txgain[2],&txgain[3]);
|
|
|
|
if (l==1) sscanf(line,"%d",&tx_max_power);
|
|
|
|
l++;
|
|
}
|
|
}
|
|
} else
|
|
printf("%s not found, running with defaults\n",txg_fname);
|
|
|
|
sprintf(rflo_fname,"%srflo.lime",optarg);
|
|
rflo_fd = fopen(rflo_fname,"r");
|
|
|
|
if (rflo_fd) {
|
|
printf("Loading RF LO parameters from %s\n",rflo_fname);
|
|
fscanf(rflo_fd,"%d %d %d %d",&rf_local[0],&rf_local[1],&rf_local[2],&rf_local[3]);
|
|
} else
|
|
printf("%s not found, running with defaults\n",rflo_fname);
|
|
|
|
sprintf(rfdc_fname,"%srfdc.lime",optarg);
|
|
rfdc_fd = fopen(rfdc_fname,"r");
|
|
|
|
if (rfdc_fd) {
|
|
printf("Loading RF DC parameters from %s\n",rfdc_fname);
|
|
fscanf(rfdc_fd,"%d %d %d %d",&rf_rxdc[0],&rf_rxdc[1],&rf_rxdc[2],&rf_rxdc[3]);
|
|
} else
|
|
printf("%s not found, running with defaults\n",rfdc_fname);
|
|
|
|
break;
|
|
|
|
/*
|
|
case 256:
|
|
mode = rx_calib_ue;
|
|
rx_input_level_dBm = atoi(optarg);
|
|
printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm);
|
|
break;
|
|
case 257:
|
|
mode = rx_calib_ue_med;
|
|
rx_input_level_dBm = atoi(optarg);
|
|
printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm);
|
|
break;
|
|
case 258:
|
|
mode = rx_calib_ue_byp;
|
|
rx_input_level_dBm = atoi(optarg);
|
|
printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm);
|
|
break;
|
|
case 259:
|
|
mode = debug_prach;
|
|
break;
|
|
case 260:
|
|
mode = no_L2_connect;
|
|
break;
|
|
*/
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UE_flag==1)
|
|
printf("configuring for UE\n");
|
|
else
|
|
printf("configuring for eNB\n");
|
|
|
|
//randominit (0);
|
|
//set_taus_seed (0);
|
|
|
|
// initialize the log (see log.h for details)
|
|
logInit();
|
|
|
|
#if defined(ENABLE_ITTI)
|
|
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
|
|
|
|
# if defined(ENABLE_USE_MME)
|
|
|
|
if (itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) {
|
|
LOG_E(EMU, "Create task failed");
|
|
LOG_D(EMU, "Initializing SCTP task interface: FAILED\n");
|
|
return -1;
|
|
}
|
|
|
|
if (itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL) < 0) {
|
|
LOG_E(EMU, "Create task failed");
|
|
LOG_D(EMU, "Initializing S1AP task interface: FAILED\n");
|
|
return -1;
|
|
}
|
|
|
|
# endif
|
|
|
|
if (itti_create_task(TASK_L2L1, l2l1_task, NULL) < 0) {
|
|
LOG_E(EMU, "Create task failed");
|
|
LOG_D(EMU, "Initializing L2L1 task interface: FAILED\n");
|
|
return -1;
|
|
}
|
|
|
|
// Handle signals until all tasks are terminated
|
|
// itti_wait_tasks_end();
|
|
#endif
|
|
|
|
if (ouput_vcd) {
|
|
if (UE_flag==1)
|
|
VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
|
|
else
|
|
VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
|
|
}
|
|
|
|
#ifdef PDCP_USE_NETLINK
|
|
netlink_init();
|
|
#endif
|
|
|
|
// to make a graceful exit when ctrl-c is pressed
|
|
signal(SIGSEGV, signal_handler);
|
|
signal(SIGINT, signal_handler);
|
|
|
|
#ifndef RTAI
|
|
check_clock();
|
|
#endif
|
|
|
|
g_log->log_component[HW].level = LOG_DEBUG;
|
|
g_log->log_component[HW].flag = LOG_HIGH;
|
|
#ifdef OPENAIR2
|
|
g_log->log_component[PHY].level = LOG_INFO;
|
|
#else
|
|
g_log->log_component[PHY].level = LOG_DEBUG;
|
|
#endif
|
|
g_log->log_component[PHY].flag = LOG_HIGH;
|
|
g_log->log_component[MAC].level = LOG_INFO;
|
|
g_log->log_component[MAC].flag = LOG_HIGH;
|
|
g_log->log_component[RLC].level = LOG_INFO;
|
|
g_log->log_component[RLC].flag = LOG_HIGH;
|
|
g_log->log_component[PDCP].level = LOG_INFO;
|
|
g_log->log_component[PDCP].flag = LOG_HIGH;
|
|
g_log->log_component[OTG].level = LOG_INFO;
|
|
g_log->log_component[OTG].flag = LOG_HIGH;
|
|
g_log->log_component[RRC].level = LOG_INFO;
|
|
g_log->log_component[RRC].flag = LOG_HIGH;
|
|
|
|
|
|
// Initialize card
|
|
ret = openair0_open();
|
|
|
|
if ( ret != 0 ) {
|
|
if (ret == -1)
|
|
printf("Error opening /dev/openair0");
|
|
|
|
if (ret == -2)
|
|
printf("Error mapping bigshm");
|
|
|
|
if (ret == -3)
|
|
printf("Error mapping RX or TX buffer");
|
|
|
|
return(ret);
|
|
}
|
|
|
|
number_of_cards = openair0_num_detected_cards;
|
|
|
|
for (card=0; card<number_of_cards; card++) {
|
|
printf ("Configuring card %d of %d (number of antennas %d).\n", card, openair0_num_detected_cards, openair0_num_antennas[card]);
|
|
|
|
p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr;
|
|
p_exmimo_id = openair0_exmimo_pci[card].exmimo_id_ptr;
|
|
|
|
printf("Card %d: ExpressMIMO %d, HW Rev %d, SW Rev 0x%d\n", card, p_exmimo_id->board_exmimoversion, p_exmimo_id->board_hwrev, p_exmimo_id->board_swrev);
|
|
|
|
if (p_exmimo_id->board_swrev>=BOARD_SWREV_CNTL2)
|
|
p_exmimo_config->framing.eNB_flag = 0;
|
|
else
|
|
p_exmimo_config->framing.eNB_flag = !UE_flag;
|
|
|
|
if (card==0)
|
|
p_exmimo_config->framing.multicard_syncmode = SYNCMODE_MASTER;
|
|
else
|
|
p_exmimo_config->framing.multicard_syncmode = SYNCMODE_SLAVE;
|
|
|
|
//p_exmimo_config->framing.multicard_syncmode = SYNCMODE_FREE;
|
|
|
|
|
|
p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_TESTRX; //TXRXSWITCH_LSB;
|
|
|
|
/*
|
|
for (ant=0;ant<max(frame_parms->nb_antennas_tx,frame_parms->nb_antennas_rx);ant++)
|
|
p_exmimo_config->rf.rf_mode[ant] = rf_mode_base;
|
|
for (ant=0;ant<frame_parms->nb_antennas_tx;ant++)
|
|
p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX);
|
|
for (ant=0;ant<frame_parms->nb_antennas_rx;ant++)
|
|
p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX);
|
|
for (ant=max(frame_parms->nb_antennas_tx,frame_parms->nb_antennas_rx);ant<4;ant++) {
|
|
p_exmimo_config->rf.rf_mode[ant] = 0;
|
|
carrier_freq[ant] = 0; //this turns off all other LIMEs
|
|
}
|
|
*/
|
|
|
|
for (ant=0; ant<4; ant++) {
|
|
if (carrier_freq[card][ant] != 0) {
|
|
p_exmimo_config->rf.rf_mode[ant] = rf_mode_base;
|
|
|
|
switch (bandwidth[card]) {
|
|
case BW20:
|
|
p_exmimo_config->framing.resampling_factor[ant] = 0;
|
|
p_exmimo_config->rf.rf_mode[ant] += RXLPF10 + TXLPF10;
|
|
break;
|
|
|
|
case BW10:
|
|
p_exmimo_config->framing.resampling_factor[ant] = 1;
|
|
p_exmimo_config->rf.rf_mode[ant] += RXLPF5 + TXLPF5;
|
|
break;
|
|
|
|
case BW5:
|
|
p_exmimo_config->framing.resampling_factor[ant] = 2;
|
|
p_exmimo_config->rf.rf_mode[ant] += RXLPF25 + TXLPF25;
|
|
break;
|
|
}
|
|
|
|
//p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX);
|
|
p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX);
|
|
} else {
|
|
p_exmimo_config->rf.rf_mode[ant] = 0;
|
|
}
|
|
}
|
|
|
|
for (ant = 0; ant<4; ant++) {
|
|
p_exmimo_config->rf.do_autocal[ant] = 1;
|
|
p_exmimo_config->rf.rf_freq_rx[ant] = carrier_freq[card][ant];
|
|
p_exmimo_config->rf.rf_freq_tx[ant] = carrier_freq[card][ant];
|
|
p_exmimo_config->rf.rx_gain[ant][0] = rxgain[ant];
|
|
p_exmimo_config->rf.tx_gain[ant][0] = txgain[ant];
|
|
|
|
p_exmimo_config->rf.rf_local[ant] = rf_local[ant];
|
|
p_exmimo_config->rf.rf_rxdc[ant] = rf_rxdc[ant];
|
|
|
|
if ((carrier_freq[card][ant] >= 850000000) && (carrier_freq[card][ant] <= 865000000)) {
|
|
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal_850[ant];
|
|
p_exmimo_config->rf.rffe_band_mode[ant] = DD_TDD;
|
|
} else if ((carrier_freq[card][ant] >= 1900000000) && (carrier_freq[card][ant] <= 2000000000)) {
|
|
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal[ant];
|
|
p_exmimo_config->rf.rffe_band_mode[ant] = B19G_TDD;
|
|
} else {
|
|
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal[ant];
|
|
p_exmimo_config->rf.rffe_band_mode[ant] = 0;
|
|
}
|
|
|
|
p_exmimo_config->rf.rffe_gain_txlow[ant] = 31;
|
|
p_exmimo_config->rf.rffe_gain_txhigh[ant] = 31;
|
|
p_exmimo_config->rf.rffe_gain_rxfinal[ant] = 52;
|
|
p_exmimo_config->rf.rffe_gain_rxlow[ant] = 31;
|
|
}
|
|
|
|
|
|
openair0_dump_config(card);
|
|
|
|
printf("EXMIMO_CONFIG card %d: freq0..3 %u %u %u %u Hz, freqtx0..1 %u %u Hz, RX gain0..1 %d %d dB\n",
|
|
card,
|
|
p_exmimo_config->rf.rf_freq_rx[0],
|
|
p_exmimo_config->rf.rf_freq_rx[1],
|
|
p_exmimo_config->rf.rf_freq_rx[2],
|
|
p_exmimo_config->rf.rf_freq_rx[3],
|
|
p_exmimo_config->rf.rf_freq_tx[0],
|
|
p_exmimo_config->rf.rf_freq_tx[1],
|
|
p_exmimo_config->rf.rx_gain[0][0],
|
|
p_exmimo_config->rf.rx_gain[1][0]);
|
|
printf("EXMIMO_CONFIG card %d: rf_mode 0x %x %x %x %x, [0]: TXRXEn %d, TXLPFEn %d, TXLPF %d, RXLPFEn %d, RXLPF %d, RFBB %d, LNA %d, LNAGain %d, RXLPFMode %d, SWITCH %d, rf_rxdc %d, rf_local %d, rf_vcocal %d\n",
|
|
card,
|
|
p_exmimo_config->rf.rf_mode[0],
|
|
p_exmimo_config->rf.rf_mode[1],
|
|
p_exmimo_config->rf.rf_mode[2],
|
|
p_exmimo_config->rf.rf_mode[3],
|
|
(p_exmimo_config->rf.rf_mode[0]&3), // RXen+TXen
|
|
(p_exmimo_config->rf.rf_mode[0]&4)>>2, //TXLPFen
|
|
(p_exmimo_config->rf.rf_mode[0]&TXLPFMASK)>>3, //TXLPF
|
|
(p_exmimo_config->rf.rf_mode[0]&128)>>7, //RXLPFen
|
|
(p_exmimo_config->rf.rf_mode[0]&RXLPFMASK)>>8, //TXLPF
|
|
(p_exmimo_config->rf.rf_mode[0]&RFBBMASK)>>16, // RFBB mode
|
|
(p_exmimo_config->rf.rf_mode[0]&LNAMASK)>>12, // RFBB mode
|
|
(p_exmimo_config->rf.rf_mode[0]&LNAGAINMASK)>>14, // RFBB mode
|
|
(p_exmimo_config->rf.rf_mode[0]&RXLPFMODEMASK)>>19, // RXLPF mode
|
|
(p_exmimo_config->framing.tdd_config&TXRXSWITCH_MASK)>>1, // Switch mode
|
|
p_exmimo_config->rf.rf_rxdc[0],
|
|
p_exmimo_config->rf.rf_local[0],
|
|
p_exmimo_config->rf.rf_vcocal[0]);
|
|
|
|
for (ant=0; ant<4; ant++)
|
|
p_exmimo_config->rf.do_autocal[ant] = 0;
|
|
} //card
|
|
|
|
card=0;
|
|
|
|
#ifdef EMOS
|
|
error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE);
|
|
|
|
if (error_code==0)
|
|
printf("[OPENAIR][SCHED][INIT] Created EMOS FIFO %d\n",CHANSOUNDER_FIFO_MINOR);
|
|
else if (error_code==ENODEV)
|
|
printf("[OPENAIR][SCHED][INIT] Problem: EMOS FIFO %d is greater than or equal to RTF_NO\n",CHANSOUNDER_FIFO_MINOR);
|
|
else if (error_code==ENOMEM)
|
|
printf("[OPENAIR][SCHED][INIT] Problem: cannot allocate memory for EMOS FIFO %d\n",CHANSOUNDER_FIFO_MINOR);
|
|
else
|
|
printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code);
|
|
|
|
#endif
|
|
|
|
mlockall(MCL_CURRENT | MCL_FUTURE);
|
|
|
|
#ifdef RTAI
|
|
// make main thread LXRT soft realtime
|
|
task = rt_task_init_schmod(nam2num("MYTASK"), 9, 0, 0, SCHED_FIFO, 0xF);
|
|
|
|
// start realtime timer and scheduler
|
|
//rt_set_oneshot_mode();
|
|
rt_set_periodic_mode();
|
|
start_rt_timer(0);
|
|
|
|
//now = rt_get_time() + 10*PERIOD;
|
|
//rt_task_make_periodic(task, now, PERIOD);
|
|
|
|
printf("Init mutex\n");
|
|
//mutex = rt_get_adr(nam2num("MUTEX"));
|
|
mutex = rt_sem_init(nam2num("MUTEX"), 1);
|
|
|
|
if (mutex==0) {
|
|
printf("Error init mutex\n");
|
|
exit(-1);
|
|
} else
|
|
printf("mutex=%p\n",mutex);
|
|
|
|
#endif
|
|
|
|
DAQ_MBOX = (volatile unsigned int *) openair0_exmimo_pci[0].rxcnt_ptr[0];
|
|
|
|
// this starts the DMA transfers
|
|
if (UE_flag!=1)
|
|
for (card=0; card<number_of_cards; card++)
|
|
openair0_start_rt_acquisition(card);
|
|
|
|
|
|
#ifdef XFORMS
|
|
|
|
if (do_forms==1) {
|
|
fl_initialize (&argc, argv, NULL, 0, 0);
|
|
/*
|
|
form_stats = create_form_stats_form();
|
|
if (UE_flag==1) {
|
|
form_ue[UE_id] = create_lte_phy_scope_ue();
|
|
sprintf (title, "LTE DL SCOPE UE");
|
|
fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
|
|
} else {
|
|
for(UE_id=0;UE_id<scope_enb_num_ue;UE_id++) {
|
|
form_enb[UE_id] = create_lte_phy_scope_enb();
|
|
sprintf (title, "UE%d LTE UL SCOPE eNB",UE_id+1);
|
|
fl_show_form (form_enb[UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
|
|
}
|
|
}
|
|
fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
|
|
if (UE_flag==0) {
|
|
for (UE_id=0;UE_id<scope_enb_num_ue;UE_id++) {
|
|
if (otg_enabled) {
|
|
fl_set_button(form_enb[UE_id]->button_0,1);
|
|
fl_set_object_label(form_enb[UE_id]->button_0,"DL Traffic ON");
|
|
}
|
|
else {
|
|
fl_set_button(form_enb[UE_id]->button_0,0);
|
|
fl_set_object_label(form_enb[UE_id]->button_0,"DL Traffic OFF");
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (openair_daq_vars.use_ia_receiver) {
|
|
fl_set_button(form_ue[UE_id]->button_0,1);
|
|
fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON");
|
|
}
|
|
else {
|
|
fl_set_button(form_ue[UE_id]->button_0,0);
|
|
fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
|
|
}
|
|
}
|
|
*/
|
|
form_lte = create_form_lte_scope();
|
|
fl_show_form (form_lte->lte_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, "Scope");
|
|
|
|
ret = pthread_create(&thread2, NULL, scope_thread, NULL);
|
|
printf("Scope thread created, ret=%d\n",ret);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef EMOS
|
|
ret = pthread_create(&thread3, NULL, emos_thread, NULL);
|
|
printf("EMOS thread created, ret=%d\n",ret);
|
|
ret = pthread_create(&thread4, NULL, gps_thread, NULL);
|
|
printf("GPS thread created, ret=%d\n",ret);
|
|
ret = pthread_create(&thread5, NULL, log_thread, NULL);
|
|
printf("LOG thread created, ret=%d\n",ret);
|
|
#endif
|
|
|
|
rt_sleep_ns(10*FRAME_PERIOD);
|
|
|
|
#ifndef RTAI
|
|
pthread_attr_init (&attr_dlsch_threads);
|
|
pthread_attr_setstacksize(&attr_dlsch_threads,OPENAIR_THREAD_STACK_SIZE);
|
|
//attr_dlsch_threads.priority = 1;
|
|
sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
|
|
pthread_attr_setschedparam (&attr_dlsch_threads, &sched_param_dlsch);
|
|
pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
|
|
#endif
|
|
|
|
// start the main thread
|
|
if (UE_flag == 1) {
|
|
/*
|
|
#ifdef RTAI
|
|
thread1 = rt_thread_create(UE_thread, NULL, 100000000);
|
|
#else
|
|
error_code = pthread_create(&thread1, &attr_dlsch_threads, UE_thread, NULL);
|
|
if (error_code!= 0) {
|
|
LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
|
|
return(error_code);
|
|
}
|
|
else {
|
|
LOG_D(HW,"[lte-softmodem.c] Allocate UE_thread successful\n");
|
|
}
|
|
#endif
|
|
#ifdef DLSCH_THREAD
|
|
init_rx_pdsch_thread();
|
|
rt_sleep_ns(FRAME_PERIOD/10);
|
|
init_dlsch_threads();
|
|
#endif
|
|
printf("UE threads created\n");
|
|
*/
|
|
} else {
|
|
#ifdef RTAI
|
|
thread0 = rt_thread_create(eNB_thread, NULL, 100000000);
|
|
#else
|
|
error_code = pthread_create(&thread0, &attr_dlsch_threads, eNB_thread, NULL);
|
|
|
|
if (error_code!= 0) {
|
|
LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
|
|
return(error_code);
|
|
} else {
|
|
LOG_D(HW,"[lte-softmodem.c] Allocate eNB_thread successful\n");
|
|
}
|
|
|
|
#endif
|
|
#ifdef ULSCH_THREAD
|
|
init_ulsch_threads();
|
|
#endif
|
|
printf("eNB threads created\n");
|
|
}
|
|
|
|
|
|
// wait for end of program
|
|
printf("TYPE <CTRL-C> TO TERMINATE\n");
|
|
|
|
//getchar();
|
|
while (oai_exit==0)
|
|
rt_sleep_ns(FRAME_PERIOD);
|
|
|
|
// stop threads
|
|
#ifdef XFORMS
|
|
printf("waiting for XFORMS thread\n");
|
|
|
|
if (do_forms==1) {
|
|
pthread_join(thread2,&status);
|
|
/*
|
|
fl_hide_form(form_stats->stats_form);
|
|
fl_free_form(form_stats->stats_form);
|
|
if (UE_flag==1) {
|
|
fl_hide_form(form_ue[UE_id]->lte_phy_scope_ue);
|
|
fl_free_form(form_ue[UE_id]->lte_phy_scope_ue);
|
|
} else {
|
|
for(UE_id=0;UE_id<scope_enb_num_ue;UE_id++) {
|
|
fl_hide_form(form_enb[UE_id]->lte_phy_scope_enb);
|
|
fl_free_form(form_enb[UE_id]->lte_phy_scope_enb);
|
|
}
|
|
}
|
|
*/
|
|
fl_hide_form(form_lte->lte_scope);
|
|
fl_free_form(form_lte->lte_scope);
|
|
}
|
|
|
|
#endif
|
|
|
|
printf("stopping MODEM threads\n");
|
|
|
|
// cleanup
|
|
if (UE_flag == 1) {
|
|
/*
|
|
#ifdef RTAI
|
|
rt_thread_join(thread1);
|
|
#else
|
|
pthread_join(thread1,&status);
|
|
#endif
|
|
#ifdef DLSCH_THREAD
|
|
cleanup_dlsch_threads();
|
|
cleanup_rx_pdsch_thread();
|
|
#endif
|
|
*/
|
|
} else {
|
|
#ifdef RTAI
|
|
rt_thread_join(thread0);
|
|
#else
|
|
pthread_join(thread0,&status);
|
|
#endif
|
|
#ifdef ULSCH_THREAD
|
|
cleanup_ulsch_threads();
|
|
#endif
|
|
}
|
|
|
|
#ifdef OPENAIR2
|
|
//cleanup_pdcp_thread();
|
|
#endif
|
|
|
|
#ifdef RTAI
|
|
stop_rt_timer();
|
|
#endif
|
|
|
|
printf("stopping card\n");
|
|
|
|
for (card=0; card<number_of_cards; card++)
|
|
openair0_stop(card);
|
|
|
|
printf("closing openair0_lib\n");
|
|
openair0_close();
|
|
|
|
#ifdef EMOS
|
|
printf("waiting for EMOS thread\n");
|
|
pthread_cancel(thread3);
|
|
pthread_join(thread3,&status);
|
|
printf("waiting for GPS thread\n");
|
|
pthread_cancel(thread4);
|
|
pthread_join(thread4,&status);
|
|
printf("waiting for log thread\n");
|
|
pthread_cancel(thread5);
|
|
pthread_join(thread5,&status);
|
|
#endif
|
|
|
|
#ifdef EMOS
|
|
error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
|
|
|
|
while (error_code>0)
|
|
error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
|
|
|
|
printf("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
|
|
#endif
|
|
|
|
if (ouput_vcd)
|
|
VCD_SIGNAL_DUMPER_CLOSE();
|
|
|
|
logClean();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void test_config(int card, int ant, unsigned int rf_mode, int UE_flag)
|
|
{
|
|
p_exmimo_config->framing.eNB_flag = !UE_flag;
|
|
p_exmimo_config->framing.tdd_config = 0;
|
|
p_exmimo_config->framing.resampling_factor[ant] = 2;
|
|
|
|
p_exmimo_config->rf.rf_freq_rx[ant] = 1907600000;
|
|
p_exmimo_config->rf.rf_freq_tx[ant] = 1907600000;;
|
|
p_exmimo_config->rf.rx_gain[ant][0] = 20;
|
|
p_exmimo_config->rf.tx_gain[ant][0] = 10;
|
|
p_exmimo_config->rf.rf_mode[ant] = rf_mode;
|
|
|
|
p_exmimo_config->rf.rf_local[ant] = build_rflocal(20,25,26,04);
|
|
p_exmimo_config->rf.rf_rxdc[ant] = build_rfdc(128, 128);
|
|
p_exmimo_config->rf.rf_vcocal[ant] = (0xE<<6) + 0xE;
|
|
}
|
|
|
|
/*
|
|
void setup_ue_buffers(PHY_VARS_UE *phy_vars_ue, LTE_DL_FRAME_PARMS *frame_parms, int carrier) {
|
|
|
|
int i;
|
|
if (phy_vars_ue) {
|
|
|
|
if ((frame_parms->nb_antennas_rx>1) && (carrier>0)) {
|
|
printf("RX antennas > 1 and carrier > 0 not possible\n");
|
|
exit(-1);
|
|
}
|
|
|
|
if ((frame_parms->nb_antennas_tx>1) && (carrier>0)) {
|
|
printf("TX antennas > 1 and carrier > 0 not possible\n");
|
|
exit(-1);
|
|
}
|
|
|
|
// replace RX signal buffers with mmaped HW versions
|
|
for (i=0;i<frame_parms->nb_antennas_rx;i++) {
|
|
free(phy_vars_ue->lte_ue_common_vars.rxdata[i]);
|
|
phy_vars_ue->lte_ue_common_vars.rxdata[i] = (int32_t*) openair0_exmimo_pci[card].adc_head[i+carrier];
|
|
|
|
|
|
printf("rxdata[%d] @ %p\n",i,phy_vars_ue->lte_ue_common_vars.rxdata[i]);
|
|
}
|
|
for (i=0;i<frame_parms->nb_antennas_tx;i++) {
|
|
free(phy_vars_ue->lte_ue_common_vars.txdata[i]);
|
|
phy_vars_ue->lte_ue_common_vars.txdata[i] = (int32_t*) openair0_exmimo_pci[card].dac_head[i+carrier];
|
|
|
|
printf("txdata[%d] @ %p\n",i,phy_vars_ue->lte_ue_common_vars.txdata[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void setup_eNB_buffers(PHY_VARS_eNB *phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms, int carrier) {
|
|
|
|
int i,j;
|
|
|
|
if (phy_vars_eNB) {
|
|
if ((frame_parms->nb_antennas_rx>1) && (carrier>0)) {
|
|
printf("RX antennas > 1 and carrier > 0 not possible\n");
|
|
exit(-1);
|
|
}
|
|
|
|
if ((frame_parms->nb_antennas_tx>1) && (carrier>0)) {
|
|
printf("TX antennas > 1 and carrier > 0 not possible\n");
|
|
exit(-1);
|
|
}
|
|
|
|
// replace RX signal buffers with mmaped HW versions
|
|
for (i=0;i<frame_parms->nb_antennas_rx;i++) {
|
|
free(phy_vars_eNB->lte_eNB_common_vars.rxdata[0][i]);
|
|
phy_vars_eNB->lte_eNB_common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[card].adc_head[i+carrier];
|
|
|
|
printf("rxdata[%d] @ %p\n",i,phy_vars_eNB->lte_eNB_common_vars.rxdata[0][i]);
|
|
for (j=0;j<16;j++) {
|
|
printf("rxbuffer %d: %x\n",j,phy_vars_eNB->lte_eNB_common_vars.rxdata[0][i][j]);
|
|
phy_vars_eNB->lte_eNB_common_vars.rxdata[0][i][j] = 16-j;
|
|
}
|
|
}
|
|
for (i=0;i<frame_parms->nb_antennas_tx;i++) {
|
|
free(phy_vars_eNB->lte_eNB_common_vars.txdata[0][i]);
|
|
phy_vars_eNB->lte_eNB_common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[card].dac_head[i+carrier];
|
|
|
|
printf("txdata[%d] @ %p\n",i,phy_vars_eNB->lte_eNB_common_vars.txdata[0][i]);
|
|
for (j=0;j<16;j++) {
|
|
printf("txbuffer %d: %x\n",j,phy_vars_eNB->lte_eNB_common_vars.txdata[0][i][j]);
|
|
phy_vars_eNB->lte_eNB_common_vars.txdata[0][i][j] = 16-j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|