From e9f32950de284ef7de3e913b4b35393f38ce13de Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 8 Dec 2013 15:50:53 +0000 Subject: [PATCH] git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4639 818b1a75-f10b-46b9-bf7c-635c3b92a50f --- targets/RTAI/USER/lte-enb.c | 1001 +++++++++++++++++++++++++++++++++++ 1 file changed, 1001 insertions(+) create mode 100644 targets/RTAI/USER/lte-enb.c diff --git a/targets/RTAI/USER/lte-enb.c b/targets/RTAI/USER/lte-enb.c new file mode 100644 index 0000000000..28c3261be5 --- /dev/null +++ b/targets/RTAI/USER/lte-enb.c @@ -0,0 +1,1001 @@ +/******************************************************************************* + + Eurecom OpenAirInterface + Copyright(c) 1999 - 2011 Eurecom + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope 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 + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information + Openair Admin: openair_admin@eurecom.fr + Openair Tech : openair_tech@eurecom.fr + Forums : http://forums.eurecom.fsr/openairinterface + Address : Eurecom, 2229, route des crĂȘtes, 06560 Valbonne Sophia Antipolis, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt_wrapper.h" + +#ifdef EMOS +#include +#endif + +#include "PHY/types.h" +#include "PHY/defs.h" +#include "openair0_lib.h" + +#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" + +#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; + +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}; + +u8 eNB_id=0; + +u32 carrier_freq_fdd[4]= {2680e6,0,0,0}; +u32 carrier_freq_tdd[4]= {2590e6-4000,0,0,0}; +u32 carrier_freq[4]; + +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 init_dlsch_threads(void); +void cleanup_dlsch_threads(void); +s32 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) +{ + void *array[10]; + size_t size; + + printf("Exiting: %s\n",s); + + oai_exit=1; + //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_idofdm_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))); + +/* 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; + 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; + + +#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 ((frame>5)&&1) + { + + 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; + } + + 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(); + } + + } + + 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_sem_signal(mutex); + 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; + + /* + u32 rf_mode_max[4] = {55759,55759,55759,55759}; + u32 rf_mode_med[4] = {39375,39375,39375,39375}; + u32 rf_mode_byp[4] = {22991,22991,22991,22991}; + */ + u32 my_rf_mode = RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX; + u32 rf_mode_base = TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON + /*LNAMax Antennas*/ LNAByp + RFBBNORM; + u32 rf_mode[4] = {my_rf_mode,0,0,0}; + u32 rf_local[4] = {8255000,8255000,8255000,8255000}; // UE zepto + //{8254617, 8254617, 8254617, 8254617}; //eNB khalifa + //{8255067,8254810,8257340,8257340}; // eNB PETRONAS + + u32 rf_vcocal[4] = {910,910,910,910}; + u32 rf_vcocal_850[4] = {2015, 2015, 2015, 2015}; + u32 rf_rxdc[4] = {32896,32896,32896,32896}; + // Gain for antennas connection + //u32 rxgain[4] = {25,20,20,20}; + //u32 txgain[4] = {30,25,25,25}; + + // Gain for Cable connection + u32 rxgain[4] = {20,20,20,20}; + u32 txgain[4] = {25,25,25,25}; + + + u8 frame_type = FDD; + u8 tdd_config = 3; + u8 tdd_config_S = 0; + u8 extended_prefix_flag = 0; + u16 Nid_cell = 0; + u8 N_RB_DL = 25; + u8 cooperation_flag = 0; + u8 transmission_mode = 1; + u8 abstraction_flag = 0; + u8 nb_antennas_rx = 1; + + u8 beta_ACK=0,beta_RI=0,beta_CQI=2; + + int c; + char do_forms=0; + unsigned int fd; + + int amp; + 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; + + int ret, ant; + + int error_code; + + mode = normal_txrx; + + mme_ip = "146.208.175.6"; + + while ((c = getopt(argc, argv, "dC:T:N:R:Vi;")) != -1) + { + switch (c) + { + case 'd': + do_forms=1; + printf("Starting XFORMS ...\n"); + break; + case 'C': + carrier_freq[0] = atoi(optarg); + carrier_freq[1] = atoi(optarg); + carrier_freq[2] = atoi(optarg); + carrier_freq[3] = atoi(optarg); + break; + case 'T': + frame_type = TDD; // default FDD + tdd_config = atoi(optarg); + break; + case 'R': + N_RB_DL = atoi(optarg); + if ((N_RB_DL != 6) && (N_RB_DL != 15) && (N_RB_DL != 25) && + (N_RB_DL != 50) && (N_RB_DL != 75) && (N_RB_DL != 100)) { + printf("Illegal N_RB_DL %d (should be one of 6,15,25,50,75,100)\n", N_RB_DL); + exit(-1); + } + break; + case 'i': + mme_ip = optarg; + break; + case 'V': + ouput_vcd = 1; + break; + default: + break; + } + } + + set_taus_seed (0); + + // initialize the log (see log.h for details) + logInit(); + + if (ouput_vcd) { + vcd_signal_dumper_init("/tmp/openair_dump_eNB.vcd"); + } + + +#ifdef NAS_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 + + init_lte_vars(&frame_parms, frame_type, tdd_config, tdd_config_S, extended_prefix_flag, N_RB_DL, + Nid_cell, cooperation_flag, transmission_mode, abstraction_flag, nb_antennas_rx,0); + + g_log->log_component[HW].level = LOG_INFO; + g_log->log_component[HW].flag = LOG_LOW; + g_log->log_component[PHY].level = LOG_INFO; + g_log->log_component[PHY].flag = LOG_LOW; + g_log->log_component[MAC].level = LOG_INFO; + g_log->log_component[MAC].flag = LOG_LOW; + g_log->log_component[RLC].level = LOG_INFO; + g_log->log_component[RLC].flag = LOG_LOW; + g_log->log_component[PDCP].level = LOG_INFO; + g_log->log_component[PDCP].flag = LOG_LOW; + g_log->log_component[S1AP].level = LOG_INFO; + g_log->log_component[S1AP].flag = LOG_LOW; + g_log->log_component[RRC].level = LOG_INFO; + g_log->log_component[RRC].flag = LOG_LOW; + g_log->log_component[OIP].level = LOG_INFO; + g_log->log_component[OIP].flag = LOG_HIGH; + + + PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB*)); + PHY_vars_eNB_g[0] = init_lte_eNB(frame_parms,eNB_id,Nid_cell,cooperation_flag,transmission_mode,abstraction_flag); + +#ifndef OPENAIR2 + for (i=0;ipusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; + PHY_vars_eNB_g[0]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; + PHY_vars_eNB_g[0]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; + + PHY_vars_eNB_g[0]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = i; + PHY_vars_eNB_g[0]->scheduling_request_config[i].sr_ConfigIndex = 7+(i%3); + PHY_vars_eNB_g[0]->scheduling_request_config[i].dsr_TransMax = sr_n4; + } +#endif + + + NB_eNB_INST=1; + NB_INST=1; + + openair_daq_vars.ue_dl_rb_alloc=0x1fff; + openair_daq_vars.target_ue_dl_mcs=16; + openair_daq_vars.ue_ul_nb_rb=6; + openair_daq_vars.target_ue_ul_mcs=9; + + + + // set eNB to max gain + PHY_vars_eNB_g[0]->rx_total_gain_eNB_dB = rxg_max[0] + rxgain[0] - 30; //was measured at rxgain=30; + for (i=0; i<4; i++) { + // frame_parms->rfmode[i] = rf_mode_max[i]; + rf_mode[i] = (rf_mode[i] & (~LNAGAINMASK)) | LNAMax; + } + + + // 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); + } + + printf ("Detected %d number of cards, %d number of antennas.\n", 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 = 0;//!UE_flag; + p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB; + p_exmimo_config->framing.resampling_factor = 2; + + for (ant=0;antnb_antennas_tx,frame_parms->nb_antennas_rx);ant++) + p_exmimo_config->rf.rf_mode[ant] = rf_mode_base; + for (ant=0;antnb_antennas_tx;ant++) + p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX); + for (ant=0;antnb_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 (frame_type == FDD) + carrier_freq[ant] = carrier_freq_fdd[ant]; + else + carrier_freq[ant] = carrier_freq_tdd[ant]; + } + for (ant = 0; ant<1; ant++) { + p_exmimo_config->rf.do_autocal[ant] = 1; + if (frame_type == FDD) + p_exmimo_config->rf.rf_freq_rx[ant] = carrier_freq[ant]-120e6; // LTE FDD band 1 duplex space + else + p_exmimo_config->rf.rf_freq_rx[ant] = carrier_freq[ant]; + + p_exmimo_config->rf.rf_freq_tx[ant] = carrier_freq[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[ant] >= 850000000) && (carrier_freq[ant] <= 865000000)) { + p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal_850[ant]; + p_exmimo_config->rf.rffe_band_mode[ant] = DD_TDD; + } + else { + p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal[ant]; + p_exmimo_config->rf.rffe_band_mode[ant] = B19G_TDD; + } + + p_exmimo_config->rf.rffe_gain_txlow[ant] = 63; + p_exmimo_config->rf.rffe_gain_txhigh[ant] = 63; + p_exmimo_config->rf.rffe_gain_rxfinal[ant] = 63; + p_exmimo_config->rf.rffe_gain_rxlow[ant] = 63; + } + + + dump_frame_parms(frame_parms); + + mac_xface = malloc(sizeof(MAC_xface)); + +#ifdef OPENAIR2 + int eMBMS_active=0; + l2_init(frame_parms,eMBMS_active, + 0,// cba_group_active + 0); //HO active + mac_xface->mrbch_phy_sync_failure (0, 0, 0); +#endif + + mac_xface->macphy_exit = &exit_fun; + + + number_of_cards = openair0_num_detected_cards; + if (p_exmimo_id->board_exmimoversion==1) //ExpressMIMO1 + openair_daq_vars.timing_advance = 138; + else //ExpressMIMO2 + openair_daq_vars.timing_advance = 15; + + setup_eNB_buffers(PHY_vars_eNB_g[0],frame_parms,0); + + openair0_dump_config(card); + + printf("EXMIMO_CONFIG: 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", + 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; + + + 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"), 0); + 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[card].rxcnt_ptr[0]; + + // this starts the DMA transfers + openair0_start_rt_acquisition(card); + + +#ifdef XFORMS + if (do_forms==1) { + printf("Running XFORMS\n"); + fl_initialize (&argc, argv, NULL, 0, 0); + form_stats = create_form_stats_form(); + for(UE_id=0;UE_idlte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + } + fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); + for (UE_id=0;UE_idbutton_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"); + } + } + + ret = pthread_create(&thread2, NULL, scope_thread, NULL); + printf("Scope 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 +#ifdef RTAI + thread0 = rt_thread_create(eNB_thread, NULL, 10000000); + rt_sleep_ns(FRAME_PERIOD*10); + rt_send(rt_get_adr(nam2num("TASK0")), (unsigned long)mutex); +#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 OPENAIR2 + init_pdcp_thread(1); +#endif + +#ifdef ULSCH_THREAD + init_ulsch_threads(); +#endif + printf("eNB threads created\n"); + + + // wait for end of program + printf("TYPE TO TERMINATE\n"); + getchar(); + //while (oai_exit==0) + // rt_sleep_ns(FRAME_PERIOD); + + rt_sem_wait(mutex); + + // 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); + for(UE_id=0;UE_idlte_phy_scope_enb); + fl_free_form(form_enb[UE_id]->lte_phy_scope_enb); + } + } +#endif + + printf("stopping MODEM threads\n"); + // cleanup +#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 + rt_sem_delete(mutex); + stop_rt_timer(); + rt_task_delete(task); +#endif + + printf("stopping card\n"); + openair0_stop(card); + printf("closing openair0_lib\n"); + openair0_close(); + + + + if (ouput_vcd) + vcd_signal_dumper_close(); + + logClean(); + + return 0; +} + +void setup_eNB_buffers(PHY_VARS_eNB *phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms, int carrier) { + + int i,j; + u16 N_TA_offset = 0; + + if (frame_parms->frame_type == TDD) + N_TA_offset = 624/4; + + 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;inb_antennas_rx;i++) { + free(phy_vars_eNB->lte_eNB_common_vars.rxdata[0][i]); + phy_vars_eNB->lte_eNB_common_vars.rxdata[0][i] = ((s32*) openair0_exmimo_pci[card].adc_head[i+carrier]) - N_TA_offset; // N_TA offset for TDD + + /* + 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;inb_antennas_tx;i++) { + free(phy_vars_eNB->lte_eNB_common_vars.txdata[0][i]); + phy_vars_eNB->lte_eNB_common_vars.txdata[0][i] = (s32*) 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; + } + */ + } + } +}