diff --git a/targets/RTAI/USER/synctest.c b/targets/RTAI/USER/synctest.c index 034a1b2a00..72feedfbb4 100644 --- a/targets/RTAI/USER/synctest.c +++ b/targets/RTAI/USER/synctest.c @@ -27,7 +27,7 @@ *******************************************************************************/ -/*! \file synctest.c +/*! \file lte-softmodem.c * \brief main program to control HW and scheduling * \author R. Knopp, F. Kaltenberger * \date 2012 @@ -51,1071 +51,547 @@ #include #include -#include -#include -#include +#include "rt_wrapper.h" #include "PHY/types.h" -#include "PHY/defs.h" +//#include "PHY/defs.h" +#include "openair0_lib.h" -#include "ARCH/COMMON/defs.h" -#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h" -#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_pci.h" -#include "SIMULATION/LTE_PHY/openair_hw.h" +#include "UTIL/LOG/log.h" +#include "UTIL/LOG/vcd_signal_dumper.h" -#include "PHY/vars.h" -#include "MAC_INTERFACE/vars.h" -#include "SCHED/vars.h" -#include "ARCH/CBMIMO1/DEVICE_DRIVER/vars.h" -#include "LAYER2/MAC/vars.h" - -#include "../../SIMU/USER/init_lte.h" - -#ifdef EMOS -#include "SCHED/phy_procedures_emos.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 -#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" - - #ifdef XFORMS -#include -#include "lte_scope.h" -//#include "USERSPACE_TOOLS/SCOPE/lte_scope.h" +#include "PHY/TOOLS/lte_phy_scope.h" #include "stats.h" -FD_lte_scope *form_dl=NULL; +// 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; #endif //XFORMS -#define FRAME_PERIOD 100000000ULL -#define DAQ_PERIOD 66666ULL +#ifdef EMOS +#include +#include +//#define CHANSOUNDER_FIFO_SIZE 10485760 // 10 Mbytes FIFO +#define CHANSOUNDER_FIFO_SIZE 20971520 // 20 Mbytes FIFO +#define CHANSOUNDER_FIFO_MINOR 4 // minor of the FIFO device - this is /dev/rtf3 +#define CHANSOUNDER_FIFO_DEV "/dev/rtf4" +#endif + +#define TIMER_ONESHOT_MODE +#define FRAME_PERIOD 100000000ULL +#define DAQ_PERIOD 66667ULL +#define LTE_SLOTS_PER_FRAME 20 +#define RESAMPLING_FACTOR 2 +#define SAMPLES_PER_SLOT (15360/(1<nb_antennas_tx_eNB : 1); - int nb_ce_symb = (UE_flag==1 ? 1 : frame_parms->symbols_per_tti); - - llr = malloc(coded_bits_per_codeword*sizeof(float)); - llr_time = malloc(coded_bits_per_codeword*sizeof(float)); - - // Channel frequency response - if ((channel_f != NULL) && (channel_f[0] != NULL)) - { - cum_avg = 0; - ind = 0; - for (j=0; jnb_antennas_rx; i++) - { - for (k=0; k<(12*frame_parms->N_RB_DL*nb_ce_symb); k++) - { - sig_time[ind] = (float)ind; - Re = (float)(channel_f[(j<<1)+i][(2*k)]); - Im = (float)(channel_f[(j<<1)+i][(2*k)+1]); - //mag_sig[ind] = (short) rand(); - mag_sig[ind] = (short)10*log10(1.0+((double)Re*Re + (double)Im*Im)); - cum_avg += (short)sqrt((double)Re*Re + (double)Im*Im) ; - ind++; - } - // ind+=NUMBER_OF_OFDM_CARRIERS/4; // spacing for visualization - } - } - - avg = cum_avg/NUMBER_OF_USEFUL_CARRIERS; - - //fl_set_xyplot_ybounds(form->channel_f,30,70); - fl_set_xyplot_data(form->channel_f,sig_time,mag_sig,ind,"","",""); - } - - // time domain channel - if ((channel != NULL) && (channel[0] !=NULL)) - { - for (i=0; i<512; i++) - { - time2[i] = (float) i; - sig2[i] = (float) (channel[0][4*i]*channel[0][4*i]+channel[0][4*i+1]*channel[0][4*i+1]); - } - fl_set_xyplot_data(form->channel_t_im,time2,sig2,128,"","",""); - //fl_set_xyplot_ybounds(form->channel_t_im,0,1e6); - } - - /* - // sync_corr - if (sync_corr != NULL) - { - for (i=0; ichannel_t_im,time2,sig2,sync_corr_len,"","",""); - //fl_set_xyplot_ybounds(form->channel_t_im,0,1e6); - } - */ - - // rx sig 0 - if (rx_sig != NULL) { - if (rx_sig[0] != NULL) - { - //for (i=30720; i<38400; i++) - //for (i=0; isymbols_per_tti/2; i++) { - for (i=0; ichannel_t_re,30,70); - //fl_set_xyplot_data(form->channel_t_re,&time2[640*12*6],&sig2[640*12*6],640*12,"","",""); - fl_set_xyplot_data(form->channel_t_re,time2,sig2,FRAME_LENGTH_COMPLEX_SAMPLES,"","",""); - } + printf("Scope thread has priority %d\n",sched_param.sched_priority); + /* - // rx sig 1 - if (rx_sig[1] !=NULL) { - //for (i=30720; i<38400; i++) - for (i=0; ichannel_t_im,30,70); - //fl_set_xyplot_data(form->channel_t_im,&time2[640*12*6],&sig2[640*12*6],640*12,"","",""); - fl_set_xyplot_data(form->channel_t_im,time2,sig2,FRAME_LENGTH_COMPLEX_SAMPLES,"","",""); - } + if (UE_flag==1) + UE_stats = fopen("UE_stats.txt", "w"); + else + eNB_stats = fopen("eNB_stats.txt", "w"); */ - } - - // PBCH LLR - if (pbch_llr!=NULL) - { - j=0; - for (i=0; i<1920; i++) - { - llr[j] = (float) pbch_llr[i]; - llr_time[j] = (float) j; - //if (i==63) - // i=127; - //else if (i==191) - // i=319; - j++; - } - - fl_set_xyplot_data(form->decoder_input,llr_time,llr,1920,"","",""); - //fl_set_xyplot_ybounds(form->decoder_input,-100,100); - } - - // PBCH I/Q - if (pbch_comp!=NULL) - { - j=0; - for (i=0; i<12*12; i++) - { - I[j] = pbch_comp[2*i]; - Q[j] = pbch_comp[2*i+1]; - j++; - //if (i==47) - // i=96; - //else if (i==191) - // i=239; - } - - fl_set_xyplot_data(form->scatter_plot,I,Q,12*12,"","",""); - fl_set_xyplot_xbounds(form->scatter_plot,-100,100); - fl_set_xyplot_ybounds(form->scatter_plot,-100,100); - } - - - // PDCCH I/Q - if (pdcch_comp!=NULL) - { - j=0; - for (i=0; i<12*25*1; i++) - { - I[j] = pdcch_comp[2*i]; - Q[j] = pdcch_comp[2*i+1]; - j++; - } - - fl_set_xyplot_data(form->scatter_plot1,I,Q,12*25*1,"","",""); - fl_set_xyplot_xbounds(form->scatter_plot1,-100,100); - fl_set_xyplot_ybounds(form->scatter_plot1,-100,100); - } - - // DLSCH LLR - if (dlsch_llr != NULL) - { - for (i=0; idemod_out,llr_time,llr,coded_bits_per_codeword,"","",""); - // fl_set_xyplot_ybounds(form->demod_out,-1000,1000); - } - else - printf("lls==NULL\n"); - - // DLSCH I/Q - if (dlsch_comp!=NULL) - { - j=0; - for (s=pdcch_symbols; ssymbols_per_tti; s++) - { - for (i=0; i<12*25; i++) - { - I[j] = dlsch_comp[(2*25*12*s)+2*i]; - Q[j] = dlsch_comp[(2*25*12*s)+2*i+1]; - j++; + + 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_idscatter_plot2,I,Q,j,"","",""); - //fl_set_xyplot_xbounds(form->scatter_plot2,-100,100); - //fl_set_xyplot_ybounds(form->scatter_plot2,-100,100); + //printf("doing forms\n"); + sleep(0.1); } - - // Throughput - if (avg_tput!=NULL) { - for (i=0; i tput_max) { - tput_max = tput[i]; - } - } - fl_set_xyplot_data(form->tput,tput_time,tput,tput_window,"","",""); - fl_set_xyplot_ybounds(form->tput,0,tput_max); - } - - fl_check_forms(); - - free(llr); - free(llr_time); - -} - -void *scope_thread(void *arg) -{ - s16 prach_corr[1024], i; - char stats_buffer[16384]; - //FILE *UE_stats, *eNB_stats; - int len=0; - u16 tput_window = 100; - unsigned int avg_tput_eNB[tput_window]; - unsigned int avg_tput_UE[tput_window]; - unsigned int tput_time_UE[tput_window]; - unsigned int tput_time_eNB[tput_window]; - memset((void*) avg_tput_UE,0,sizeof(unsigned int)*tput_window); - memset((void*) avg_tput_eNB,0,sizeof(unsigned int)*tput_window); - memset((void*) tput_time_UE,0,sizeof(unsigned int)*tput_window); - memset((void*) tput_time_eNB,0,sizeof(unsigned int)*tput_window); - - /* - 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); - /* - if (PHY_vars_UE_g[0]->frameframe] = PHY_vars_UE_g[0]->bitrate[0]/1000; - tput_time_UE[PHY_vars_UE_g[0]->frame] = PHY_vars_UE_g[0]->frame; - } - else { - */ - memcpy((void*)avg_tput_UE,(void*)&avg_tput_UE[1],(tput_window-1)*sizeof(unsigned int)); - memcpy((void*)tput_time_UE,(void*)&tput_time_UE[1],(tput_window-1)*sizeof(unsigned int)); - avg_tput_UE[tput_window-1] = PHY_vars_UE_g[0]->bitrate[0]/1000; - tput_time_UE[tput_window-1] = PHY_vars_UE_g[0]->frame; - - do_forms2(form_dl, - &(PHY_vars_UE_g[0]->lte_frame_parms), - PHY_vars_UE_g[0]->lte_ue_pdcch_vars[0]->num_pdcch_symbols, - UE_flag, - (s16**)PHY_vars_UE_g[0]->lte_ue_common_vars.dl_ch_estimates_time[0], - (s16**)PHY_vars_UE_g[0]->lte_ue_common_vars.dl_ch_estimates[0], - (s16**)PHY_vars_UE_g[0]->lte_ue_common_vars.rxdata, - (s16**)PHY_vars_UE_g[0]->lte_ue_common_vars.rxdataF, - (s16*)PHY_vars_UE_g[0]->lte_ue_pdcch_vars[0]->rxdataF_comp[0], - (s16*)PHY_vars_UE_g[0]->lte_ue_pdsch_vars[0]->rxdataF_comp[0], - (s16*)PHY_vars_UE_g[0]->lte_ue_pdsch_vars[1]->rxdataF_comp[0], - (s16*)PHY_vars_UE_g[0]->lte_ue_pdsch_vars[0]->llr[0], - (s16*)PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->rxdataF_comp[0], - (s8*)PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->llr, - avg_tput_UE, - tput_time_UE, - tput_window, - 15000, - /*get_G(&PHY_vars_UE_g[0]->lte_frame_parms, - PHY_vars_UE_g[0]->dlsch_ue[0][0]->nb_rb, - PHY_vars_UE_g[0]->dlsch_ue[0][0]->rb_alloc, - get_Qm(PHY_vars_UE_g[0]->dlsch_ue[0][0]->harq_processes[0]->mcs), - PHY_vars_UE_g[0]->lte_ue_pdcch_vars[0]->num_pdcch_symbols,7),*/ - sync_corr_ue0, - PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti*10); - } - 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); - - /* - if (PHY_vars_eNB_g[0]->frameframe] = PHY_vars_UE_g[0]->bitrate[0]/1000; - tput_time_UE[PHY_vars_UE_g[0]->frame] = PHY_vars_UE_g[0]->frame; - } - else { - */ - memcpy((void*)avg_tput_eNB,(void*)&avg_tput_eNB[1],(tput_window-1)*sizeof(unsigned int)); - memcpy((void*)tput_time_eNB,(void*)&tput_time_eNB[1],(tput_window-1)*sizeof(unsigned int)); - avg_tput_eNB[tput_window-1] = PHY_vars_eNB_g[0]->total_dlsch_bitrate/1000; - tput_time_eNB[tput_window-1] = PHY_vars_eNB_g[0]->frame; - - for (i=0;i<1024;i++) - prach_corr[i] = ((s32)prach_ifft[0][i<<2]*prach_ifft[0][i<<2]+ - (s32)prach_ifft[0][1+(i<<2)]*prach_ifft[0][1+(i<<2)]) >> 15; - do_forms2(form_dl, - &(PHY_vars_eNB_g[0]->lte_frame_parms), - 0, - UE_flag, - (s16**)PHY_vars_eNB_g[0]->lte_eNB_pusch_vars[0]->drs_ch_estimates_time[0], - (s16**)PHY_vars_eNB_g[0]->lte_eNB_pusch_vars[0]->drs_ch_estimates[0], - (s16**)PHY_vars_eNB_g[0]->lte_eNB_common_vars.rxdata[0], - (s16**)PHY_vars_eNB_g[0]->lte_eNB_common_vars.rxdataF[0], - NULL, - (s16*)PHY_vars_eNB_g[0]->lte_eNB_pusch_vars[0]->rxdataF_comp[0][0], - NULL, - (s16*)PHY_vars_eNB_g[0]->lte_eNB_pusch_vars[0]->llr, - NULL, - NULL, - avg_tput_eNB, - tput_time_eNB, - tput_window, - PHY_vars_eNB_g[0]->ulsch_eNB[0]->harq_processes[0]->nb_rb*12*get_Qm(PHY_vars_eNB_g[0]->ulsch_eNB[0]->harq_processes[0]->mcs)*PHY_vars_eNB_g[0]->ulsch_eNB[0]->Nsymb_pusch, - prach_corr, - 1024); - - - } - //printf("doing forms\n"); - usleep(100000); // 100 ms - } - - //fclose (UE_stats); - //fclose (eNB_stats); - - return (void*)(1); + + //fclose (UE_stats); + //fclose (eNB_stats); + + pthread_exit((void*)arg); } #endif int dummy_tx_buffer[3840*4] __attribute__((aligned(16))); -static void *sync_hw(void *arg) +#ifdef EMOS +#define NO_ESTIMATES_DISK 20 //No. of estimates that are aquired before dumped to disk +int channel_buffer_size = SAMPLES_PER_SLOT*4; //one slot, 4 byte per sample + + +void *emos_thread (void *arg) { - RT_TASK *task; - task = rt_task_init_schmod(nam2num("TASK2"), 0, 0, 0, SCHED_FIFO, 0xF); - mlockall(MCL_CURRENT | MCL_FUTURE); + char c; + char *fifo2file_buffer, *fifo2file_ptr; - rt_printk("fun0: task %p\n",task); + int fifo, counter=0, bytes; + long long unsigned int total_bytes=0; -#ifdef HARD_RT - rt_make_hard_real_time(); + FILE *dumpfile_id; + char dumpfile_name[1024]; + time_t starttime_tmp; + struct tm starttime; + + time_t timer; + struct tm *now; + + struct gps_data_t *gps_data = NULL; + struct gps_fix_t dummy_gps_data; + + struct sched_param sched_param; + int ret; + + 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); + + memset(&dummy_gps_data,1,sizeof(struct gps_fix_t)); + +#if GPSD_API_MAJOR_VERSION>=5 + ret = gps_open("127.0.0.1","2947",gps_data); + if (ret!=0) +#else + gps_data = gps_open("127.0.0.1","2947"); + if (gps_data == NULL) #endif - - while (!oai_exit) { + printf("[EMOS] Could not open GPS\n"); + //exit(-1); + } +#if GPSD_API_MAJOR_VERSION>=4 + else if (gps_stream(gps_data, WATCH_ENABLE,NULL) != 0) +#else + else if (gps_query(gps_data, "w+x") != 0) +#endif + { + //sprintf(tmptxt,"Error sending command to GPS, gps_data = %x", gps_data); + printf("[EMOS] Error sending command to GPS\n"); + //exit(-1); + } + else + printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data); + + /* + if (UE_flag==0) + channel_buffer_size = sizeof(fifo_dump_emos_eNB); + else + channel_buffer_size = sizeof(fifo_dump_emos_UE); + */ - rt_printk("exmimo_pci_interface->mbox = %d\n",((unsigned int *)DAQ_MBOX)[0]); + // allocate memory for NO_FRAMES_DISK channes estimations + fifo2file_buffer = malloc(NO_ESTIMATES_DISK*channel_buffer_size); + fifo2file_ptr = fifo2file_buffer; - rt_sleep(nano2count(FRAME_PERIOD*10)); + 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,"/tmp/%s_data_%d%02d%02d_%02d%02d%02d.EMOS", + (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); + if (bytes<=0) + continue; + + /* + 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%NO_ESTIMATES_DISK)==0) + { + //reset stuff + fifo2file_ptr = fifo2file_buffer; + //counter = 0; + + //flush buffer to disk + if (fwrite(fifo2file_buffer, sizeof(char), NO_ESTIMATES_DISK*channel_buffer_size, dumpfile_id) != NO_ESTIMATES_DISK*channel_buffer_size) + { + fprintf(stderr, "[EMOS] Error writing to dumpfile\n"); + exit(EXIT_FAILURE); + } + /* + if (gps_data) + { + if (gps_poll(gps_data) != 0) { + printf("[EMOS] problem polling data from gps\n"); + } + else { + printf("[EMOS] lat %g, lon %g\n",gps_data->fix.latitude,gps_data->fix.longitude); + } + if (fwrite(&(gps_data->fix), sizeof(char), sizeof(struct gps_fix_t), dumpfile_id) != sizeof(struct gps_fix_t)) + { + printf("[EMOS] Error writing to dumpfile, stopping recording\n"); + exit(EXIT_FAILURE); + } + } + else + { + printf("[EMOS] WARNING: No GPS data available, storing dummy packet\n"); + if (fwrite(&(dummy_gps_data), sizeof(char), sizeof(struct gps_fix_t), dumpfile_id) != sizeof(struct gps_fix_t)) + { + printf("[EMOS] Error writing to dumpfile, stopping recording\n"); + exit(EXIT_FAILURE); + } + } + */ + } + if ((counter%2000)==0) + printf("[EMOS] count %d (%d sec), total bytes wrote %llu\n", counter, counter/2000, total_bytes); + } + + 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; - int slot=0,hw_slot,last_slot, next_slot,frame=0; + RTIME now; +#endif + unsigned char slot=0,last_slot, next_slot; + int hw_slot,frame=0; unsigned int msg1; unsigned int aa,slot_offset, slot_offset_F; int diff; int delay_cnt; - RTIME time_in; + RTIME time_in, time_diff; int mbox_target=0,mbox_current=0; - int i; + int i,ret; int tx_offset; + int bytes; +#ifdef RTAI task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF); - mlockall(MCL_CURRENT | MCL_FUTURE); - - rt_printk("Started eNB thread (id %p)\n",task); + LOG_D(HW,"Started eNB thread (id %p)\n",task); +#ifndef TIMER_ONESHOT_MODE + now = rt_get_time(); + ret = rt_task_make_periodic(task, now, nano2count(500000LL)); + if (ret!=0) + LOG_E(HW,"Problem with periodic timer\n"); +#endif +#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) { - // rt_printk("eNB: slot %d\n",slot); - -#ifdef CBMIMO1 - rt_sem_wait(mutex); - /* - if ((slot%2000)<10) - rt_printk("fun0: Hello World %d, instance_cnt %d!\n",slot,*instance_cnt_ptr_user); - */ - while (*instance_cnt_ptr_user<0) - { - rt_sem_signal(mutex); - rt_receive(0,&msg1); - rt_sem_wait(mutex); - /* - if ((slot%2000)<10) - rt_printk("fun0: instance_cnt %d, msg1 %d!\n",*instance_cnt_ptr_user,msg1); - */ - } - rt_sem_signal(mutex); - slot = msg1 % LTE_SLOTS_PER_FRAME; - -#else - hw_slot = (((((unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; + 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 = ((((slot+1)%20)*15+1)>>1)%150; + mbox_target = mbox_bounds[slot]; //this is the mbox counter where we are - mbox_current = ((unsigned int *)DAQ_MBOX)[0]; + 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; + + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_ENB, slot); + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_ENB, frame); + 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); + + 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); + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1); +#ifdef TIMER_ONESHOT_MODE + //ret = rt_sleep_ns(DAQ_PERIOD * (slot%4==0?6:8)); + ret = rt_sleep_ns(500000); + if (ret) + LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in); +#else + rt_task_wait_period(); +#endif + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0); + + //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()); + + 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; - - if (diff < (-5)) { - rt_printk("eNB Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, slot, hw_slot, diff); - slot++; - if (slot==20) - slot=0; - continue; - } - if (diff>8) - rt_printk("eNB Frame %d: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, slot, hw_slot, mbox_current, mbox_target, diff); + diff = mbox_target - mbox_current; + - delay_cnt = 0; - while ((diff>0) && (!oai_exit)) - { - time_in = rt_get_time_ns(); - //rt_printk("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); - //rt_printk("Frame %d: slot %d, sleeping for %llu\n", frame, slot, diff*DAQ_PERIOD); - rt_sleep(nano2count(diff*DAQ_PERIOD)); - hw_slot = (((((unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - //rt_printk("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; - rt_printk("eNB Frame %d: HW stopped ... \n",frame); - } - mbox_current = ((unsigned int *)DAQ_MBOX)[0]; - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround - diff = 150-mbox_current+mbox_target; - else - diff = mbox_target - mbox_current; - } - -#endif last_slot = (slot)%LTE_SLOTS_PER_FRAME; if (last_slot <0) last_slot+=20; next_slot = (slot+3)%LTE_SLOTS_PER_FRAME; - - //PHY_vars_eNB_g[0]->frame = frame; - if (frame>5) - { - /* - if (frame%100==0) - rt_printk("frame %d (%d), slot %d, hw_slot %d, next_slot %d (before): DAQ_MBOX %d\n",frame, PHY_vars_eNB_g[0]->frame, slot, hw_slot,next_slot,DAQ_MBOX[0]); - */ - if (fs4_test==0) - { - phy_procedures_eNB_lte (last_slot, next_slot, PHY_vars_eNB_g[0], 0); -#ifndef IFFT_FPGA - slot_offset_F = (next_slot)* - (PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)* - ((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7); - slot_offset = (next_slot)* - (PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1); - 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))) - { - // rt_printk("Frame %d: Generating slot %d\n",frame,next_slot); - - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) - { - if (PHY_vars_eNB_g[0]->lte_frame_parms.Ncp == 1) - { - PHY_ofdm_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], -#ifdef BIT8_TX - &PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset>>1], -#else - dummy_tx_buffer,//&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset], -#endif - PHY_vars_eNB_g[0]->lte_frame_parms.log2_symbol_size, - 6, - PHY_vars_eNB_g[0]->lte_frame_parms.nb_prefix_samples, - PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft, - PHY_vars_eNB_g[0]->lte_frame_parms.rev, - CYCLIC_PREFIX); - } - else - { - normal_prefix_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], -#ifdef BIT8_TX - &PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset>>1], -#else - dummy_tx_buffer,//&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset], -#endif - 7, - &(PHY_vars_eNB_g[0]->lte_frame_parms)); - } -#ifdef EXMIMO - for (i=0; ilte_frame_parms.samples_per_tti/2; i++) - { - tx_offset = (int)slot_offset+time_offset[aa]+i; - if (tx_offset<0) - tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; - ((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= - ((short*)dummy_tx_buffer)[2*i]<<4; - ((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]= - ((short*)dummy_tx_buffer)[2*i+1]<<4; - } -#endif //EXMIMO - } - } - } - -#endif //IFFT_FPGA - /* - if (frame%100==0) - rt_printk("hw_slot %d (after): DAQ_MBOX %d\n",hw_slot,DAQ_MBOX[0]); - */ - } - - /* - if ((slot%2000)<10) - rt_printk("fun0: doing very hard work\n"); - */ -#ifndef CBMIMO1 - slot++; - if (slot==20) - slot=0; -#endif - //slot++; - if ((slot%20)==0) - frame++; -#ifdef CBMIMO1 - rt_sem_wait(mutex); - (*instance_cnt_ptr_user)--; - //rt_printk("fun0: instance_cnt %d!\n",*instance_cnt_ptr_user); - rt_sem_signal(mutex); -#endif - - } - - rt_printk("fun0: finished, ran %d times.\n",slot); - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - - // clean task - rt_task_delete(task); - rt_printk("Task deleted. returning\n"); - return 0; -} - -/* This is the main UE thread. Initially it is doing a periodic get_frame. One synchronized it gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */ -static void *UE_thread(void *arg) -{ - RT_TASK *task; - RTIME in, out, diff; - int slot=0,frame=0,hw_slot,last_slot, next_slot; - unsigned int msg1; - unsigned int aa,slot_offset, slot_offset_F; - static int is_synchronized = 0; - static int received_slots = 0; - static int slot0 = 0; - int delay_cnt; - RTIME time_in; - int hw_slot_offset=0,rx_offset_mbox=0,mbox_target=0,mbox_current=0; - int diff2; - static int first_run=1; - int carrier_freq_offset = 0; //-7500; - int i; - - task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF); - mlockall(MCL_CURRENT | MCL_FUTURE); - - rt_printk("Started UE thread (id %p)\n",task); - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - if (mode == rx_calib_ue) { - carrier_freq_offset = -7500; - for (i=0; i<4; i++) { - frame_parms->carrier_freq[i] = carrier_freq[i]+carrier_freq_offset; - frame_parms->carrier_freqtx[i] = carrier_freq[i]+carrier_freq_offset; - } - ioctl(openair_fd,openair_DUMP_CONFIG,frame_parms); - // dump_frame_parms(frame_parms); - } - - while (!oai_exit) - { -#ifdef CBMIMO1 - rt_sem_wait(mutex); - /* - if ((slot%2000)<10) - rt_printk("fun0: Hello World %d, instance_cnt %d!\n",slot,*instance_cnt_ptr_user); - */ - while (*instance_cnt_ptr_user<0) - { - rt_sem_signal(mutex); - rt_receive(0,&msg1); - rt_sem_wait(mutex); - /* - if ((slot%2000)<10) - rt_printk("fun0: instance_cnt %d, msg1 %d!\n",*instance_cnt_ptr_user,msg1); - */ - } - - rt_sem_signal(mutex); - - slot = (msg1 - slot0) % LTE_SLOTS_PER_FRAME; -#else - hw_slot = (((((unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; //the slot the hw is about to store - if (is_synchronized) { - //this is the mbox counter that indicates the start of the frame - rx_offset_mbox = (PHY_vars_UE_g[0]->rx_offset * 150) / (10*PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti); - //this is the mbox counter where we should be - mbox_target = (((((slot+1)%20)*15+1)>>1) + rx_offset_mbox + 1)%150; - //this is the mbox counter where we are - mbox_current = ((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>=120) && (mbox_target<30)) //handle the frame wrap-arround - diff2 = 150-mbox_current+mbox_target; - else if ((mbox_current<30) && (mbox_target>=120)) - diff2 = -150+mbox_target-mbox_current; - else - diff2 = mbox_target - mbox_current; - - if (diff2 <(-5)) { - rt_printk("UE Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, slot, hw_slot, diff2); - slot++; - if (slot==20) - slot=0; - continue; - } - if (diff2>8) - rt_printk("UE Frame %d: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, slot, hw_slot, mbox_current, mbox_target, diff2); - - /* - if (frame%100==0) - rt_printk("frame %d (%d), slot %d, hw_slot %d, rx_offset_mbox %d, mbox_target %d, mbox_current %d, diff %d\n",frame, PHY_vars_UE_g[0]->frame, slot,hw_slot,rx_offset_mbox,mbox_target,mbox_current,diff2); - */ - timing_info[slot].time0 = rt_get_time_ns(); - timing_info[slot].mbox0 = ((unsigned int *)DAQ_MBOX)[0]; - - delay_cnt = 0; - while ((diff2>0) && (!oai_exit) && (is_synchronized) ) - { - rt_sleep(nano2count(diff2*DAQ_PERIOD)); - hw_slot = (((((unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - delay_cnt++; - if (delay_cnt == 30) - { - oai_exit = 1; - rt_printk("UE frame %d: HW stopped ... \n",frame); - } - mbox_current = ((unsigned int *)DAQ_MBOX)[0]; - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround - diff2 = 150-mbox_current+mbox_target; - else - diff2 = mbox_target - mbox_current; - } - - timing_info[slot].time1 = rt_get_time_ns(); - timing_info[slot].mbox1 = ((unsigned int *)DAQ_MBOX)[0]; - timing_info[slot].mbox_target = mbox_target; - } -#endif - last_slot = (slot)%LTE_SLOTS_PER_FRAME; - if (last_slot <0) - last_slot+=LTE_SLOTS_PER_FRAME; - next_slot = (slot+3)%LTE_SLOTS_PER_FRAME; - - timing_info[slot].frame = PHY_vars_UE_g[0]->frame; - timing_info[slot].hw_slot = hw_slot; - timing_info[slot].last_slot = last_slot; - timing_info[slot].next_slot = next_slot; - - if (is_synchronized) - { - /* - if (frame%100==0) - rt_printk("frame %d (%d), slot %d, hw_slot %d, last_slot %d (before): DAQ_MBOX %d\n",frame, PHY_vars_UE_g[0]->frame, slot,hw_slot,last_slot,DAQ_MBOX[0]); - */ - in = rt_get_time_ns(); - phy_procedures_UE_lte (last_slot, next_slot, PHY_vars_UE_g[0], 0, 0,mode); - out = rt_get_time_ns(); - diff = out-in; - /* - if (frame % 100 == 0) - rt_printk("hw_slot %d (after): DAQ_MBOX %d\n",hw_slot,DAQ_MBOX[0]); - - rt_printk("Frame %d: last_slot %d, phy_procedures_lte_ue time_in %llu, time_out %llu, diff %llu\n", - frame, last_slot,in,out,diff); - */ - - timing_info[slot].time2 = rt_get_time_ns(); - timing_info[slot].mbox2 = ((unsigned int *)DAQ_MBOX)[0]; - - } - else // we are not yet synchronized - { - hw_slot_offset = 0; - -#ifdef CBMIMO1 - if (received_slots==0) - { - ioctl(openair_fd,openair_GET_BUFFER,NULL); - } - if (received_slots==(100*LTE_SLOTS_PER_FRAME)-1) //we got enough slots so we can do sync (the factor 100 is to wait some time longer) - { - rt_printk("fun0: slot %d: doing sync\n",slot); - received_slots = -1; // will be increased below - if (initial_sync(PHY_vars_UE_g[0],mode)==0) - { - lte_adjust_synch(&PHY_vars_UE_g[0]->lte_frame_parms, - PHY_vars_UE_g[0], - 0, - 1, - 16384); - - ioctl(openair_fd,openair_SET_RX_OFFSET,&PHY_vars_UE_g[0]->rx_offset); //synchronize hardware - // here we should actually do another dump config with the parameters obtained from the sync. - - ioctl(openair_fd,openair_START_TX_SIG,NULL); //start the DMA transfers - - //for better visualization afterwards - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) - memset(PHY_vars_UE_g[0]->lte_ue_common_vars.rxdata[aa],0, - PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)); - is_synchronized = 1; - slot0 = msg1; - } - } - received_slots++; -#else - slot = 0; - ioctl(openair_fd,openair_GET_BUFFER,NULL); - rt_sleep(nano2count(FRAME_PERIOD)); - // rt_printk("fun0: slot %d: doing sync\n",slot); - - if (initial_sync(PHY_vars_UE_g[0],mode)==0) { - /* - lte_adjust_synch(&PHY_vars_UE_g[0]->lte_frame_parms, - PHY_vars_UE_g[0], - 0, - 1, - 16384); - */ - //for better visualization afterwards - /* - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) - memset(PHY_vars_UE_g[0]->lte_ue_common_vars.rxdata[aa],0, - PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)); - */ - if (mode == rx_calib_ue) { - oai_exit=1; - } - else { - is_synchronized = 1; - ioctl(openair_fd,openair_START_TX_SIG,NULL); //start the DMA transfers - - hw_slot_offset = (PHY_vars_UE_g[0]->rx_offset<<1) / PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti; - rt_printk("Got synch: hw_slot_offset %d\n",hw_slot_offset); - } - } - else { - carrier_freq_offset += 100; - if (carrier_freq_offset > 7500) { - LOG_I(PHY,"[initial_sync] No cell synchronization found, abondoning\n"); - oai_exit = 1; - } - else { - LOG_I(PHY,"[initial_sync] trying carrier off %d Hz\n",carrier_freq_offset); - for (i=0; i<4; i++) { - frame_parms->carrier_freq[i] = carrier_freq[i]+carrier_freq_offset; - frame_parms->carrier_freqtx[i] = carrier_freq[i]+carrier_freq_offset; - } - ioctl(openair_fd,openair_DUMP_CONFIG,frame_parms); - // dump_frame_parms(frame_parms); - - } - } - -#endif - } - - /* - if ((slot%2000)<10) - rt_printk("fun0: doing very hard work\n"); - */ -#ifdef CBMIMO1 - rt_sem_wait(mutex); - (*instance_cnt_ptr_user)--; - //rt_printk("fun0: instance_cnt %d!\n",*instance_cnt_ptr_user); - rt_sem_signal(mutex); -#else slot++; - if (slot==20) - { - slot=0; - frame++; - } + if (slot==20) { + slot=0; + frame++; + } + + if (frame==1000) + oai_exit=1; + +#if defined(ENABLE_ITTI) + itti_update_lte_time(frame, slot); #endif } - rt_printk("fun0: finished, ran %d times.\n",slot); + + 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); - rt_printk("Task deleted. returning\n"); +#endif + LOG_D(HW,"Task deleted. returning\n"); return 0; } - - - int main(int argc, char **argv) { +#ifdef RTAI RT_TASK *task; + RTIME period; +#endif int i,j,aa; + void *status; - -#ifdef EXMIMO + /* 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 + 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}; - u32 rxgain[4]={30,30,30,30}; - u32 txgain[4]={25,25,25,25}; -#endif + u32 rxgain[4] = {20,20,20,20}; + u32 txgain[4] = {20,20,20,20}; - u8 eNB_id=0,UE_id=0; u16 Nid_cell = 0; u8 cooperation_flag=0, transmission_mode=1, abstraction_flag=0; u8 beta_ACK=0,beta_RI=0,beta_CQI=2; @@ -1132,18 +608,21 @@ int main(int argc, char **argv) { 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; + int tx_max_power=0; char line[1000]; int l; + int ret, ant; + int ant_offset=0; -#ifdef EMOS int error_code; -#endif + char *itti_dump_file = NULL; const struct option long_options[] = { {"calib-ue-rx", required_argument, NULL, 256}, @@ -1153,17 +632,16 @@ int main(int argc, char **argv) { {"no-L2-connect", no_argument, NULL, 260}, {NULL, 0, NULL, 0}}; - mode = normal_txrx; + //mode = normal_txrx; -#ifdef XFORMS - char title[255]; -#endif - - while ((c = getopt_long (argc, argv, "C:ST:UdF:",long_options,NULL)) != -1) + 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; @@ -1182,6 +660,28 @@ int main(int argc, char **argv) { 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': +#if defined(ENABLE_USE_MME) + EPC_MODE_ENABLED = 1; + if (optarg == NULL) /* No IP address provided: use localhost */ + { + memcpy(&EPC_MODE_MME_ADDRESS[0], "127.0.0.1", 10); + } else { + u8 ip_length = strlen(optarg) + 1; + memcpy(&EPC_MODE_MME_ADDRESS[0], optarg, + ip_length > 16 ? 16 : ip_length); + } +#else + printf("You enabled mme mode without s1ap compiled...\n"); +#endif + break; case 'F': sprintf(rxg_fname,"%srxg.lime",optarg); rxg_fd = fopen(rxg_fname,"r"); @@ -1218,7 +718,7 @@ int main(int argc, char **argv) { } } else - printf("%s not found, running with defaults\n",rxg_fname); + printf("%s not found, running with defaults\n",txg_fname); sprintf(rflo_fname,"%srflo.lime",optarg); rflo_fd = fopen(rflo_fname,"r"); @@ -1229,8 +729,17 @@ int main(int argc, char **argv) { 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); @@ -1252,6 +761,7 @@ int main(int argc, char **argv) { case 260: mode = no_L2_connect; break; + */ default: break; } @@ -1263,63 +773,58 @@ int main(int argc, char **argv) { printf("configuring for eNB\n"); //randominit (0); - set_taus_seed (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 NAS_NETLINK netlink_init(); #endif // to make a graceful exit when ctrl-c is pressed signal(SIGSEGV, signal_handler); + signal(SIGINT, signal_handler); - // init the parameters - frame_parms = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS)); - frame_parms->N_RB_DL = 25; - frame_parms->N_RB_UL = 25; - frame_parms->Ncp = 0; - frame_parms->Ncp_UL = 0; - frame_parms->Nid_cell = Nid_cell; - frame_parms->nushift = 0; - frame_parms->nb_antennas_tx_eNB = 2; //initial value overwritten by initial sync later - frame_parms->nb_antennas_tx = (UE_flag==0) ? 2 : 1; - frame_parms->nb_antennas_rx = (UE_flag==0) ? 1 : 1; - frame_parms->mode1_flag = (transmission_mode == 1) ? 1 : 0; - frame_parms->frame_type = 1; -#ifdef CBMIMO1 - if (fs4_test==1) - frame_parms->tdd_config = 255; - else +#ifndef RTAI + check_clock(); #endif - frame_parms->tdd_config = 3; - frame_parms->tdd_config_S = 0; - frame_parms->phich_config_common.phich_resource = oneSixth; - frame_parms->phich_config_common.phich_duration = normal; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 - // hardware specific parameters - // for CBMIMO - frame_parms->dual_tx = 0; - frame_parms->freq_idx = 1; - - init_frame_parms(frame_parms,1); - - phy_init_top(frame_parms); - phy_init_lte_top(frame_parms); - - //init prach for openair1 test - frame_parms->prach_config_common.rootSequenceIndex=1; - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; - frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; - frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; - prach_fmt = get_prach_fmt(frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - frame_parms->frame_type); - N_ZC = (prach_fmt <4)?839:139; - - if (UE_flag==1) { + 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 @@ -1334,252 +839,155 @@ int main(int argc, char **argv) { 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; - frame_parms->node_id = NODE; - PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE*)); - PHY_vars_UE_g[0] = init_lte_UE(frame_parms, UE_id,abstraction_flag,transmission_mode); - - for (i=0;ipusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; - PHY_vars_UE_g[0]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; - PHY_vars_UE_g[0]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; - } - - compute_prach_seq(&PHY_vars_UE_g[0]->lte_frame_parms.prach_config_common, - PHY_vars_UE_g[0]->lte_frame_parms.frame_type, - PHY_vars_UE_g[0]->X_u); - PHY_vars_UE_g[0]->lte_ue_pdcch_vars[0]->crnti = 0x1234; -#ifndef OPENAIR2 - PHY_vars_UE_g[0]->lte_ue_pdcch_vars[0]->crnti = 0x1235; - //PHY_vars_UE_g[0]->lte_frame_parms. -#endif - NB_UE_INST=1; - NB_INST=1; - - openair_daq_vars.manual_timing_advance = 0; - //openair_daq_vars.timing_advance = TIMING_ADVANCE_HW; - openair_daq_vars.rx_gain_mode = DAQ_AGC_ON; - openair_daq_vars.use_ia_receiver = 0; + // 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); + } - // if AGC is off, the following values will be used - for (i=0;i<4;i++) - rxgain[i]=30; - - for (i=0;i<4;i++) { - PHY_vars_UE_g[0]->rx_gain_max[i] = rxg_max[i]; - PHY_vars_UE_g[0]->rx_gain_med[i] = rxg_med[i]; - PHY_vars_UE_g[0]->rx_gain_byp[i] = rxg_byp[i]; - } + printf ("Detected %d number of cards, %d number of antennas.\n", openair0_num_detected_cards, openair0_num_antennas[card]); - if ((mode == normal_txrx) || (mode == rx_calib_ue) || (mode == no_L2_connect) || (mode == debug_prach)) { - for (i=0; i<4; i++) { - PHY_vars_UE_g[0]->rx_gain_mode[i] = max_gain; - frame_parms->rfmode[i] = rf_mode_max[i]; - } - PHY_vars_UE_g[0]->rx_total_gain_dB = PHY_vars_UE_g[0]->rx_gain_max[0]; - } - else if ((mode == rx_calib_ue_med)) { - for (i=0; i<4; i++) { - PHY_vars_UE_g[0]->rx_gain_mode[i] = med_gain; - frame_parms->rfmode[i] = rf_mode_med[i]; - } - PHY_vars_UE_g[0]->rx_total_gain_dB = PHY_vars_UE_g[0]->rx_gain_med[0]; - } - else if ((mode == rx_calib_ue_byp)) { - for (i=0; i<4; i++) { - PHY_vars_UE_g[0]->rx_gain_mode[i] = byp_gain; - frame_parms->rfmode[i] = rf_mode_byp[i]; - } - PHY_vars_UE_g[0]->rx_total_gain_dB = PHY_vars_UE_g[0]->rx_gain_byp[0]; - } + 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); - PHY_vars_UE_g[0]->tx_power_max_dBm = tx_max_power; + 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; - } - else { -#ifdef OPENAIR2 - g_log->log_component[PHY].level = LOG_INFO; -#else - g_log->log_component[PHY].level = LOG_INFO; -#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; - - - frame_parms->node_id = PRIMARY_CH; - 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); - - 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; - } - - compute_prach_seq(&PHY_vars_eNB_g[0]->lte_frame_parms.prach_config_common, - PHY_vars_eNB_g[0]->lte_frame_parms.frame_type, - PHY_vars_eNB_g[0]->X_u); - - 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=10; - openair_daq_vars.target_ue_ul_mcs=4; - - // if AGC is off, the following values will be used - for (i=0;i<4;i++) - rxgain[i]=30; - - // set eNB to max gain - PHY_vars_eNB_g[0]->rx_total_gain_eNB_dB = rxg_max[0]; //was measured at rxgain=30; - for (i=0; i<4; i++) { - frame_parms->rfmode[i] = rf_mode_max[i]; - } - - - } + p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB; + for (ant=0; ant<4; ant++) + p_exmimo_config->framing.resampling_factor[ant] = RESAMPLING_FACTOR; - // for Express MIMO - for (i=0; i<4; i++) { - frame_parms->carrier_freq[i] = carrier_freq[i]; - frame_parms->carrier_freqtx[i] = carrier_freq[i]; - frame_parms->rxgain[i] = rxgain[i]; - frame_parms->txgain[i] = txgain[i]; - //frame_parms->rf_mode is set above (individually for UE and eNB) - frame_parms->rflocal[i] = rf_local[i]; - frame_parms->rfvcolocal[i] = rf_vcocal[i]; - frame_parms->rxdc[i] = rf_rxdc[i]; + /* + 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 + } + */ + + ant_offset = 0; + for (ant=0; ant<4; ant++) { + if (ant==ant_offset) { + //if (1) { + p_exmimo_config->rf.rf_mode[ant] = rf_mode_base; + //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; + carrier_freq[ant] = 0; //this turns off all other LIMEs + } } - dump_frame_parms(frame_parms); + for (ant = 0; ant<4; ant++) { + p_exmimo_config->rf.do_autocal[ant] = 1; + 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 if ((carrier_freq[ant] >= 1900000000) && (carrier_freq[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; + } + + + 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 = 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]); - mac_xface = malloc(sizeof(MAC_xface)); - -#ifdef OPENAIR2 - int eMBMS_active=0; - l2_init(frame_parms,eMBMS_active); - if (UE_flag == 1) - mac_xface->dl_phy_sync_success (0, 0, 0, 1); - else - mac_xface->mrbch_phy_sync_failure (0, 0, 0); -#endif - - - mac_xface->macphy_exit = &exit_fun; - -#ifdef OPENAIR2 - //if (otg_enabled) { - init_all_otg(0); - g_otg->seed = 0; - init_seeds(g_otg->seed); - g_otg->num_nodes = 2; - for (i=0; inum_nodes; i++){ - for (j=0; jnum_nodes; j++){ - g_otg->application_idx[i][j] = 1; - //g_otg->packet_gen_type=SUBSTRACT_STRING; - g_otg->aggregation_level[i][j][0]=1; - g_otg->application_type[i][j][0] = BCBR; //MCBR, BCBR - } - } - init_predef_traffic(); - //} -#endif - - // start up the hardware - openair_fd=setup_oai_hw(frame_parms); - - number_of_cards = 1; - - // connect the TX/RX buffers - if (UE_flag==1) - { - setup_ue_buffers(PHY_vars_UE_g[0],frame_parms,0); -#ifndef CBMIMO1 - for (i=0; isamples_per_tti*10; i++) - for (aa=0; aanb_antennas_tx; aa++) - PHY_vars_UE_g[0]->lte_ue_common_vars.txdata[aa][i] = 0x00010001; -#endif - } - else - { - setup_eNB_buffers(PHY_vars_eNB_g[0],frame_parms); - if (fs4_test==0) - { -#ifndef CBMIMO1 - printf("Setting eNB buffer to all-RX\n"); - // Set LSBs for antenna switch (ExpressMIMO) - for (i=0; isamples_per_tti*10; i++) - for (aa=0; aanb_antennas_tx; aa++) - PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][i] = 0x00010001; - - // Set the last OFDM symbol of subframe 4 to TX to allow enough time for switch to settle - // (that's ok since the last symbol can be configured as SRS) - /* - for (i=frame_parms->samples_per_tti*5-0*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); - isamples_per_tti*5; i++) - for (aa=0; aanb_antennas_tx; aa++) - PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][i] = 0x0; - */ - -#endif - } - else - { - printf("Setting eNB buffer to fs/4 test signal\n"); - for (j=0; jlte_frame_parms.samples_per_tti*10; j+=4) - for (aa=0; aanb_antennas_tx; aa++) - { -#ifdef CBMIMO1 - amp = 0x80; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+1] = 0; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+3] = amp-1; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+5] = 0; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+7] = amp; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j] = amp-1; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+2] = 0; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+4] = amp; - ((char*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+6] = 0; -#else - amp = 0x8000; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+1] = 0; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+3] = amp-1; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+5] = 0; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+7] = amp; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j] = amp-1; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+2] = 0; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+4] = amp; - ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+6] = 0; -#endif - } - } - } + for (ant=0;ant<4;ant++) + p_exmimo_config->rf.do_autocal[ant] = 0; #ifdef EMOS error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE); - printf("[OPENAIR][SCHED][INIT] Created EMOS FIFO %d, error code %d\n",CHANSOUNDER_FIFO_MINOR,error_code); + 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 - // make main thread LXRT soft realtime - task = rt_task_init_schmod(nam2num("MYTASK"), 9, 0, 0, SCHED_FIFO, 0xF); mlockall(MCL_CURRENT | MCL_FUTURE); - // start realtime timer and scheduler - //rt_set_oneshot_mode(); - rt_set_periodic_mode(); - start_rt_timer(0); +#ifdef RTAI + // make main thread LXRT soft realtime + task = rt_task_init_schmod(nam2num("MYTASK"), 9, 0, 0, SCHED_FIFO, 0xF); - //now = rt_get_time() + 10*PERIOD; - //rt_task_make_periodic(task, now, PERIOD); + // start realtime timer and scheduler +#ifdef TIMER_ONESHOT_MODE + rt_set_oneshot_mode(); + start_rt_timer(0); + printf("started RTAI timer inoneshot mode\n"); +#else + rt_set_periodic_mode(); + period = start_rt_timer(nano2count(500000)); + printf("started RTAI timer with period %llu ns\n",count2nano(period)); +#endif printf("Init mutex\n"); //mutex = rt_get_adr(nam2num("MUTEX")); @@ -1591,154 +999,287 @@ int main(int argc, char **argv) { } else printf("mutex=%p\n",mutex); - - /* - cond = rt_cond_init(nam2num("CONDITION")); - //cond = rt_get_adr(nam2num("CONDITION")); - if (cond==0) - printf("Error init cond\n"); - */ - - // initialize the instance cnt before starting the thread - instance_cnt_ptr_user = &instance_cnt; - - - - // signal the driver to set up for user-space operation - // this will initialize the semaphore and the task pointers in the kernel - // further we receive back the pointer to the shared instance counter which is used to signal if the thread is busy or not. This pointer needs to be mapped to user space. - ioctl(openair_fd,openair_START_LXRT,&instance_cnt_ptr_kern); - instance_cnt_ptr_user = (int*) (instance_cnt_ptr_kern -bigphys_top+mem_base); - *instance_cnt_ptr_user = -1; - printf("instance_cnt_ptr_kern %p, instance_cnt_ptr_user %p, *instance_cnt_ptr_user %d\n", (void*) instance_cnt_ptr_kern, (void*) instance_cnt_ptr_user,*instance_cnt_ptr_user); - - rt_sleep(nano2count(FRAME_PERIOD)); - - ioctl(openair_fd,openair_GET_PCI_INTERFACE,&pci_interface_ptr_kern); - -#ifdef CBMIMO1 - ioctl(openair_fd,openair_SET_TCXO_DAC,(void *)&tcxo); #endif -#ifdef CBMIMO1 - pci_interface[0] = (PCI_interface_t*) (pci_interface_ptr_kern-bigphys_top+mem_base); - printf("pci_interface_ptr_kern = %p, pci_interface = %p, tcxo_dac =%d\n", (void*) pci_interface_ptr_kern, pci_interface[0],pci_interface[0]->tcxo_dac); -#else - exmimo_pci_interface = (exmimo_pci_interface_t*) (pci_interface_ptr_kern-bigphys_top+mem_base); - printf("pci_interface_ptr_kern = %p, exmimo_pci_interface = %p\n", (void*) pci_interface_ptr_kern, exmimo_pci_interface); - DAQ_MBOX = (unsigned int *)(0xc0000000+exmimo_pci_interface->rf.mbox-bigphys_top+mem_base); -#endif + DAQ_MBOX = (volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0]; + // this starts the DMA transfers if (UE_flag!=1) - ioctl(openair_fd,openair_START_TX_SIG,NULL); + openair0_start_rt_acquisition(card); #ifdef XFORMS - if (do_forms==1) - { + if (do_forms==1) { fl_initialize (&argc, argv, NULL, 0, 0); - form_dl = create_form_lte_scope(); form_stats = create_form_stats_form(); - if (UE_flag==1) - sprintf (title, "LTE DL SCOPE UE"); - else - sprintf (title, "LTE UL SCOPE eNB"); - fl_show_form (form_dl->lte_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + 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_idlte_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) { - //fl_hide_object(form->ia_receiver_button); - if (otg_enabled) { - fl_set_button(form_dl->ia_receiver_button,1); - fl_set_object_label(form_dl->ia_receiver_button,"DL traffic ON"); - } - else { - fl_set_button(form_dl->ia_receiver_button,0); - fl_set_object_label(form_dl->ia_receiver_button,"DL traffic OFF"); - } + 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"); + } + } } else { - //fl_show_object(form->ia_receiver_button); - if (openair_daq_vars.use_ia_receiver) { - fl_set_button(form_dl->ia_receiver_button,1); - fl_set_object_label(form_dl->ia_receiver_button, "IA Receiver ON"); - } - else { - fl_set_button(form_dl->ia_receiver_button,0); - fl_set_object_label(form_dl->ia_receiver_button, "IA Receiver OFF"); - } + 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"); + } } - thread2 = pthread_create(&thread2, NULL, scope_thread, NULL); + ret = pthread_create(&thread2, NULL, scope_thread, NULL); + printf("Scope thread created, ret=%d\n",ret); } #endif - rt_sleep(nano2count(10*FRAME_PERIOD)); +#ifdef EMOS + ret = pthread_create(&thread3, NULL, emos_thread, NULL); + printf("EMOS 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_threads(); - rt_sleep(nano2count(FRAME_PERIOD/10)); + 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"); } -#ifndef CBMIMO1 - // sync_thread = rt_thread_create(sync_hw,NULL,10000000); -#endif - - printf("threads created\n"); // wait for end of program - printf("TYPE TO TERMINATE\n"); - getchar(); + printf("TYPE 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? - fl_hide_form(form_stats->stats_form); - fl_free_form(form_stats->stats_form); - fl_hide_form(form_dl->lte_scope); - fl_free_form(form_dl->lte_scope); + 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_idlte_phy_scope_enb); + fl_free_form(form_enb[UE_id]->lte_phy_scope_enb); + } + } } #endif - // stop threads - oai_exit=1; - rt_sleep(nano2count(FRAME_PERIOD)); - + 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_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 } - stop_rt_timer(); - fd = 0; - ioctl(openair_fd,openair_STOP,&fd); - munmap((void*)mem_base, BIGPHYS_NUMPAGES*4096); +#ifdef OPENAIR2 + //cleanup_pdcp_thread(); +#endif + +#ifdef RTAI + stop_rt_timer(); +#endif + + printf("stopping card\n"); + 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); +#endif #ifdef EMOS 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;inb_antennas_rx;i++) { + free(phy_vars_ue->lte_ue_common_vars.rxdata[i]); + phy_vars_ue->lte_ue_common_vars.rxdata[i] = (s32*) 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;inb_antennas_tx;i++) { + free(phy_vars_ue->lte_ue_common_vars.txdata[i]); + phy_vars_ue->lte_ue_common_vars.txdata[i] = (s32*) 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;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]; + + 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; + } + } + } +} +*/