Commit f563135b authored by Florian Kaltenberger's avatar Florian Kaltenberger
Browse files

removing unused lte-enb.c and lte-softmodem-usrp.c


git-svn-id: http://svn.eurecom.fr/openair4G/trunk@6447 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 26907257
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file 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"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include "assertions.h"
#ifdef EMOS
#include <gps.h>
#endif
#include "PHY/types.h"
#include "PHY/defs.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "openair0_lib.h"
#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "PHY/vars.h"
#include "MAC_INTERFACE/vars.h"
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"
#include "../../SIMU/USER/init_lte.h"
#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif
#ifdef OPENAIR2
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
#ifndef CELLULAR
#include "RRC/LITE/vars.h"
#endif
#include "PHY_INTERFACE/vars.h"
#endif
#include "UTIL/LOG/log_extern.h"
#include "UTIL/OTG/otg.h"
#include "UTIL/OTG/otg_vars.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "enb_config.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
# include "create_tasks.h"
# if defined(ENABLE_USE_MME)
# include "s1ap_eNB.h"
# endif
#endif
#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];
int UE_id;
unsigned char scope_enb_num_ue = 1;
#endif //XFORMS
unsigned char UE_flag=0;
char *mme_ip;
#define FRAME_PERIOD 100000000ULL
#define DAQ_PERIOD 66667ULL
#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 int thread0;
static int thread1;
//static 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;
pthread_t thread3;
/*
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 card = 0;
exmimo_config_t *p_exmimo_config;
exmimo_id_t *p_exmimo_id;
volatile unsigned int *DAQ_MBOX;
#if defined(ENABLE_ITTI)
volatile int start_eNB = 0;
#endif
volatile int oai_exit = 0;
int oai_flag = 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};
uint8_t eNB_id=0;
uint32_t carrier_freq_fdd[4]= {2680e6,0,0,0};
uint32_t carrier_freq_tdd[4]= {2590e6-4000,0,0,0};
uint32_t carrier_freq[4];
static char *conf_config_file_name = NULL;
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;
runmode_t mode;
int rx_input_level_dBm;
#ifdef XFORMS
extern int otg_enabled;
#else
int otg_enabled;
#endif
int number_of_cards = 1;
//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[10] = {15, 30, 45, 60, 75, 90, 105, 120, 135, 0}; // mbox boundaries of subframes
int mbox_bounds[10] = {14, 28, 44, 58, 74, 88, 104, 118, 134, 148}; // mbox boundaries of subframes
//int mbox_bounds[10] = {16, 30, 46, 60, 76, 90, 106, 120, 136, 0}; ///boundaries of slots in terms ob mbox counter rounded up to even numbers
int init_dlsch_threads(void);
void cleanup_dlsch_threads(void);
int32_t init_rx_pdsch_thread(void);
void cleanup_rx_pdsch_thread(void);
int init_ulsch_threads(void);
void cleanup_ulsch_threads(void);
LTE_DL_FRAME_PARMS *frame_parms;
void setup_eNB_buffers(PHY_VARS_eNB *phy_vars_eNB,
LTE_DL_FRAME_PARMS *frame_parms, int carrier);
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)
{
if (s != NULL) {
printf("Exiting: %s\n",s);
}
oai_exit=1;
#if defined(ENABLE_ITTI)
itti_terminate_tasks (TASK_UNKNOWN);
#endif
//rt_sleep_ns(FRAME_PERIOD);
//exit (-1);
}
#ifdef XFORMS
void *scope_thread(void *arg)
{
s16 prach_corr[1024], i;
char stats_buffer[16384];
//FILE *UE_stats, *eNB_stats;
int len=0;
/*
if (UE_flag==1)
UE_stats = fopen("UE_stats.txt", "w");
else
eNB_stats = fopen("eNB_stats.txt", "w");
*/
while (!oai_exit) {
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);
}
//printf("doing forms\n");
usleep(100000); // 100 ms
}
//fclose (UE_stats);
//fclose (eNB_stats);
pthread_exit((void *)arg);
}
#endif
void do_OFDM_mod(mod_sym_t **txdataF, int32_t **txdata, uint16_t next_slot,
LTE_DL_FRAME_PARMS *frame_parms)
{
int aa, slot_offset, slot_offset_F;
slot_offset_F = (next_slot)*(frame_parms->ofdm_symbol_size)*((
frame_parms->Ncp == EXTENDED) ? 6 : 7);
slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1);
for (aa = 0; aa < frame_parms->nb_antennas_tx; aa++) {
if (frame_parms->Ncp == EXTENDED) {
PHY_ofdm_mod(&txdataF[aa][slot_offset_F],
&txdata[aa][slot_offset],
frame_parms->log2_symbol_size,
6,
frame_parms->nb_prefix_samples,
frame_parms->twiddle_fft,
frame_parms->rev,
CYCLIC_PREFIX);
} else {
normal_prefix_mod(&txdataF[aa][slot_offset_F],
&txdata[aa][slot_offset],
7,
frame_parms);
}
}
}
int dummy_tx_buffer[3840*4] __attribute__((aligned(16)));
#if defined(ENABLE_ITTI)
void *l2l1_task(void *arg)
{
MessageDef *message_p = NULL;
int result;
itti_set_task_real_time(TASK_L2L1);
itti_mark_task_ready(TASK_L2L1);
if (UE_flag == 0) {
/* Wait for the initialize message */
do {
if (message_p != NULL) {
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
itti_receive_msg (TASK_L2L1, &message_p);
switch (ITTI_MSG_ID(message_p)) {
case INITIALIZE_MESSAGE:
/* Start eNB thread */
start_eNB = 1;
break;
case TERMINATE_MESSAGE:
oai_exit=1;
itti_exit_task ();
break;
default:
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
break;
}
} while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
do {
// Wait for a message
itti_receive_msg (TASK_L2L1, &message_p);
switch (ITTI_MSG_ID(message_p)) {
case TERMINATE_MESSAGE:
oai_exit=1;
itti_exit_task ();
break;
case MESSAGE_TEST:
LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
break;
default:
LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
break;
}
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
} while(1);
return NULL;
}
#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;
SEM *sem;
#endif
unsigned char last_slot, next_slot;
int subframe = 0, hw_subframe;
int frame=0;
int skip_first=1;
unsigned int msg1;
unsigned int aa,slot_offset, slot_offset_F;
int diff;
int delay_cnt;
RTIME time_in, time_diff;
RTIME period;
int mbox_target=0,mbox_current=0;
int i,ret;
int tx_offset;
#if defined(ENABLE_ITTI)
/* Wait for eNB application initialization to be complete (eNB registration to MME) */
{
char *indicator[] = {". ", ".. ", "...", " ..", " .", " "};
int i = 0;
while ((!oai_exit) && (start_eNB == 0)) {
LOG_D(HW,"Waiting for eNB application to be ready %s\r", indicator[i]);
i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
usleep(200000);
}
LOG_D(HW,"\n");
}
#endif
#ifdef RTAI
task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF);
rt_receive(0, (unsigned long *)((void *)&sem));
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;
// sync to HW subframe == 0
mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
rt_sleep_ns((165-mbox_current)*DAQ_PERIOD);
time_in = rt_get_time_ns();
while (!oai_exit) {
//this is the mbox counter where we should be
mbox_target = mbox_bounds[subframe];
//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 < -15) {
LOG_D(HW,
"Time %.3f: Frame %d, missed subframe, proceeding with next one (subframe %d, hw_subframe %d, mbox_currend %d, mbox_target %d,diff %d) processing time %.3f\n",
(float)(rt_get_time_ns()-time_in)/1e6,
frame, subframe, hw_subframe, mbox_current, mbox_target, diff,
(float)(timing_info.time_now-timing_info.time_last)/1e6);
subframe++;
if (frame>0) {
oai_exit=1;
}
if (subframe==10) {
subframe=0;
frame++;
}
continue;
}
if (diff > 15) {
LOG_D(HW,
"Time %.3f: Frame %d, skipped subframe, waiting for hw to catch up (subframe %d, hw_subframe %d, mbox_current %d, mbox_target %d, diff %d), processing time %.3f\n",
(float)(rt_get_time_ns()-time_in)/1e6,
frame, subframe, hw_subframe, mbox_current, mbox_target, diff,
(float)(timing_info.time_now-timing_info.time_last)/1e6);
//exit(-1);
}
delay_cnt = 0;
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX,
*((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0]));
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff);
while ((diff>0) && (!oai_exit)) {
time_diff = rt_get_time_ns() - time_in;
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);
}
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;
}
}
hw_subframe = ((((volatile unsigned int *)DAQ_MBOX)[0]+135)%150)/15;
LOG_D(HW,
"Time: %.3f: Frame %d, subframe %d, hw_subframe %d (mbox %d) processing time %0.3f\n",
(float)(rt_get_time_ns()-time_in)/1e6,
frame,subframe,hw_subframe,((volatile unsigned int *)DAQ_MBOX)[0],
(float)(timing_info.time_now-timing_info.time_last)/1e6);
last_slot = (subframe<<1)+1;
if (last_slot <0) {
last_slot+=20;
}
next_slot = ((subframe<<1)+4)%LTE_SLOTS_PER_FRAME;
if ((skip_first == 0) || (frame>5))
{
skip_first = 0;
timing_info.time_last = rt_get_time_ns();
//msg("subframe %d, last_slot %d,next_slot %d\n", subframe,last_slot,next_slot);
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX,
*((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0]));
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff);
phy_procedures_eNB_lte (last_slot, next_slot, PHY_vars_eNB_g[0], 0,0,NULL);
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX,
*((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0]));
#ifndef IFFT_FPGA
if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL)||
((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S)
&&((next_slot&1)==0))) {
//LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
/*
do_OFDM_mod(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0],
PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0],
next_slot,
&PHY_vars_eNB_g[0]->lte_frame_parms);
do_OFDM_mod(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0],
PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0],
next_slot+1,
&PHY_vars_eNB_g[0]->lte_frame_parms);
*/
vcd_signal_dumper_dump_function_by_name(
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN,1);
slot_offset_F = (next_slot)*
(PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)*7;
slot_offset = (next_slot)*
(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1);
normal_prefix_mod(
&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][0][slot_offset_F],
dummy_tx_buffer,
7,
&(PHY_vars_eNB_g[0]->lte_frame_parms));
for (i = 0; i < PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti/2; i++) {
tx_offset = slot_offset + time_offset[0] + i;
((short *)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][0][tx_offset])[0]
= ((short *)dummy_tx_buffer)[2*i]<<4;
((short *)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][0][tx_offset])[1]
= ((short *)dummy_tx_buffer)[2*i+1]<<4;
}
slot_offset_F = (next_slot+1)*
(PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)*7;
slot_offset = (next_slot+1)*
(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1);
normal_prefix_mod(
&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][0][slot_offset_F],
dummy_tx_buffer,
7,
&(PHY_vars_eNB_g[0]->lte_frame_parms));
for (i = 0; i < PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti/2; i++) {
tx_offset = slot_offset + i;
((short *)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][0][tx_offset])[0]
= ((short *)dummy_tx_buffer)[2*i]<<4;
((short *)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][0][tx_offset])[1]
= ((short *)dummy_tx_buffer)[2*i+1]<<4;
}
}
vcd_signal_dumper_dump_function_by_name(
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN,0);
timing_info.time_now = rt_get_time_ns();
#endif //IFFT_FPGA
/*
if (frame%100==0)
LOG_D(HW,"hw_slot %d (after): DAQ_MBOX %d\n",hw_slot,DAQ_MBOX[0]);
*/
}
/*
if ((slot%2000)<10)
LOG_D(HW,"fun0: doing very hard work\n");
*/
if (oai_flag == 2) {
//dump_ulsch(PHY_vars_eNB_g[0], subframe, 0);
//exit(-1);
oai_exit=1;
exit_fun("[HW][eNB] HW stopped");
}
if (oai_flag == 1) {
oai_flag = 2;
}
subframe++;
if (subframe==10) {
subframe=0;
frame++;
}
if(frame == 1024) {
frame = 0;
time_in = rt_get_time_ns();
}
#if defined(ENABLE_ITTI)
itti_update_lte_time(frame, subframe * 2);
#endif
}
LOG_D(HW,"eNB_thread: finished, ran %d times.\n",frame);