/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Author and copyright: Laurent Thomas, open-cells.com * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /* Form definition file generated by fdesign */ #include #include "nr_phy_scope.h" #include "executables/nr-softmodem-common.h" #define TPUT_WINDOW_LENGTH 100 #define localBuff(NaMe,SiZe) float NaMe[SiZe]; memset(NaMe,0,sizeof(NaMe)); int otg_enabled; FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW}; float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_ue_max[NUMBER_OF_UE_MAX] = {0}; typedef struct { int16_t r; int16_t i; } scopeSample_t; #define SquaredNorm(VaR) ((VaR).r*(VaR).r+(VaR).i*(VaR).i) typedef struct OAIgraph { FL_OBJECT *graph; void (*gNBfunct) (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id); void (*nrUEfunct) (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id); } OAIgraph_t; /* Forms and Objects */ typedef struct { FL_FORM *phy_scope; OAIgraph_t graph[20]; FL_OBJECT *button_0; } FD_phy_scope_t; typedef struct { FL_FORM *stats_form; void *vdata; char *cdata; long ldata; FL_OBJECT *stats_text; FL_OBJECT *stats_button; } FD_stats_form; static void drawsymbol(FL_OBJECT *obj, int id, FL_POINT *p, int n, int w, int h) { fl_points( p, n, FL_YELLOW); } static void ia_receiver_on_off( FL_OBJECT *button, long arg) { if (fl_get_button(button)) { fl_set_object_label(button, "IA Receiver ON"); // PHY_vars_UE_g[0][0]->use_ia_receiver = 1; fl_set_object_color(button, FL_GREEN, FL_GREEN); } else { fl_set_object_label(button, "IA Receiver OFF"); // PHY_vars_UE_g[0][0]->use_ia_receiver = 0; fl_set_object_color(button, FL_RED, FL_RED); } } static void dl_traffic_on_off( FL_OBJECT *button, long arg) { if (fl_get_button(button)) { fl_set_object_label(button, "DL Traffic ON"); otg_enabled = 1; fl_set_object_color(button, FL_GREEN, FL_GREEN); } else { fl_set_object_label(button, "DL Traffic OFF"); otg_enabled = 0; fl_set_object_color(button, FL_RED, FL_RED); } } static FL_OBJECT *commonGraph( int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { FL_OBJECT *graph; graph=fl_add_xyplot(type, x, y, w, h, label); fl_set_object_boxtype(graph, FL_EMBOSSED_BOX ); fl_set_object_lcolor(graph, FL_WHITE ); // Label color fl_set_xyplot_symbol(graph, 0, drawsymbol); fl_set_object_color(graph, FL_BLACK, pointColor); return graph; } static OAIgraph_t gNBcommonGraph( void (*funct) (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id), int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { OAIgraph_t graph; graph.graph=commonGraph(type, x, y, w, h, label, pointColor); graph.gNBfunct=funct; graph.nrUEfunct=NULL; return graph; } static OAIgraph_t nrUEcommonGraph( void (*funct) (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id), int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { OAIgraph_t graph; graph.graph=commonGraph(type, x, y, w, h, label, pointColor); graph.gNBfunct=NULL; graph.nrUEfunct=funct; return graph; } void phy_scope_gNB(FD_phy_scope_t *form, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { static FD_phy_scope_t *remeberForm=NULL; if (form==NULL) form=remeberForm; else remeberForm=form; if (form==NULL) return; int i=0; while (form->graph[i].graph) { form->graph[i].gNBfunct(form->graph[i].graph, phy_vars_gnb, phy_vars_ru, UE_id); i++; } fl_check_forms(); } static void timeSignal (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { // Received signal in time domain of receive antenna 0 if (!phy_vars_ru->common.rxdata) return; NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; scopeSample_t **rxsig_t = (scopeSample_t **)phy_vars_ru->common.rxdata; float rxsig_t_dB[frame_parms->samples_per_frame]; float time[frame_parms->samples_per_frame]; for (int arx=0; arxsamples_per_frame; i++) { rxsig_t_dB[i] = 10*log10(1.0+SquaredNorm(rxsig_t[arx][i])); } if (arx==0) fl_set_xyplot_data(graph,time,rxsig_t_dB, frame_parms->samples_per_frame,"","",""); else fl_add_xyplot_overlay(graph,arx,time,rxsig_t_dB,frame_parms->samples_per_frame,rx_antenna_colors[arx]); } } } static void timeResponse (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { if (!phy_vars_gnb->pusch_vars[UE_id]->ul_ch_estimates_time) return; NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; scopeSample_t **chest_t = (scopeSample_t **) phy_vars_gnb->pusch_vars[UE_id]->ul_ch_estimates_time; int ymax = 0; float time2[2*frame_parms->ofdm_symbol_size]; float chest_t_abs[2*frame_parms->ofdm_symbol_size]; for (int arx=0; arxofdm_symbol_size); i++) { time2[i] = (float)i; chest_t_abs[i] = 10*log10(1.0 + SquaredNorm(chest_t[0][i])); if (chest_t_abs[i] > ymax) ymax = chest_t_abs[i]; } if (arx==0) fl_set_xyplot_data(graph,time2,chest_t_abs,(2*frame_parms->ofdm_symbol_size),"","",""); else { fl_add_xyplot_overlay(graph,arx,time2,chest_t_abs,(frame_parms->ofdm_symbol_size>>3),rx_antenna_colors[arx]); fl_set_xyplot_overlay_type(graph,arx,FL_DASHED_XYPLOT); } } } // Avoid flickering effect // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); fl_set_xyplot_ybounds(graph,0,ymax); } static void frequencyResponse (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { // Channel Frequency Response if (!phy_vars_ru->common.rxdataF) return; NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; //uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; scopeSample_t **rxsig_f = (scopeSample_t **) phy_vars_ru->common.rxdataF; float rxsig_f_dB[frame_parms->samples_per_slot_wCP]; float time[frame_parms->samples_per_slot_wCP]; if (rxsig_f[0] != NULL) { for (int i=0; isamples_per_slot_wCP; i++) { rxsig_f_dB[i] = 10*log10(1.0+ SquaredNorm(rxsig_f[0][i])); time[i] = (float) i; } fl_set_xyplot_data(graph,time,rxsig_f_dB,frame_parms->samples_per_slot_wCP,"","",""); } /* for (int arx=1; arxchest_f,1,time,chest_f_abs,nsymb_ce,rx_antenna_colors[arx]); } } */ /* // tx antenna 0 fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,3); fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); */ } static void puschLLR (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { // PUSCH LLRs if (!phy_vars_gnb->pusch_vars[UE_id]->llr) return; //NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; //int Qm = 2; int16_t *pusch_llr = (int16_t *) phy_vars_gnb->pusch_vars[UE_id]->llr; int coded_bits_per_codeword =3*8*6144+12; // (8*((3*8*6144)+12)); // frame_parms->N_RB_UL*12*Qm*frame_parms->symbols_per_tti; float llr[coded_bits_per_codeword]; float bit[coded_bits_per_codeword]; for (int i=0; ipusch_vars[UE_id]->rxdataF_comp) return; NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; scopeSample_t *pusch_comp = (scopeSample_t *) phy_vars_gnb->pusch_vars[UE_id]->rxdataF_comp[0]; int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot; float I[sz], Q[sz]; for (int k=0; kpucch1ab_stats[UE_id]; int32_t *pucch1_comp = (int32_t *) NULL; //phy_vars_gnb->pucch1_stats[UE_id]; float I_pucch[10240],Q_pucch[10240],A_pucch[10240],B_pucch[10240],C_pucch[10240]; for (int ind=0; ind<10240; ind++) { I_pucch[ind] = (float)pucch1ab_comp[2*(ind)]; Q_pucch[ind] = (float)pucch1ab_comp[2*(ind)+1]; A_pucch[ind] = pucch1_comp?(10*log10(pucch1_comp[ind])):0; B_pucch[ind] = ind; int32_t *pucch1_thres = (int32_t *) NULL; // phy_vars_gnb->pucch1_stats_thres[UE_id]; C_pucch[ind] = pucch1_thres?(float)pucch1_thres[ind]:0; } fl_set_xyplot_data(graph,I_pucch,Q_pucch,10240,"","",""); fl_set_xyplot_data(graph,B_pucch,A_pucch,1024,"","",""); fl_add_xyplot_overlay(graph,1,B_pucch,C_pucch,1024,FL_RED); fl_set_xyplot_ybounds(graph,-5000,5000); fl_set_xyplot_xbounds(graph,-5000,5000); fl_set_xyplot_ybounds(graph,0,80); } } static void pucchEnergy (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { } static void pucchIQ (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { } static void puschThroughtput (FL_OBJECT *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id) { // PUSCH Throughput memmove( tput_time_enb[UE_id], &tput_time_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); memmove( tput_enb[UE_id], &tput_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); tput_time_enb[UE_id][TPUT_WINDOW_LENGTH-1] = (float) 0; // tput_enb[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0; fl_set_xyplot_data(graph,tput_time_enb[UE_id],tput_enb[UE_id],TPUT_WINDOW_LENGTH,"","",""); // fl_get_xyplot_ybounds(form->pusch_tput,&ymin,&ymax); // fl_set_xyplot_ybounds(form->pusch_tput,0,ymax); } static FD_phy_scope_t *create_phy_scope_gnb(int UE_id ) { FL_OBJECT *obj; FD_phy_scope_t *fdui = fl_malloc( sizeof *fdui ); // Define form fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 800 ); // This the whole UI box obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 800, "" ); fl_set_object_color( obj, FL_BLACK, FL_BLACK ); // Received signal fdui->graph[0] = gNBcommonGraph( timeSignal, FL_IMPULSE_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)", FL_RED ); // Time-domain channel response fdui->graph[1] = gNBcommonGraph( timeResponse, FL_NORMAL_XYPLOT, 410, 20, 370, 100, "SRS Frequency Response (samples, abs)", FL_RED ); // Frequency-domain channel response fdui->graph[2] = gNBcommonGraph( frequencyResponse, FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency Response (RE, dB)", FL_RED ); // LLR of PUSCH fdui->graph[3] = gNBcommonGraph( puschLLR, FL_POINTS_XYPLOT, 20, 260, 500, 200, "PUSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW ); // I/Q PUSCH comp fdui->graph[4] = gNBcommonGraph( puschIQ, FL_POINTS_XYPLOT, 540, 260, 240, 200, "PUSCH I/Q of MF Output", FL_YELLOW ); // I/Q PUCCH comp (format 1) fdui->graph[5] = gNBcommonGraph( pucchEnergy, FL_POINTS_XYPLOT, 540, 480, 240, 100, "PUCCH1 Energy (SR)", FL_YELLOW ); // fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); // I/Q PUCCH comp (fromat 1a/b) fdui->graph[6] = gNBcommonGraph( pucchIQ, FL_POINTS_XYPLOT, 540, 600, 240, 100, "PUCCH I/Q of MF Output", FL_YELLOW ); // Throughput on PUSCH fdui->graph[7] = gNBcommonGraph( puschThroughtput, FL_NORMAL_XYPLOT, 20, 480, 500, 100, "PUSCH Throughput [frame]/[kbit/s]", FL_WHITE ); fdui->graph[8].graph=NULL; // Generic eNB Button if (0) { // code kept to later add command buttons fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 20, 600, 240, 40, "" ); fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); fl_set_button(fdui->button_0,0); otg_enabled = 0; fl_set_object_label(fdui->button_0, "DL Traffic OFF"); fl_set_object_color(fdui->button_0, FL_RED, FL_RED); fl_set_object_callback(fdui->button_0, dl_traffic_on_off, 0 ); } fl_end_form( ); fdui->phy_scope->fdui = fdui; char title[100]; sprintf (title, "LTE UL SCOPE eNB for UE %d",UE_id); fl_show_form (fdui->phy_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); return fdui; } static FD_phy_scope_t *form_gnb[NUMBER_OF_UE_MAX]= {0}; static unsigned char scope_enb_num_ue = 1; static void *scope_thread_gNB(void *arg) { scopeParms_t *p=(scopeParms_t *) arg; //# ifdef ENABLE_XFORMS_WRITE_STATS // FILE *gNB_stats = fopen("gNB_stats.txt", "w"); //#endif size_t stksize; pthread_attr_t atr; pthread_attr_getstacksize(&atr, &stksize); pthread_attr_setstacksize(&atr,32*1024*1024 ); sleep(3); // no clean interthread barriers while (!oai_exit) { int ue_cnt=0; for(int UE_id=0; UE_idgNB, p->ru, UE_id); ue_cnt++; } } usleep(99*1000); } // printf("%s",stats_buffer); /*#ifdef ENABLE_XFORMS_WRITE_STATS if (eNB_stats) { rewind (gNB_stats); fwrite (stats_buffer, 1, len, gNB_stats); fclose (gNB_stats); } #endif pthread_exit((void *)arg); }*/ return NULL; } void gNBinitScope(scopeParms_t *p) { //FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; fl_initialize (p->argc, p->argv, NULL, 0, 0); /* form_stats_l2 = create_form_stats_form(); fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats"); form_stats = create_form_stats_form(); fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); */ for(int UE_id=0; UE_idcommon_vars.rxdata) return; NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; int samples_per_frame = frame_parms->samples_per_frame; scopeSample_t **rxsig_t = (scopeSample_t **) phy_vars_ue->common_vars.rxdata; float rxsig_t_dB[samples_per_frame]; float time[samples_per_frame]; if (rxsig_t[0] != NULL) { for (int i=0; iis_synchronized==0) { //float corr[samples_per_frame]; for (int ind=0; ind<3; ind++) { /* if (pss_corr_ue[ind]) { for (i=0; ichest_t,time,corr,samples_per_frame,"","",""); else fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]); overlay = 1; } */ } // if the UE is not synchronized, we can make only the time*power graph } } static void ueChannelResponse (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // Channel Impulse Response if (!phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates_time) return; NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; scopeSample_t **chest_t = (scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates_time; int ymax = 0; float chest_t_abs[frame_parms->ofdm_symbol_size]; float time[frame_parms->ofdm_symbol_size>>3]; if (chest_t[0] !=NULL) { for (int i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { chest_t_abs[i] = SquaredNorm(chest_t[0][i]); time[i] = (float) i; if (chest_t_abs[i] > ymax) ymax = chest_t_abs[i]; } fl_set_xyplot_data(graph,time,chest_t_abs,(frame_parms->ofdm_symbol_size>>3),"","",""); } for (int arx=1; arxofdm_symbol_size>>3); i++) { chest_t_abs[i] = SquaredNorm(chest_t[arx][i]); if (chest_t_abs[i] > ymax) ymax = chest_t_abs[i]; } fl_add_xyplot_overlay(graph,arx,time,chest_t_abs,(frame_parms->ofdm_symbol_size>>3),rx_antenna_colors[arx]); fl_set_xyplot_overlay_type(graph,arx,FL_DASHED_XYPLOT); } } // Avoid flickering effect // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); // Does not always work... fl_set_xyplot_ybounds(graph,0,(double) ymax); } static void uePbchFrequencyResp (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // Channel Frequency Response (includes 5 complex sample for filter) if (!phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates) return; NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_gNB; scopeSample_t **chest_f = (scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates; int ind = 0; float chest_f_abs[frame_parms->ofdm_symbol_size]; float freq[frame_parms->ofdm_symbol_size]; for (int atx=0; atxofdm_symbol_size; k++) { freq[ind] = (float)ind; chest_f_abs[ind] = (short)10*log10(1.0+SquaredNorm(chest_f[(atx<<1)+arx][6144+k])); ind++; } } } } // tx antenna 0 //fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); fl_set_xyplot_data(graph,freq,chest_f_abs,frame_parms->ofdm_symbol_size,"","",""); } static void uePbchLLR (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PBCH LLRs if ( !phy_vars_ue->pbch_vars[eNB_id]->llr) return; int16_t *pbch_llr = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->llr; float llr_pbch[864], bit_pbch[864]; for (int i=0; i<864; i++) { llr_pbch[i] = (float) pbch_llr[i]; bit_pbch[i] = (float) i; } fl_set_xyplot_data(graph,bit_pbch,llr_pbch,864,"","",""); } static void uePbchIQ (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PBCH I/Q of MF Output if (!phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]) return; int16_t *pbch_comp = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; localBuff(I,180*3); localBuff(Q,180*3); int first_symbol=1; int base=0; for (int symbol=first_symbol; symbol<(first_symbol+3); symbol++) { int nb_re; if (symbol == 2 || symbol == 6) nb_re = 72; else nb_re = 180; AssertFatal(base+nb_re<180*3,""); for (int i=0; ipdcch_vars[0][eNB_id]->llr) return; NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx; scopeSample_t **chest_f = (scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates; int ind = 0; float chest_f_abs[frame_parms->ofdm_symbol_size]; float freq[frame_parms->ofdm_symbol_size]; for (int atx=0; atxofdm_symbol_size; k++) { freq[ind] = (float)ind; chest_f_abs[ind] = (short)10*log10(1.0+SquaredNorm(chest_f[(atx<<1)+arx][6144+k])); ind++; } } } } // tx antenna 0 //fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); fl_set_xyplot_data(graph,freq,chest_f_abs,frame_parms->ofdm_symbol_size,"","",""); } static void uePcchIQ (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PDCCH I/Q of MF Output if (!phy_vars_ue->pdcch_vars[0][eNB_id]->rxdataF_comp[0]) return; int nb=12*273*4; // 12*frame_parms->N_RB_DL*num_pdcch_symbols localBuff(I,nb*RX_NB_TH_MAX); localBuff(Q,nb*RX_NB_TH_MAX); int base=0; for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { int16_t *pdcch_comp = (int16_t *) phy_vars_ue->pdcch_vars[thr][eNB_id]->rxdataF_comp[0]; for (int i=0; i< nb; i++) { I[base+i] = pdcch_comp[i*2]; Q[base+i] = pdcch_comp[i*2+1]; } base+=nb; } fl_set_xyplot_data(graph,I,Q,base,"","",""); } static void uePdschLLR (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PDSCH LLRs if (!phy_vars_ue->pdsch_vars[0][eNB_id]->llr[0]) return; int num_re = 4500; int Qm = 2; int coded_bits_per_codeword = num_re*Qm; localBuff(llr,coded_bits_per_codeword*RX_NB_TH_MAX); localBuff(bit,coded_bits_per_codeword*RX_NB_TH_MAX); int base=0; for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { int16_t *pdsch_llr = (int16_t *) phy_vars_ue->pdsch_vars[thr][eNB_id]->llr[0]; // stream 0 for (int i=0; ipdsch_llr,0,coded_bits_per_codeword); fl_set_xyplot_data(graph,bit,llr,base,"","",""); } static void uePdschIQ (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PDSCH I/Q of MF Output if (!phy_vars_ue->pdsch_vars[0][eNB_id]->rxdataF_comp0[0]) return; NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; int sz=7*2*frame_parms->N_RB_DL*12; // size of the malloced buffer localBuff(I,sz*RX_NB_TH_MAX); localBuff(Q,sz*RX_NB_TH_MAX); int base=0; for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { int16_t *pdsch_comp = (int16_t *) phy_vars_ue->pdsch_vars[thr][eNB_id]->rxdataF_comp0[0]; for (int s=0; s tput_ue_max[UE_id]) { tput_ue_max[UE_id] = tput_ue[UE_id][TPUT_WINDOW_LENGTH-1]; } fl_set_xyplot_data(form->pdsch_tput,tput_time_ue[UE_id],tput_ue[UE_id],TPUT_WINDOW_LENGTH,"","",""); fl_set_xyplot_ybounds(form->pdsch_tput,0,tput_ue_max[UE_id]); */ } static void uePdschThroughput (FL_OBJECT *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { } static FD_phy_scope_t *create_phy_scope_nrue( int ID ) { FL_OBJECT *obj; FD_phy_scope_t *fdui = fl_malloc( sizeof *fdui ); // Define form fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 900 ); // This the whole UI box obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 900, "" ); fl_set_object_color( obj, FL_BLACK, FL_BLACK ); // Received signal fdui->graph[0] = nrUEcommonGraph(ueTimeResponse, FL_IMPULSE_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)", FL_RED ); // Time-domain channel response fdui->graph[1] = nrUEcommonGraph(ueChannelResponse, FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)", FL_RED ); // Frequency-domain channel response fdui->graph[2] = nrUEcommonGraph(uePbchFrequencyResp, FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency data (RE, dB)", FL_RED ); // LLR of PBCH fdui->graph[3] = nrUEcommonGraph(uePbchLLR, FL_POINTS_XYPLOT, 20, 260, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)", FL_GREEN ); fl_set_xyplot_xgrid(fdui->graph[3].graph,FL_GRID_MAJOR); // I/Q PBCH comp fdui->graph[4] = nrUEcommonGraph(uePbchIQ, FL_POINTS_XYPLOT, 540, 260, 240, 100, "PBCH I/Q of MF Output", FL_GREEN ); // LLR of PDCCH fdui->graph[5] = nrUEcommonGraph(uePcchLLR, FL_POINTS_XYPLOT, 20, 380, 500, 100, "PDCCH Log-Likelihood Ratios (LLR, mag)", FL_CYAN ); // I/Q PDCCH comp fdui->graph[6] = nrUEcommonGraph(uePcchIQ, FL_POINTS_XYPLOT, 540, 380, 240, 100, "PDCCH I/Q of MF Output", FL_CYAN ); // LLR of PDSCH fdui->graph[7] = nrUEcommonGraph(uePdschLLR, FL_POINTS_XYPLOT, 20, 500, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW ); // I/Q PDSCH comp fdui->graph[8] = nrUEcommonGraph(uePdschIQ, FL_POINTS_XYPLOT, 540, 500, 240, 200, "PDSCH I/Q of MF Output", FL_YELLOW ); // Throughput on PDSCH fdui->graph[9] = nrUEcommonGraph(uePdschThroughput, FL_NORMAL_XYPLOT, 20, 720, 500, 100, "PDSCH Throughput [frame]/[kbit/s]", FL_WHITE ); fdui->graph[10].graph=NULL; // Generic UE Button fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 540, 720, 240, 40, "" ); fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); //openair_daq_vars.use_ia_receiver = 0; fl_set_button(fdui->button_0,0); fl_set_object_label(fdui->button_0, "IA Receiver OFF"); fl_set_object_color(fdui->button_0, FL_RED, FL_RED); fl_set_object_callback(fdui->button_0, ia_receiver_on_off, 0 ); fl_hide_object(fdui->button_0); fl_end_form( ); fdui->phy_scope->fdui = fdui; char buf[100]; sprintf(buf,"NR DL SCOPE UE %d", ID); fl_show_form (fdui->phy_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, buf); return fdui; } void phy_scope_nrUE(FD_phy_scope_t *form, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { static FD_phy_scope_t *remeberForm=NULL; if (form==NULL) form=remeberForm; else remeberForm=form; if (form==NULL) return; int i=0; while (form->graph[i].graph) { form->graph[i].nrUEfunct(form->graph[i].graph, phy_vars_ue, eNB_id, UE_id); i++; } fl_check_forms(); } static FD_phy_scope_t *form_nrue[NUMBER_OF_UE_MAX]; static pthread_t forms_thread; static void *nrUEscopeThread(void *arg) { PHY_VARS_NR_UE *ue=(PHY_VARS_NR_UE *)arg; size_t stksize; pthread_attr_t atr; pthread_attr_getstacksize(&atr, &stksize); pthread_attr_setstacksize(&atr,32*1024*1024 ); while (!oai_exit) { phy_scope_nrUE(form_nrue[0], ue, 0,0); usleep(99*1000); } pthread_exit((void *)arg); } void nrUEinitScope(PHY_VARS_NR_UE *ue) { int fl_argc=1; char *name="5G-UE-scope"; fl_initialize (&fl_argc, &name, NULL, 0, 0); form_nrue[0] = create_phy_scope_nrue(0); threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW); } // Kept to put back the functionality soon #if 0 //FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; //char title[255]; //static pthread_t forms_thread; //xforms static void reset_stats_gNB(FL_OBJECT *button, long arg) { int i,k; //PHY_VARS_gNB *phy_vars_gNB = RC.gNB[0][0]; for (i=0; idlsch[i][0]->Mlimit; j++) { phy_vars_gNB->UE_stats[i].dlsch_NAK[k][j]=0; phy_vars_gNB->UE_stats[i].dlsch_ACK[k][j]=0; phy_vars_gNB->UE_stats[i].dlsch_trials[k][j]=0; } phy_vars_gNB->UE_stats[i].dlsch_l2_errors[k]=0; phy_vars_gNB->UE_stats[i].ulsch_errors[k]=0; phy_vars_gNB->UE_stats[i].ulsch_consecutive_errors=0; phy_vars_gNB->UE_stats[i].dlsch_sliding_cnt=0; phy_vars_gNB->UE_stats[i].dlsch_NAK_round0=0; phy_vars_gNB->UE_stats[i].dlsch_mcs_offset=0;*/ } } } static FD_stats_form *create_form_stats_form(int ID) { FL_OBJECT *obj; FD_stats_form *fdui = fl_malloc( sizeof *fdui ); fdui->vdata = fdui->cdata = NULL; fdui->ldata = 0; fdui->stats_form = fl_bgn_form( FL_NO_BOX, 1115, 900 ); obj = fl_add_box( FL_UP_BOX, 0, 0, 1115, 900, "" ); //fdui->stats_text = obj = fl_add_text( FL_NORMAL_TEXT, 60, 50, 1000, 810, "test" ); //fl_set_object_lsize( obj, FL_TINY_SIZE ); fdui->stats_text = obj = fl_add_browser( FL_NORMAL_BROWSER, 60, 50, 1000, 810, "test" ); fl_set_browser_fontsize(obj,FL_TINY_SIZE); fdui->stats_button = obj = fl_add_button( FL_PUSH_BUTTON, 60, 10, 130, 30, "Reset Stats" ); fl_set_object_lalign( obj, FL_ALIGN_CENTER ); fl_set_object_color( obj, FL_GREEN, FL_GREEN); fl_end_form( ); fdui->stats_form->fdui = fdui; return fdui; } #endif