From 68fb9ef07fb9a95d2b5e2ad7344f54482f20e29b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 4 Apr 2016 16:29:06 -0700 Subject: [PATCH 001/206] modifications to eMBMS-related L1 processing. mbmssim now works again (performance to be checked for 10/20 MHz), but error rates decay as they should with SNR. --- .../lte_dl_mbsfn_channel_estimation.c | 13 +++++----- openair1/PHY/LTE_TRANSPORT/pmch.c | 2 ++ openair1/SIMULATION/LTE_PHY/mbmssim.c | 26 ++++++++++++++----- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c index dbb2ba231f..a22df77b69 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c @@ -711,7 +711,7 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, //------------------------Temporal Interpolation ------------------------------ if (l==6) { ch = (short *)&dl_ch_estimates[aarx][ch_offset]; - // printf("Interpolating ch 2,6 => %d\n",ch_offset); + // printf("Interpolating ch 2,6 => %d\n",ch_offset); ch_prev = (short *)&dl_ch_estimates[aarx][2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; ch0 = (short *)&dl_ch_estimates[aarx][0*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; memcpy(ch0,ch_prev,4*phy_vars_ue->lte_frame_parms.ofdm_symbol_size); @@ -722,6 +722,7 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, // 3/4 ch2 + 1/4 ch6 => ch3 multadd_complex_vector_real_scalar(ch_prev,24576,ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); multadd_complex_vector_real_scalar(ch,8192,ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + // 1/2 ch2 + 1/2 ch6 => ch4 multadd_complex_vector_real_scalar(ch_prev,16384,ch_prev+(4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); multadd_complex_vector_real_scalar(ch,16384,ch_prev+(4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); @@ -755,26 +756,26 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, if (phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa]) { switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { case 6: - idft128((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][LTE_CE_OFFSET], + idft128((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; case 25: - idft512((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][LTE_CE_OFFSET], + idft512((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; case 50: - idft1024((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][LTE_CE_OFFSET], + idft1024((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; case 75: - idft1536((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][LTE_CE_OFFSET], + idft1536((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa]); break; case 100: - idft2048((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][LTE_CE_OFFSET], + idft2048((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index fbcec50333..7b93201dd0 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -379,6 +379,7 @@ void mch_extract_rbs(int **rxdataF, dl_ch_estimates_ext[aarx][(frame_parms->N_RB_DL*3)+j+symbol*(frame_parms->N_RB_DL*12)] = dl_ch_estimates[aarx][i+(frame_parms->N_RB_DL*6)+(symbol*frame_parms->ofdm_symbol_size)]; } } else { + memcpy((void*)&rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)], (void*)&rxdataF[aarx][frame_parms->first_carrier_offset + (symbol*frame_parms->ofdm_symbol_size)], frame_parms->N_RB_DL*24); @@ -388,6 +389,7 @@ void mch_extract_rbs(int **rxdataF, memcpy((void*)&dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)], (void*)&dl_ch_estimates[aarx][(symbol*frame_parms->ofdm_symbol_size)], frame_parms->N_RB_DL*48); + } } diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index 8522b7be9a..e2fa439be5 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -128,7 +128,7 @@ int main(int argc, char **argv) char c; - int i,l,aa,aarx,k; + int i,l,l2,aa,aarx,k; double sigma2, sigma2_dB=0,SNR,snr0=-2.0,snr1=0.0; uint8_t snr1set=0; double snr_step=1,input_snr_step=1; @@ -538,11 +538,25 @@ int main(int argc, char **argv) } } } - - rx_pmch(PHY_vars_UE, - 0, - subframe%10, - l); + + if (l==6) + for (l2=2;l2<7;l2++) + rx_pmch(PHY_vars_UE, + 0, + subframe%10, + l2); + if (l==6) + for (l2=2;l2<7;l2++) + rx_pmch(PHY_vars_UE, + 0, + subframe%10, + l2); + if (l==11) + for (l2=7;l2<12;l2++) + rx_pmch(PHY_vars_UE, + 0, + subframe%10, + l2); } PHY_vars_UE->dlsch_ue_MCH[0]->harq_processes[0]->G = get_G(&PHY_vars_UE->lte_frame_parms, From 2176299a2d3108fcbb52aa9b616e9a47a52b563d Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 14 Apr 2016 00:40:50 -0700 Subject: [PATCH 002/206] pdcchsim change for debugging CCE allocations --- openair1/SIMULATION/LTE_PHY/pdcchsim.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c index 0c51959f14..4adf61a3c0 100644 --- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c @@ -373,9 +373,9 @@ DCI_PDU *get_dci(LTE_DL_FRAME_PARMS *lte_frame_parms,uint8_t log2L, uint8_t log2 if (lte_frame_parms->N_RB_DL >= 25) { // add ue specific dci DCI_pdu.dci_alloc[1].dci_length = dci_length; - DCI_pdu.dci_alloc[1].L = log2L; - DCI_pdu.dci_alloc[1].rnti = rnti; - DCI_pdu.dci_alloc[1].format = format1; + DCI_pdu.dci_alloc[1].L = log2Lcommon;//log2L; + DCI_pdu.dci_alloc[1].rnti = 12;//rnti; + DCI_pdu.dci_alloc[1].format = format1A; //format1 DCI_pdu.dci_alloc[1].ra_flag = 0; memcpy((void*)&DCI_pdu.dci_alloc[1].dci_pdu[0], &DLSCH_alloc_pdu[0], dci_length_bytes); DCI_pdu.Num_ue_spec_dci++; From d54fe24f9e536c7d079c0f3911397106cd2603e0 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 21 Apr 2016 00:53:28 -0700 Subject: [PATCH 003/206] acceleration of dlsch_modulation --- openair1/PHY/CODING/lte_rate_matching.c | 8 +- .../PHY/LTE_TRANSPORT/dlsch_llr_computation.c | 2 +- openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 531 ++++++++++++++++-- openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c | 51 +- openair1/PHY/LTE_TRANSPORT/proto.h | 4 +- openair1/PHY/TOOLS/cmult_vv.c | 2 +- openair1/PHY/TOOLS/lte_dfts.c | 4 +- openair1/SIMULATION/LTE_PHY/dlsim.c | 8 +- 8 files changed, 524 insertions(+), 86 deletions(-) diff --git a/openair1/PHY/CODING/lte_rate_matching.c b/openair1/PHY/CODING/lte_rate_matching.c index 96663bd8a6..483cda3f93 100644 --- a/openair1/PHY/CODING/lte_rate_matching.c +++ b/openair1/PHY/CODING/lte_rate_matching.c @@ -53,7 +53,7 @@ uint32_t sub_block_interleaving_turbo(uint32_t D, uint8_t *d,uint8_t *w) { uint32_t RTC = (D>>5), ND, ND3; - uint32_t row,col,Kpi,index; + uint32_t row,col,Kpi; uint32_t index3,k,k2; #ifdef RM_DEBUG uint32_t nulled=0; @@ -84,7 +84,6 @@ uint32_t sub_block_interleaving_turbo(uint32_t D, uint8_t *d,uint8_t *w) #ifdef RM_DEBUG printf("Col %d\n",col); #endif - index = bitrev[col]; index3 = bitrev_x3[col];//3*index; for (row=0; row>2; // length in quad words (4 REs) - len2+=(len_mod4?0:1); + len2+=((len_mod4==0)?0:1); for (i=0; i>15); */ } +uint32_t FOUR[2]={0,4}; +uint32_t TWO[2]={0,2}; + +int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, + mod_sym_t **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + int *P1_SHIFT, + int *P2_SHIFT) +{ + + + uint8_t *x0 = dlsch0_harq->e; + uint32_t qam16_table_offset_re = 0; + uint32_t qam16_table_offset_im = 0; + + uint32_t tti_offset; + uint8_t re; + uint8_t *x0p; + + if (skip_dc == 0) { + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<12; + re++,x0p+=4,tti_offset++) { + + qam16_table_offset_re=TWO[x0p[0]]; + qam16_table_offset_im=TWO[x0p[1]]; + qam16_table_offset_re+=x0p[2]; + qam16_table_offset_im+=x0p[3]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; + } + } + else { + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<6; + re++,x0p+=4,tti_offset++) { + + qam16_table_offset_re=TWO[x0p[0]]; + qam16_table_offset_im=TWO[x0p[1]]; + qam16_table_offset_re+=x0p[2]; + qam16_table_offset_im+=x0p[3]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; + } + + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7; + re<12; + re++,x0p+=4,tti_offset++) { + + qam16_table_offset_re=TWO[x0p[0]]; + qam16_table_offset_im=TWO[x0p[1]]; + qam16_table_offset_re+=x0p[2]; + qam16_table_offset_im+=x0p[3]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; + } + } + *re_allocated = *re_allocated + 12; + *jj=*jj + 48; + + return(0); +} + +int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, + mod_sym_t **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + int *P1_SHIFT, + int *P2_SHIFT) +{ + + + uint8_t *x0 = dlsch0_harq->e; + uint32_t qam16_table_offset_re = 0; + uint32_t qam16_table_offset_im = 0; + + uint32_t tti_offset; + uint8_t re; + uint8_t *x0p; + + + if (skip_dc == 0) { + // printf("pilots: P1_SHIFT[0] %d\n",P1_SHIFT[0]); + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<12; + x0p+=4) { + + qam16_table_offset_re=TWO[x0p[0]]; + qam16_table_offset_im=TWO[x0p[1]]; + qam16_table_offset_re+=x0p[2]; + qam16_table_offset_im+=x0p[3]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; + // printf("pilots: re %d, tti_offset %d, P1_SHIFT %d\n",re,tti_offset,P1_SHIFT[re+1]); + tti_offset+=P1_SHIFT[re+1]; + re+=P1_SHIFT[re+1]; + } + } + else { + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<6; + x0p+=4) { + + qam16_table_offset_re=TWO[x0p[0]]; + qam16_table_offset_im=TWO[x0p[1]]; + qam16_table_offset_re+=x0p[2]; + qam16_table_offset_im+=x0p[3]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; + tti_offset+=P1_SHIFT[re+1]; + re+=P1_SHIFT[re+1]; + } + + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+6+P1_SHIFT[6]; + re<12; + x0p+=4) { + + qam16_table_offset_re=TWO[x0p[0]]; + qam16_table_offset_im=TWO[x0p[1]]; + qam16_table_offset_re+=x0p[2]; + qam16_table_offset_im+=x0p[3]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; + tti_offset+=P1_SHIFT[re+1]; + re+=P1_SHIFT[re+1]; + } + } + *re_allocated = *re_allocated + 10; + *jj=*jj + 40; + + return(0); +} + +int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, + mod_sym_t **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + int *P1_SHIFT, + int *P2_SHIFT) +{ + + + uint8_t *x0 = dlsch0_harq->e; + uint32_t qam64_table_offset_re = 0; + uint32_t qam64_table_offset_im = 0; + + uint32_t tti_offset; + uint8_t re; + uint8_t *x0p; + + if (skip_dc == 0) { + + + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<12; + re++,x0p+=6,tti_offset++) { + + qam64_table_offset_re=FOUR[x0p[0]]; + qam64_table_offset_im=FOUR[x0p[1]]; + qam64_table_offset_re+=TWO[x0p[2]]; + qam64_table_offset_im+=TWO[x0p[3]]; + qam64_table_offset_re+=x0p[4]; + qam64_table_offset_im+=x0p[5]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; + } + } + else { + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; + re<6; + re++,x0p+=6,tti_offset++) { + + qam64_table_offset_re=FOUR[x0p[0]]; + qam64_table_offset_im=FOUR[x0p[1]]; + qam64_table_offset_re+=TWO[x0p[2]]; + qam64_table_offset_im+=TWO[x0p[3]]; + qam64_table_offset_re+=x0p[4]; + qam64_table_offset_im+=x0p[5]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; + } + + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7; + re<12; + re++,x0p+=6,tti_offset++) { + + qam64_table_offset_re=FOUR[x0p[0]]; + qam64_table_offset_im=FOUR[x0p[1]]; + qam64_table_offset_re+=TWO[x0p[2]]; + qam64_table_offset_im+=TWO[x0p[3]]; + qam64_table_offset_re+=x0p[4]; + qam64_table_offset_im+=x0p[5]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; + } + } + + *re_allocated = *re_allocated + 12; + *jj=*jj + 72; + + return(0); +} + +int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, + mod_sym_t **txdataF, + uint32_t *jj, + uint32_t *jj2, + uint16_t re_offset, + uint32_t symbol_offset, + LTE_DL_eNB_HARQ_t *dlsch0_harq, + LTE_DL_eNB_HARQ_t *dlsch1_harq, + uint8_t pilots, + int16_t amp, + uint8_t precoder_index, + int16_t *qam_table_s0, + int16_t *qam_table_s1, + uint32_t *re_allocated, + uint8_t skip_dc, + uint8_t skip_half, + int *P1_SHIFT, + int *P2_SHIFT) +{ + + + uint8_t *x0 = dlsch0_harq->e; + uint32_t qam64_table_offset_re = 0; + uint32_t qam64_table_offset_im = 0; + + uint32_t tti_offset; + uint8_t re; + uint8_t *x0p; + + + if (skip_dc == 0) { + // printf("pilots: P1_SHIFT[0] %d\n",P1_SHIFT[0]); + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<12; + x0p+=6) { + + qam64_table_offset_re=FOUR[x0p[0]]; + qam64_table_offset_im=FOUR[x0p[1]]; + qam64_table_offset_re+=TWO[x0p[2]]; + qam64_table_offset_im+=TWO[x0p[3]]; + qam64_table_offset_re+=x0p[4]; + qam64_table_offset_im+=x0p[5]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; + // printf("pilots: re %d, tti_offset %d, P1_SHIFT %d\n",re,tti_offset,P1_SHIFT[re+1]); + tti_offset+=P1_SHIFT[re+1]; + re+=P1_SHIFT[re+1]; + } + } + else { + for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0]; + re<6; + x0p+=6) { + + qam64_table_offset_re=FOUR[x0p[0]]; + qam64_table_offset_im=FOUR[x0p[1]]; + qam64_table_offset_re+=TWO[x0p[2]]; + qam64_table_offset_im+=TWO[x0p[3]]; + qam64_table_offset_re+=x0p[4]; + qam64_table_offset_im+=x0p[5]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; + tti_offset+=P1_SHIFT[re+1]; + re+=P1_SHIFT[re+1]; + } + + for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+6+P1_SHIFT[6]; + re<12; + x0p+=6) { + + qam64_table_offset_re=FOUR[x0p[0]]; + qam64_table_offset_im=FOUR[x0p[1]]; + qam64_table_offset_re+=TWO[x0p[2]]; + qam64_table_offset_im+=TWO[x0p[3]]; + qam64_table_offset_re+=x0p[4]; + qam64_table_offset_im+=x0p[5]; + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; + tti_offset+=P1_SHIFT[re+1]; + re+=P1_SHIFT[re+1]; + } + } + *re_allocated = *re_allocated + 10; + *jj=*jj + 60; + + return(0); +} + int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, mod_sym_t **txdataF, uint32_t *jj, @@ -151,7 +479,9 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, int16_t *qam_table_s1, uint32_t *re_allocated, uint8_t skip_dc, - uint8_t skip_half) + uint8_t skip_half, + int *P1_SHIFT, + int *P2_SHIFT) { @@ -209,27 +539,6 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, } - /* - switch (mod_order) { - case 2: - // QPSK single stream - - break; - case 4: - //16QAM Single stream - gain_lin_16QAM1 = (int16_t)(((int32_t)amp*QAM16_n1)>>15); - gain_lin_16QAM2 = (int16_t)(((int32_t)amp*QAM16_n2)>>15); - - break; - - case 6: - //64QAM Single stream - break; - default: - break; - } - */ - #ifdef DEBUG_DLSCH_MODULATION printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj], x0[1+*jj]); #endif @@ -242,6 +551,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, else if (skip_half==2) first_re=6; + for (re=first_re; renb_antennas_tx; aa++) { - ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15); - ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15); + ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im]; } break; @@ -970,7 +1280,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, } } } else if (mimo_mode>=TM9_10) { - msg("allocate_REs_in_RB() [dlsch.c] : ERROR, unknown mimo_mode %d\n",mimo_mode); + printf("allocate_REs_in_RB() [dlsch.c] : ERROR, unknown mimo_mode %d\n",mimo_mode); return(-1); } } @@ -1191,7 +1501,7 @@ int dlsch_modulation(mod_sym_t **txdataF, uint8_t harq_pid = dlsch0->current_harq_pid; LTE_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid]; LTE_DL_eNB_HARQ_t *dlsch1_harq; //= dlsch1->harq_processes[harq_pid]; - uint32_t i,jj,jj2,re_allocated,symbol_offset; + uint32_t i,i2,jj,jj2,re_allocated,symbol_offset; uint16_t l,rb,re_offset; uint32_t rb_alloc_ind; uint32_t *rb_alloc = dlsch0_harq->rb_alloc; @@ -1202,7 +1512,28 @@ int dlsch_modulation(mod_sym_t **txdataF, int16_t amp_rho_a, amp_rho_b; int16_t qam16_table_a0[4],qam64_table_a0[8],qam16_table_b0[4],qam64_table_b0[8]; int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8]; - int16_t *qam_table_s0,*qam_table_s1; + int16_t *qam_table_s0=NULL,*qam_table_s1=NULL; + int (*allocate_REs)(LTE_DL_FRAME_PARMS *, + mod_sym_t **, + uint32_t*, + uint32_t*, + uint16_t, + uint32_t, + LTE_DL_eNB_HARQ_t *, + LTE_DL_eNB_HARQ_t *, + uint8_t, + int16_t, + uint8_t, + int16_t *, + int16_t *, + uint32_t *, + uint8_t, + uint8_t, + int *, + int *); + int P1_SHIFT[13],P2_SHIFT[13]; + int offset,nushiftmod3; + #ifdef DEBUG_DLSCH_MODULATION uint8_t Nl0 = dlsch0_harq->Nl; uint8_t Nl1; @@ -1255,7 +1586,7 @@ int dlsch_modulation(mod_sym_t **txdataF, for (l=num_pdcch_symbols; lmimo_mode, pmi2hex_2Ar1(dlsch0_harq->pmi_alloc), @@ -1281,6 +1612,32 @@ int dlsch_modulation(mod_sym_t **txdataF, pilots=0; } + offset = (pilots==2)?3:0; + nushiftmod3 = frame_parms->nushift%3; + + if (pilots>0) { // compute pilot arrays, could be done statically if performance suffers + if (frame_parms->mode1_flag == 1) { + // printf("l %d, nushift %d, offset %d\n",l,frame_parms->nushift,offset); + for (i=0,i2=0;i<12;i++) { + if ((i!=(frame_parms->nushift+offset)) && (i!=((frame_parms->nushift+6+offset)%12))) + P1_SHIFT[i2++]=1; + else + P1_SHIFT[i2++]=2; + } + P1_SHIFT[0]--; + } + else { + for (i=0,i2=0;i<12;i++) { + if ((i!=nushiftmod3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+3) && (i!=nushiftmod3+9)) + P2_SHIFT[i2++]=1; + else + P2_SHIFT[i2++]=2; + } + P2_SHIFT[0]--; + } + } + P1_SHIFT[12]=1;P2_SHIFT[12]=1; + re_offset = frame_parms->first_carrier_offset; symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe_offset*nsymb)); @@ -1421,50 +1778,100 @@ int dlsch_modulation(mod_sym_t **txdataF, } if (dlsch0_harq->Nlayers>1) { - msg("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); + printf("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); return(-1); } if (dlsch1) { if (dlsch1_harq->Nlayers>1) { - msg("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); + printf("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); return(-1); } } - if (mod_order0 == 4) - qam_table_s0 = ((pilots) ? qam16_table_b0 : qam16_table_a0); - else if (mod_order0 == 6) - qam_table_s0 = ((pilots) ? qam64_table_b0 : qam64_table_a0); - else - qam_table_s0 = NULL; + allocate_REs = allocate_REs_in_RB; - if (mod_order1 == 4) - qam_table_s1 = ((pilots) ? qam16_table_b1 : qam16_table_a1); - else if (mod_order1 == 6) - qam_table_s1 = ((pilots) ? qam64_table_b1 : qam64_table_a1); - else - qam_table_s1 = NULL; + switch (mod_order0) { + case 2: + qam_table_s0 = NULL; + break; + case 4: + if (pilots) { + qam_table_s0 = qam16_table_b0; + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_pilots_16QAM_siso : + allocate_REs_in_RB; + } + else { + qam_table_s0 = qam16_table_a0; + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_no_pilots_16QAM_siso : + allocate_REs_in_RB; + + } + break; + + case 6: + if (pilots) { + qam_table_s0 = qam64_table_b0; + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_pilots_64QAM_siso : + allocate_REs_in_RB; + } + else { + qam_table_s0 = qam64_table_a0; + allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ? + allocate_REs_in_RB_no_pilots_64QAM_siso : + allocate_REs_in_RB; + } + break; + + } + + switch (mod_order1) { + case 2: + qam_table_s1 = NULL; + allocate_REs = allocate_REs_in_RB; + break; + case 4: + if (pilots) { + qam_table_s1 = qam16_table_b1; + } + else { + qam_table_s1 = qam16_table_a1; + } + break; + case 6: + if (pilots) { + qam_table_s1 = qam64_table_b1; + } + else { + qam_table_s1 = qam64_table_a1; + } + break; + + } if (rb_alloc_ind > 0) { - // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); - allocate_REs_in_RB(frame_parms, - txdataF, - &jj, - &jj2, - re_offset, - symbol_offset, - dlsch0->harq_processes[harq_pid], - (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid], - pilots, - ((pilots) ? amp_rho_b : amp_rho_a), - get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb), - qam_table_s0, - qam_table_s1, - &re_allocated, - skip_dc, - skip_half); - + // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); + allocate_REs(frame_parms, + txdataF, + &jj, + &jj2, + re_offset, + symbol_offset, + dlsch0->harq_processes[harq_pid], + (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid], + pilots, + ((pilots) ? amp_rho_b : amp_rho_a), + get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb), + qam_table_s0, + qam_table_s1, + &re_allocated, + skip_dc, + skip_half, + P1_SHIFT, + P2_SHIFT); } re_offset+=12; // go to next RB @@ -1484,7 +1891,7 @@ int dlsch_modulation(mod_sym_t **txdataF, #ifdef DEBUG_DLSCH_MODULATION - msg("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset)); + printf("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset)); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT); @@ -1583,7 +1990,7 @@ int mch_modulation(mod_sym_t **txdataF, #ifdef DEBUG_DLSCH_MODULATION - msg("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset)); + printf("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset)); #endif return (re_allocated); diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c index dd971748cb..a5dd4bf764 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c @@ -56,10 +56,11 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, uint8_t Ns) { - int i,j,k=0; + int i; // uint8_t reset; uint32_t x1, x2, s=0; - uint8_t *e=dlsch->harq_processes[dlsch->current_harq_pid]->e; + uint8_t *dlsch_e=dlsch->harq_processes[dlsch->current_harq_pid]->e; + uint8_t *e=dlsch_e; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_IN); @@ -78,24 +79,56 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, for (i=0; i<(1+(G>>5)); i++) { - for (j=0; j<32; j++,k++) { #ifdef DEBUG_SCRAMBLING - printf("scrambling %d : %d => ",k,e[k]); + printf("scrambling %d : %d => ",k,e[k]); #endif - e[k] = (e[k]&1) ^ ((s>>j)&1); + + e[0] = (e[0]&1) ^ (s&1); + e[1] = (e[1]&1) ^ ((s>>1)&1); + e[2] = (e[2]&1) ^ ((s>>2)&1); + e[3] = (e[3]&1) ^ ((s>>3)&1); + e[4] = (e[4]&1) ^ ((s>>4)&1); + e[5] = (e[5]&1) ^ ((s>>5)&1); + e[6] = (e[6]&1) ^ ((s>>6)&1); + e[7] = (e[7]&1) ^ ((s>>7)&1); + e[8] = (e[8]&1) ^ ((s>>8)&1); + e[9] = (e[9]&1) ^ ((s>>9)&1); + e[10] = (e[10]&1) ^ ((s>>10)&1); + e[11] = (e[11]&1) ^ ((s>>11)&1); + e[12] = (e[12]&1) ^ ((s>>12)&1); + e[13] = (e[13]&1) ^ ((s>>13)&1); + e[14] = (e[14]&1) ^ ((s>>14)&1); + e[15] = (e[15]&1) ^ ((s>>15)&1); + e[16] = (e[16]&1) ^ ((s>>16)&1); + e[17] = (e[17]&1) ^ ((s>>17)&1); + e[18] = (e[18]&1) ^ ((s>>18)&1); + e[19] = (e[19]&1) ^ ((s>>19)&1); + e[20] = (e[20]&1) ^ ((s>>20)&1); + e[21] = (e[21]&1) ^ ((s>>21)&1); + e[22] = (e[22]&1) ^ ((s>>22)&1); + e[23] = (e[23]&1) ^ ((s>>23)&1); + e[24] = (e[24]&1) ^ ((s>>24)&1); + e[25] = (e[25]&1) ^ ((s>>25)&1); + e[26] = (e[26]&1) ^ ((s>>26)&1); + e[27] = (e[27]&1) ^ ((s>>27)&1); + e[28] = (e[28]&1) ^ ((s>>28)&1); + e[29] = (e[29]&1) ^ ((s>>29)&1); + e[30] = (e[30]&1) ^ ((s>>30)&1); + e[31] = (e[31]&1) ^ ((s>>31)&1); + #ifdef DEBUG_SCRAMBLING - printf("%d\n",e[k]); + printf("%d\n",e[k]); #endif - } - + + s = lte_gold_generic(&x1, &x2, 0); + e += 32; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_OUT); } - void dlsch_unscrambling(LTE_DL_FRAME_PARMS *frame_parms, int mbsfn_flag, LTE_UE_DLSCH_t *dlsch, diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 9afea790b3..ab1119020c 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -183,7 +183,9 @@ int32_t allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, int16_t *qam_table_s1, uint32_t *re_allocated, uint8_t skip_dc, - uint8_t skip_half); + uint8_t skip_half, + int *P1_SHIFT, + int *P2_SHIFT); /** \fn int32_t dlsch_modulation(mod_sym_t **txdataF, diff --git a/openair1/PHY/TOOLS/cmult_vv.c b/openair1/PHY/TOOLS/cmult_vv.c index f970d33224..ec6aacc440 100755 --- a/openair1/PHY/TOOLS/cmult_vv.c +++ b/openair1/PHY/TOOLS/cmult_vv.c @@ -85,7 +85,7 @@ int mult_cpx_conj_vector(int16_t *x1, // we compute 4 cpx multiply for each loop for(i=0; i<(N>>2); i++) { - #if defined(__x86_64__) || defined(__i386__) +#if defined(__x86_64__) || defined(__i386__) tmp_re = _mm_madd_epi16(*x1_128,*x2_128); tmp_im = _mm_shufflelo_epi16(*x1_128,_MM_SHUFFLE(2,3,0,1)); tmp_im = _mm_shufflehi_epi16(tmp_im,_MM_SHUFFLE(2,3,0,1)); diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/lte_dfts.c index b010f93aab..e2c23c8538 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/lte_dfts.c @@ -105,7 +105,6 @@ static inline void cmacc(__m128i a,__m128i b, __m128i *re32, __m128i *im32) - static inline void cmult(__m128i a,__m128i b, __m128i *re32, __m128i *im32) __attribute__((always_inline)); static inline void cmult(__m128i a,__m128i b, __m128i *re32, __m128i *im32) @@ -1754,7 +1753,8 @@ int16_t tw64c[96] __attribute__((aligned(16))) = { 0,32767,3212,32609,6393,32137 #define simdshort_q15_t __m64 #define shiftright_int16(a,shift) _mm_srai_epi16(a,shift) #define set1_int16(a) _mm_set1_epi16(a); -#define mulhi_int16(a,b) _mm_slli_epi16(_mm_mulhi_epi16(a,b),1); +//#define mulhi_int16(a,b) _mm_slli_epi16(_mm_mulhi_epi16(a,b),1); +#define mulhi_int16(a,b) _mm_mulhrs_epi16 (a,b) #elif defined(__arm__) #define simd_q15_t int16x8_t #define simdshort_q15_t int16x4_t diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6f2c1f1d22..58cf77568a 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -215,7 +215,7 @@ int main(int argc, char **argv) // void *data; // int ii; // int bler; - double blerr[4],uncoded_ber;//,avg_ber; + double blerr[4],uncoded_ber,avg_ber; short *uncoded_ber_bit=NULL; uint8_t N_RB_DL=25,osf=1; frame_t frame_type = FDD; @@ -2623,7 +2623,7 @@ PMI_FEEDBACK: &PHY_vars_eNB->lte_frame_parms, num_pdcch_symbols, PHY_vars_eNB->dlsch_eNB[k][0], - PHY_vars_eNB->dlsch_eNB[k][1]); + (transmission_mode==3)||(transmission_mode==4) ? PHY_vars_eNB->dlsch_eNB[k][1] : NULL); /* avoid gcc warnings */ (void)re_allocated; @@ -3292,7 +3292,7 @@ PMI_FEEDBACK: PHY_vars_UE->dlsch_ue[0][cw]->harq_processes[PHY_vars_UE->dlsch_ue[0][cw]->current_harq_pid]->G = coded_bits_per_codeword; - /* + // calculate uncoded BLER uncoded_ber=0; for (i=0;idlsch_unscrambling_stats); dlsch_unscrambling(&PHY_vars_UE->lte_frame_parms, From 58ba008937b2d7f0c3bdd32735bcab57dabe9134 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 8 May 2016 10:23:34 -0700 Subject: [PATCH 004/206] added lte-enb.c which extracts all enb-specific code from lte-softmodem. corrects merge from develop branch in dlsch_modulations.c. removal of HW-specific code in lte-softmodem.c --- cmake_targets/CMakeLists.txt | 1 + openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 10 +- targets/RT/USER/lte-enb.c | 1474 +++++++++++ targets/RT/USER/lte-softmodem.c | 2175 +---------------- 4 files changed, 1524 insertions(+), 2136 deletions(-) create mode 100644 targets/RT/USER/lte-enb.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index b50c017a92..166da4a48d 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1579,6 +1579,7 @@ add_executable(lte-softmodem ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/RT/USER/lte-ue.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c + ${OPENAIR_TARGETS}/RT/USER/lte-enb.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c ${OPENAIR_TARGETS}/COMMON/create_tasks.c diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index af6c72fc6a..034dc0ada8 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -140,7 +140,7 @@ uint32_t FOUR[2]={0,4}; uint32_t TWO[2]={0,2}; int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -213,7 +213,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, } int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -295,7 +295,7 @@ int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, } int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -377,7 +377,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, } int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -1514,7 +1514,7 @@ int dlsch_modulation(int32_t **txdataF, int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8]; int16_t *qam_table_s0=NULL,*qam_table_s1=NULL; int (*allocate_REs)(LTE_DL_FRAME_PARMS *, - mod_sym_t **, + int **, uint32_t*, uint32_t*, uint16_t, diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c new file mode 100644 index 0000000000..7234cf4f08 --- /dev/null +++ b/targets/RT/USER/lte-enb.c @@ -0,0 +1,1474 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + +*******************************************************************************/ + +/*! \file lte-enb.c + * \brief Top-level threads for eNodeB + * \author R. Knopp, F. Kaltenberger, Navid Nikaein + * \date 2012 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr + * \note + * \warning + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rt_wrapper.h" + +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "assertions.h" +#include "msc.h" + +#include "PHY/types.h" + +#include "PHY/defs.h" +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "../../ARCH/COMMON/common_lib.h" + +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "PHY/extern.h" +#include "SCHED/extern.h" +#include "LAYER2/MAC/extern.h" + +#include "../../SIMU/USER/init_lte.h" + +#include "LAYER2/MAC/defs.h" +#include "LAYER2/MAC/extern.h" +#include "LAYER2/MAC/proto.h" +#include "RRC/LITE/extern.h" +#include "PHY_INTERFACE/extern.h" + +#ifdef SMBV +#include "PHY/TOOLS/smbv.h" +unsigned short config_frames[4] = {2,9,11,13}; +#endif +#include "UTIL/LOG/log_extern.h" +#include "UTIL/OTG/otg_tx.h" +#include "UTIL/OTG/otg_externs.h" +#include "UTIL/MATH/oml.h" +#include "UTIL/LOG/vcd_signal_dumper.h" +#include "UTIL/OPT/opt.h" +#include "enb_config.h" +//#include "PHY/TOOLS/time_meas.h" + +#ifndef OPENAIR2 +#include "UTIL/OTG/otg_extern.h" +#endif + +#if defined(ENABLE_ITTI) +# if defined(ENABLE_USE_MME) +# include "s1ap_eNB.h" +#ifdef PDCP_USE_NETLINK +# include "SIMULATION/ETH_TRANSPORT/proto.h" +#endif +# endif +#endif + + + + + +//#define DEBUG_THREADS 1 + +//#define USRP_DEBUG 1 +struct timing_info_t { + //unsigned int frame, hw_slot, last_slot, next_slot; + RTIME time_min, time_max, time_avg, time_last, time_now; + //unsigned int mbox0, mbox1, mbox2, mbox_target; + unsigned int n_samples; +} timing_info; + + +extern openair0_device openair0; + +#if defined(ENABLE_ITTI) +extern volatile int start_eNB; +extern volatile int start_UE; +#endif +extern volatile int oai_exit; + +extern openair0_config_t openair0_cfg[MAX_CARDS]; + +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; + +pthread_attr_t attr_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS]; +pthread_attr_t attr_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS]; + +#ifndef LOWLATENCY +struct sched_param sched_param_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS]; +struct sched_param sched_param_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS]; +#endif + +pthread_t main_eNB_thread; +pthread_attr_t attr_dlsch_threads; +#ifndef LOWLATENCY +struct sched_param sched_param_dlsch; +#endif + +time_stats_t softmodem_stats_mt; // main thread +time_stats_t softmodem_stats_hw; // hw acquisition +time_stats_t softmodem_stats_tx_sf[10]; // total tx time +time_stats_t softmodem_stats_rx_sf[10]; // total rx time +int32_t **rxdata; +int32_t **txdata; + +static int time_offset[4] = {0,0,0,0}; + +/* mutex, cond and variable to serialize phy proc TX calls + * (this mechanism may be relaxed in the future for better + * performances) + */ +static struct { + pthread_mutex_t mutex_phy_proc_tx; + pthread_cond_t cond_phy_proc_tx; + volatile uint8_t phy_proc_CC_id; +} sync_phy_proc[NUM_ENB_THREADS]; + + +void exit_fun(const char* s); + +void init_eNB(void); +void stop_eNB(void); + +void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) +{ + + unsigned int aa,slot_offset, slot_offset_F; + int dummy_tx_b[7680*4] __attribute__((aligned(32))); + int i, tx_offset; + int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)* + ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7); + int len; + + slot_offset_F = (subframe<<1)*slot_sizeF; + + slot_offset = subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti; + + if ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_DL)|| + ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_S))) { + // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); + + + for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED) { + PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], + dummy_tx_b, + phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, + 6, + phy_vars_eNB->lte_frame_parms.nb_prefix_samples, + CYCLIC_PREFIX); + PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], + dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1), + phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, + 6, + phy_vars_eNB->lte_frame_parms.nb_prefix_samples, + CYCLIC_PREFIX); + } else { + normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], + dummy_tx_b, + 7, + &(phy_vars_eNB->lte_frame_parms)); + // if S-subframe generate first slot only + if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_DL) + normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], + dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1), + 7, + &(phy_vars_eNB->lte_frame_parms)); + } + + // if S-subframe generate first slot only + if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) + len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1; + else + len = phy_vars_eNB->lte_frame_parms.samples_per_tti; + /* + for (i=0;ilte_frame_parms.samples_per_tti; + + if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) + tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + + ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_frame_parms,subframe) == SF_S) { + for (i=0; ilte_eNB_common_vars.txdata[0][aa][tx_offset++] = 0x00010001; + } + } + + if ((((phy_vars_eNB->lte_frame_parms.tdd_config==0) || + (phy_vars_eNB->lte_frame_parms.tdd_config==1) || + (phy_vars_eNB->lte_frame_parms.tdd_config==2) || + (phy_vars_eNB->lte_frame_parms.tdd_config==6)) && + (subframe==0)) || (subframe==5)) { + // turn on tx switch N_TA_offset before + //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset); + for (i=0; iN_TA_offset; i++) { + tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset/2; + if (tx_offset<0) + tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + + if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) + tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + + phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset] = 0x00000000; + } + } + } + } +} + +/*! + * \brief The transmit thread of eNB. + * \ref NUM_ENB_THREADS threads of this type are active at the same time. + * \param param is a \ref eNB_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +static void* eNB_thread_tx( void* param ) +{ + static int eNB_thread_tx_status[NUM_ENB_THREADS]; + + eNB_proc_t *proc = (eNB_proc_t*)param; + FILE *tx_time_file = NULL; + char tx_time_name[101]; + + if (opp_enabled == 1) { + snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->subframe); + tx_time_file = fopen(tx_time_name,"w"); + } + // set default return value + eNB_thread_tx_status[proc->subframe] = 0; + + MSC_START_USE(); + +#ifdef LOWLATENCY + struct sched_attr attr; + unsigned int flags = 0; + uint64_t runtime = 850000 ; + uint64_t deadline = 1 * 1000000 ; // each tx thread will finish within 1ms + uint64_t period = 1 * 10000000; // each tx thread has a period of 10ms from the starting point + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0; + + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = runtime; + attr.sched_deadline = deadline; + attr.sched_period = period; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] eNB tx thread: sched_setattr failed\n"); + return &eNB_thread_tx_status[proc->subframe]; + } + + LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() ); + +#else //LOW_LATENCY + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD threads */ + /* CPU 1 is reserved for all TX threads */ + /* Enable CPU Affinity only if number of CPUs >2 */ + CPU_ZERO(&cpuset); + +#ifdef CPU_AFFINITY + if (get_nprocs() > 2) + { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_setaffinity_np"); + exit_fun("Error setting processor affinity"); + } + } +#endif //CPU_AFFINITY + + /* Check the actual affinity mask assigned to the thread */ + + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_getaffinity_np"); + exit_fun("Error getting processor affinity "); + } + memset(cpu_affinity,0,sizeof(cpu_affinity)); + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) + { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } + + memset(&sparam, 0 , sizeof (sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + policy = SCHED_FIFO ; + + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) + { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) + { + perror("pthread_getschedparam : "); + exit_fun("Error getting thread priority"); + + } + + LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n", proc->subframe, sched_getcpu(),gettid(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, cpu_affinity ); + + +#endif //LOW_LATENCY + + + mlockall(MCL_CURRENT | MCL_FUTURE); + + while (!oai_exit) { + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 ); + + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe ); + exit_fun("nothing to add"); + break; + } + + while (proc->instance_cnt_tx < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_tx is -1 + pthread_cond_wait( &proc->cond_tx, &proc->mutex_tx ); // this unlocks mutex_tx while waiting and then locks it again + } + + if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe); + exit_fun("nothing to add"); + break; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); + start_meas( &softmodem_stats_tx_sf[proc->subframe] ); + + if (oai_exit) break; + + if (((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD) && + ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_DL) || + (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S))) || + (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD)) { + /* run PHY TX procedures the one after the other for all CCs to avoid race conditions + * (may be relaxed in the future for performance reasons) + */ + if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe); + exit_fun("nothing to add"); + break; + } + /* wait for our turn or oai_exit */ + while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) { + pthread_cond_wait(&sync_phy_proc[proc->subframe].cond_phy_proc_tx, + &sync_phy_proc[proc->subframe].mutex_phy_proc_tx); + } + + if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe); + exit_fun("nothing to add"); + } + + if (oai_exit) + break; + + phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); + + /* we're done, let the next one proceed */ + if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe); + exit_fun("nothing to add"); + break; + } + sync_phy_proc[proc->subframe].phy_proc_CC_id++; + sync_phy_proc[proc->subframe].phy_proc_CC_id %= MAX_NUM_CCs; + pthread_cond_broadcast(&sync_phy_proc[proc->subframe].cond_phy_proc_tx); + if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe); + exit_fun("nothing to add"); + break; + } + } + + do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); + /* + short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->lte_eNB_common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.samples_per_tti]; + int i; + for (i=0;iCC_id]->lte_frame_parms.samples_per_tti*2;i+=8) { + txdata[i] = 2047; + txdata[i+1] = 0; + txdata[i+2] = 0; + txdata[i+3] = 2047; + txdata[i+4] = -2047; + txdata[i+5] = 0; + txdata[i+6] = 0; + txdata[i+7] = -2047; + } + */ + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe ); + exit_fun("nothing to add"); + break; + } + + proc->instance_cnt_tx--; + + if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->subframe ); + exit_fun("nothing to add"); + break; + } + + proc->frame_tx++; + + if (proc->frame_tx==1024) + proc->frame_tx=0; + stop_meas( &softmodem_stats_tx_sf[proc->subframe] ); +#ifdef LOWLATENCY + if (opp_enabled){ + if(softmodem_stats_tx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0); + } + } +#endif + print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file); + + } + + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 ); + +#ifdef DEBUG_THREADS + printf( "Exiting eNB thread TX %d\n", proc->subframe ); +#endif + + eNB_thread_tx_status[proc->subframe] = 0; + return &eNB_thread_tx_status[proc->subframe]; +} + + +/*! + * \brief The receive thread of eNB. + * \ref NUM_ENB_THREADS threads of this type are active at the same time. + * \param param is a \ref eNB_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +static void* eNB_thread_rx( void* param ) +{ + static int eNB_thread_rx_status[NUM_ENB_THREADS]; + + eNB_proc_t *proc = (eNB_proc_t*)param; + + FILE *rx_time_file = NULL; + char rx_time_name[101]; + //int i; + + if (opp_enabled == 1){ + snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf_%d", "eNB", proc->subframe); + rx_time_file = fopen(rx_time_name,"w"); + } + // set default return value + eNB_thread_rx_status[proc->subframe] = 0; + + MSC_START_USE(); + +#ifdef LOWLATENCY + struct sched_attr attr; + unsigned int flags = 0; + uint64_t runtime = 870000 ; + uint64_t deadline = 1 * 1000000; + uint64_t period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0; + + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = runtime; + attr.sched_deadline = deadline; + attr.sched_period = period; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] eNB RX sched_setattr failed\n"); + return &eNB_thread_rx_status[proc->subframe]; + } + + LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() ); +#else // LOW_LATENCY + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD */ + /* CPU 1 is reserved for all TX threads */ + /* CPU 2..MAX_CPUS is reserved for all RX threads */ + /* Set CPU Affinity only if number of CPUs >2 */ + CPU_ZERO(&cpuset); +#ifdef CPU_AFFINITY + if (get_nprocs() >2) + { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_setaffinity_np"); + exit_fun (" Error setting processor affinity :"); + } + } +#endif //CPU_AFFINITY + /* Check the actual affinity mask assigned to the thread */ + + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror ("pthread_getaffinity_np"); + exit_fun (" Error getting processor affinity :"); + } + memset(cpu_affinity,0, sizeof(cpu_affinity)); + + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) + { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } + + + memset(&sparam, 0 , sizeof (sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + + policy = SCHED_FIFO ; + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) + { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + + memset(&sparam, 0 , sizeof (sparam)); + + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) + { + perror("pthread_getschedparam"); + exit_fun("Error getting thread priority"); + } + + + LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", proc->subframe, sched_getcpu(),gettid(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, cpu_affinity); + + +#endif // LOWLATENCY + + mlockall(MCL_CURRENT | MCL_FUTURE); + + + while (!oai_exit) { + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 ); + + if (pthread_mutex_lock(&proc->mutex_rx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe ); + exit_fun( "error locking mutex" ); + break; + } + + while (proc->instance_cnt_rx < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_rx is -1 + pthread_cond_wait( &proc->cond_rx, &proc->mutex_rx ); // this unlocks mutex_rx while waiting and then locks it again + } + + if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe ); + exit_fun( "error unlocking mutex" ); + break; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + start_meas( &softmodem_stats_rx_sf[proc->subframe] ); + + if (oai_exit) break; + + if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_UL)) || + (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) { + + phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); + } + + if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx) == SF_S)) { + phy_procedures_eNB_S_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); + } + + if (pthread_mutex_lock(&proc->mutex_rx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe ); + exit_fun( "error locking mutex" ); + break; + } + + proc->instance_cnt_rx--; + + if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe ); + exit_fun( "error unlocking mutex" ); + break; + } + + proc->frame_rx++; + + if (proc->frame_rx==1024) + proc->frame_rx=0; + + stop_meas( &softmodem_stats_rx_sf[proc->subframe] ); +#ifdef LOWLATENCY + if (opp_enabled){ + if(softmodem_stats_rx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0); + } + } +#endif // LOWLATENCY + print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file); + } + + //stop_meas( &softmodem_stats_rx_sf[proc->subframe] ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 ); + + +#ifdef DEBUG_THREADS + printf( "Exiting eNB thread RX %d\n", proc->subframe ); +#endif + + eNB_thread_rx_status[proc->subframe] = 0; + return &eNB_thread_rx_status[proc->subframe]; +} + + + + +void init_eNB_proc(void) +{ + int i; + int CC_id; + + for (CC_id=0; CC_idproc[i].instance_cnt_tx = -1; + PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = -1; + PHY_vars_eNB_g[0][CC_id]->proc[i].subframe = i; + PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id; + pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx, NULL); + pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx, NULL); + pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx, NULL); + pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx, NULL); +#ifndef LOWLATENCY + pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, &attr_eNB_proc_tx[CC_id][i], eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); + pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, &attr_eNB_proc_rx[CC_id][i], eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); +#else + pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, NULL, eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); + pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, NULL, eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); +#endif + char name[16]; + snprintf( name, sizeof(name), "TX %d", i ); + pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, name ); + snprintf( name, sizeof(name), "RX %d", i ); + pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, name ); + PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0; + PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0; + PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_rx = i; + PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_tx = (i+2)%10; + } + + + + // TX processes subframe +2, RX subframe + // Note this inialization is because the first process awoken for frame 0 is number 1 and so processes 8,9 and 0 have to start with frame 1 + // PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1; + PHY_vars_eNB_g[0][CC_id]->proc[8].frame_tx = 1; + PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1; + // PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1; + } + + /* setup PHY proc TX sync mechanism */ + for (i=0; iproc[i].instance_cnt_tx = 0; // FIXME data race! + pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx ); + pthread_cond_broadcast(&sync_phy_proc[i].cond_phy_proc_tx); + +#ifdef DEBUG_THREADS + printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i ); +#endif + int result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, (void**)&status ); + +#ifdef DEBUG_THREADS + + if (result != 0) { + printf( "Error joining thread.\n" ); + } else { + if (status) { + printf( "status %d\n", *status ); + } else { + printf( "The thread was killed. No status available.\n" ); + } + } + +#else + UNUSED(result) +#endif + +#ifdef DEBUG_THREADS + printf( "Killing RX CC_id %d thread %d\n", CC_id, i ); +#endif + + PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = 0; // FIXME data race! + pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx ); + +#ifdef DEBUG_THREADS + printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i ); +#endif + result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, (void**)&status ); + +#ifdef DEBUG_THREADS + + if (result != 0) { + printf( "Error joining thread.\n" ); + } else { + if (status) { + printf( "status %d\n", *status ); + } else { + printf( "The thread was killed. No status available.\n" ); + } + } + +#else + UNUSED(result) +#endif + + pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx ); + pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx ); + pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx ); + pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx ); + } +} + + +/* this function maps the phy_vars_eNB tx and rx buffers to the available rf chains. + Each rf chain is is addressed by the card number and the chain on the card. The + rf_map specifies for each CC, on which rf chain the mapping should start. Multiple + antennas are mapped to successive RF chains on the same card. */ +int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) +{ + + int i, CC_id; +#ifndef EXMIMO + uint16_t N_TA_offset = 0; +#else + int j; +#endif + LTE_DL_FRAME_PARMS *frame_parms; + + + for (CC_id=0; CC_idlte_frame_parms); + printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms); + } else { + printf("phy_vars_eNB[%d] not initialized\n", CC_id); + return(-1); + } + +#ifndef EXMIMO + + if (frame_parms->frame_type == TDD) { + if (frame_parms->N_RB_DL == 100) + N_TA_offset = 624; + else if (frame_parms->N_RB_DL == 50) + N_TA_offset = 624/2; + else if (frame_parms->N_RB_DL == 25) + N_TA_offset = 624/4; + } + +#endif + + // replace RX signal buffers with mmaped HW versions +#ifdef EXMIMO + openair0_cfg[CC_id].tx_num_channels = 0; + openair0_cfg[CC_id].rx_num_channels = 0; + + for (i=0; inb_antennas_rx; i++) { + printf("Mapping eNB CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); + free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); + phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i]; + + if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) { + printf("Error with rf_map! A channel has already been allocated!\n"); + return(-1); + } else { + openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i]; + openair0_cfg[rf_map[CC_id].card].rx_num_channels++; + } + + printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); + + for (j=0; j<16; j++) { + printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j]); + phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j] = 16-j; + } + } + + for (i=0; inb_antennas_tx; i++) { + printf("Mapping eNB CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); + free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); + phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i]; + + if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) { + printf("Error with rf_map! A channel has already been allocated!\n"); + return(-1); + } else { + openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i]; + openair0_cfg[rf_map[CC_id].card].tx_num_channels++; + } + + printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); + + for (j=0; j<16; j++) { + printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j]); + phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j] = 16-j; + } + } + +#else // not EXMIMO + rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*)); + txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); + + for (i=0; inb_antennas_rx; i++) { + free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); + rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory + memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); + printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i],rxdata[i],N_TA_offset); + + } + + for (i=0; inb_antennas_tx; i++) { + free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); + txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i]; + memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); + printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); + + } + +#endif + } + + return(0); +} + + +#if defined(ENABLE_ITTI) +static void wait_system_ready (char *message, volatile int *start_flag) +{ + /* Wait for eNB application initialization to be complete (eNB registration to MME) */ + { + static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", + " ....", " ...", " ..", " .", " " + }; + int i = 0; + + while ((!oai_exit) && (*start_flag == 0)) { + LOG_N(EMU, message, indicator[i]); + fflush(stdout); + i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); + usleep(200000); + } + + LOG_D(EMU,"\n"); + } +} +#endif + +/*! + * \brief This is the main eNB thread. + * \param arg unused + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +static void* eNB_thread( void* arg ) +{ + UNUSED(arg); + static int eNB_thread_status; + + unsigned char slot; + // the USRP implementation operates on subframes, not slots + // one subframe consists of one even and one odd slot + slot = 1; + int spp; + int tx_launched = 0; + int card=0; + + void *rxp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_rx + void *txp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_tx + + int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9 + + unsigned int rx_pos = 0; + unsigned int tx_pos = 0; + + int CC_id=0; + struct timespec trx_time0, trx_time1, trx_time2; + + /* avoid gcc warnings */ + (void)trx_time0; + (void)trx_time1; + (void)trx_time2; + +#ifdef LOWLATENCY + struct sched_attr attr; + unsigned int flags = 0; + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0; + + /* This creates a .2 ms reservation */ + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = (0.3 * 100) * 10000; + attr.sched_deadline = (0.9 * 100) * 10000; + attr.sched_period = 1 * 1000000; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] main eNB thread: sched_setattr failed\n"); + exit_fun("Nothing to add"); + } else { + LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n", + gettid(),sched_getcpu()); + } + +#else + + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD threads */ + CPU_ZERO(&cpuset); +#ifdef CPU_AFFINITY + if (get_nprocs() >2) + { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_setaffinity_np"); + exit_fun("Error setting processor affinity"); + } + } +#endif // CPU_AFFINITY + + /* Check the actual affinity mask assigned to the thread */ + + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_getaffinity_np"); + exit_fun("Error getting processor affinity "); + } + memset(cpu_affinity, 0 , sizeof(cpu_affinity)); + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) + { + char temp[1024]; + sprintf(temp, " CPU_%d ", j); + strcat(cpu_affinity, temp); + } + + memset(&sparam, 0 , sizeof (sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + policy = SCHED_FIFO ; + + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) + { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) + { + perror("pthread_getschedparam : "); + exit_fun("Error getting thread priority"); + + } + + + LOG_I( HW, "[SCHED][eNB] Started eNB main thread on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + (int) sparam.sched_priority, cpu_affinity); + + +#endif //LOWLATENCY + + + // stop early, if an exit is requested + // FIXME really neccessary? + if (oai_exit) + goto eNB_thread_cleanup; + + printf("eNB_thread: mlockall in ...\n"); + mlockall(MCL_CURRENT | MCL_FUTURE); + printf("eNB_thread: mlockall out ...\n"); + + timing_info.time_min = 100000000ULL; + timing_info.time_max = 0; + timing_info.time_avg = 0; + timing_info.n_samples = 0; + + printf( "waiting for sync (eNB_thread)\n" ); + pthread_mutex_lock( &sync_mutex ); + + while (sync_var<0) + pthread_cond_wait( &sync_cond, &sync_mutex ); + + pthread_mutex_unlock(&sync_mutex); + + printf( "got sync (eNB_thread)\n" ); + + int frame = 0; + + + spp = openair0_cfg[0].samples_per_packet; + tx_pos = openair0_cfg[0].tx_scheduling_advance; + +#if defined(ENABLE_ITTI) + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); +#endif + + while (!oai_exit) { + start_meas( &softmodem_stats_mt ); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame ); + tx_launched = 0; + + while (rx_pos < ((1+hw_subframe)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti)) { + + unsigned int rxs; +#ifndef USRP_DEBUG + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos ); + + clock_gettime( CLOCK_MONOTONIC, &trx_time0 ); + + start_meas( &softmodem_stats_hw ); + + openair0_timestamp timestamp; + int i=0; + // prepare rx buffer pointers + for (i=0; ilte_frame_parms.nb_antennas_rx; i++) + rxp[i] = (void*)&rxdata[i][rx_pos]; + // check if nsymb_read == spp + // map antenna port i to the cc_id. Now use the 1:1 mapping + rxs = openair0.trx_read_func(&openair0, + ×tamp, + rxp, + spp, + PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx); + + stop_meas( &softmodem_stats_hw ); + if (frame > 50) { + clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); + } + + if (frame > 20){ + if (rxs != spp) + exit_fun( "problem receiving samples" ); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + + // Transmit TX buffer based on timestamp from RX + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + for (i=0; ilte_frame_parms.nb_antennas_tx; i++) + txp[i] = (void*)&txdata[i][tx_pos]; + // if symb_written < spp ==> error + if (frame > 50) { + openair0.trx_write_func(&openair0, + (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance), + txp, + spp, + PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx, + 1); + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance)&0xffffffff ); + + stop_meas( &softmodem_stats_mt ); + if (frame > 50) { + clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); + //update_difftimes(trx_time1, trx_time2); + } + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0); +#else + // USRP_DEBUG is active + rt_sleep_ns(1000000); +#endif + /* FT configurable tx lauch delay (in slots): txlaunch_wait, txlaunch_wait_slotcount is device specific and + set in the corresponding library (with txlaunch_wait=1 and txlaunch_wait_slotcount=1 the check is as it previously was) */ + /* old check: + if ((frame>50) && + (tx_launched == 0) && + (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/ + if ( (frame>50) && (tx_launched == 0) && + ((openair0_cfg[card].txlaunch_wait == 0) || + ((openair0_cfg[card].txlaunch_wait == 1) && + (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { + + tx_launched = 1; + + for (CC_id=0; CC_idproc[hw_subframe].mutex_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", hw_subframe, PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx ); + exit_fun( "error locking mutex_tx" ); + break; + } + + int cnt_tx = ++PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx; + + pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].mutex_tx ); + + if (cnt_tx == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].cond_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n", hw_subframe ); + exit_fun( "ERROR pthread_cond_signal" ); + break; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (rx_cnt %u, cnt_tx %i)\n", PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].frame_tx, hw_subframe, rx_pos, cnt_tx ); + exit_fun( "TX thread busy" ); + break; + } + } + } + + rx_pos += spp; + tx_pos += spp; + + if (tx_pos >= openair0_cfg[card].samples_per_frame) + tx_pos -= openair0_cfg[card].samples_per_frame; + } + + if (rx_pos >= openair0_cfg[card].samples_per_frame) + rx_pos -= openair0_cfg[card].samples_per_frame; + + + + if (oai_exit) break; + + timing_info.time_last = timing_info.time_now; + timing_info.time_now = rt_get_time_ns(); + + if (timing_info.n_samples>0) { + RTIME time_diff = timing_info.time_now - timing_info.time_last; + + if (time_diff < timing_info.time_min) + timing_info.time_min = time_diff; + + if (time_diff > timing_info.time_max) + timing_info.time_max = time_diff; + + timing_info.time_avg += time_diff; + } + + timing_info.n_samples++; + + if ((slot&1) == 1) { + // odd slot + int sf = hw_subframe; + if (frame>50) { + for (int CC_id=0; CC_idproc[sf].mutex_rx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n", sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx ); + exit_fun( "error locking mutex_rx" ); + break; + } + + int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx; + + pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx ); + + if (cnt_rx == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_rx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RX thread %d\n", sf ); + exit_fun( "ERROR pthread_cond_signal" ); + break; + } + } else { + LOG_W( PHY, "[eNB] Frame %d, eNB RX thread %d busy!! instance_cnt %d CC_id %d\n", PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_rx, sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx, CC_id ); + exit_fun( "RX thread busy" ); + break; + } + } + } + } + + hw_subframe++; + slot += 2; + + if (hw_subframe == NUM_ENB_THREADS) { + // the radio frame is complete, start over + hw_subframe = 0; + frame++; + slot = 1; + } + +#if defined(ENABLE_ITTI) + itti_update_lte_time( frame, slot ); +#endif + } + +eNB_thread_cleanup: +#ifdef DEBUG_THREADS + printf( "eNB_thread: finished, ran %d times.\n", frame ); +#endif + +#ifdef DEBUG_THREADS + printf( "Exiting eNB_thread ..." ); +#endif + + eNB_thread_status = 0; + + // print_difftimes(); + + return &eNB_thread_status; +} + +void reset_opp_meas(void) { + int sfn; + reset_meas(&softmodem_stats_mt); + reset_meas(&softmodem_stats_hw); + + for (sfn=0; sfn < 10; sfn++) { + reset_meas(&softmodem_stats_tx_sf[sfn]); + reset_meas(&softmodem_stats_rx_sf[sfn]); + } +} + +void print_opp_meas(void) { + + int sfn=0; + print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL); + print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL); + + for (sfn=0; sfn < 10; sfn++) { + print_meas(&softmodem_stats_tx_sf[sfn],"[eNB][total_phy_proc_tx]",NULL, NULL); + print_meas(&softmodem_stats_rx_sf[sfn],"[eNB][total_phy_proc_rx]",NULL,NULL); + } +} + + +void init_eNB() { + + int error_code; + + pthread_attr_init (&attr_dlsch_threads); + pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN); + +#ifndef LOWLATENCY + 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); + printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority); +#endif + + init_eNB_proc(); + sleep(1); + LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); + + + printf("Creating main eNB_thread \n"); + error_code = pthread_create( &main_eNB_thread, &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); + } else { + LOG_D( HW, "[lte-softmodem.c] Allocate eNB_thread successful\n" ); + pthread_setname_np( main_eNB_thread, "main eNB" ); + } +} + + +void stop_eNB() { + +#ifdef DEBUG_THREADS + printf("Joining eNB_thread ..."); +#endif + int *eNB_thread_status_p; + int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p ); +#ifdef DEBUG_THREADS + + if (result != 0) { + printf( "\nError joining main_eNB_thread.\n" ); + } else { + if (eNB_thread_status_p) { + printf( "status %d\n", *eNB_thread_status_p ); + } else { + printf( "The thread was killed. No status available.\n"); + } + } + +#else + UNUSED(result); +#endif // DEBUG_THREADS + + printf("Killing eNB processing threads\n"); + kill_eNB_proc(); +} diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index b6c3e20464..4664b0aa21 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -27,8 +27,8 @@ *******************************************************************************/ -/*! \file lte-softmodem.c - * \brief main program to control HW and scheduling +/*! \file lte-enb.c + * \brief Top-level threads for eNodeB * \author R. Knopp, F. Kaltenberger, Navid Nikaein * \date 2012 * \version 0.1 @@ -58,22 +58,13 @@ #include "assertions.h" #include "msc.h" -#ifdef EMOS -#include -struct gps_fix_t dummy_gps_data; -#endif - #include "PHY/types.h" #include "PHY/defs.h" #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all -#ifdef EXMIMO -#include "openair0_lib.h" -#else #include "../../ARCH/COMMON/common_lib.h" -#endif //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all @@ -83,10 +74,6 @@ struct gps_fix_t dummy_gps_data; #include "../../SIMU/USER/init_lte.h" -#ifdef EMOS -#include "SCHED/phy_procedures_emos.h" -#endif - #include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/vars.h" #include "LAYER2/MAC/proto.h" @@ -126,32 +113,10 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "stats.h" #endif -#define FRAME_PERIOD 100000000ULL -#define DAQ_PERIOD 66667ULL - -//#define DEBUG_THREADS 1 - -//#define USRP_DEBUG 1 - -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; - - - -openair0_config_t openair0_cfg[MAX_CARDS]; - -int32_t **rxdata; -int32_t **txdata; -int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); - -uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] -uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] -double cpuf; +int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); +extern void init_eNB(void); +extern void stop_eNB(void); void fill_ue_band_info(void); #ifdef XFORMS @@ -164,22 +129,13 @@ char title[255]; unsigned char scope_enb_num_ue = 2; #endif //XFORMS -#ifdef RTAI -static long main_eNB_thread; -static long main_ue_thread; - -#else -pthread_t main_eNB_thread; pthread_t main_ue_thread; -pthread_attr_t attr_dlsch_threads; pthread_attr_t attr_UE_thread; -#ifndef LOWLATENCY -struct sched_param sched_param_dlsch; -#endif -#endif + + pthread_cond_t sync_cond; pthread_mutex_t sync_mutex; @@ -190,43 +146,24 @@ int sync_var=-1; //!< protected by mutex \ref sync_mutex. struct sched_param sched_param_UE_thread; -pthread_attr_t attr_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS]; -pthread_attr_t attr_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS]; -#ifndef LOWLATENCY -struct sched_param sched_param_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS]; -struct sched_param sched_param_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS]; -#endif + #ifdef XFORMS static pthread_t forms_thread; //xforms #endif -#ifdef EMOS -static pthread_t thread3; //emos -static pthread_t thread4; //GPS -#endif openair0_device openair0; - -/* - 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; +uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] +uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] #if defined(ENABLE_ITTI) -static volatile int start_eNB = 0; -static volatile int start_UE = 0; +volatile int start_eNB = 0; +volatile int start_UE = 0; #endif volatile int oai_exit = 0; -//static int time_offset[4] = {-138,-138,-138,-138}; -//static int time_offset[4] = {-145,-145,-145,-145}; -static int time_offset[4] = {0,0,0,0}; + static char UE_flag=0; @@ -251,37 +188,18 @@ runmode_t mode = normal_txrx; FILE *input_fd=NULL; -#ifdef EXMIMO -#if MAX_NUM_CCs == 1 -double tx_gain[MAX_NUM_CCs][4] = {{20,20,0,0}}; -double rx_gain[MAX_NUM_CCs][4] = {{20,20,0,0}}; -#else -double tx_gain[MAX_NUM_CCs][4] = {{20,20,0,0},{20,20,0,0}}; -double rx_gain[MAX_NUM_CCs][4] = {{20,20,0,0},{20,20,0,0}}; -#endif -// these are for EXMIMO2 target only -/* - static unsigned int rxg_max[4] = {133,133,133,133}; - static unsigned int rxg_med[4] = {127,127,127,127}; - static unsigned int rxg_byp[4] = {120,120,120,120}; - */ -// these are for EXMIMO2 card 39 -unsigned int rxg_max[4] = {128,128,128,126}; -unsigned int rxg_med[4] = {122,123,123,120}; -unsigned int rxg_byp[4] = {116,117,116,116}; -unsigned int nf_max[4] = {7,9,16,12}; -unsigned int nf_med[4] = {12,13,22,17}; -unsigned int nf_byp[4] = {15,20,29,23}; #if MAX_NUM_CCs == 1 rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}}; -#else -rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}}; -#endif -#else double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}}; +#else +rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}}; +double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}}; +double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; #endif + + double sample_rate=30.72e6; double bw = 10.0e6; @@ -292,12 +210,10 @@ char rf_config_file[1024]; int chain_offset=0; int phy_test = 0; -#ifndef EXMIMO + char ref[128] = "internal"; char channels[128] = "0"; -#endif - int rx_input_level_dBm; static int online_log_messages=0; #ifdef XFORMS @@ -307,14 +223,11 @@ static char do_forms=0; int otg_enabled; #endif //int number_of_cards = 1; -#ifdef EXMIMO -static 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 -//static int mbox_bounds[20] = {6,14,22,28,36,44,52,58,66,74,82,88,96,104,112,118,126,134,142, 148}; ///boundaries of slots in terms ob mbox counter rounded up to even numbers -#endif + static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; -int multi_thread=1; + uint32_t target_dl_mcs = 28; //maximum allowed mcs uint32_t target_ul_mcs = 20; uint32_t timing_advance = 0; @@ -322,12 +235,9 @@ uint8_t exit_missed_slots=1; uint64_t num_missed_slots=0; // counter for the number of missed slots -time_stats_t softmodem_stats_mt; // main thread -time_stats_t softmodem_stats_hw; // hw acquisition -time_stats_t softmodem_stats_tx_sf[10]; // total tx time -time_stats_t softmodem_stats_rx_sf[10]; // total rx time -void reset_opp_meas(void); -void print_opp_meas(void); + +extern void reset_opp_meas(void); +extern void print_opp_meas(void); int transmission_mode=1; int16_t glog_level = LOG_INFO; @@ -369,9 +279,14 @@ uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; /* struct for ethernet specific parameters given in eNB conf file */ eth_params_t *eth_params; +openair0_config_t openair0_cfg[MAX_CARDS]; + +double cpuf; + char uecap_xer[1024],uecap_xer_in=0; extern void *UE_thread(void *arg); extern void init_UE_threads(void); +extern void kill_eNB_proc(void); /*---------------------BMC: timespec helpers -----------------------------*/ @@ -486,6 +401,7 @@ void help (void) { printf(" -x Set the transmission mode, valid options: 1 \n"RESET); } + void exit_fun(const char* s) { if (s != NULL) { @@ -499,9 +415,6 @@ void exit_fun(const char* s) itti_terminate_tasks (TASK_UNKNOWN); #endif - //rt_sleep_ns(FRAME_PERIOD); - - //exit (-1); } @@ -634,227 +547,8 @@ static void *scope_thread(void *arg) } #endif -#ifdef EMOS -#define NO_ESTIMATES_DISK 100 //No. of estimates that are aquired before dumped to disk - -void* gps_thread (void *arg) -{ - - struct gps_data_t gps_data; - struct gps_data_t *gps_data_ptr = &gps_data; - struct sched_param sched_param; - int ret; - - sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; - sched_setscheduler(0, SCHED_FIFO,&sched_param); - - printf("GPS thread has priority %d\n",sched_param.sched_priority); - - memset(&dummy_gps_data,0,sizeof(struct gps_fix_t)); - -#if GPSD_API_MAJOR_VERSION>=5 - ret = gps_open("127.0.0.1","2947",gps_data_ptr); - - if (ret!=0) -#else - gps_data_ptr = gps_open("127.0.0.1","2947"); - - if (gps_data_ptr == NULL) -#endif - { - printf("[EMOS] Could not open GPS\n"); - pthread_exit((void*)arg); - } - -#if GPSD_API_MAJOR_VERSION>=4 - else if (gps_stream(gps_data_ptr, WATCH_ENABLE,NULL) != 0) -#else - else if (gps_query(gps_data_ptr, "w+x") != 0) -#endif - { - printf("[EMOS] Error sending command to GPS\n"); - pthread_exit((void*) arg); - } else - printf("[EMOS] Opened GPS, gps_data=%p\n", gps_data_ptr); - while (!oai_exit) { - printf("[EMOS] polling data from gps\n"); -#if GPSD_API_MAJOR_VERSION>=5 - - if (gps_waiting(gps_data_ptr,500)) { - if (gps_read(gps_data_ptr) <= 0) { -#else - - if (gps_waiting(gps_data_ptr)) { - if (gps_poll(gps_data_ptr) != 0) { -#endif - printf("[EMOS] problem polling data from gps\n"); - } else { - memcpy(&dummy_gps_data,&(gps_data_ptr->fix),sizeof(struct gps_fix_t)); - printf("[EMOS] lat %g, lon %g\n",gps_data_ptr->fix.latitude,gps_data_ptr->fix.longitude); - } - } //gps_waiting - else { - printf("[EMOS] WARNING: No GPS data available, storing dummy packet\n"); - } - - //rt_sleep_ns(1000000000LL); - sleep(1); - } //oai_exit - - pthread_exit((void*) arg); - -} - -void *emos_thread (void *arg) -{ - char c; - char *fifo2file_buffer, *fifo2file_ptr; - - int fifo, counter=0, bytes; - - FILE *dumpfile_id; - char dumpfile_name[1024]; - time_t starttime_tmp; - struct tm starttime; - - int channel_buffer_size,ret; - - time_t timer; - struct tm *now; - - struct sched_param sched_param; - - 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); - - if (UE_flag==0) - channel_buffer_size = sizeof(fifo_dump_emos_eNB); - else - channel_buffer_size = sizeof(fifo_dump_emos_UE); - - // allocate memory for NO_FRAMES_DISK channes estimations - fifo2file_buffer = malloc(NO_ESTIMATES_DISK*channel_buffer_size); - fifo2file_ptr = fifo2file_buffer; - - if (fifo2file_buffer == NULL) { - printf("[EMOS] Cound not allocate memory for fifo2file_buffer\n"); - exit(EXIT_FAILURE); - } - - if ((fifo = open(CHANSOUNDER_FIFO_DEV, O_RDONLY)) < 0) { - fprintf(stderr, "[EMOS] Error opening the fifo\n"); - exit(EXIT_FAILURE); - } - - - time(&starttime_tmp); - localtime_r(&starttime_tmp,&starttime); - snprintf(dumpfile_name,1024,"/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, fifo %d\n",channel_buffer_size,fifo); - - while (!oai_exit) { - /* - bytes = rtf_read_timed(fifo, fifo2file_ptr, channel_buffer_size,100); - if (bytes==0) - continue; - */ - bytes = rtf_read_all_at_once(fifo, fifo2file_ptr, channel_buffer_size); - - if (bytes<=0) { - usleep(100); - continue; - } - - if (bytes != channel_buffer_size) { - printf("[EMOS] ERROR! Only got %d bytes instead of %d!\n",bytes,channel_buffer_size); - } - - /* - if (UE_flag==0) - printf("eNB: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx,bytes); - else - printf("UE: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_UE*)fifo2file_ptr)->frame_rx,bytes); - */ - - fifo2file_ptr += channel_buffer_size; - counter ++; - - if (counter == NO_ESTIMATES_DISK) { - //reset stuff - fifo2file_ptr = fifo2file_buffer; - counter = 0; - - //flush buffer to disk - if (UE_flag==0) - printf("[EMOS] eNB: count %d, frame %d, flushing buffer to disk\n", - counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx); - else - printf("[EMOS] UE: count %d, frame %d, flushing buffer to disk\n", - counter, ((fifo_dump_emos_UE*)fifo2file_ptr)->frame_rx); - - - 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 (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); - } - } - } - - free(fifo2file_buffer); - fclose(dumpfile_id); - close(fifo); - - pthread_exit((void*) arg); - -} -#endif - - - -#if defined(ENABLE_ITTI) -static void wait_system_ready (char *message, volatile int *start_flag) -{ - /* Wait for eNB application initialization to be complete (eNB registration to MME) */ - { - static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", - " ....", " ...", " ..", " .", " " - }; - int i = 0; - - while ((!oai_exit) && (*start_flag == 0)) { - LOG_N(EMU, message, indicator[i]); - fflush(stdout); - i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); - usleep(200000); - } - - LOG_D(EMU,"\n"); - } -} -#endif #if defined(ENABLE_ITTI) void *l2l1_task(void *arg) @@ -935,1347 +629,9 @@ void *l2l1_task(void *arg) #endif -void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) -{ - unsigned int aa,slot_offset, slot_offset_F; - int dummy_tx_b[7680*4] __attribute__((aligned(32))); - int i, tx_offset; - int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)* - ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7); - int len; - slot_offset_F = (subframe<<1)*slot_sizeF; - slot_offset = subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti; - - if ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_DL)|| - ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_S))) { - // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); - - - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { - if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED) { - PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], - dummy_tx_b, - phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, - 6, - phy_vars_eNB->lte_frame_parms.nb_prefix_samples, - CYCLIC_PREFIX); - PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], - dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1), - phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, - 6, - phy_vars_eNB->lte_frame_parms.nb_prefix_samples, - CYCLIC_PREFIX); - } else { - normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], - dummy_tx_b, - 7, - &(phy_vars_eNB->lte_frame_parms)); - // if S-subframe generate first slot only - if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_DL) - normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], - dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1), - 7, - &(phy_vars_eNB->lte_frame_parms)); - } - - // if S-subframe generate first slot only - if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) - len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1; - else - len = phy_vars_eNB->lte_frame_parms.samples_per_tti; - /* - for (i=0;ilte_frame_parms.samples_per_tti; - - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; - - ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_frame_parms,subframe) == SF_S) { - for (i=0; ilte_eNB_common_vars.txdata[0][aa][tx_offset++] = 0x00010001; - } - } - - if ((((phy_vars_eNB->lte_frame_parms.tdd_config==0) || - (phy_vars_eNB->lte_frame_parms.tdd_config==1) || - (phy_vars_eNB->lte_frame_parms.tdd_config==2) || - (phy_vars_eNB->lte_frame_parms.tdd_config==6)) && - (subframe==0)) || (subframe==5)) { - // turn on tx switch N_TA_offset before - //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset); - for (i=0; iN_TA_offset; i++) { - tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset/2; - if (tx_offset<0) - tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; - - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; - - phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset] = 0x00000000; - } - } - } - } -} - -/* mutex, cond and variable to serialize phy proc TX calls - * (this mechanism may be relaxed in the future for better - * performances) - */ -static struct { - pthread_mutex_t mutex_phy_proc_tx; - pthread_cond_t cond_phy_proc_tx; - volatile uint8_t phy_proc_CC_id; -} sync_phy_proc[NUM_ENB_THREADS]; - -/*! - * \brief The transmit thread of eNB. - * \ref NUM_ENB_THREADS threads of this type are active at the same time. - * \param param is a \ref eNB_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -static void* eNB_thread_tx( void* param ) -{ - static int eNB_thread_tx_status[NUM_ENB_THREADS]; - - eNB_proc_t *proc = (eNB_proc_t*)param; - FILE *tx_time_file = NULL; - char tx_time_name[101]; - - if (opp_enabled == 1) { - snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->subframe); - tx_time_file = fopen(tx_time_name,"w"); - } - // set default return value - eNB_thread_tx_status[proc->subframe] = 0; - - MSC_START_USE(); - -#ifdef RTAI - RT_TASK *task; - char task_name[8]; - - sprintf(task_name,"TXC%dS%d",proc->CC_id,proc->subframe); - task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task == NULL) { - LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name); - return 0; - } else { - LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n", - proc->CC_id, - proc->subframe, - task); - } - -#else -#ifdef LOWLATENCY - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 850000 ; - uint64_t deadline = 1 * 1000000 ; // each tx thread will finish within 1ms - uint64_t period = 1 * 10000000; // each tx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB tx thread: sched_setattr failed\n"); - return &eNB_thread_tx_status[proc->subframe]; - } - - LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() ); -#else - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ - /* CPU 1 is reserved for all TX threads */ - /* Enable CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); - - #ifdef CPU_AFFINITY - if (get_nprocs() > 2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } - #endif - - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity,0,sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - - } - - LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n", proc->subframe, sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity ); - - -#endif - -#endif - - mlockall(MCL_CURRENT | MCL_FUTURE); - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - while (!oai_exit) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 ); - - if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe ); - exit_fun("nothing to add"); - break; - } - - while (proc->instance_cnt_tx < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_tx is -1 - pthread_cond_wait( &proc->cond_tx, &proc->mutex_tx ); // this unlocks mutex_tx while waiting and then locks it again - } - - if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe); - exit_fun("nothing to add"); - break; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 1 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); - start_meas( &softmodem_stats_tx_sf[proc->subframe] ); - - if (oai_exit) break; - - if (((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD) && - ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_DL) || - (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S))) || - (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD)) { - /* run PHY TX procedures the one after the other for all CCs to avoid race conditions - * (may be relaxed in the future for performance reasons) - */ - if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe); - exit_fun("nothing to add"); - break; - } - /* wait for our turn or oai_exit */ - while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) { - pthread_cond_wait(&sync_phy_proc[proc->subframe].cond_phy_proc_tx, - &sync_phy_proc[proc->subframe].mutex_phy_proc_tx); - } - - if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe); - exit_fun("nothing to add"); - } - - if (oai_exit) - break; - - phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); - - /* we're done, let the next one proceed */ - if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe); - exit_fun("nothing to add"); - break; - } - sync_phy_proc[proc->subframe].phy_proc_CC_id++; - sync_phy_proc[proc->subframe].phy_proc_CC_id %= MAX_NUM_CCs; - pthread_cond_broadcast(&sync_phy_proc[proc->subframe].cond_phy_proc_tx); - if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe); - exit_fun("nothing to add"); - break; - } - } - - do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); - /* - short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->lte_eNB_common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.samples_per_tti]; - int i; - for (i=0;iCC_id]->lte_frame_parms.samples_per_tti*2;i+=8) { - txdata[i] = 2047; - txdata[i+1] = 0; - txdata[i+2] = 0; - txdata[i+3] = 2047; - txdata[i+4] = -2047; - txdata[i+5] = 0; - txdata[i+6] = 0; - txdata[i+7] = -2047; - } - */ - if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe ); - exit_fun("nothing to add"); - break; - } - - proc->instance_cnt_tx--; - - if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->subframe ); - exit_fun("nothing to add"); - break; - } - - proc->frame_tx++; - - if (proc->frame_tx==1024) - proc->frame_tx=0; - stop_meas( &softmodem_stats_tx_sf[proc->subframe] ); -#ifdef LOWLATENCY - if (opp_enabled){ - if(softmodem_stats_tx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0); - } - } -#endif - print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file); - - } - - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 ); - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - -#ifdef DEBUG_THREADS - printf( "Exiting eNB thread TX %d\n", proc->subframe ); -#endif - // clean task -#ifdef RTAI - rt_task_delete(task); -#endif - - eNB_thread_tx_status[proc->subframe] = 0; - return &eNB_thread_tx_status[proc->subframe]; -} - - -/*! - * \brief The receive thread of eNB. - * \ref NUM_ENB_THREADS threads of this type are active at the same time. - * \param param is a \ref eNB_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -static void* eNB_thread_rx( void* param ) -{ - static int eNB_thread_rx_status[NUM_ENB_THREADS]; - - eNB_proc_t *proc = (eNB_proc_t*)param; - - FILE *rx_time_file = NULL; - char rx_time_name[101]; - //int i; - - if (opp_enabled == 1){ - snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf_%d", "eNB", proc->subframe); - rx_time_file = fopen(rx_time_name,"w"); - } - // set default return value - eNB_thread_rx_status[proc->subframe] = 0; - - MSC_START_USE(); - -#ifdef RTAI - RT_TASK *task; - char task_name[8]; - - sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe); - task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name); - return 0; - } else { - LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /* on CPU %d*/ - proc->CC_id, - proc->subframe, - task); /*,rtai_cpuid()*/ - } - -#else -#ifdef LOWLATENCY - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 870000 ; - uint64_t deadline = 1 * 1000000; - uint64_t period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB RX sched_setattr failed\n"); - return &eNB_thread_rx_status[proc->subframe]; - } - - LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() ); -#else - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD */ - /* CPU 1 is reserved for all TX threads */ - /* CPU 2..MAX_CPUS is reserved for all RX threads */ - /* Set CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); - #ifdef CPU_AFFINITY - if (get_nprocs() >2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun (" Error setting processor affinity :"); - } - } - #endif - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); - } - memset(cpu_affinity,0, sizeof(cpu_affinity)); - - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; - - policy = SCHED_FIFO ; - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - memset(&sparam, 0 , sizeof (sparam)); - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } - - -LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", proc->subframe, sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity); - - -#endif -#endif // RTAI - - mlockall(MCL_CURRENT | MCL_FUTURE); - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - while (!oai_exit) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 ); - - if (pthread_mutex_lock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe ); - exit_fun( "error locking mutex" ); - break; - } - - while (proc->instance_cnt_rx < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_rx is -1 - pthread_cond_wait( &proc->cond_rx, &proc->mutex_rx ); // this unlocks mutex_rx while waiting and then locks it again - } - - if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe ); - exit_fun( "error unlocking mutex" ); - break; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 1 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - start_meas( &softmodem_stats_rx_sf[proc->subframe] ); - - if (oai_exit) break; - - if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_UL)) || - (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) { - - phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); - } - - if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx) == SF_S)) { - phy_procedures_eNB_S_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); - } - - if (pthread_mutex_lock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe ); - exit_fun( "error locking mutex" ); - break; - } - - proc->instance_cnt_rx--; - - if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe ); - exit_fun( "error unlocking mutex" ); - break; - } - - proc->frame_rx++; - - if (proc->frame_rx==1024) - proc->frame_rx=0; - - stop_meas( &softmodem_stats_rx_sf[proc->subframe] ); -#ifdef LOWLATENCY - if (opp_enabled){ - if(softmodem_stats_rx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0); - } - } -#endif - print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file); - } - - //stop_meas( &softmodem_stats_rx_sf[proc->subframe] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 ); - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - -#ifdef DEBUG_THREADS - printf( "Exiting eNB thread RX %d\n", proc->subframe ); -#endif - // clean task -#ifdef RTAI - rt_task_delete(task); -#endif - - eNB_thread_rx_status[proc->subframe] = 0; - return &eNB_thread_rx_status[proc->subframe]; -} - - - - -void init_eNB_proc(void) -{ - int i; - int CC_id; - - for (CC_id=0; CC_idproc[i].instance_cnt_tx = -1; - PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = -1; - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe = i; - PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id; - pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx, NULL); - pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx, NULL); - pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx, NULL); - pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx, NULL); -#ifndef LOWLATENCY - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, &attr_eNB_proc_tx[CC_id][i], eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, &attr_eNB_proc_rx[CC_id][i], eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); -#else - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, NULL, eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, NULL, eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); -#endif - char name[16]; - snprintf( name, sizeof(name), "TX %d", i ); - pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, name ); - snprintf( name, sizeof(name), "RX %d", i ); - pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, name ); - PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0; - PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0; -#ifdef EXMIMO - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_rx = (i+9)%10; - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_tx = (i+1)%10; -#else - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_rx = i; - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_tx = (i+2)%10; -#endif - } - - -#ifdef EXMIMO - // TX processes subframe + 1, RX subframe -1 - // Note this inialization is because the first process awoken for frame 0 is number 1 and so processes 9 and 0 have to start with frame 1 - - //PHY_vars_eNB_g[0][CC_id]->proc[0].frame_rx = 1023; - PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1; - PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1; -#else - // TX processes subframe +2, RX subframe - // Note this inialization is because the first process awoken for frame 0 is number 1 and so processes 8,9 and 0 have to start with frame 1 - // PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1; - PHY_vars_eNB_g[0][CC_id]->proc[8].frame_tx = 1; - PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1; - // PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1; -#endif - } - - /* setup PHY proc TX sync mechanism */ - for (i=0; iproc[i].instance_cnt_tx = 0; // FIXME data race! - pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx ); - pthread_cond_broadcast(&sync_phy_proc[i].cond_phy_proc_tx); - -#ifdef DEBUG_THREADS - printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i ); -#endif - int result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, (void**)&status ); - -#ifdef DEBUG_THREADS - - if (result != 0) { - printf( "Error joining thread.\n" ); - } else { - if (status) { - printf( "status %d\n", *status ); - } else { - printf( "The thread was killed. No status available.\n" ); - } - } - -#else - UNUSED(result) -#endif - -#ifdef DEBUG_THREADS - printf( "Killing RX CC_id %d thread %d\n", CC_id, i ); -#endif - - PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = 0; // FIXME data race! - pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx ); - -#ifdef DEBUG_THREADS - printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i ); -#endif - result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, (void**)&status ); - -#ifdef DEBUG_THREADS - - if (result != 0) { - printf( "Error joining thread.\n" ); - } else { - if (status) { - printf( "status %d\n", *status ); - } else { - printf( "The thread was killed. No status available.\n" ); - } - } - -#else - UNUSED(result) -#endif - - pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx ); - pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx ); - pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx ); - pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx ); - } -} - - - - - - -/*! - * \brief This is the main eNB thread. - * \param arg unused - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -static void* eNB_thread( void* arg ) -{ - UNUSED(arg); - static int eNB_thread_status; - - unsigned char slot; -#ifdef EXMIMO - slot=0; - RTIME time_in; - volatile unsigned int *DAQ_MBOX = openair0_daq_cnt(); - int mbox_target=0,mbox_current=0; - int hw_slot,delay_cnt; - int diff; - int ret; - int first_run=1; -#else - // the USRP implementation operates on subframes, not slots - // one subframe consists of one even and one odd slot - slot = 1; - int spp; - int tx_launched = 0; - int card=0; - - void *rxp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_rx - void *txp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_tx - - int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9 - - unsigned int rx_pos = 0; - unsigned int tx_pos = 0; -#endif - int CC_id=0; - struct timespec trx_time0, trx_time1, trx_time2; - - /* avoid gcc warnings */ - (void)trx_time0; - (void)trx_time1; - (void)trx_time2; - -#ifdef RTAI - RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF); -#else -#ifdef LOWLATENCY - struct sched_attr attr; - unsigned int flags = 0; - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - /* This creates a .2 ms reservation */ - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = (0.3 * 100) * 10000; - attr.sched_deadline = (0.9 * 100) * 10000; - attr.sched_period = 1 * 1000000; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] main eNB thread: sched_setattr failed\n"); - exit_fun("Nothing to add"); - } else { - LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n", - gettid(),sched_getcpu()); - } - -#else - - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ - CPU_ZERO(&cpuset); - #ifdef CPU_AFFINITY - if (get_nprocs() >2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } - #endif - - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity, 0 , sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf(temp, " CPU_%d ", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - - } - - - LOG_I( HW, "[SCHED][eNB] Started eNB main thread on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - (int) sparam.sched_priority, cpu_affinity); - - -#endif -#endif - - // stop early, if an exit is requested - // FIXME really neccessary? - if (oai_exit) - goto eNB_thread_cleanup; - -#ifdef RTAI - LOG_I( HW, "[SCHED][eNB] Started eNB main thread (id %p)\n", task ); -#endif - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - printf("eNB_thread: mlockall in ...\n"); - mlockall(MCL_CURRENT | MCL_FUTURE); - printf("eNB_thread: mlockall out ...\n"); - - timing_info.time_min = 100000000ULL; - timing_info.time_max = 0; - timing_info.time_avg = 0; - timing_info.n_samples = 0; - - printf( "waiting for sync (eNB_thread)\n" ); - pthread_mutex_lock( &sync_mutex ); - - while (sync_var<0) - pthread_cond_wait( &sync_cond, &sync_mutex ); - - pthread_mutex_unlock(&sync_mutex); - - printf( "got sync (eNB_thread)\n" ); - - int frame = 0; - -#ifndef EXMIMO - spp = openair0_cfg[0].samples_per_packet; - tx_pos = openair0_cfg[0].tx_scheduling_advance; -#endif - -#if defined(ENABLE_ITTI) - wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); -#endif - - while (!oai_exit) { - start_meas( &softmodem_stats_mt ); - -#ifdef EXMIMO - 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]); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_slot>>1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame); - //this is the mbox counter where we should be - mbox_target = mbox_bounds[slot]; - //this is the mbox counter where we are - mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; - - //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD) - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround - diff = 150-mbox_current+mbox_target; - else if ((mbox_current<15) && (mbox_target>=135)) - diff = -150+mbox_target-mbox_current; - else - diff = mbox_target - mbox_current; - - //when we start the aquisition we want to start with slot 0, so we rather wait for the hardware than to advance the slot number (a positive diff will cause the programm to go into the second if clause rather than the first) - if (first_run==1) { - first_run=0; - - if (diff<0) - diff = diff + 150; - - LOG_I(HW,"eNB Frame %d, time %llu: slot %d, hw_slot %d, diff %d\n",frame, rt_get_time_ns(), slot, hw_slot, diff); - } - - if (((slot%2==0) && (diff < (-14))) || ((slot%2==1) && (diff < (-7)))) { - - // at the eNB, even slots have double as much time since most of the processing is done here and almost nothing in odd slots - LOG_W(HW,"eNB Frame %d, time %llu: missed slot %d, proceeding with next one (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n", - frame, rt_get_time_ns(), num_missed_slots, slot, hw_slot, mbox_current,mbox_target, diff); - - if (exit_missed_slots==1) { - stop_meas(&softmodem_stats_mt); - exit_fun("[HW][eNB] missed slot"); - } else { - num_missed_slots++; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB,num_missed_slots ); - } - - if ((slot&1) == 1) { - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++){ - if (PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_rx==1023) - PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_rx=0; - else - PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_rx += 1; - - if (PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_tx==1023) - PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_tx=0; - else - PHY_vars_eNB_g[0][CC_id]->proc[((slot>>1)+1)%10].frame_tx += 1; - } - } - - slot++; - if (slot == 20) { - frame++; - slot = 0; - } - - - } - - if (diff>8) - LOG_D(HW,"eNB Frame %d, time %llu: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, mbox_current, - mbox_target, diff); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff); - - delay_cnt = 0; - - while ((diff>0) && (!oai_exit)) { - time_in = rt_get_time_ns(); - //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d, (slot+1)*15=%d, diff %d, time %llu\n",frame,delay_cnt,hw_slot,((unsigned int *)DAQ_MBOX)[0],slot,(((slot+1)*15)>>1),diff,time_in); - //LOG_D(HW,"eNB Frame %d, time %llu: sleeping for %llu (slot %d, hw_slot %d, diff %d, mbox %d, delay_cnt %d)\n", frame, time_in, diff*DAQ_PERIOD,slot,hw_slot,diff,((volatile unsigned int *)DAQ_MBOX)[0],delay_cnt); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1); - ret = rt_sleep_ns(diff*DAQ_PERIOD); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX); - - if (ret) - LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in); - - hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_slot>>1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame); -//LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns()); - delay_cnt++; - - if (delay_cnt == 10) { - stop_meas(&softmodem_stats_mt); - LOG_D(HW,"eNB Frame %d: HW stopped ... \n",frame); - exit_fun("[HW][eNB] HW stopped"); - } - - 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; - } - -#else // EXMIMO - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame ); - tx_launched = 0; - - while (rx_pos < ((1+hw_subframe)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti)) { - - unsigned int rxs; -#ifndef USRP_DEBUG - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos ); - - clock_gettime( CLOCK_MONOTONIC, &trx_time0 ); - - start_meas( &softmodem_stats_hw ); - - openair0_timestamp timestamp; - int i=0; - // prepare rx buffer pointers - for (i=0; ilte_frame_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&rxdata[i][rx_pos]; - // check if nsymb_read == spp - // map antenna port i to the cc_id. Now use the 1:1 mapping - rxs = openair0.trx_read_func(&openair0, - ×tamp, - rxp, - spp, - PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx); - - stop_meas( &softmodem_stats_hw ); - if (frame > 50) { - clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); - } - - if (frame > 20){ - if (rxs != spp) - exit_fun( "problem receiving samples" ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - - // Transmit TX buffer based on timestamp from RX - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - for (i=0; ilte_frame_parms.nb_antennas_tx; i++) - txp[i] = (void*)&txdata[i][tx_pos]; - // if symb_written < spp ==> error - if (frame > 50) { - openair0.trx_write_func(&openair0, - (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance), - txp, - spp, - PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx, - 1); - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance)&0xffffffff ); - - stop_meas( &softmodem_stats_mt ); - if (frame > 50) { - clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); - //update_difftimes(trx_time1, trx_time2); - } - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0); -#else - // USRP_DEBUG is active - rt_sleep_ns(1000000); -#endif - /* FT configurable tx lauch delay (in slots): txlaunch_wait, txlaunch_wait_slotcount is device specific and - set in the corresponding library (with txlaunch_wait=1 and txlaunch_wait_slotcount=1 the check is as it previously was) */ - /* old check: - if ((frame>50) && - (tx_launched == 0) && - (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/ - if ( (frame>50) && (tx_launched == 0) && - ((openair0_cfg[card].txlaunch_wait == 0) || - ((openair0_cfg[card].txlaunch_wait == 1) && - (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { - - tx_launched = 1; - - for (CC_id=0; CC_idproc[hw_subframe].mutex_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", hw_subframe, PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx ); - exit_fun( "error locking mutex_tx" ); - break; - } - - int cnt_tx = ++PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx; - - pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].mutex_tx ); - - if (cnt_tx == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].cond_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n", hw_subframe ); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (rx_cnt %u, cnt_tx %i)\n", PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].frame_tx, hw_subframe, rx_pos, cnt_tx ); - exit_fun( "TX thread busy" ); - break; - } - } - } - - rx_pos += spp; - tx_pos += spp; - - if (tx_pos >= openair0_cfg[card].samples_per_frame) - tx_pos -= openair0_cfg[card].samples_per_frame; - } - - if (rx_pos >= openair0_cfg[card].samples_per_frame) - rx_pos -= openair0_cfg[card].samples_per_frame; - - -#endif // USRP - - if (oai_exit) break; - - timing_info.time_last = timing_info.time_now; - timing_info.time_now = rt_get_time_ns(); - - if (timing_info.n_samples>0) { - RTIME time_diff = timing_info.time_now - timing_info.time_last; - - if (time_diff < timing_info.time_min) - timing_info.time_min = time_diff; - - if (time_diff > timing_info.time_max) - timing_info.time_max = time_diff; - - timing_info.time_avg += time_diff; - } - - timing_info.n_samples++; - - if ((slot&1) == 1) { - // odd slot -#ifdef EXMIMO - int sf = ((slot>>1)+1)%10; -#else - int sf = hw_subframe; -#endif - if (frame>50) { - for (int CC_id=0; CC_idproc[sf].mutex_tx) != 0) { - LOG_E(PHY,"[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx); - } else { - // LOG_I(PHY,"[eNB] Waking up eNB process %d (IC %d)\n",sf,PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt); - PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx++; - pthread_mutex_unlock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_tx); - - if (PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_tx == 0) { - if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_tx) != 0) { - LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n",sf); - exit_fun("nothing to add"); - } - } else { - LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!!\n",PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_tx,sf); - exit_fun("nothing to add"); - } - } - -#endif - - if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n", sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx ); - exit_fun( "error locking mutex_rx" ); - break; - } - - int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx; - - pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx ); - - if (cnt_rx == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_rx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RX thread %d\n", sf ); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - } else { - LOG_W( PHY, "[eNB] Frame %d, eNB RX thread %d busy!! instance_cnt %d CC_id %d\n", PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_rx, sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx, CC_id ); - exit_fun( "RX thread busy" ); - break; - } - } - } - } - -#ifdef EXMIMO - slot++; - - if (slot == 20) { - frame++; - slot = 0; - } - -#else - hw_subframe++; - slot += 2; - - if (hw_subframe == NUM_ENB_THREADS) { - // the radio frame is complete, start over - hw_subframe = 0; - frame++; - slot = 1; - } - -#endif - -#if defined(ENABLE_ITTI) - itti_update_lte_time( frame, slot ); -#endif - } - -eNB_thread_cleanup: -#ifdef DEBUG_THREADS - printf( "eNB_thread: finished, ran %d times.\n", frame ); -#endif - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - -#ifdef DEBUG_THREADS - printf( "Exiting eNB_thread ..." ); -#endif - // clean task -#ifdef RTAI - rt_task_delete(task); -#endif - - eNB_thread_status = 0; - - // print_difftimes(); - - return &eNB_thread_status; -} @@ -2290,12 +646,6 @@ static void get_options (int argc, char **argv) int clock_src; #endif int CC_id; -#ifdef EXMIMO - char rxg_fname[256], line[1000]; - FILE *rxg_fd; - int l; -#endif - @@ -2586,30 +936,6 @@ static void get_options (int argc, char **argv) break; case 'F': -#ifdef EXMIMO - sprintf(rxg_fname,"%srxg.lime",optarg); - rxg_fd = fopen(rxg_fname,"r"); - - if (rxg_fd) { - printf("Loading RX Gain parameters from %s\n",rxg_fname); - l=0; - - while (fgets(line, sizeof(line), rxg_fd)) { - if ((strlen(line)==0) || (*line == '#')) continue; //ignore empty or comment lines - else { - if (l==0) sscanf(line,"%d %d %d %d",&rxg_max[0],&rxg_max[1],&rxg_max[2],&rxg_max[3]); - - if (l==1) sscanf(line,"%d %d %d %d",&rxg_med[0],&rxg_med[1],&rxg_med[2],&rxg_med[3]); - - if (l==2) sscanf(line,"%d %d %d %d",&rxg_byp[0],&rxg_byp[1],&rxg_byp[2],&rxg_byp[3]); - - l++; - } - } - } else - printf("%s not found, running with defaults\n",rxg_fname); - -#endif break; case 'G': @@ -2786,7 +1112,7 @@ static void get_options (int argc, char **argv) int main( int argc, char **argv ) { int i,aa,card=0; -#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO) +#if defined (XFORMS) void *status; #endif @@ -2794,17 +1120,11 @@ int main( int argc, char **argv ) uint16_t Nid_cell = 0; uint8_t cooperation_flag=0, abstraction_flag=0; uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; - -#ifdef ENABLE_TCXO - unsigned int tcxo = 114; -#endif + int error_code; #if defined (XFORMS) int ret; #endif -#if defined (EMOS) || (! defined (RTAI)) - int error_code; -#endif #ifdef DEBUG_CONSOLE setvbuf(stdout, NULL, _IONBF, 0); @@ -2961,9 +1281,8 @@ int main( int argc, char **argv ) signal(SIGINT, signal_handler); #endif -#ifndef RTAI + check_clock(); -#endif // init the parameters for (CC_id=0; CC_idlte_ue_pdcch_vars[0]->crnti = 0x1235; -#ifdef EXMIMO - for (i=0; i<4; i++) { - UE[CC_id]->rx_gain_max[i] = rxg_max[i]; - UE[CC_id]->rx_gain_med[i] = rxg_med[i]; - UE[CC_id]->rx_gain_byp[i] = rxg_byp[i]; - } - - if ((UE[0]->mode == normal_txrx) || - (UE[0]->mode == rx_calib_ue) || - (UE[0]->mode == no_L2_connect) || - (UE[0]->mode == debug_prach)) { - for (i=0; i<4; i++) - rx_gain_mode[CC_id][i] = max_gain; - - UE[CC_id]->rx_total_gain_dB = UE[CC_id]->rx_gain_max[0] + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain - } else if ((mode == rx_calib_ue_med)) { - for (i=0; i<4; i++) - rx_gain_mode[CC_id][i] = med_gain; - - UE[CC_id]->rx_total_gain_dB = UE[CC_id]->rx_gain_med[0] + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain; - } else if ((mode == rx_calib_ue_byp)) { - for (i=0; i<4; i++) - rx_gain_mode[CC_id][i] = byp_gain; - - UE[CC_id]->rx_total_gain_dB = UE[CC_id]->rx_gain_byp[0] + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain; - } - -#else UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0]; -#endif - UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; - - -#ifdef EXMIMO - //N_TA_offset - if (UE[CC_id]->lte_frame_parms.frame_type == TDD) { - if (UE[CC_id]->lte_frame_parms.N_RB_DL == 100) - UE[CC_id]->N_TA_offset = 624; - else if (UE[CC_id]->lte_frame_parms.N_RB_DL == 50) - UE[CC_id]->N_TA_offset = 624/2; - else if (UE[CC_id]->lte_frame_parms.N_RB_DL == 25) - UE[CC_id]->N_TA_offset = 624/4; - } else { - UE[CC_id]->N_TA_offset = 0; - } -#else - //already taken care of in lte-softmodem UE[CC_id]->N_TA_offset = 0; -#endif + } openair_daq_vars.manual_timing_advance = 0; @@ -3138,39 +1411,10 @@ int main( int argc, char **argv ) PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.frame_type, PHY_vars_eNB_g[0][CC_id]->X_u); -#ifndef EXMIMO - PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB = (int)rx_gain[CC_id][0]; -#else - PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB = rxg_max[0] + (int)rx_gain[CC_id][0] - 30; //was measured at rxgain=30; - - printf("Setting RX total gain to %d\n",PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB); - - // set eNB to max gain - for (i=0; i<4; i++) - rx_gain_mode[CC_id][i] = max_gain; - -#endif - -#ifdef EXMIMO - - //N_TA_offset - if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.frame_type == TDD) { - if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 100) - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624; - else if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 50) - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/2; - else if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 25) - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/4; - } else { - PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0; - } - -#else //already taken care of in lte-softmodem.c PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0; -#endif } @@ -3184,10 +1428,10 @@ int main( int argc, char **argv ) openair_daq_vars.target_ue_ul_mcs=target_ul_mcs; } -#ifndef RTAI + fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); cpuf=get_cpu_freq_GHz(); -#endif + dump_frame_parms(frame_parms[0]); @@ -3254,7 +1498,7 @@ int main( int argc, char **argv ) // in the case of the USRP, the following variables need to be initialized before the init // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC. // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer -#ifndef EXMIMO + openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx)); openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx)); @@ -3277,32 +1521,10 @@ int main( int argc, char **argv ) openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB; } -#if 0 // UHD 3.8 - switch(frame_parms[0]->N_RB_DL) { - case 6: - openair0_cfg[card].rx_gain[i] -= 12; - break; - - case 25: - openair0_cfg[card].rx_gain[i] -= 6; - break; - - case 50: - openair0_cfg[card].rx_gain[i] -= 3; - break; - - case 100: - openair0_cfg[card].rx_gain[i] -= 0; - break; - - default: - break; - } -#endif } -#endif + } #ifndef LOWLATENCY @@ -3412,30 +1634,7 @@ int main( int argc, char **argv ) mac_xface->mrbch_phy_sync_failure (0, 0, 0); } - /* #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(UE_flag ? 1 : 0, UE_flag ? 0 : 1); - // } - #endif */ - -#ifdef EXMIMO - number_of_cards = openair0_num_detected_cards; -#else number_of_cards = 1; -#endif - for(CC_id=0; CC_idrf.do_autocal[ant] = 0; - */ - -#ifdef EMOS - error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE); - - if (error_code==0) - printf("[OPENAIR][SCHED][INIT] Created EMOS FIFO %d\n",CHANSOUNDER_FIFO_MINOR); - else if (error_code==ENODEV) - printf("[OPENAIR][SCHED][INIT] Problem: EMOS FIFO %d is greater than or equal to RTF_NO\n",CHANSOUNDER_FIFO_MINOR); - else if (error_code==ENOMEM) - printf("[OPENAIR][SCHED][INIT] Problem: cannot allocate memory for EMOS FIFO %d\n",CHANSOUNDER_FIFO_MINOR); - else - printf("[OPENAIR][SCHED][INIT] Problem creating EMOS FIFO %d, error_code %d\n",CHANSOUNDER_FIFO_MINOR,error_code); - -#endif - mlockall(MCL_CURRENT | MCL_FUTURE); -#ifdef RTAI - // make main thread LXRT soft realtime - /* task = */ rt_task_init_schmod(nam2num("MAIN"), 9, 0, 0, SCHED_FIFO, 0xF); - - // start realtime timer and scheduler - //rt_set_oneshot_mode(); - rt_set_periodic_mode(); - start_rt_timer(0); -#endif - pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); - // this starts the DMA transfers -#ifdef EXMIMO - - if (UE_flag!=1) - for (card=0; card0) { - init_eNB_proc(); - sleep(1); - LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); - } - - printf("Creating main eNB_thread \n"); -#ifdef RTAI - main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN); -#else - error_code = pthread_create( &main_eNB_thread, &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" ); - pthread_setname_np( main_eNB_thread, "main eNB" ); - } - -#endif + init_eNB(); } // Sleep to allow all threads to setup @@ -3684,7 +1795,7 @@ int main( int argc, char **argv ) -#ifndef EXMIMO + #ifndef USRP_DEBUG if (mode!=loop_through_memory) @@ -3693,7 +1804,6 @@ int main( int argc, char **argv ) #endif -#endif printf("Sending sync to all threads\n"); @@ -3713,7 +1823,7 @@ int main( int argc, char **argv ) #else while (oai_exit==0) - rt_sleep_ns(FRAME_PERIOD); + rt_sleep_ns(100000000ULL); #endif @@ -3748,79 +1858,16 @@ int main( int argc, char **argv ) // cleanup if (UE_flag == 1) { -#ifdef EXMIMO -#ifdef RTAI - rt_thread_join(main_ue_thread); -#else - pthread_join(main_ue_thread,&status); -#endif -#ifdef DLSCH_THREAD - cleanup_dlsch_threads(); - cleanup_rx_pdsch_thread(); -#endif -#endif } else { -#ifdef DEBUG_THREADS - printf("Joining eNB_thread ..."); -#endif -#ifdef RTAI - rt_thread_join(main_eNB_thread); -#else - int *eNB_thread_status_p; - int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p ); -#ifdef DEBUG_THREADS - - if (result != 0) { - printf( "\nError joining main_eNB_thread.\n" ); - } else { - if (eNB_thread_status_p) { - printf( "status %d\n", *eNB_thread_status_p ); - } else { - printf( "The thread was killed. No status available.\n"); - } - } - -#else - UNUSED(result); -#endif // DEBUG_THREADS -#endif // RTAI - - if (multi_thread>0) { - printf("Killing eNB processing threads\n"); - kill_eNB_proc(); - } + stop_eNB(); } -#ifdef RTAI - stop_rt_timer(); -#endif pthread_cond_destroy(&sync_cond); pthread_mutex_destroy(&sync_mutex); -#ifdef EXMIMO - printf("stopping card\n"); - openair0_stop(0); - printf("closing openair0_lib\n"); - openair0_close(); -#else openair0.trx_end_func(&openair0); -#endif - -#ifdef EMOS - printf("waiting for EMOS thread\n"); - pthread_cancel(thread3); - pthread_join(thread3,&status); - printf("waiting for GPS thread\n"); - pthread_cancel(thread4); - pthread_join(thread4,&status); -#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(); @@ -3834,142 +1881,8 @@ int main( int argc, char **argv ) } -/* this function maps the phy_vars_eNB tx and rx buffers to the available rf chains. - Each rf chain is is addressed by the card number and the chain on the card. The - rf_map specifies for each CC, on which rf chain the mapping should start. Multiple - antennas are mapped to successive RF chains on the same card. */ -int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) -{ - - int i, CC_id; -#ifndef EXMIMO - uint16_t N_TA_offset = 0; -#else - int j; -#endif - LTE_DL_FRAME_PARMS *frame_parms; - for (CC_id=0; CC_idlte_frame_parms); - printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms); - } else { - printf("phy_vars_eNB[%d] not initialized\n", CC_id); - return(-1); - } -#ifndef EXMIMO - - if (frame_parms->frame_type == TDD) { - if (frame_parms->N_RB_DL == 100) - N_TA_offset = 624; - else if (frame_parms->N_RB_DL == 50) - N_TA_offset = 624/2; - else if (frame_parms->N_RB_DL == 25) - N_TA_offset = 624/4; - } - -#endif - - // replace RX signal buffers with mmaped HW versions -#ifdef EXMIMO - openair0_cfg[CC_id].tx_num_channels = 0; - openair0_cfg[CC_id].rx_num_channels = 0; - - for (i=0; inb_antennas_rx; i++) { - printf("Mapping eNB CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i]; - - if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) { - printf("Error with rf_map! A channel has already been allocated!\n"); - return(-1); - } else { - openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].rx_num_channels++; - } - - printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); - - for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j] = 16-j; - } - } - - for (i=0; inb_antennas_tx; i++) { - printf("Mapping eNB CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i]; - - if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) { - printf("Error with rf_map! A channel has already been allocated!\n"); - return(-1); - } else { - openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].tx_num_channels++; - } - - printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); - - for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j] = 16-j; - } - } - -#else // not EXMIMO - rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*)); - txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); - - for (i=0; inb_antennas_rx; i++) { - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); - rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation - phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory - memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); - printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i],rxdata[i],N_TA_offset); - - } - - for (i=0; inb_antennas_tx; i++) { - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); - txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation - phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i]; - memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); - printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); - - } - -#endif - } - - return(0); -} - -void reset_opp_meas(void) { - int sfn; - reset_meas(&softmodem_stats_mt); - reset_meas(&softmodem_stats_hw); - - for (sfn=0; sfn < 10; sfn++) { - reset_meas(&softmodem_stats_tx_sf[sfn]); - reset_meas(&softmodem_stats_rx_sf[sfn]); - } -} - -void print_opp_meas(void) { - - int sfn=0; - print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL); - print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL); - - for (sfn=0; sfn < 10; sfn++) { - print_meas(&softmodem_stats_tx_sf[sfn],"[eNB][total_phy_proc_tx]",NULL, NULL); - print_meas(&softmodem_stats_rx_sf[sfn],"[eNB][total_phy_proc_rx]",NULL,NULL); - } -} From e2c322280296d18f9afa33fe3e27f1c4c2309acf Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 9 May 2016 23:40:36 -0700 Subject: [PATCH 005/206] removal of EXPRESSMIMO #ifdef's in lte-ue. move UE-specific code from lte-softmodem.c to lte-ue.c --- cmake_targets/CMakeLists.txt | 13 - targets/RT/USER/lte-softmodem.c | 54 +-- targets/RT/USER/lte-ue.c | 667 ++++--------------------------- targets/RT/USER/sched_dlsch.c | 354 ---------------- targets/RT/USER/sched_rx_pdsch.c | 321 --------------- targets/RT/USER/sched_ulsch.c | 255 ------------ 6 files changed, 95 insertions(+), 1569 deletions(-) delete mode 100644 targets/RT/USER/sched_dlsch.c delete mode 100644 targets/RT/USER/sched_rx_pdsch.c delete mode 100644 targets/RT/USER/sched_ulsch.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 166da4a48d..966ef6e085 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -259,15 +259,6 @@ if (${ENABLE_ITTI}) endif (${ENABLE_ITTI}) add_boolean_option(RTAI False "Use RTAI") -if (${RTAI}) - set(LOWLATENCY False) - set(CPU_AFFINITY False) - add_definitions("-DENABLE_RTAI_CLOCK") - add_definitions("-DCONFIG_RTAI_LXRT_INLINE") - include_directories ("/usr/realtime/include") - include_directories ("/usr/realtime/include/asm") - set(RTAI_SOURCE sched_dlsch.c sched_rx_pdsch.c rt_wrapper.c vcd_signal_dumper.c log.c) -endif (${RTAI}) ############################# # ASN.1 grammar C code generation & dependancies @@ -1574,8 +1565,6 @@ add_executable(lte-softmodem ${rrc_h} ${s1ap_h} ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/RT/USER/sched_dlsch.c - ${OPENAIR_TARGETS}/RT/USER/sched_rx_pdsch.c ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/RT/USER/lte-ue.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c @@ -1611,8 +1600,6 @@ add_executable(lte-softmodem-nos1 ${rrc_h} ${s1ap_h} ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/RT/USER/sched_dlsch.c - ${OPENAIR_TARGETS}/RT/USER/sched_rx_pdsch.c ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/RT/USER/lte-ue.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4664b0aa21..822409f302 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -113,12 +113,18 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "stats.h" #endif +// In lte-enb.c int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); -int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); + extern void init_eNB(void); extern void stop_eNB(void); +extern void kill_eNB_proc(void); +// In lte-ue.c +int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); void fill_ue_band_info(void); +extern void init_UE(void); + #ifdef XFORMS // 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 @@ -130,9 +136,6 @@ unsigned char scope_enb_num_ue = 2; #endif //XFORMS -pthread_t main_ue_thread; - -pthread_attr_t attr_UE_thread; @@ -144,7 +147,6 @@ int sync_var=-1; //!< protected by mutex \ref sync_mutex. -struct sched_param sched_param_UE_thread; #ifdef XFORMS @@ -284,9 +286,8 @@ openair0_config_t openair0_cfg[MAX_CARDS]; double cpuf; char uecap_xer[1024],uecap_xer_in=0; -extern void *UE_thread(void *arg); -extern void init_UE_threads(void); -extern void kill_eNB_proc(void); + + /*---------------------BMC: timespec helpers -----------------------------*/ @@ -1120,7 +1121,6 @@ int main( int argc, char **argv ) uint16_t Nid_cell = 0; uint8_t cooperation_flag=0, abstraction_flag=0; uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; - int error_code; #if defined (XFORMS) int ret; @@ -1752,43 +1752,11 @@ int main( int argc, char **argv ) rt_sleep_ns(10*100000000ULL); - pthread_attr_init (&attr_UE_thread); - pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN); -#ifndef LOWLATENCY - sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO); - pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread); -#endif // start the main thread - if (UE_flag == 1) { - printf("Intializing UE Threads ...\n"); - init_UE_threads(); - sleep(1); - error_code = pthread_create(&main_ue_thread, &attr_UE_thread, 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" ); - pthread_setname_np( main_ue_thread, "main UE" ); - } - - printf("UE threads created\n"); -#ifdef USE_MME - - while (start_UE == 0) { - sleep(1); - } - -#endif - - - - } else { - init_eNB(); - } + if (UE_flag == 1) init_UE(); + else init_eNB(); // Sleep to allow all threads to setup sleep(1); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 561554516c..3049fd4e02 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -69,11 +69,7 @@ #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all -#ifdef EXMIMO -#include "openair0_lib.h" -#else #include "../../ARCH/COMMON/common_lib.h" -#endif #include "PHY/extern.h" #include "SCHED/extern.h" @@ -96,10 +92,9 @@ typedef enum { si=2 } sync_mode_t; -int init_dlsch_threads(void); -void cleanup_dlsch_threads(void); -int32_t init_rx_pdsch_thread(void); -void cleanup_rx_pdsch_thread(void); +void init_UE_threads(void); +void *UE_thread(void *arg); +void init_UE(void); extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; @@ -125,19 +120,6 @@ extern uint64_t num_missed_slots; // counter for the number of missed slots extern void exit_fun(const char* s); -#ifdef EXMIMO - -extern unsigned int rxg_max[4]; -extern unsigned int rxg_med[4]; -extern unsigned int rxg_byp[4]; -extern unsigned int nf_max[4]; -extern unsigned int nf_med[4]; -extern unsigned int nf_byp[4]; -extern rx_gain_t rx_gain_mode[MAX_NUM_CCs][4]; - -extern double tx_gain[MAX_NUM_CCs][4]; -extern double rx_gain[MAX_NUM_CCs][4]; -#endif #define KHz (1000UL) #define MHz (1000 * KHz) @@ -189,6 +171,38 @@ static const eutra_band_t eutra_bands[] = { {44, 703 * MHz, 803 * MHz, 703 * MHz, 803 * MHz, TDD}, }; +pthread_t main_ue_thread; +pthread_attr_t attr_UE_thread; +struct sched_param sched_param_UE_thread; + +void init_UE() { + + int error_code; + + printf("Intializing UE Threads ...\n"); + init_UE_threads(); + sleep(1); + error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL); + + if (error_code!= 0) { + LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code); + return; + } else { + LOG_D( HW, "[lte-softmodem.c] Allocate UE_thread successful\n" ); + pthread_setname_np( main_ue_thread, "main UE" ); + } + + printf("UE threads created\n"); +#ifdef USE_MME + + while (start_UE == 0) { + sleep(1); + } + +#endif + +} + /*! * \brief This is the UE synchronize thread. * It performs band scanning and synchonization. @@ -512,15 +526,10 @@ static void *UE_thread_synch(void *arg) // openair0_cfg[0].rx_gain[0] -= 0; break; } -#ifndef EXMIMO + openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0); //openair0.trx_set_gains_func(&openair0,&openair0_cfg[0]); //openair0.trx_stop_func(0); -#else - openair0_set_frequencies(&openair0,&openair0_cfg[0],0); - openair0_set_gains(&openair0,&openair0_cfg[0]); - openair0_stop(0); -#endif sleep(1); init_frame_parms(&UE->lte_frame_parms,1); } @@ -550,13 +559,9 @@ static void *UE_thread_synch(void *arg) } -#ifndef EXMIMO + UE->slot_rx = 0; UE->slot_tx = 4; -#else - UE->slot_rx = 18; - UE->slot_tx = 2; -#endif } } else { // initial sync failed @@ -598,42 +603,13 @@ static void *UE_thread_synch(void *arg) for (i=0; irx_total_gain_dB;//-USRP_GAIN_OFFSET; -#if 0 - switch(UE->lte_frame_parms.N_RB_DL) { - case 6: - openair0_cfg[card].rx_gain[i] -= 12; - break; - - case 25: - openair0_cfg[card].rx_gain[i] -= 6; - break; - - case 50: - openair0_cfg[card].rx_gain[i] -= 0;//3; - break; - - case 100: - openair0_cfg[card].rx_gain[i] -= 0; - break; - - default: - printf("Unknown number of RBs %d\n",UE->lte_frame_parms.N_RB_DL); - break; - } -#endif -#endif } } if (UE->UE_scan_carrier==1) { @@ -690,17 +666,6 @@ static void *UE_thread_tx(void *arg) UE->instance_cnt_tx=-1; -#ifdef RTAI - RT_TASK *task = rt_task_init_schmod(nam2num("UE TX Thread"), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][UE] Problem starting UE TX thread!!!!\n"); - return 0; - } - - LOG_D(HW,"Started UE TX thread (id %p)\n",task); -#else - #ifdef LOWLATENCY struct sched_attr attr; unsigned int flags = 0; @@ -745,7 +710,7 @@ static void *UE_thread_tx(void *arg) exit_fun("Error setting processor affinity"); } } - #endif +#endif /* Check the actual affinity mask assigned to the thread */ @@ -790,7 +755,6 @@ static void *UE_thread_tx(void *arg) (int) sparam.sched_priority, cpu_affinity); -#endif #endif printf("waiting for sync (UE_thread_tx)\n"); @@ -909,17 +873,6 @@ static void *UE_thread_rx(void *arg) UE->instance_cnt_rx=-1; -#ifdef RTAI - RT_TASK *task = rt_task_init_schmod(nam2num("UE RX Thread"), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][UE] Problem starting UE RX thread!!!!\n"); - return &UE_thread_rx_retval; - } - - LOG_D(HW,"Started UE RX thread (id %p)\n",task); -#else - #ifdef LOWLATENCY struct sched_attr attr; unsigned int flags = 0; @@ -1008,7 +961,6 @@ static void *UE_thread_rx(void *arg) (int) sparam.sched_priority, cpu_affinity); -#endif #endif // Lock memory from swapping. This is a process wide call (not constraint to this thread). @@ -1186,7 +1138,7 @@ static void *UE_thread_rx(void *arg) -#ifndef EXMIMO + #define RX_OFF_MAX 10 #define RX_OFF_MIN 5 #define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2) @@ -1227,16 +1179,6 @@ void *UE_thread(void *arg) MessageDef *message_p; #endif -#ifdef RTAI - RT_TASK *task = rt_task_init_schmod(nam2num("UE thread"), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][UE] Problem starting UE thread!!!!\n"); - return 0; - } - -#else - #ifdef LOWLATENCY struct sched_attr attr; unsigned int flags = 0; @@ -1264,7 +1206,6 @@ void *UE_thread(void *arg) struct sched_param sp; sp.sched_priority = sched_get_priority_max(SCHED_FIFO); pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); -#endif #endif // Lock memory from swapping. This is a process wide call (not constraint to this thread). @@ -1591,410 +1532,9 @@ void *UE_thread(void *arg) return &UE_thread_retval; } -#endif -#ifdef EXMIMO -/* 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). */ -void *UE_thread(void *arg) -{ - PHY_VARS_UE *UE=PHY_vars_UE_g[0][0]; -#ifdef RTAI - RT_TASK *task; -#endif - // RTIME in, out, diff; - int slot=0,frame=0,hw_slot; - // unsigned int aa; - int delay_cnt; - RTIME time_in; - int /* hw_slot_offset=0, */ rx_offset_mbox=0,mbox_target=0,mbox_current=0; - int diff2; - int /* i, */ ret; - int /* CC_id, */ card; - volatile unsigned int *DAQ_MBOX = openair0_daq_cnt(); - - int wait_sync_cnt = 0; - int first_synch = 1; -#ifdef LOWLATENCY - struct sched_attr attr; - unsigned int flags = 0; - // unsigned long mask = 1; // processor 0 -#endif - int freq_offset; - - -#ifdef RTAI - task = rt_task_init_schmod(nam2num("UE thread"), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][UE] Problem starting UE thread!!!!\n"); - return 0; - } - -#endif - - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - -#ifdef LOWLATENCY - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - // This creates a .25 ms reservation - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = (0.1 * 100) * 10000; - attr.sched_deadline = (0.25 * 100) * 10000; - attr.sched_period = (0.5 * 100) * 10000; - - // pin the UE main thread to CPU0 - // if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) <0) { - // perror("[MAIN_ENB_THREAD] pthread_setaffinity_np failed\n"); - // } - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] main UE thread: sched_setattr failed\n"); - exit_fun("Nothing to add"); - } else { - LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n", - gettid(),sched_getcpu()); - } - -#endif - - - mlockall(MCL_CURRENT | MCL_FUTURE); - - printf("waiting for sync (UE_thread)\n"); - - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_thread)\n"); - - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); - - pthread_mutex_unlock(&sync_mutex); - printf("unlocked sync_mutex, waiting (UE_thread)\n"); - - printf("starting UE thread\n"); - - freq_offset = 0; //-7500; - - first_synch = 1; - - while (!oai_exit) { - - hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; //the slot the hw is about to store - - - if (UE->is_synchronized) { - - if (first_synch == 1) { - first_synch = 0; - - for (card=0; cardrx_offset * 150) / (10*UE->lte_frame_parms.samples_per_tti); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_RX_OFFSET, UE->rx_offset); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_OFFSET_MBOX, rx_offset_mbox); - //this is the mbox counter where we should be - mbox_target = (((((slot+1)%20)*15+1)>>1) + rx_offset_mbox + 1)%150; - // round up to the next multiple of two (mbox counter from express MIMO gives only even numbers) - mbox_target = ((mbox_target+1)-((mbox_target-1)%2))%150; - //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>=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 <(-7)) { - LOG_D(HW,"UE Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, slot, hw_slot, diff2); - - if (frame>0) { - if (exit_missed_slots==1) - exit_fun("[HW][UE] missed slot"); - else { - num_missed_slots++; - LOG_W(HW,"[UE] just missed slot (total missed slots %ld)\n", num_missed_slots); - } - } - - slot++; - - if (slot==20) { - slot=0; - frame++; - } - - // update thread slot/frame counters because of skipped slot - UE->slot_rx++; - UE->slot_tx++; - - if (UE->slot_rx == 20) { - UE->slot_rx = 0; - UE->frame_rx++; - } - - if (UE->slot_tx == 20) { - UE->slot_tx = 0; - UE->frame_tx++; - } - - continue; - } - - if (diff2>8) - LOG_D(HW,"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); - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff2); - - - - // This loop implements the delay of 1 slot to allow for processing - delay_cnt = 0; - - while ((diff2>0) && (!oai_exit) ) { - time_in = rt_get_time_ns(); - //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d (%d), diff %d, time %llu\n",frame,delay_cnt,hw_slot,((volatile unsigned int *)DAQ_MBOX)[0],slot,mbox_target,diff2,time_in); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1); - ret = rt_sleep_ns(diff2*DAQ_PERIOD); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX); - - if (ret) - LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in); - - hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - //LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns()); - delay_cnt++; - - if (delay_cnt == 30) { - LOG_D(HW,"UE frame %d: HW stopped ... \n",frame); - exit_fun("[HW][UE] HW stopped"); - } - - mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; - - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround - diff2 = 150-mbox_current+mbox_target; - else if ((mbox_current<15) && (mbox_target>=135)) - diff2 = -150+mbox_target-mbox_current; - else - diff2 = mbox_target - mbox_current; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff2); - } - - // on even slots, schedule processing of entire subframe - if ((slot&1) == 0) { - - if (pthread_mutex_lock(&UE->mutex_rx) != 0) { - LOG_E(PHY,"[SCHED][UE] error locking mutex for UE RX thread\n"); - exit_fun("nothing to add"); - } else { - - int instance_cnt_rx = ++UE->instance_cnt_rx; - - pthread_mutex_unlock(&UE->mutex_rx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, instance_cnt_rx); - - - if (instance_cnt_rx == 0) { - LOG_D(HW,"Scheduling UE RX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_rx,frame,slot>>1,UE->slot_rx>>1,UE->mode); - - if (pthread_cond_signal(&UE->cond_rx) != 0) { - LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n"); - exit_fun("nothing to add"); - } else { - // printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0); - } - - if (UE->mode == rx_calib_ue) { - if (frame == 10) { - LOG_D(PHY, - "[SCHED][UE] Found cell with N_RB_DL %d, PHICH CONFIG (%d,%d), Nid_cell %d, NB_ANTENNAS_TX %d, initial frequency offset %d Hz, frequency offset %d Hz, RSSI (digital) %d dB, measured Gain %d dB, total_rx_gain %d dB, USRP rx gain %f dB\n", - UE->lte_frame_parms.N_RB_DL, - UE->lte_frame_parms.phich_config_common.phich_duration, - UE->lte_frame_parms.phich_config_common.phich_resource, - UE->lte_frame_parms.Nid_cell, - UE->lte_frame_parms.nb_antennas_tx_eNB, - freq_offset, - UE->lte_ue_common_vars.freq_offset, - UE->PHY_measurements.rx_power_avg_dB[0], - UE->PHY_measurements.rx_power_avg_dB[0] - rx_input_level_dBm, - UE->rx_total_gain_dB, - openair0_cfg[0].rx_gain[0] - ); - exit_fun("[HW][UE] UE in RX calibration mode, exiting"); - } - } - } else { - LOG_E(PHY,"[SCHED][UE] UE RX thread busy!!\n"); - exit_fun("nothing to add"); - } - } - - if (pthread_mutex_lock(&UE->mutex_tx) != 0) { - LOG_E(PHY,"[SCHED][UE] error locking mutex for UE TX thread\n"); - exit_fun("nothing to add"); - } else { - - int instance_cnt_tx = ++UE->instance_cnt_tx; - - pthread_mutex_unlock(&UE->mutex_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX, instance_cnt_tx); - - if (instance_cnt_tx == 0) { - LOG_D(HW,"Scheduling UE TX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_tx,frame,slot>>1,UE->slot_tx>>1,UE->mode); - - if (pthread_cond_signal(&UE->cond_tx) != 0) { - LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE TX thread\n"); - exit_fun("nothing to add"); - } else { - // printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0); - } - } else { - LOG_E(PHY,"[SCHED][UE] UE TX thread busy!!\n"); - exit_fun("nothing to add"); - } - } - } - - /* - if ((slot%2000)<10) - LOG_D(HW,"fun0: doing very hard work\n"); - */ - // now increment slot and frame counters - slot++; - - if (slot==20) { - slot=0; - frame++; - } - } else if (UE->is_synchronized == 0) { // we are not yet synchronized - //hw_slot_offset = 0; - first_synch = 1; - slot = 0; - - - // wait until we can lock mutex_synch - //printf("Locking mutex_synch (UE_thread)\n"); - if (pthread_mutex_lock(&UE->mutex_synch) != 0) { - LOG_E(PHY,"[SCHED][UE] error locking mutex for UE initial synch thread\n"); - exit_fun("noting to add"); - } else { - - if (UE->instance_cnt_synch < 0) { - - wait_sync_cnt=0; - openair0_config(&openair0_cfg[0],1); - // openair0_set_gains(&openair0,&openair0_cfg[0]); - - printf("Getting frame\n"); - openair0_get_frame(0); - rt_sleep_ns(FRAME_PERIOD); - // increment instance count for sync thread - UE->instance_cnt_synch++; - pthread_mutex_unlock(&UE->mutex_synch); - - if (pthread_cond_signal(&UE->cond_synch) != 0) { - LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n"); - exit_fun("nothing to add"); - } - } else { - wait_sync_cnt++; - pthread_mutex_unlock(&UE->mutex_synch); - - if (wait_sync_cnt>1000) - exit_fun("waiting to long for synch thread"); - else - rt_sleep_ns(FRAME_PERIOD); - } - } - - - /* - if (initial_sync(UE,mode)==0) { - - if (mode == rx_calib_ue) { - exit_fun("[HW][UE] UE in RX calibration mode"); - } - else { - is_synchronized = 1; - //start the streaming DMA transfers - for (card=0;cardrx_offset<<1) / UE->lte_frame_parms.samples_per_tti; - } - } - else { - if (freq_offset >= 0) { - freq_offset += 100; - freq_offset *= -1; - } - else { - freq_offset *= -1; - } - if (abs(freq_offset) > 7500) { - LOG_I(PHY,"[initial_sync] No cell synchronization found, abondoning\n"); - mac_xface->macphy_exit("No cell synchronization found, abondoning"); - } - else { - // LOG_I(PHY,"[initial_sync] trying carrier off %d Hz\n",freq_offset); - #ifndef USRP - for (CC_id=0;CC_idinstance_cnt_tx = -1; UE->instance_cnt_rx = -1; @@ -2063,97 +1611,50 @@ void fill_ue_band_info(void) int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) { - //#ifndef EXMIMO - // uint16_t N_TA_offset = 0; - //#endif - int i, CC_id; LTE_DL_FRAME_PARMS *frame_parms; - + for (CC_id=0; CC_idlte_frame_parms); - } else { - printf("phy_vars_UE[%d] not initialized\n", CC_id); - return(-1); - } + if (phy_vars_ue[CC_id]) { + frame_parms = &(phy_vars_ue[CC_id]->lte_frame_parms); + } else { + printf("phy_vars_UE[%d] not initialized\n", CC_id); + return(-1); + } - //#ifndef EXMIMO - // if (frame_parms->frame_type == TDD) { - // if (frame_parms->N_RB_DL == 100) - // N_TA_offset = 624; - // else if (frame_parms->N_RB_DL == 50) - // N_TA_offset = 624/2; - // else if (frame_parms->N_RB_DL == 25) - // N_TA_offset = 624/4; - // } - //#endif - -#ifdef EXMIMO - openair0_cfg[CC_id].tx_num_channels = 0; - openair0_cfg[CC_id].rx_num_channels = 0; + if (frame_parms->frame_type == TDD) { + if (frame_parms->N_RB_DL == 100) + N_TA_offset = 624; + else if (frame_parms->N_RB_DL == 50) + N_TA_offset = 624/2; + else if (frame_parms->N_RB_DL == 25) + N_TA_offset = 624/4; + } + // replace RX signal buffers with mmaped HW versions - for (i=0; inb_antennas_rx; i++) { - printf("Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]); - phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i]; + rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) { - printf("Error with rf_map! A channel has already been allocated!\n"); - return(-1); - } else { - openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].rxg_mode[rf_map[CC_id].chain+i] = rx_gain_mode[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].rx_num_channels++; - } - - printf("rxdata[%d] @ %p\n",i,phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]); - } - - for (i=0; inb_antennas_tx; i++) { - printf("Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]); - phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i]; - - if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) { - printf("Error with rf_map! A channel has already been allocated!\n"); - return(-1); - } else { - openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].tx_num_channels++; - } - - printf("txdata[%d] @ %p\n",i,phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]); - } - -#else - // replace RX signal buffers with mmaped HW versions - rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - printf( "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); - free( phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] ); - rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); - phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD - } - - for (i=0; inb_antennas_tx; i++) { - printf( "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); - free( phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] ); - txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); - phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = txdata[i]; - } - - // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[x] - // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[x] - // be careful when releasing memory! - // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes) -#endif + for (i=0; inb_antennas_rx; i++) { + printf( "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); + free( phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] ); + rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); + phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD + } + + for (i=0; inb_antennas_tx; i++) { + printf( "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); + free( phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] ); + txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); + phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = txdata[i]; + } + + // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[x] + // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[x] + // be careful when releasing memory! + // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes) } diff --git a/targets/RT/USER/sched_dlsch.c b/targets/RT/USER/sched_dlsch.c deleted file mode 100644 index 48fac642a9..0000000000 --- a/targets/RT/USER/sched_dlsch.c +++ /dev/null @@ -1,354 +0,0 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ - -/*! \file sched_dlsch.c -* \brief DLSCH decoding thread (RTAI) -* \author R. Knopp, F. Kaltenberger -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr -* \note -* \warning -*/ -#include -#include -#include - -#include "rt_wrapper.h" - -#include - -#include "PHY/types.h" -#include "PHY/defs.h" -#include "PHY/extern.h" - -#include "SCHED/defs.h" - -#include "UTIL/LOG/vcd_signal_dumper.h" - -#define DEBUG_PHY - -/// Mutex for instance count on dlsch scheduling -pthread_mutex_t dlsch_mutex[8]; -/// Condition variable for dlsch thread -pthread_cond_t dlsch_cond[8]; - -pthread_t dlsch_threads[8]; -pthread_attr_t attr_dlsch_threads; -unsigned char dlsch_thread_indices[8]; - -// activity indicators for harq_pid's -int dlsch_instance_cnt[8]; -// process ids for cpu -int dlsch_cpuid[8]; -// subframe number for each harq_pid (needed to store ack in right place for UL) -int dlsch_subframe[8]; - -extern int oai_exit; - -/* -extern int dlsch_errors; -extern int dlsch_received; -extern int dlsch_errors_last; -extern int dlsch_received_last; -extern int dlsch_fer; -extern int current_dlsch_cqi; -*/ - -/** DLSCH Decoding Thread */ -static void * dlsch_thread(void *param) -{ - - //unsigned long cpuid; - unsigned char dlsch_thread_index = *((unsigned char *)param); - unsigned int ret=0; - uint8_t harq_pid; - - -#ifdef RTAI - RT_TASK *task; - char task_name[8]; -#endif - - int eNB_id = 0, UE_id = 0, CC_id=0; - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[UE_id][CC_id]; - - if ((dlsch_thread_index <0) || (dlsch_thread_index>7)) { - LOG_E(PHY,"[SCHED][DLSCH] Illegal dlsch_thread_index %d (%p)!!!!\n",dlsch_thread_index,param); - return 0; - } - -#ifdef RTAI - sprintf(task_name,"DLSCH%d",dlsch_thread_index); - task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][DLSCH] Problem starting dlsch_thread_index %d (%s)!!!!\n",dlsch_thread_index,task_name); - return 0; - } else { - LOG_I(PHY,"[SCHED][DLSCH] dlsch_thread for process %d started with id %p\n", - dlsch_thread_index, - task); - } - -#endif - - mlockall(MCL_CURRENT | MCL_FUTURE); - - //rt_set_runnable_on_cpuid(task,1); - //cpuid = rtai_cpuid(); - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - //dlsch_cpuid[dlsch_thread_index] = cpuid; - - while (!oai_exit) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD0+dlsch_thread_index,0); - - if (pthread_mutex_lock(&dlsch_mutex[dlsch_thread_index]) != 0) { - LOG_E(PHY,"[SCHED][DLSCH] error locking mutex.\n"); - } else { - - while (dlsch_instance_cnt[dlsch_thread_index] < 0) { - pthread_cond_wait(&dlsch_cond[dlsch_thread_index],&dlsch_mutex[dlsch_thread_index]); - } - - if (pthread_mutex_unlock(&dlsch_mutex[dlsch_thread_index]) != 0) { - LOG_E(PHY,"[SCHED][DLSCH] error unlocking mutex.\n"); - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD0+dlsch_thread_index,1); - - if (oai_exit) break; - - LOG_I(PHY,"[SCHED][DLSCH] Frame %d: Calling dlsch_decoding with dlsch_thread_index = %d\n",phy_vars_ue->frame_rx,dlsch_thread_index); - - - - if (phy_vars_ue->frame_rx < phy_vars_ue->dlsch_errors[eNB_id]) { - phy_vars_ue->dlsch_errors[eNB_id]=0; - phy_vars_ue->dlsch_received[eNB_id] = 0; - } - - harq_pid = dlsch_thread_index; - - if (phy_vars_ue->dlsch_ue[eNB_id][0]) { - - // rt_printk("[SCHED][DLSCH] Frame %d, slot %d, start %llu, end %llu, proc time: %llu ns\n",phy_vars_ue->frame,last_slot,time0,time1,(time1-time0)); - - dlsch_unscrambling(&phy_vars_ue->lte_frame_parms, - 0, - phy_vars_ue->dlsch_ue[eNB_id][0], - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->G, - phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->llr[0], - 0, - dlsch_subframe[dlsch_thread_index]<<1); - - LOG_I(PHY,"[UE %d] PDSCH Calling dlsch_decoding for subframe %d, harq_pid %d, G%d\n", phy_vars_ue->Mod_id,dlsch_subframe[dlsch_thread_index], harq_pid, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->G); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0+dlsch_thread_index,1); - ret = dlsch_decoding(phy_vars_ue, - phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->llr[0], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue[eNB_id][0], - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid], - dlsch_subframe[dlsch_thread_index], - harq_pid, - 1, // is_crnti - 0); // llr8_flag - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0+dlsch_thread_index,0); - - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)\n", - phy_vars_ue->Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti,harq_pid, - phy_vars_ue->frame_rx,dlsch_subframe[dlsch_thread_index],ret, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); - - - if (ret == (1+MAX_TURBO_ITERATIONS)) { - phy_vars_ue->dlsch_errors[eNB_id]++; - -#ifdef DEBUG_PHY - LOG_I(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d)\n", - phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, - harq_pid,phy_vars_ue->frame_rx,dlsch_subframe[dlsch_thread_index], - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs); -#endif - } else { - LOG_I(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: Received DLSCH (rv %d,mcs %d)\n", - phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, - harq_pid,phy_vars_ue->frame_rx,dlsch_subframe[dlsch_thread_index], - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs); - -#ifdef OPENAIR2 - mac_xface->ue_send_sdu(phy_vars_ue->Mod_id, - 0, // CC_id - phy_vars_ue->frame_rx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->b, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS>>3, - eNB_id); -#endif - phy_vars_ue->total_TBS[eNB_id] = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS + phy_vars_ue->total_TBS[eNB_id]; - phy_vars_ue->total_received_bits[eNB_id] = phy_vars_ue->total_received_bits[eNB_id] + phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS; - } - } - - // this is done in main thread - /* - if (phy_vars_ue->frame % 100 == 0) { - if ((phy_vars_ue->dlsch_received[eNB_id] - phy_vars_ue->dlsch_received_last[eNB_id]) != 0) - phy_vars_ue->dlsch_fer[eNB_id] = (100*(phy_vars_ue->dlsch_errors[eNB_id] - phy_vars_ue->dlsch_errors_last[eNB_id]))/(phy_vars_ue->dlsch_received[eNB_id] - phy_vars_ue->dlsch_received_last[eNB_id]); - phy_vars_ue->dlsch_errors_last[eNB_id] = phy_vars_ue->dlsch_errors[eNB_id]; - phy_vars_ue->dlsch_received_last[eNB_id] = phy_vars_ue->dlsch_received[eNB_id]; - } - */ - - -#ifdef DEBUG_PHY - - if (phy_vars_ue->dlsch_ue[eNB_id][0]) { - LOG_I(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)\n", - phy_vars_ue->Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti,harq_pid, - phy_vars_ue->frame_rx,dlsch_subframe[dlsch_thread_index],ret, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); - - if (phy_vars_ue->frame_rx%100==0) { - LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d dlsch_errors %d, dlsch_received %d, dlsch_fer %d, current_dlsch_cqi %d\n", - phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, - phy_vars_ue->frame_rx,dlsch_subframe[dlsch_thread_index], - phy_vars_ue->dlsch_errors[eNB_id], - phy_vars_ue->dlsch_received[eNB_id], - phy_vars_ue->dlsch_fer[eNB_id], - phy_vars_ue->PHY_measurements.wideband_cqi_tot[eNB_id]); - } - } else { - LOG_I( PHY,"[UE %d][PDSCH ?/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (phy_vars_ue->dlsch_ue[eNB_id][0] == 0)\n", - phy_vars_ue->Mod_id, - harq_pid, - phy_vars_ue->frame_rx, dlsch_subframe[dlsch_thread_index], ret ); - } - -#endif - - if (pthread_mutex_lock(&dlsch_mutex[dlsch_thread_index]) != 0) { - msg("[openair][SCHED][DLSCH] error locking mutex.\n"); - } else { - dlsch_instance_cnt[dlsch_thread_index]--; - - if (pthread_mutex_unlock(&dlsch_mutex[dlsch_thread_index]) != 0) { - msg("[openair][SCHED][DLSCH] error unlocking mutex.\n"); - } - } - - } - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - - msg("[openair][SCHED][DLSCH] DLSCH thread %d exiting\n",dlsch_thread_index); - - return 0; -} - -int init_dlsch_threads(void) -{ - - int error_code; - struct sched_param p; - unsigned char dlsch_thread_index; - - pthread_attr_init (&attr_dlsch_threads); - pthread_attr_setstacksize(&attr_dlsch_threads,OPENAIR_THREAD_STACK_SIZE); - //attr_dlsch_threads.priority = 1; - - p.sched_priority = OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&attr_dlsch_threads, &p); -#ifndef RTAI_ISNT_POSIX - pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO); -#endif - - for(dlsch_thread_index=0; dlsch_thread_index<8; dlsch_thread_index++) { - - pthread_mutex_init(&dlsch_mutex[dlsch_thread_index],NULL); - pthread_cond_init(&dlsch_cond[dlsch_thread_index],NULL); - - dlsch_instance_cnt[dlsch_thread_index] = -1; - dlsch_thread_indices[dlsch_thread_index] = dlsch_thread_index; - rt_printk("[openair][SCHED][DLSCH][INIT] Allocating DLSCH thread for dlsch_thread_index %d (%p)\n",dlsch_thread_index,&dlsch_thread_indices[dlsch_thread_index]); - error_code = pthread_create(&dlsch_threads[dlsch_thread_index], - &attr_dlsch_threads, - dlsch_thread, - (void *)&dlsch_thread_indices[dlsch_thread_index]); - - if (error_code!= 0) { - rt_printk("[openair][SCHED][DLSCH][INIT] Could not allocate dlsch_thread %d, error %d\n",dlsch_thread_index,error_code); - return(error_code); - } else { - rt_printk("[openair][SCHED][DLSCH][INIT] Allocate dlsch_thread %d successful\n",dlsch_thread_index); - } - } - - return(0); -} - -void cleanup_dlsch_threads(void) -{ - - unsigned char dlsch_thread_index; - - for(dlsch_thread_index=0; dlsch_thread_index<8; dlsch_thread_index++) { - // pthread_exit(&dlsch_threads[dlsch_thread_index]); - rt_printk("[openair][SCHED][DLSCH] Scheduling dlsch_thread %d to exit\n",dlsch_thread_index); - - dlsch_instance_cnt[dlsch_thread_index] = 0; - - if (pthread_cond_signal(&dlsch_cond[dlsch_thread_index]) != 0) - rt_printk("[openair][SCHED][DLSCH] ERROR pthread_cond_signal\n"); - else - rt_printk("[openair][SCHED][DLSCH] Signalled dlsch_thread %d to exit\n",dlsch_thread_index); - - rt_printk("[openair][SCHED][DLSCH] Exiting ...\n"); - pthread_cond_destroy(&dlsch_cond[dlsch_thread_index]); - pthread_mutex_destroy(&dlsch_mutex[dlsch_thread_index]); - } -} diff --git a/targets/RT/USER/sched_rx_pdsch.c b/targets/RT/USER/sched_rx_pdsch.c deleted file mode 100644 index e792fe737d..0000000000 --- a/targets/RT/USER/sched_rx_pdsch.c +++ /dev/null @@ -1,321 +0,0 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ - -/*! \file sched_dlsch.c -* \brief DLSCH decoding thread (RTAI) -* \author R. Knopp, F. Kaltenberger -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr -* \note -* \warning -*/ -#include -#include -#include - -#include "rt_wrapper.h" - -#include - -#include "PHY/types.h" -#include "PHY/defs.h" -#include "PHY/extern.h" -#include "SCHED/defs.h" -#include "SCHED/extern.h" - -#include "UTIL/LOG/vcd_signal_dumper.h" - -RTIME time0,time1; - -#define DEBUG_PHY - -/// Mutex for instance count on rx_pdsch scheduling -pthread_mutex_t rx_pdsch_mutex; -/// Condition variable for rx_pdsch thread -pthread_cond_t rx_pdsch_cond; - -pthread_t rx_pdsch_thread_var; -pthread_attr_t attr_rx_pdsch_thread; - -// activity indicators for harq_pid's -int rx_pdsch_instance_cnt; -// process ids for cpu -int rx_pdsch_cpuid; -// subframe number for each harq_pid (needed to store ack in right place for UL) -int rx_pdsch_slot; - -extern int oai_exit; -extern pthread_mutex_t dlsch_mutex[8]; -extern int dlsch_instance_cnt[8]; -extern int dlsch_subframe[8]; -extern pthread_cond_t dlsch_cond[8]; - -/** RX_PDSCH Decoding Thread */ -static void * rx_pdsch_thread(void *param) -{ - - //unsigned long cpuid; - uint8_t dlsch_thread_index = 0; - uint8_t pilot2,harq_pid,subframe; - // uint8_t last_slot; - - uint8_t dual_stream_UE = 0; - uint8_t i_mod = 0; - - -#ifdef RTAI - RT_TASK *task; -#endif - - int m,eNB_id = 0; - int eNB_id_i = 1; - PHY_VARS_UE *UE = PHY_vars_UE_g[0][0]; - -#ifdef RTAI - task = rt_task_init_schmod(nam2num("RX_PDSCH_THREAD"), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][RX_PDSCH] Problem starting rx_pdsch thread!!!!\n"); - return 0; - } else { - LOG_I(PHY,"[SCHED][RX_PDSCH] rx_pdsch_thread started for with id %p\n",task); - } - -#endif - - mlockall(MCL_CURRENT | MCL_FUTURE); - - //rt_set_runnable_on_cpuid(task,1); - //cpuid = rtai_cpuid(); - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - if (UE->lte_frame_parms.Ncp == NORMAL) { // normal prefix - pilot2 = 7; - } else { // extended prefix - pilot2 = 6; - } - - - while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD, 0); - - if (pthread_mutex_lock(&rx_pdsch_mutex) != 0) { - LOG_E(PHY,"[SCHED][RX_PDSCH] error locking mutex.\n"); - } else { - while (rx_pdsch_instance_cnt < 0) { - pthread_cond_wait(&rx_pdsch_cond,&rx_pdsch_mutex); - } - - if (pthread_mutex_unlock(&rx_pdsch_mutex) != 0) { - LOG_E(PHY,"[SCHED][RX_PDSCH] error unlocking mutex.\n"); - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD, 1); - - // last_slot = rx_pdsch_slot; - subframe = UE->slot_rx>>1; - // Important! assumption that PDCCH procedure of next SF is not called yet - harq_pid = UE->dlsch_ue[eNB_id][0]->current_harq_pid; - UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->G = get_G(&UE->lte_frame_parms, - UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->nb_rb, - UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, - get_Qm(UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs), - UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Nl, - UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, - UE->frame_rx,subframe); - - if ((UE->transmission_mode[eNB_id] == 5) && - (UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (openair_daq_vars.use_ia_receiver > 0)) { - dual_stream_UE = 1; - eNB_id_i = UE->n_connected_eNB; - - if (openair_daq_vars.use_ia_receiver == 2) { - i_mod = get_Qm(((UE->frame_rx%1024)/3)%28); - } else { - i_mod = get_Qm(UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs); - } - } else { - dual_stream_UE = 0; - eNB_id_i = eNB_id+1; - i_mod = 0; - } - - if (oai_exit) break; - - LOG_D(PHY,"[SCHED][RX_PDSCH] Frame %d, slot %d: Calling rx_pdsch_decoding with harq_pid %d\n",UE->frame_rx,UE->slot_rx,harq_pid); - - - // Check if we are in even or odd slot - if (UE->slot_rx%2) { // odd slots - - // measure time - //time0 = rt_get_time_ns(); - // rt_printk("[SCHED][RX_PDSCH][before rx_pdsch] Frame %d, slot %d, time %llu\n",UE->frame,last_slot,rt_get_time_ns()); - for (m=pilot2; mlte_frame_parms.symbols_per_tti; m++) { - - rx_pdsch(UE, - PDSCH, - eNB_id, - eNB_id_i, - subframe, - m, - 0, - dual_stream_UE, - i_mod, - harq_pid); - - } - - // time1 = rt_get_time_ns(); - // rt_printk("[SCHED][RX_PDSCH] Frame %d, slot %d, start %llu, end %llu, proc time: %llu ns\n",UE->frame_rx,last_slot,time0,time1,(time1-time0)); - - dlsch_thread_index = harq_pid; - - if (pthread_mutex_lock (&dlsch_mutex[dlsch_thread_index]) != 0) { // Signal MAC_PHY Scheduler - LOG_E(PHY,"[UE %d] ERROR pthread_mutex_lock\n",UE->Mod_id); // lock before accessing shared resource - // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - //return(-1); - } - - dlsch_instance_cnt[dlsch_thread_index]++; - dlsch_subframe[dlsch_thread_index] = subframe; - pthread_mutex_unlock (&dlsch_mutex[dlsch_thread_index]); - - if (dlsch_instance_cnt[dlsch_thread_index] == 0) { - if (pthread_cond_signal(&dlsch_cond[dlsch_thread_index]) != 0) { - LOG_E(PHY,"[UE %d] ERROR pthread_cond_signal for dlsch_cond[%d]\n",UE->Mod_id,dlsch_thread_index); - // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - //return(-1); - } - } else { - LOG_W(PHY,"[UE %d] DLSCH thread for dlsch_thread_index %d busy!!!\n",UE->Mod_id,dlsch_thread_index); - // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - //return(-1); - } - - } else { // even slots - - for (m=UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols; mlte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag - dual_stream_UE, - i_mod, - harq_pid); - } - } - - - if (pthread_mutex_lock(&rx_pdsch_mutex) != 0) { - msg("[openair][SCHED][RX_PDSCH] error locking mutex.\n"); - } else { - rx_pdsch_instance_cnt--; - - if (pthread_mutex_unlock(&rx_pdsch_mutex) != 0) { - msg("[openair][SCHED][RX_PDSCH] error unlocking mutex.\n"); - } - } - - } - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - - LOG_D(PHY,"[openair][SCHED][RX_PDSCH] RX_PDSCH thread exiting\n"); - - return 0; -} - -int init_rx_pdsch_thread(void) -{ - - int error_code; - struct sched_param p; - - pthread_mutex_init(&rx_pdsch_mutex,NULL); - - pthread_cond_init(&rx_pdsch_cond,NULL); - - pthread_attr_init (&attr_rx_pdsch_thread); - pthread_attr_setstacksize(&attr_rx_pdsch_thread,OPENAIR_THREAD_STACK_SIZE); - - //attr_rx_pdsch_thread.priority = 1; - - p.sched_priority = OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&attr_rx_pdsch_thread, &p); -#ifndef RTAI_ISNT_POSIX - pthread_attr_setschedpolicy (&attr_rx_pdsch_thread, SCHED_FIFO); -#endif - - rx_pdsch_instance_cnt = -1; - rt_printk("[openair][SCHED][RX_PDSCH][INIT] Allocating RX_PDSCH thread\n"); - error_code = pthread_create(&rx_pdsch_thread_var, - &attr_rx_pdsch_thread, - rx_pdsch_thread, - 0); - - if (error_code!= 0) { - rt_printk("[openair][SCHED][RX_PDSCH][INIT] Could not allocate rx_pdsch_thread, error %d\n",error_code); - return(error_code); - } else { - rt_printk("[openair][SCHED][RX_PDSCH][INIT] Allocate rx_pdsch_thread successful\n"); - return(0); - } - -} - -void cleanup_rx_pdsch_thread(void) -{ - - rt_printk("[openair][SCHED][RX_PDSCH] Scheduling rx_pdsch_thread to exit\n"); - - rx_pdsch_instance_cnt = 0; - - if (pthread_cond_signal(&rx_pdsch_cond) != 0) - rt_printk("[openair][SCHED][RX_PDSCH] ERROR pthread_cond_signal\n"); - else - rt_printk("[openair][SCHED][RX_PDSCH] Signalled rx_pdsch_thread to exit\n"); - - rt_printk("[openair][SCHED][RX_PDSCH] Exiting ...\n"); - pthread_cond_destroy(&rx_pdsch_cond); - pthread_mutex_destroy(&rx_pdsch_mutex); -} diff --git a/targets/RT/USER/sched_ulsch.c b/targets/RT/USER/sched_ulsch.c deleted file mode 100644 index 3ab0c312f5..0000000000 --- a/targets/RT/USER/sched_ulsch.c +++ /dev/null @@ -1,255 +0,0 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ - -/*! \file sched_ulsch.c -* \brief ULSCH decoding thread (RTAI) -* \author R. Knopp, F. Kaltenberger -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr -* \note -* \warning -*/ -#include -#include -#include - -#include "rt_wrapper.h" - -#include - -#include "PHY/types.h" -#include "PHY/defs.h" -#include "PHY/extern.h" - -#include "SCHED/defs.h" - -#include "MAC_INTERFACE/extern.h" - -#ifdef CBMIMO1 -#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h" -#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h" -#include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h" -#endif // CBMIMO1 - - - -#define DEBUG_PHY - -/// Mutex for instance count on ulsch scheduling -pthread_mutex_t ulsch_mutex[NUMBER_OF_UE_MAX]; -/// Condition variable for ulsch thread -pthread_cond_t ulsch_cond[NUMBER_OF_UE_MAX]; - -pthread_t ulsch_threads[NUMBER_OF_UE_MAX]; -pthread_attr_t attr_ulsch_threads; - -// activity indicators for harq_pid's -int ulsch_instance_cnt[NUMBER_OF_UE_MAX]; -// process ids for cpu -int ulsch_cpuid[NUMBER_OF_UE_MAX]; -// subframe number for each harq_pid (needed to store ack in right place for UL) -int ulsch_subframe[NUMBER_OF_UE_MAX]; - -extern int oai_exit; - -/* -extern int ulsch_errors; -extern int ulsch_received; -extern int ulsch_errors_last; -extern int ulsch_received_last; -extern int ulsch_fer; -extern int current_ulsch_cqi; -*/ - -/** ULSCH Decoding Thread */ -static void * ulsch_thread(void *param) -{ - - //unsigned long cpuid; - unsigned int ulsch_thread_index = (unsigned int)param; - - RTIME time_in,time_out; -#ifdef RTAI - RT_TASK *task; - char ulsch_thread_name[64]; -#endif - - int eNB_id = 0, UE_id = 0; - PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[eNB_id]; - - if ((ulsch_thread_index <0) || (ulsch_thread_index>NUMBER_OF_UE_MAX)) { - LOG_E(PHY,"[SCHED][ULSCH] Illegal ulsch_thread_index %d!!!!\n",ulsch_thread_index); - return 0; - } - -#ifdef RTAI - sprintf(ulsch_thread_name,"ULSCH_THREAD%d",ulsch_thread_index); - - LOG_I(PHY,"[SCHED][ULSCH] starting ulsch_thread %s for process %d\n", - ulsch_thread_name, - ulsch_thread_index); - - task = rt_task_init_schmod(nam2num(ulsch_thread_name), 0, 0, 0, SCHED_FIFO, 0xF); - - if (task==NULL) { - LOG_E(PHY,"[SCHED][ULSCH] Problem starting ulsch_thread_index %d!!!!\n",ulsch_thread_index); - return 0; - } else { - LOG_I(PHY,"[SCHED][ULSCH] ulsch_thread for process %d started with id %p\n", - ulsch_thread_index, - task); - } - -#endif - - mlockall(MCL_CURRENT | MCL_FUTURE); - - //rt_set_runnable_on_cpuid(task,1); - //cpuid = rtai_cpuid(); - -#ifdef HARD_RT - rt_make_hard_real_time(); -#endif - - //ulsch_cpuid[ulsch_thread_index] = cpuid; - - while (!oai_exit) { - - if (pthread_mutex_lock(&ulsch_mutex[ulsch_thread_index]) != 0) { - LOG_E(PHY,"[SCHED][ULSCH] error locking mutex.\n"); - } else { - - while (ulsch_instance_cnt[ulsch_thread_index] < 0) { - pthread_cond_wait(&ulsch_cond[ulsch_thread_index],&ulsch_mutex[ulsch_thread_index]); - } - - if (pthread_mutex_unlock(&ulsch_mutex[ulsch_thread_index]) != 0) { - LOG_E(PHY,"[SCHED][ULSCH] error unlocking mutex.\n"); - } - } - - if (oai_exit) break; - - LOG_D(PHY,"[SCHED][ULSCH] Frame %d: Calling ulsch_decoding with ulsch_thread_index = %d\n",phy_vars_eNB->proc[0].frame_tx,ulsch_thread_index); - - time_in = rt_get_time_ns(); - - ulsch_decoding_procedures(ulsch_subframe[ulsch_thread_index]<<1,ulsch_thread_index,phy_vars_eNB,0); - - time_out = rt_get_time_ns(); - - if (pthread_mutex_lock(&ulsch_mutex[ulsch_thread_index]) != 0) { - msg("[openair][SCHED][ULSCH] error locking mutex.\n"); - } else { - ulsch_instance_cnt[ulsch_thread_index]--; - - if (pthread_mutex_unlock(&ulsch_mutex[ulsch_thread_index]) != 0) { - msg("[openair][SCHED][ULSCH] error unlocking mutex.\n"); - } - } - } - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - - msg("[openair][SCHED][ULSCH] ULSCH thread %d exiting\n",ulsch_thread_index); - - return 0; -} - -int init_ulsch_threads(void) -{ - - int error_code, return_code=0; - struct sched_param p; - int ulsch_thread_index; - - // later loop on all harq_pids, do 0 for now - for (ulsch_thread_index=0; ulsch_thread_index Date: Fri, 13 May 2016 02:15:09 -0700 Subject: [PATCH 006/206] RRCConnectionSetupComplete-Timer --- cmake_targets/CMakeLists.txt | 2 +- openair1/PHY/CODING/3gpplte_sse.c | 2 +- openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c | 1 + openair2/RRC/LITE/rrc_common.c | 4 ++-- openair2/RRC/LITE/rrc_eNB.c | 8 +++++++- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index b50c017a92..611ce31e54 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -138,7 +138,7 @@ else (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mavx2") endif() if (CPUINFO MATCHES "sse4_1") - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1") + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1 -mavx2") endif() if (CPUINFO MATCHES "ssse3") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mssse3") diff --git a/openair1/PHY/CODING/3gpplte_sse.c b/openair1/PHY/CODING/3gpplte_sse.c index 50c084d2a8..6806967921 100755 --- a/openair1/PHY/CODING/3gpplte_sse.c +++ b/openair1/PHY/CODING/3gpplte_sse.c @@ -52,7 +52,7 @@ #define print_bytes2(s,x) printf("%s %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7],(x)[8],(x)[9],(x)[10],(x)[11],(x)[12],(x)[13],(x)[14],(x)[15],(x)[16],(x)[17],(x)[18],(x)[19],(x)[20],(x)[21],(x)[22],(x)[23],(x)[24],(x)[25],(x)[26],(x)[27],(x)[28],(x)[29],(x)[30],(x)[31]) //#define DEBUG_TURBO_ENCODER 1 -#define CALLGRIND 1 +//#define CALLGRIND 1 unsigned short threegpplte_interleaver_output; unsigned long long threegpplte_interleaver_tmp; diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c index b70b1aee95..f5be10ae39 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c @@ -44,6 +44,7 @@ /// /// +#undef __AVX2__ #include "PHY/sse_intrin.h" #ifndef TEST_DEBUG diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c index bd77c8463a..2092317647 100644 --- a/openair2/RRC/LITE/rrc_common.c +++ b/openair2/RRC/LITE/rrc_common.c @@ -536,8 +536,8 @@ rrc_rx_tx( } if (ue_context_p->ue_context.ue_release_timer>0) { ue_context_p->ue_context.ue_release_timer++; - if (ue_context_p->ue_context.ue_release_timer >= 100) { - // remove UE after 10 frames after RRCConnectionRelease is triggered + if (ue_context_p->ue_context.ue_release_timer >= + ue_context_p->ue_context.ue_release_timer_thres) { LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti); ue_to_be_removed = ue_context_p; break; diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index e67f0af0d3..0d7c8f915e 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -1094,7 +1094,8 @@ rrc_eNB_generate_RRCConnectionRelease( size = do_RRCConnectionRelease(ctxt_pP->module_id, buffer,rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id)); // set release timer ue_context_pP->ue_context.ue_release_timer=1; - + // remove UE after 10 frames after RRCConnectionRelease is triggered + ue_context_pP->ue_context.ue_release_timer_thres=100; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCConnectionRelease (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), @@ -3385,6 +3386,10 @@ rrc_eNB_generate_RRCConnectionSetup( PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); + // activate release timer, if RRCSetupComplete not received after 10 frames, remove UE + ue_context_pP->ue_context.ue_release_timer=1; + // remove UE after 10 frames after RRCConnectionRelease is triggered + ue_context_pP->ue_context.ue_release_timer_thres=100; } #if defined(ENABLE_ITTI) @@ -4132,6 +4137,7 @@ rrc_eNB_decode_dcch( } } + ue_context_p->ue_context.ue_release_timer=0; break; case UL_DCCH_MessageType__c1_PR_securityModeComplete: From 475f1f8937f343ecdf5c4b324b5b6fc0a108fad6 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 15 May 2016 02:07:06 -0700 Subject: [PATCH 007/206] removed -mavx2 from CMakelists.txt for non AVX2 targets --- cmake_targets/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 611ce31e54..b50c017a92 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -138,7 +138,7 @@ else (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mavx2") endif() if (CPUINFO MATCHES "sse4_1") - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1 -mavx2") + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1") endif() if (CPUINFO MATCHES "ssse3") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mssse3") From d3d423f51ebbe94affbb3999aa30313781c839d3 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 15 May 2016 14:10:04 -0700 Subject: [PATCH 008/206] split phy_procedures_eNB_TX into sub-modules for better understanding. No functional differences. --- openair1/PHY/LTE_TRANSPORT/defs.h | 4 +- openair1/PHY/LTE_TRANSPORT/prach.c | 2 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 4 +- openair1/PHY/TOOLS/lte_phy_scope.c | 4 +- openair1/PHY/TOOLS/lte_phy_scope.h | 1 - openair1/PHY/defs.h | 14 + openair1/SCHED/defs.h | 3 +- openair1/SCHED/extern.h | 1 - openair1/SCHED/phy_mac_stub.c | 66 +- openair1/SCHED/phy_procedures_lte_eNb.c | 2743 ++++++++++----------- openair1/SCHED/phy_procedures_lte_ue.c | 71 +- openair1/SCHED/vars.h | 1 - openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 10 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 8 +- openair2/LAYER2/MAC/pre_processor.c | 2 +- targets/RT/USER/lte-softmodem.c | 49 +- targets/RT/USER/lte-ue.c | 4 +- targets/SIMU/USER/oaisim.c | 2 +- targets/SIMU/USER/oaisim_functions.c | 21 +- 19 files changed, 1440 insertions(+), 1570 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index 43bc7e3515..a8ebb99c8a 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -726,7 +726,9 @@ typedef enum {format0, format2B, format2C, format2D, - format3 + format3, + format3A, + format4 } DCI_format_t; typedef enum { diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index b93519d393..5e58b13737 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -638,7 +638,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra prach_start = ((subframe*phy_vars_ue->lte_frame_parms.samples_per_tti)<<1)-phy_vars_ue->N_TA_offset; #else #if defined(EXMIMO) || defined(OAI_USRP) - prach_start = (phy_vars_ue->rx_offset+subframe*phy_vars_ue->lte_frame_parms.samples_per_tti-openair_daq_vars.timing_advance-phy_vars_ue->N_TA_offset); + prach_start = (phy_vars_ue->rx_offset+subframe*phy_vars_ue->lte_frame_parms.samples_per_tti-phy_vars_ue->hw_timing_advance-phy_vars_ue->N_TA_offset); if (prach_start<0) prach_start+=(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 7445fca40f..16cc75b290 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -102,7 +102,7 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t len += sprintf(&buffer[len], "[UE PROC] RX Gain %d dB\n",phy_vars_ue->rx_total_gain_dB); #endif #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - len += sprintf(&buffer[len], "[UE_PROC] Frequency offset %d Hz (%d), estimated carrier frequency %f Hz\n",phy_vars_ue->lte_ue_common_vars.freq_offset,openair_daq_vars.freq_offset,openair0_cfg[0].rx_freq[0]-phy_vars_ue->lte_ue_common_vars.freq_offset); + len += sprintf(&buffer[len], "[UE_PROC] Frequency offset %d Hz, estimated carrier frequency %f Hz\n",phy_vars_ue->lte_ue_common_vars.freq_offset,openair0_cfg[0].rx_freq[0]-phy_vars_ue->lte_ue_common_vars.freq_offset); #endif len += sprintf(&buffer[len], "[UE PROC] UE mode = %s (%d)\n",mode_string[phy_vars_ue->UE_mode[0]],phy_vars_ue->UE_mode[0]); len += sprintf(&buffer[len], "[UE PROC] timing_advance = %d\n",phy_vars_ue->timing_advance); @@ -529,7 +529,7 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t #endif len += sprintf(&buffer[len], "[UE PROC] DLSCH Bitrate %dkbps\n",(phy_vars_ue->bitrate[0]/1000)); len += sprintf(&buffer[len], "[UE PROC] Total Received Bits %dkbits\n",(phy_vars_ue->total_received_bits[0]/1000)); - len += sprintf(&buffer[len], "[UE PROC] IA receiver %d\n",openair_daq_vars.use_ia_receiver); + len += sprintf(&buffer[len], "[UE PROC] IA receiver %d\n",phy_vars_ue->use_ia_receiver); } diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 4b623fb9dc..468aae8052 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -47,11 +47,11 @@ static void ia_receiver_on_off( FL_OBJECT *button, long arg) if (fl_get_button(button)) { fl_set_object_label(button, "IA Receiver ON"); - openair_daq_vars.use_ia_receiver = 1; + // 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"); - openair_daq_vars.use_ia_receiver = 0; + // PHY_vars_UE_g[0][0]->use_ia_receiver = 0; fl_set_object_color(button, FL_RED, FL_RED); } } diff --git a/openair1/PHY/TOOLS/lte_phy_scope.h b/openair1/PHY/TOOLS/lte_phy_scope.h index 877934fc7a..814e340808 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.h +++ b/openair1/PHY/TOOLS/lte_phy_scope.h @@ -37,7 +37,6 @@ #include "../defs.h" #include "../../SCHED/defs.h" // for OPENAIR_DAQ_VARS -extern OPENAIR_DAQ_VARS openair_daq_vars; /* Forms and Objects */ typedef struct { diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 26239b024c..b72c5f648a 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -330,6 +330,15 @@ typedef struct PHY_VARS_eNB_s { MU_MIMO_mode mu_mimo_mode[NUMBER_OF_UE_MAX]; + /// target_ue_dl_mcs : only for debug purposes + uint32_t target_ue_dl_mcs; + /// target_ue_ul_mcs : only for debug purposes + uint32_t target_ue_ul_mcs; + /// target_ue_dl_rballoc : only for debug purposes + uint32_t ue_dl_rb_alloc; + /// target ul PRBs : only for debug + uint32_t ue_ul_nb_rb; + ///check for Total Transmissions uint32_t check_for_total_transmissions; @@ -347,6 +356,8 @@ typedef struct PHY_VARS_eNB_s { uint32_t total_transmitted_bits; uint32_t total_system_throughput; + int hw_timing_advance; + time_stats_t phy_proc; time_stats_t phy_proc_tx; time_stats_t phy_proc_rx; @@ -577,6 +588,7 @@ typedef struct { // uint8_t prach_timer; int rx_offset; /// Timing offset int timing_advance; ///timing advance signalled from eNB + int hw_timing_advance; int N_TA_offset; ///timing offset used in TDD /// Flag to tell if UE is secondary user (cognitive mode) unsigned char is_secondary_ue; @@ -645,6 +657,8 @@ typedef struct { time_stats_t phy_proc_tx; time_stats_t phy_proc_rx; + uint32_t use_ia_receiver; + time_stats_t ofdm_mod_stats; time_stats_t ulsch_encoding_stats; time_stats_t ulsch_modulation_stats; diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index af6acca880..23e44d6692 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -86,7 +86,7 @@ enum openair_SYNCH_STATUS { #define DAQ_AGC_OFF 0 - +/* typedef struct { boolean_t is_eNB; uint8_t mode; @@ -133,6 +133,7 @@ typedef struct { uint32_t get_frame_done; uint32_t use_ia_receiver; } OPENAIR_DAQ_VARS; +*/ #ifndef USER_MODE int32_t openair_sched_init(void); diff --git a/openair1/SCHED/extern.h b/openair1/SCHED/extern.h index dd3892a290..657037b823 100644 --- a/openair1/SCHED/extern.h +++ b/openair1/SCHED/extern.h @@ -75,7 +75,6 @@ extern int openair_sched_status; extern int synch_wait_cnt; -extern OPENAIR_DAQ_VARS openair_daq_vars; extern int16_t hundred_times_delta_TF[100]; extern uint16_t hundred_times_log10_NPRB[100]; diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c index 286b11b4ad..ea6e45e739 100644 --- a/openair1/SCHED/phy_mac_stub.c +++ b/openair1/SCHED/phy_mac_stub.c @@ -234,7 +234,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; @@ -253,7 +253,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -265,7 +265,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; //((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rv = 0; @@ -284,7 +284,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -301,7 +301,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; @@ -320,7 +320,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t)); @@ -332,7 +332,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; //((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rv = 0; @@ -351,7 +351,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t)); @@ -367,7 +367,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; @@ -386,7 +386,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -398,7 +398,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; //((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rv = 0; @@ -417,7 +417,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; //((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = openair_daq_vars.target_ue_dl_mcs; + ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_20MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -438,14 +438,14 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tpmi = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv1 = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi1 = phy_vars_eNB->proc[sched_subframe].frame_tx&1; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs1 = openair_daq_vars.target_ue_dl_mcs; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs1 = phy_vars_eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv2 = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi2 = phy_vars_eNB->proc[sched_subframe].frame_tx&1; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs2 = openair_daq_vars.target_ue_dl_mcs; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs2 = phy_vars_eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tb_swap = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->TPC = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rballoc = openair_daq_vars.ue_dl_rb_alloc; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rballoc = phy_vars_eNB->ue_dl_rb_alloc; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rah = 0; } else if (transmission_mode==5) { @@ -462,13 +462,13 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e DLSCH_alloc_pdu1E.ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; //DLSCH_alloc_pdu1E.mcs = cqi_to_mcs[phy_vars_eNB->eNB_UE_stats->DL_cqi[0]]; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); - DLSCH_alloc_pdu1E.mcs = openair_daq_vars.target_ue_dl_mcs; + DLSCH_alloc_pdu1E.mcs = phy_vars_eNB->target_ue_dl_mcs; //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); phy_vars_eNB->eNB_UE_stats[0].dlsch_mcs1 = DLSCH_alloc_pdu1E.mcs; DLSCH_alloc_pdu1E.harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; DLSCH_alloc_pdu1E.dai = 0; DLSCH_alloc_pdu1E.TPC = 0; - DLSCH_alloc_pdu1E.rballoc = openair_daq_vars.ue_dl_rb_alloc; + DLSCH_alloc_pdu1E.rballoc = phy_vars_eNB->ue_dl_rb_alloc; DLSCH_alloc_pdu1E.rah = 0; DLSCH_alloc_pdu1E.dl_power_off = 0; //0=second user present memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); @@ -479,7 +479,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e DCI_pdu->dci_alloc[1].rnti = 0x1236; DCI_pdu->dci_alloc[1].format = format1E_2A_M10PRB; DCI_pdu->dci_alloc[1].ra_flag = 0; - //DLSCH_alloc_pdu1E.mcs = openair_daq_vars.target_ue_dl_mcs; + //DLSCH_alloc_pdu1E.mcs = phy_vars_eNB->target_ue_dl_mcs; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); DLSCH_alloc_pdu1E.mcs = (unsigned char) (((phy_vars_eNB->proc[sched_subframe].frame_tx%1024)/3)%28); @@ -531,8 +531,8 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; - UL_alloc_pdu.rballoc = computeRIV(25,2,openair_daq_vars.ue_ul_nb_rb); - UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs; + UL_alloc_pdu.rballoc = computeRIV(25,2,phy_vars_eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; UL_alloc_pdu.ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; UL_alloc_pdu.TPC = 0; UL_alloc_pdu.cshift = 0; @@ -551,10 +551,10 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; if (cooperation_flag==0) - UL_alloc_pdu.rballoc = computeRIV(25,2+openair_daq_vars.ue_ul_nb_rb,openair_daq_vars.ue_ul_nb_rb); + UL_alloc_pdu.rballoc = computeRIV(25,2+phy_vars_eNB->ue_ul_nb_rb,phy_vars_eNB->ue_ul_nb_rb); else - UL_alloc_pdu.rballoc = computeRIV(25,0,openair_daq_vars.ue_ul_nb_rb); - UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs; + UL_alloc_pdu.rballoc = computeRIV(25,0,phy_vars_eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; UL_alloc_pdu.ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; UL_alloc_pdu.TPC = 0; if ((cooperation_flag==0) || (cooperation_flag==1)) @@ -611,11 +611,11 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN DCI_pdu->dci_alloc[0].format = format1; DCI_pdu->dci_alloc[0].ra_flag = 0; - DLSCH_alloc_pdu.rballoc = openair_daq_vars.ue_dl_rb_alloc; + DLSCH_alloc_pdu.rballoc = phy_vars_eNB->ue_dl_rb_alloc; DLSCH_alloc_pdu.TPC = 0; DLSCH_alloc_pdu.dai = 0; DLSCH_alloc_pdu.harq_pid = 1; - DLSCH_alloc_pdu.mcs = openair_daq_vars.target_ue_dl_mcs; + DLSCH_alloc_pdu.mcs = phy_vars_eNB->target_ue_dl_mcs; DLSCH_alloc_pdu.ndi = 1; DLSCH_alloc_pdu.rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -632,7 +632,7 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN DLSCH_alloc_pdu.TPC = 0; DLSCH_alloc_pdu.dai = 0; DLSCH_alloc_pdu.harq_pid = 1; - DLSCH_alloc_pdu.mcs = openair_daq_vars.target_ue_dl_mcs; + DLSCH_alloc_pdu.mcs = phy_vars_eNB->target_ue_dl_mcs; DLSCH_alloc_pdu.ndi = 1; DLSCH_alloc_pdu.rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -649,11 +649,11 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback DLSCH_alloc_pdu1E.rv = 0; DLSCH_alloc_pdu1E.ndi = 1; - DLSCH_alloc_pdu1E.mcs = openair_daq_vars.target_ue_dl_mcs; + DLSCH_alloc_pdu1E.mcs = phy_vars_eNB->target_ue_dl_mcs; DLSCH_alloc_pdu1E.harq_pid = 1; DLSCH_alloc_pdu1E.dai = 0; DLSCH_alloc_pdu1E.TPC = 0; - DLSCH_alloc_pdu1E.rballoc = openair_daq_vars.ue_dl_rb_alloc; + DLSCH_alloc_pdu1E.rballoc = phy_vars_eNB->ue_dl_rb_alloc; DLSCH_alloc_pdu1E.rah = 0; DLSCH_alloc_pdu1E.dl_power_off = 0; //0=second user present memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); @@ -705,8 +705,8 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; - UL_alloc_pdu.rballoc = computeRIV(25,0,openair_daq_vars.ue_ul_nb_rb); - UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs; + UL_alloc_pdu.rballoc = computeRIV(25,0,phy_vars_eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; UL_alloc_pdu.ndi = 1; UL_alloc_pdu.TPC = 0; UL_alloc_pdu.cshift = 0; @@ -725,10 +725,10 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; if (cooperation_flag==0) - UL_alloc_pdu.rballoc = computeRIV(25,2+openair_daq_vars.ue_ul_nb_rb,openair_daq_vars.ue_ul_nb_rb); + UL_alloc_pdu.rballoc = computeRIV(25,2+phy_vars_eNB->ue_ul_nb_rb,phy_vars_eNB->ue_ul_nb_rb); else - UL_alloc_pdu.rballoc = computeRIV(25,0,openair_daq_vars.ue_ul_nb_rb); - UL_alloc_pdu.mcs = openair_daq_vars.target_ue_ul_mcs; + UL_alloc_pdu.rballoc = computeRIV(25,0,phy_vars_eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; UL_alloc_pdu.ndi = 1; UL_alloc_pdu.TPC = 0; if ((cooperation_flag==0) || (cooperation_flag==1)) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6a785ebf33..b0a94b8f59 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -90,7 +90,7 @@ int max_sync_pos; fifo_dump_emos_eNB emos_dump_eNB; #endif -#if defined(SMBV) && !defined(EXMIMO) +#if defined(SMBV) extern const char smbv_fname[]; extern unsigned short config_frames[4]; extern uint8_t smbv_frame_cnt; @@ -211,7 +211,7 @@ int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) { #ifdef DEBUG_PHY_PROC LOG_I(PHY,"eNB %d removing UE %d with rnti %x\n",phy_vars_eNB->Mod_id,i,rnti); #endif - //msg("[PHY] UE_id %d\n",i); + //LOG_D(PHY,("[PHY] UE_id %d\n",i); clean_eNb_dlsch(phy_vars_eNB->dlsch_eNB[i][0]); clean_eNb_ulsch(phy_vars_eNB->ulsch_eNB[i]); //phy_vars_eNB->eNB_UE_stats[i].crnti = 0; @@ -562,49 +562,710 @@ void phy_eNB_lte_check_measurement_thresholds(instance_t instanceP, ral_threshol unsigned int taus(void); -void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag, - relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn) -{ - UNUSED(phy_vars_rn); - uint8_t *pbch_pdu=&phy_vars_eNB->pbch_pdu[0]; - uint16_t input_buffer_length, re_allocated=0; - uint32_t i,aa; - uint8_t harq_pid; - DCI_PDU *DCI_pdu; - uint8_t *DLSCH_pdu=NULL; - DCI_PDU DCI_pdu_tmp; - uint8_t DLSCH_pdu_tmp[768*8]; - int8_t UE_id; - uint8_t num_pdcch_symbols=0; - uint8_t ul_subframe; - uint32_t ul_frame; +void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int sched_subframe,int abstraction_flag,relaying_type_t r_type) { + #ifdef Rel10 MCH_PDU *mch_pduP; MCH_PDU mch_pdu; // uint8_t sync_area=255; #endif -#if defined(SMBV) && !defined(EXMIMO) + + if (abstraction_flag==0) { + // This is DL-Cell spec pilots in Control region + generate_pilots_slot(eNB, + eNB->lte_eNB_common_vars.txdataF[0], + AMP, + subframe<<1,1); + } + +#ifdef Rel10 + // if mcch is active, send regardless of the node type: eNB or RN + // when mcch is active, MAC sched does not allow MCCH and MTCH multiplexing + mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id, + eNB->CC_id, + eNB->proc[sched_subframe].frame_tx, + subframe); + + switch (r_type) { + case no_relay: + if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0 + LOG_I(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n", + eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->mcs, + eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3); + else { + LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n", + eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->sync_area, + (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment"); + mch_pduP = NULL; + } + + break; + + case multicast_relay: + if ((mch_pduP->Pdu_size > 0) && ((mch_pduP->mcch_active == 1) || mch_pduP->msi_active==1)) { + LOG_I(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Got the MCH PDU for MBSFN sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n", + rn->Mod_id,rn->frame, subframe, + mch_pduP->sync_area,mch_pduP->mcs,mch_pduP->Pdu_size); + } else if (rn->mch_avtive[subframe%5] == 1) { // SF2 -> SF7, SF3 -> SF8 + mch_pduP= &mch_pdu; + memcpy(&mch_pduP->payload, // could be a simple copy + rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->b, + rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3); + mch_pduP->Pdu_size = (uint16_t) (rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3); + mch_pduP->mcs = rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->mcs; + LOG_I(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Forward the MCH PDU for MBSFN received on SF %d sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n", + rn->Mod_id,rn->frame, subframe,subframe%5, + rn->sync_area[subframe%5],mch_pduP->mcs,mch_pduP->Pdu_size); + } else { + mch_pduP=NULL; + } + + rn->mch_avtive[subframe]=0; + break; + + default: + LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n", + eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,r_type); + mch_pduP=NULL; + break; + }// switch + + if (mch_pduP) { + fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0, abstraction_flag); + // Generate PMCH + generate_mch(eNB,sched_subframe,(uint8_t*)mch_pduP->payload,abstraction_flag); + } else { + LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",eNB->proc[sched_subframe].frame_tx,subframe); + } + +#endif +} + +void common_signal_procedures (int subframe,int sched_subframe,PHY_VARS_eNB *eNB,int abstraction_flag) { + + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + int **txdataF = eNB->lte_eNB_common_vars.txdataF[0]; + uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; + + // generate Cell-Specific Reference Signals for both slots + if (abstraction_flag==0) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1); + generate_pilots_slot(eNB, + txdataF, + AMP, + subframe<<1,0); + // check that 2nd slot is for DL + if (subframe_select(fp,subframe) == SF_DL) + generate_pilots_slot(eNB, + txdataF, + AMP, + (subframe<<1)+1,0); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0); + } + + // First half of PSS/SSS (FDD, slot 0) + if (subframe == 0) { + if ((fp->frame_type == FDD) && + (abstraction_flag==0)) { + generate_pss(txdataF, + AMP, + fp, + (fp->Ncp==NORMAL) ? 6 : 5, + 0); + generate_sss(txdataF, + AMP, + fp, + (fp->Ncp==NORMAL) ? 5 : 4, + 0); + + } + + // generate PBCH (Physical Broadcast CHannel) info + if ((eNB->proc[sched_subframe].frame_tx&3) == 0) { + pbch_pdu[2] = 0; + + // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators + switch (fp->N_RB_DL) { + case 6: + pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (0<<5); + break; + + case 15: + pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (1<<5); + break; + + case 25: + pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5); + break; + + case 50: + pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (3<<5); + break; + + case 75: + pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (4<<5); + break; + + case 100: + pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (5<<5); + break; + + default: + // FIXME if we get here, this should be flagged as an error, right? + pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5); + break; + } + + pbch_pdu[2] = (pbch_pdu[2]&0xef) | + ((fp->phich_config_common.phich_duration << 4)&0x10); + + switch (fp->phich_config_common.phich_resource) { + case oneSixth: + pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (0<<2); + break; + + case half: + pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (1<<2); + break; + + case one: + pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (2<<2); + break; + + case two: + pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (3<<2); + break; + + default: + // unreachable + break; + } + + pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((eNB->proc[sched_subframe].frame_tx>>8)&0x3); + pbch_pdu[1] = eNB->proc[sched_subframe].frame_tx&0xfc; + pbch_pdu[0] = 0; + } + + /// First half of SSS (TDD, slot 1) + + if ((fp->frame_type == TDD)&& + (abstraction_flag==0)){ + generate_sss(txdataF, + AMP, + fp, + (fp->Ncp==NORMAL) ? 6 : 5, + 1); + } + + /// generate PBCH + if (abstraction_flag==0) { + generate_pbch(&eNB->lte_eNB_pbch, + txdataF, + AMP, + fp, + pbch_pdu, + eNB->proc[sched_subframe].frame_tx&3); + } +#ifdef PHY_ABSTRACTION + else { + generate_pbch_emul(eNB,pbch_pdu); + } +#endif + + } + else if ((subframe == 1) && + (fp->frame_type == TDD)&& + (abstraction_flag==0)) { + generate_pss(txdataF, + AMP, + fp, + 2, + 2); + } + + // Second half of PSS/SSS (FDD, slot 10) + else if ((subframe == 5) && + (fp->frame_type == FDD) && + (abstraction_flag==0)) { + generate_pss(txdataF, + AMP, + &eNB->lte_frame_parms, + (fp->Ncp==NORMAL) ? 6 : 5, + 10); + generate_sss(txdataF, + AMP, + &eNB->lte_frame_parms, + (fp->Ncp==NORMAL) ? 5 : 4, + 10); + + } + + // Second-half of SSS (TDD, slot 11) + else if ((subframe == 5) && + (fp->frame_type == TDD) && + (abstraction_flag==0)) { + generate_sss(txdataF, + AMP, + fp, + (fp->Ncp==NORMAL) ? 6 : 5, + 11); + } + + // Second half of PSS (TDD, slot 12) + else if ((subframe == 6) && + (fp->frame_type == TDD) && + (abstraction_flag==0)) { + generate_pss(txdataF, + AMP, + fp, + 2, + 12); + } + +} + +void generate_eNB_dlsch_params(const int frame,const int subframe,int sched_subframe,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { + + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + + // if we have SI_RNTI, configure dlsch parameters and CCE index + if (dci_alloc->rnti == SI_RNTI) { + LOG_D(PHY,"Generating dlsch params for SI_RNTI\n"); + generate_eNB_dlsch_params_from_dci(frame, + subframe, + &dci_alloc->dci_pdu[0], + dci_alloc->rnti, + dci_alloc->format, + &eNB->dlsch_eNB_SI, + fp, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->eNB_UE_stats[0].DL_pmi_single); + + + eNB->dlsch_eNB_SI->nCCE[subframe] = dci_alloc->firstCCE; + + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe, + eNB->dlsch_eNB_SI->nCCE[subframe]); + +#if defined(SMBV) + + // configure SI DCI + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", dci_alloc, i); + } + +#endif + + + } else if (dci_alloc->ra_flag == 1) { // This is format 1A allocation for RA + // configure dlsch parameters and CCE index + LOG_D(PHY,"Generating dlsch params for RA_RNTI\n"); + generate_eNB_dlsch_params_from_dci(frame, + subframe, + &dci_alloc->dci_pdu[0], + dci_alloc->rnti, + dci_alloc->format, + &eNB->dlsch_eNB_ra, + fp, + eNB->pdsch_config_dedicated, + SI_RNTI, + dci_alloc->rnti, + P_RNTI, + eNB->eNB_UE_stats[0].DL_pmi_single); + + + eNB->dlsch_eNB_ra->nCCE[subframe] = dci_alloc->firstCCE; + + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe, + eNB->dlsch_eNB_ra->nCCE[subframe]); +#if defined(SMBV) + + // configure RA DCI + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", dci_alloc, i); + } + +#endif + + } + + else if ((dci_alloc->format != format0)&& + (dci_alloc->format != format3)&& + (dci_alloc->format != format3A)&& + (dci_alloc->format != format4)){ // this is a normal DLSCH allocation + + + + if (UE_id>=0) { +#if defined(SMBV) + // Configure this user + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %"PRIu16" in TM%"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,subframe,(smbv_frame_cnt*10) + (subframe),UE_id+1, + dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]); + smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti); + } + +#endif + + LOG_D(PHY,"Generating dlsch params for RNTI %x\n",dci_alloc->rnti); + generate_eNB_dlsch_params_from_dci(frame, + subframe, + &dci_alloc->dci_pdu[0], + dci_alloc->rnti, + dci_alloc->format, + eNB->dlsch_eNB[(uint8_t)UE_id], + fp, + eNB->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + eNB->eNB_UE_stats[(uint8_t)UE_id].DL_pmi_single); + LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n", + eNB->Mod_id,dci_alloc->rnti,eNB->dlsch_eNB[(uint8_t)UE_id][0]->current_harq_pid,eNB->proc[sched_subframe].frame_tx,subframe); + + + eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE; + + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe, + dci_alloc->rnti,eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]); + +#if defined(SMBV) + + // configure UE-spec DCI + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1,dci_alloc, i); + } + +#endif + + LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n", + eNB->Mod_id, dci_alloc->rnti, + eNB->proc[sched_subframe].frame_tx, subframe,UE_id, + dci_alloc->format, + 1<L); + } else { + LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n", + eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,dci_alloc->rnti); + } + } + +} + +void generate_eNB_ulsch_params(const int frame,const int subframe,int sched_subframe,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { + + int harq_pid; + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + + LOG_D(PHY, + "[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8"), aggregation %d\n", + eNB->Mod_id, + subframe2harq_pid(fp, + pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe), + pdcch_alloc2ul_subframe(fp,subframe)), + eNB->proc[sched_subframe].frame_tx, + subframe, + pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe), + pdcch_alloc2ul_subframe(fp,subframe), + dci_alloc->rnti, + dci_alloc->dci_pdu[0], + 1<L); + + generate_eNB_ulsch_params_from_dci(&dci_alloc->dci_pdu[0], + dci_alloc->rnti, + sched_subframe, + format0, + UE_id, + eNB, + SI_RNTI, + 0, + P_RNTI, + CBA_RNTI, + 0); // do_srs + + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d\n", + eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,dci_alloc->rnti, + dci_alloc->firstCCE); + +#if defined(SMBV) + + // configure UE-spec DCI for UL Grant + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); + } + +#endif + + + // get the hard_pid for this subframe + harq_pid = subframe2harq_pid(fp, + pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe), + pdcch_alloc2ul_subframe(fp,subframe)); + + if (harq_pid==255) { // should not happen, log an error and exit, this is a fatal error + LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx); + mac_xface->macphy_exit("FATAL\n"); + } + + if ((dci_alloc->rnti >= CBA_RNTI) && (dci_alloc->rnti < P_RNTI)) + eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1; + else + eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + +} + +void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int subframe,int sched_subframe,int num_pdcch_symbols,int abstraction_flag) { + + int harq_pid = dlsch->current_harq_pid; + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid]; + int input_buffer_length = dlsch_harq->TBS/8; + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + uint8_t *DLSCH_pdu=NULL; + uint8_t DLSCH_pdu_tmp[768*8]; + uint8_t DLSCH_pdu_rar[256]; + int i; + + LOG_D(PHY, + "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n", + eNB->Mod_id, dlsch->rnti,harq_pid, + eNB->proc[sched_subframe].frame_tx, subframe, input_buffer_length, + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + get_Qm(dlsch_harq->mcs), + dlsch_harq->Nl, + num_pdcch_symbols,eNB->proc[sched_subframe].frame_tx,subframe), + dlsch_harq->nb_rb, + dlsch_harq->mcs, + pmi2hex_2Ar1(dlsch_harq->pmi_alloc), + dlsch_harq->rvidx, + dlsch_harq->round); + +#if defined(MESSAGE_CHART_GENERATOR_PHY) + MSC_LOG_TX_MESSAGE( + MSC_PHY_ENB,MSC_PHY_UE, + NULL,0, + "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")", + eNB->proc[sched_subframe].frame_tx, subframe, + input_buffer_length, + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + get_Qm(dlsch_harq->mcs), + dlsch_harq->Nl, + num_pdcch_symbols,eNB->proc[sched_subframe].frame_tx,subframe), + dlsch_harq->nb_rb, + dlsch_harq->mcs, + pmi2hex_2Ar1(dlsch_harq->pmi_alloc), + dlsch_harq->rvidx, + dlsch_harq->round); +#endif + + if (ue_stats) ue_stats->dlsch_sliding_cnt++; + + if (dlsch_harq->round == 0) { + + if (ue_stats) + ue_stats->dlsch_trials[harq_pid][0]++; + + if (eNB->mac_enabled==1) { + if (ra_flag == 0) { + DLSCH_pdu = mac_xface->get_dlsch_sdu(eNB->Mod_id, + eNB->CC_id, + eNB->proc[sched_subframe].frame_tx, + dlsch->rnti, + 0); + } + else { + int16_t crnti = mac_xface->fill_rar(eNB->Mod_id, + eNB->CC_id, + eNB->proc[sched_subframe].frame_tx, + DLSCH_pdu_rar, + fp->N_RB_UL, + input_buffer_length); + DLSCH_pdu = DLSCH_pdu_rar; + + int UE_id; + + if (crnti!=0) + UE_id = add_ue(crnti,eNB); + else + UE_id = -1; + + if (UE_id==-1) { + LOG_W(PHY,"[eNB] Max user count reached.\n"); + mac_xface->cancel_ra_proc(eNB->Mod_id, + eNB->CC_id, + eNB->proc[sched_subframe].frame_tx, + crnti); + } else { + eNB->eNB_UE_stats[(uint32_t)UE_id].mode = RA_RESPONSE; + // Initialize indicator for first SR (to be cleared after ConnectionSetup is acknowledged) + eNB->first_sr[(uint32_t)UE_id] = 1; + + generate_eNB_ulsch_params_from_rar(DLSCH_pdu, + eNB->proc[sched_subframe].frame_tx, + (subframe), + eNB->ulsch_eNB[(uint32_t)UE_id], + fp); + + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active = 1; + + get_Msg3_alloc(fp, + subframe, + eNB->proc[sched_subframe].frame_tx, + &eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, + &eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); + LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n", + eNB->proc[sched_subframe].frame_tx, + subframe, + UE_id, + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); + } + if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS; + } + } + else { + DLSCH_pdu = DLSCH_pdu_tmp; + + for (i=0; iproc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + smbv_configure_datalist_for_user(smbv_fname, find_ue(dlsch->rnti,eNB)+1, DLSCH_pdu, input_buffer_length); + } + +#endif + + +#ifdef DEBUG_PHY_PROC +#ifdef DEBUG_DLSCH + LOG_T(PHY,"eNB DLSCH SDU: \n"); + + for (i=0; iTBS>>3; i++) + LOG_T(PHY,"%"PRIx8".",DLSCH_pdu[i]); + + LOG_T(PHY,"\n"); +#endif +#endif + } else { + ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++; +#ifdef DEBUG_PHY_PROC +#ifdef DEBUG_DLSCH + LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n"); +#endif +#endif + } + + if (abstraction_flag==0) { + + LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag); + // 36-212 + start_meas(&eNB->dlsch_encoding_stats); + dlsch_encoding(DLSCH_pdu, + fp, + num_pdcch_symbols, + dlsch, + eNB->proc[sched_subframe].frame_tx,subframe, + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_interleaving_stats); + stop_meas(&eNB->dlsch_encoding_stats); + // 36-211 + start_meas(&eNB->dlsch_scrambling_stats); + dlsch_scrambling(fp, + 0, + dlsch, + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + get_Qm(dlsch_harq->mcs), + dlsch_harq->Nl, + num_pdcch_symbols,eNB->proc[sched_subframe].frame_tx,subframe), + 0, + subframe<<1); + stop_meas(&eNB->dlsch_scrambling_stats); + start_meas(&eNB->dlsch_modulation_stats); + + + dlsch_modulation(eNB->lte_eNB_common_vars.txdataF[0], + AMP, + subframe, + fp, + num_pdcch_symbols, + dlsch, + dlsch1); + + stop_meas(&eNB->dlsch_modulation_stats); + } + +#ifdef PHY_ABSTRACTION + else { + start_meas(&eNB->dlsch_encoding_stats); + dlsch_encoding_emul(eNB, + DLSCH_pdu, + dlsch); + stop_meas(&eNB->dlsch_encoding_stats); + } + +#endif + dlsch->active = 0; +} + +void phy_procedures_eNB_TX(unsigned char sched_subframe, + PHY_VARS_eNB *eNB, + uint8_t abstraction_flag, + relaying_type_t r_type, + PHY_VARS_RN *rn) +{ + UNUSED(rn); + uint16_t input_buffer_length; + uint32_t i,aa; + uint8_t harq_pid; + DCI_PDU *DCI_pdu; + DCI_PDU DCI_pdu_tmp; + int8_t UE_id; + uint8_t num_pdcch_symbols=0; + uint8_t ul_subframe; + uint32_t ul_frame; + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL; + +#if defined(SMBV) // counts number of allocations in subframe // there is at least one allocation for PDCCH uint8_t smbv_alloc_cnt = 1; #endif - int frame = phy_vars_eNB->proc[sched_subframe].frame_tx; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_tx; + int frame = eNB->proc[sched_subframe].frame_tx; + int subframe = eNB->proc[sched_subframe].subframe_tx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,1); - start_meas(&phy_vars_eNB->phy_proc_tx); + start_meas(&eNB->phy_proc_tx); for (i=0; ieNB_UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) { + if (eNB->eNB_UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) { LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->CC_id,frame,subframe, i, phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors); - phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0; - mac_xface->UL_failure_indication(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->eNB_UE_stats[i].ulsch_consecutive_errors); + eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0; + mac_xface->UL_failure_indication(eNB->Mod_id, + eNB->CC_id, frame, - phy_vars_eNB->eNB_UE_stats[i].crnti, + eNB->eNB_UE_stats[i].crnti, subframe); } @@ -613,589 +1274,134 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e } - // Get scheduling info for next subframe - if (phy_vars_eNB->mac_enabled==1) { - if (phy_vars_eNB->CC_id == 0) { - mac_xface->eNB_dlsch_ulsch_scheduler(phy_vars_eNB->Mod_id,0,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe);//,1); +// Get scheduling info for next subframe +// This is called only for the CC_id = 0 and triggers scheduling for all CC_id's + if (eNB->mac_enabled==1) { + if (eNB->CC_id == 0) { + mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,eNB->proc[sched_subframe].frame_tx,subframe);//,1); } } +// clear the transmit data array for the current subframe if (abstraction_flag==0) { - // clear the transmit data array for the current subframe - for (aa=0; aalte_frame_parms.nb_antennas_tx_eNB; aa++) { - - memset(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][subframe*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti)], - 0,phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti)*sizeof(int32_t)); + for (aa=0; aanb_antennas_tx_eNB; aa++) { + memset(&eNB->lte_eNB_common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], + 0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t)); } } - - if (is_pmch_subframe(phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,&phy_vars_eNB->lte_frame_parms)) { - - if (abstraction_flag==0) { - // This is DL-Cell spec pilots in Control region - generate_pilots_slot(phy_vars_eNB, - phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - subframe<<1,1); - } - -#ifdef Rel10 - // if mcch is active, send regardless of the node type: eNB or RN - // when mcch is active, MAC sched does not allow MCCH and MTCH multiplexing - mch_pduP = mac_xface->get_mch_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, - phy_vars_eNB->proc[sched_subframe].frame_tx, - subframe); - - switch (r_type) { - case no_relay: - if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0 - LOG_I(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->mcs, - phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3); - else { - LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->sync_area, - (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment"); - mch_pduP = NULL; - } - - break; - - case multicast_relay: - if ((mch_pduP->Pdu_size > 0) && ((mch_pduP->mcch_active == 1) || mch_pduP->msi_active==1)) { - LOG_I(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Got the MCH PDU for MBSFN sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n", - phy_vars_rn->Mod_id,phy_vars_rn->frame, subframe, - mch_pduP->sync_area,mch_pduP->mcs,mch_pduP->Pdu_size); - } else if (phy_vars_rn->mch_avtive[subframe%5] == 1) { // SF2 -> SF7, SF3 -> SF8 - mch_pduP= &mch_pdu; - memcpy(&mch_pduP->payload, // could be a simple copy - phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->b, - phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3); - mch_pduP->Pdu_size = (uint16_t) (phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3); - mch_pduP->mcs = phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->mcs; - LOG_I(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Forward the MCH PDU for MBSFN received on SF %d sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n", - phy_vars_rn->Mod_id,phy_vars_rn->frame, subframe,subframe%5, - phy_vars_rn->sync_area[subframe%5],mch_pduP->mcs,mch_pduP->Pdu_size); - } else { - mch_pduP=NULL; - } - - phy_vars_rn->mch_avtive[subframe]=0; - break; - - default: - LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,r_type); - mch_pduP=NULL; - break; - }// switch - - if (mch_pduP) { - fill_eNB_dlsch_MCH(phy_vars_eNB,mch_pduP->mcs,1,0, abstraction_flag); - // Generate PMCH - generate_mch(phy_vars_eNB,sched_subframe,(uint8_t*)mch_pduP->payload,abstraction_flag); -#ifdef DEBUG_PHY - - for (i=0; iPdu_size; i++) - msg("%2"PRIx8".",(uint8_t)mch_pduP->payload[i]); - - msg("\n"); -#endif - } else { - LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - } - -#endif + if (is_pmch_subframe(eNB->proc[sched_subframe].frame_tx,subframe,fp)) { + pmch_procedures(eNB,rn,subframe,sched_subframe,abstraction_flag,r_type); } - else { - // this is not a pmch subframe - - if (abstraction_flag==0) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1); - generate_pilots_slot(phy_vars_eNB, - phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - subframe<<1,0); - if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_DL) - generate_pilots_slot(phy_vars_eNB, - phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - (subframe<<1)+1,0); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0); - - // First half of PSS/SSS (FDD) - if (subframe == 0) { - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { - generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5, - 0); - generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 5 : 4, - 0); - - } - } - } + // this is not a pmch subframe, so generate PSS/SSS/PBCH + common_signal_procedures(subframe,sched_subframe,eNB,abstraction_flag); } - if (subframe == 0) { - // generate PBCH (Physical Broadcast CHannel) info - if ((phy_vars_eNB->proc[sched_subframe].frame_tx&3) == 0) { - pbch_pdu[2] = 0; - - // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators - switch (phy_vars_eNB->lte_frame_parms.N_RB_DL) { - case 6: - pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (0<<5); - break; - - case 15: - pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (1<<5); - break; - - case 25: - pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5); - break; - - case 50: - pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (3<<5); - break; - - case 75: - pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (4<<5); - break; - - case 100: - pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (5<<5); - break; - - default: - // FIXME if we get here, this should be flagged as an error, right? - pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5); - break; - } - - pbch_pdu[2] = (pbch_pdu[2]&0xef) | - ((phy_vars_eNB->lte_frame_parms.phich_config_common.phich_duration << 4)&0x10); - - switch (phy_vars_eNB->lte_frame_parms.phich_config_common.phich_resource) { - case oneSixth: - pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (0<<2); - break; - - case half: - pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (1<<2); - break; - - case one: - pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (2<<2); - break; - - case two: - pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (3<<2); - break; - - default: - // unreachable - break; - } - - pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((phy_vars_eNB->proc[sched_subframe].frame_tx>>8)&0x3); - pbch_pdu[1] = phy_vars_eNB->proc[sched_subframe].frame_tx&0xfc; - pbch_pdu[0] = 0; - } - - /// First half of SSS (TDD) - if (abstraction_flag==0) { - - if (phy_vars_eNB->lte_frame_parms.frame_type == TDD) { - generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5, - 1); - } - } - - - - - if (abstraction_flag==0) { - - generate_pbch(&phy_vars_eNB->lte_eNB_pbch, - phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - pbch_pdu, - phy_vars_eNB->proc[sched_subframe].frame_tx&3); - - } - -#ifdef PHY_ABSTRACTION - else { - generate_pbch_emul(phy_vars_eNB,pbch_pdu); - } - -#endif - - - } - - if (subframe == 1) { - - if (abstraction_flag==0) { - - if (phy_vars_eNB->lte_frame_parms.frame_type == TDD) { - generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - 2, - 2); - } - } - } - - // Second half of PSS/SSS (FDD) - if (subframe == 5) { - - if (abstraction_flag==0) { - - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { - generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5, - 10); - generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 5 : 4, - 10); - - } - } - } - - // Second-half of SSS (TDD) - if (subframe == 5) { - if (abstraction_flag==0) { - - if (phy_vars_eNB->lte_frame_parms.frame_type == TDD) { - generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5, - 11); - } - } - } - - // Second half of PSS (TDD) - if (subframe == 6) { - - if (abstraction_flag==0) { - - if (phy_vars_eNB->lte_frame_parms.frame_type == TDD) { - generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - &phy_vars_eNB->lte_frame_parms, - 2, - 12); - } - } - } - - - -#if defined(SMBV) && !defined(EXMIMO) +#if defined(SMBV) // PBCH takes one allocation - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { if (subframe==0) smbv_alloc_cnt++; } #endif - if (phy_vars_eNB->mac_enabled==1) { + if (eNB->mac_enabled==1) { // Parse DCI received from MAC VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1); - DCI_pdu = mac_xface->get_dci_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, - phy_vars_eNB->proc[sched_subframe].frame_tx, + DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id, + eNB->CC_id, + eNB->proc[sched_subframe].frame_tx, subframe); } else { DCI_pdu = &DCI_pdu_tmp; #ifdef EMOS_CHANNEL - fill_dci_emos(DCI_pdu,sched_subframe,phy_vars_eNB); + fill_dci_emos(DCI_pdu,sched_subframe,eNB); #else - fill_dci(DCI_pdu,sched_subframe,phy_vars_eNB); + fill_dci(DCI_pdu,sched_subframe,eNB); #endif } // clear existing ulsch dci allocations before applying info from MAC (this is table - ul_subframe = pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,subframe); - ul_frame = pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); + ul_subframe = pdcch_alloc2ul_subframe(fp,subframe); + ul_frame = pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe); - if ((subframe_select(&phy_vars_eNB->lte_frame_parms,ul_subframe)==SF_UL) || - (phy_vars_eNB->lte_frame_parms.frame_type == FDD)) { - harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms,ul_frame,ul_subframe); + if ((subframe_select(fp,ul_subframe)==SF_UL) || + (fp->frame_type == FDD)) { + harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); + // clear DCI allocation maps for new subframe for (i=0; iulsch_eNB[i]) { - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc=0; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc=0; + if (eNB->ulsch_eNB[i]) { + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc=0; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc=0; } } // clear previous allocation information for all UEs for (i=0; idlsch_eNB[i][0]->subframe_tx[subframe] = 0; + eNB->dlsch_eNB[i][0]->subframe_tx[subframe] = 0; } num_pdcch_symbols = DCI_pdu->num_pdcch_symbols; - - LOG_D(PHY,"num_pdcch_symbols %"PRIu8", nCCE %u (dci commond %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,DCI_pdu->nCCE, + LOG_D(PHY,"num_pdcch_symbols %"PRIu8", (dci commond %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); -#if defined(SMBV) && !defined(EXMIMO) - +#if defined(SMBV) // Sets up PDCCH and DCI table - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) { - msg("[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); - dump_dci(&phy_vars_eNB->lte_frame_parms,&DCI_pdu->dci_alloc[0]); + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); + dump_dci(fp,&DCI_pdu->dci_alloc[0]); smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); } - #endif - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols); + // loop over all DCIs for this subframe to generate DLSCH allocations for (i=0; iNum_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) { LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].rnti); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].format); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].firstCCE); + dci_alloc = &DCI_pdu->dci_alloc[i]; - if (DCI_pdu->dci_alloc[i].rnti == SI_RNTI) { - - generate_eNB_dlsch_params_from_dci(frame, - subframe, - &DCI_pdu->dci_alloc[i].dci_pdu[0], - DCI_pdu->dci_alloc[i].rnti, - DCI_pdu->dci_alloc[i].format, - &phy_vars_eNB->dlsch_eNB_SI, - &phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI, - phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single); - - - phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; - - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe],DCI_pdu->nCCE); - -#if defined(SMBV) && !defined(EXMIMO) - - // configure SI DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", &DCI_pdu->dci_alloc[i], i); - } - -#endif - - - } else if (DCI_pdu->dci_alloc[i].ra_flag == 1) { - - generate_eNB_dlsch_params_from_dci(frame, - subframe, - &DCI_pdu->dci_alloc[i].dci_pdu[0], - DCI_pdu->dci_alloc[i].rnti, - DCI_pdu->dci_alloc[i].format, - &phy_vars_eNB->dlsch_eNB_ra, - &phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->pdsch_config_dedicated, - SI_RNTI, - DCI_pdu->dci_alloc[i].rnti, - P_RNTI, - phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single); - - - phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; - - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe],DCI_pdu->nCCE); -#if defined(SMBV) && !defined(EXMIMO) - - // configure RA DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", &DCI_pdu->dci_alloc[i], i); - } - -#endif - - } - - else if (DCI_pdu->dci_alloc[i].format != format0) { // this is a normal DLSCH allocation - - if (phy_vars_eNB->mac_enabled==1) - UE_id = find_ue((int16_t)DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB); + if ((dci_alloc->rnti<= P_RNTI) && + (dci_alloc->ra_flag!=1)) { + if (eNB->mac_enabled==1) + UE_id = find_ue((int16_t)dci_alloc->rnti,eNB); else UE_id = i; - - if (UE_id>=0) { - if ((frame%100)==0) { - LOG_D(PHY,"Frame %3d, SF %d \n",frame,subframe); - dump_dci(&phy_vars_eNB->lte_frame_parms,&DCI_pdu->dci_alloc[i]); - } -#if defined(SMBV) && !defined(EXMIMO) - // Configure this user - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %"PRIu16" in TM%"PRIu8"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,(smbv_frame_cnt*10) + (subframe),UE_id+1, - DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->transmission_mode[(uint8_t)UE_id]); - smbv_configure_user(smbv_fname,UE_id+1,phy_vars_eNB->transmission_mode[(uint8_t)UE_id],DCI_pdu->dci_alloc[i].rnti); - } - -#endif - - generate_eNB_dlsch_params_from_dci(frame, - subframe, - &DCI_pdu->dci_alloc[i].dci_pdu[0], - DCI_pdu->dci_alloc[i].rnti, - DCI_pdu->dci_alloc[i].format, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id], - &phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI, - phy_vars_eNB->eNB_UE_stats[(uint8_t)UE_id].DL_pmi_single); - LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n", - phy_vars_eNB->Mod_id,DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->current_harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - - - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; - - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->nCCE); - -#if defined(SMBV) && !defined(EXMIMO) - - // configure UE-spec DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); - } - -#endif - - LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n", - phy_vars_eNB->Mod_id, DCI_pdu->dci_alloc[i].rnti, - phy_vars_eNB->proc[sched_subframe].frame_tx, subframe,UE_id, - DCI_pdu->dci_alloc[i].format, - 1<dci_alloc[i].L); - } else { - LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,DCI_pdu->dci_alloc[i].rnti); - } } + else UE_id=0; + + generate_eNB_dlsch_params(frame,subframe,sched_subframe,eNB,dci_alloc,UE_id); } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe); // Apply physicalConfigDedicated if needed - phy_config_dedicated_eNB_step2(phy_vars_eNB); - + // This is for UEs that have received this IE, which changes these DL and UL configuration, we apply after a delay for the eNodeB UL parameters + phy_config_dedicated_eNB_step2(eNB); + + // Now loop again over the DCIs for UL configuration for (i=0; iNum_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) { - if (DCI_pdu->dci_alloc[i].format == format0) { // this is a ULSCH allocation - - harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms, - pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,subframe)); - - if (harq_pid==255) { - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx); - return; - } - - if (phy_vars_eNB->mac_enabled==1) - UE_id = find_ue((int16_t)DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB); + if (dci_alloc->format == format0) { // this is a ULSCH allocation + if (eNB->mac_enabled==1) + UE_id = find_ue((int16_t)dci_alloc->rnti,eNB); else UE_id = i; - - if (UE_id<0) { - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,DCI_pdu->dci_alloc[i].rnti); - mac_exit_wrapper("Invalid UE id (< 0) detected"); - return; // not reached + + if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error + LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,dci_alloc->rnti); + mac_xface->macphy_exit("FATAL\n"); } - - LOG_D(PHY, - "[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8") (DCI pos %"PRIu32"/%d), aggregation %d\n", - phy_vars_eNB->Mod_id, - subframe2harq_pid(&phy_vars_eNB->lte_frame_parms, - pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,subframe)), - phy_vars_eNB->proc[sched_subframe].frame_tx, - subframe, - pdcch_alloc2ul_frame(&phy_vars_eNB->lte_frame_parms,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - pdcch_alloc2ul_subframe(&phy_vars_eNB->lte_frame_parms,subframe), - DCI_pdu->dci_alloc[i].rnti, - DCI_pdu->dci_alloc[i].dci_pdu[0], - i, - DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci, - 1<dci_alloc[i].L); - - generate_eNB_ulsch_params_from_dci(&DCI_pdu->dci_alloc[i].dci_pdu[0], - DCI_pdu->dci_alloc[i].rnti, - sched_subframe, - format0, - UE_id, - phy_vars_eNB, - SI_RNTI, - 0, - P_RNTI, - CBA_RNTI, - 0); // do_srs - - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d/%u\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->dci_alloc[i].rnti, - DCI_pdu->dci_alloc[i].firstCCE,DCI_pdu->nCCE); - -#if defined(SMBV) && !defined(EXMIMO) - - // configure UE-spec DCI for UL Grant - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); - } - -#endif - - - - if ((DCI_pdu->dci_alloc[i].rnti >= CBA_RNTI) && (DCI_pdu->dci_alloc[i].rnti < P_RNTI)) - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1; - else - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; - + generate_eNB_ulsch_params(frame,subframe,sched_subframe,eNB,dci_alloc,UE_id); } } @@ -1208,14 +1414,14 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e } else { // for emulation!! - phy_vars_eNB->num_ue_spec_dci[(subframe)&1]=0; - phy_vars_eNB->num_common_dci[(subframe)&1]=0; + eNB->num_ue_spec_dci[(subframe)&1]=0; + eNB->num_common_dci[(subframe)&1]=0; } if (abstraction_flag == 0) { if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx, subframe, + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx, subframe, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); @@ -1224,16 +1430,16 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e DCI_pdu->dci_alloc, 0, AMP, - &phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->lte_eNB_common_vars.txdataF[0], + fp, + eNB->lte_eNB_common_vars.txdataF[0], subframe); } #ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious else { - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top_emul\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx, subframe); - num_pdcch_symbols = generate_dci_top_emul(phy_vars_eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,subframe); + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx, subframe); + num_pdcch_symbols = generate_dci_top_emul(eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,subframe); } #endif @@ -1242,361 +1448,65 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e // Check for SI activity - if (phy_vars_eNB->dlsch_eNB_SI->active == 1) { - input_buffer_length = phy_vars_eNB->dlsch_eNB_SI->harq_processes[0]->TBS/8; + if (eNB->dlsch_eNB_SI->active == 1) { + pdsch_procedures(eNB,eNB->dlsch_eNB_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,subframe,sched_subframe,num_pdcch_symbols,abstraction_flag); - if (phy_vars_eNB->mac_enabled==1) { - DLSCH_pdu = mac_xface->get_dlsch_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, - phy_vars_eNB->proc[sched_subframe].frame_tx, - SI_RNTI, - 0); - } - else { - DLSCH_pdu = DLSCH_pdu_tmp; - - for (i=0; iproc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length); } #endif - - if (abstraction_flag == 0) { - - start_meas(&phy_vars_eNB->dlsch_encoding_stats); - dlsch_encoding(DLSCH_pdu, - &phy_vars_eNB->lte_frame_parms, - num_pdcch_symbols, - phy_vars_eNB->dlsch_eNB_SI, - phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - &phy_vars_eNB->dlsch_rate_matching_stats, - &phy_vars_eNB->dlsch_turbo_encoding_stats, - &phy_vars_eNB->dlsch_interleaving_stats); - stop_meas(&phy_vars_eNB->dlsch_encoding_stats); - - start_meas(&phy_vars_eNB->dlsch_scrambling_stats); - dlsch_scrambling(&phy_vars_eNB->lte_frame_parms, - 0, - phy_vars_eNB->dlsch_eNB_SI, - get_G(&phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->dlsch_eNB_SI->harq_processes[0]->nb_rb, - phy_vars_eNB->dlsch_eNB_SI->harq_processes[0]->rb_alloc, - get_Qm(phy_vars_eNB->dlsch_eNB_SI->harq_processes[0]->mcs), - 1, - num_pdcch_symbols,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - 0, - subframe<<1); - - stop_meas(&phy_vars_eNB->dlsch_scrambling_stats); - - start_meas(&phy_vars_eNB->dlsch_modulation_stats); - - re_allocated = dlsch_modulation(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - subframe, - &phy_vars_eNB->lte_frame_parms, - num_pdcch_symbols, - phy_vars_eNB->dlsch_eNB_SI, - (LTE_eNB_DLSCH_t *)NULL); - stop_meas(&phy_vars_eNB->dlsch_modulation_stats); - } - -#ifdef PHY_ABSTRACTION - else { - start_meas(&phy_vars_eNB->dlsch_encoding_stats); - dlsch_encoding_emul(phy_vars_eNB, - DLSCH_pdu, - phy_vars_eNB->dlsch_eNB_SI); - stop_meas(&phy_vars_eNB->dlsch_encoding_stats); - } - -#endif - phy_vars_eNB->dlsch_eNB_SI->active = 0; - } // Check for RA activity - if (phy_vars_eNB->dlsch_eNB_ra->active == 1) { + if (eNB->dlsch_eNB_ra->active == 1) { - input_buffer_length = phy_vars_eNB->dlsch_eNB_ra->harq_processes[0]->TBS/8; - - int16_t crnti = mac_xface->fill_rar(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, - phy_vars_eNB->proc[sched_subframe].frame_tx, - dlsch_input_buffer, - phy_vars_eNB->lte_frame_parms.N_RB_UL, - input_buffer_length); - if (crnti!=0) - UE_id = add_ue(crnti,phy_vars_eNB); - else - UE_id = -1; - - if (UE_id==-1) { - LOG_W(PHY,"[eNB] Max user count reached.\n"); - mac_xface->cancel_ra_proc(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, - phy_vars_eNB->proc[sched_subframe].frame_tx, - crnti); - } else { - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].mode = RA_RESPONSE; - // Initialize indicator for first SR (to be cleared after ConnectionSetup is acknowledged) - phy_vars_eNB->first_sr[(uint32_t)UE_id] = 1; - - generate_eNB_ulsch_params_from_rar(dlsch_input_buffer, - phy_vars_eNB->proc[sched_subframe].frame_tx, - (subframe), - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id], - &phy_vars_eNB->lte_frame_parms); - - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active = 1; - - get_Msg3_alloc(&phy_vars_eNB->lte_frame_parms, - subframe, - phy_vars_eNB->proc[sched_subframe].frame_tx, - &phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, - &phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); - LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n", - phy_vars_eNB->proc[sched_subframe].frame_tx, - subframe, - UE_id, - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); - -#if defined(SMBV) && !defined(EXMIMO) - - // Configures the data source of allocation (allocation is configured by DCI) - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); - smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length); - } +#if defined(SMBV) + // Configures the data source of allocation (allocation is configured by DCI) + if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length); + } + #endif - - - LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA) with input size = %"PRIu16",Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n", - phy_vars_eNB->Mod_id, - phy_vars_eNB->proc[sched_subframe].frame_tx, subframe,input_buffer_length, - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); - - - if (abstraction_flag == 0) { - - dlsch_encoding(dlsch_input_buffer, - &phy_vars_eNB->lte_frame_parms, - num_pdcch_symbols, - phy_vars_eNB->dlsch_eNB_ra, - phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - &phy_vars_eNB->dlsch_rate_matching_stats, - &phy_vars_eNB->dlsch_turbo_encoding_stats, - &phy_vars_eNB->dlsch_interleaving_stats); - - // phy_vars_eNB->dlsch_eNB_ra->rnti = RA_RNTI; - dlsch_scrambling(&phy_vars_eNB->lte_frame_parms, - 0, - phy_vars_eNB->dlsch_eNB_ra, - get_G(&phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->dlsch_eNB_ra->harq_processes[0]->nb_rb, - phy_vars_eNB->dlsch_eNB_ra->harq_processes[0]->rb_alloc, - get_Qm(phy_vars_eNB->dlsch_eNB_ra->harq_processes[0]->mcs), - 1, - num_pdcch_symbols,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - 0, - subframe<<1); - - re_allocated = dlsch_modulation(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - subframe, - &phy_vars_eNB->lte_frame_parms, - num_pdcch_symbols, - phy_vars_eNB->dlsch_eNB_ra, - (LTE_eNB_DLSCH_t *)NULL); - } - -#ifdef PHY_ABSTRACTION - else { - dlsch_encoding_emul(phy_vars_eNB, - dlsch_input_buffer, - phy_vars_eNB->dlsch_eNB_ra); - } - -#endif - LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d subframe %d Deactivating DLSCH RA\n",phy_vars_eNB->Mod_id, - phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - - } //max user count - - phy_vars_eNB->dlsch_eNB_ra->active = 0; + + + LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA) with input size = %"PRIu16",Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n", + eNB->Mod_id, + eNB->proc[sched_subframe].frame_tx, subframe,input_buffer_length, + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); + + pdsch_procedures(eNB,eNB->dlsch_eNB_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,subframe,sched_subframe,num_pdcch_symbols,abstraction_flag); + + + eNB->dlsch_eNB_ra->active = 0; } - + // Now scan UE specific DLSCH for (UE_id=0; UE_iddlsch_eNB[(uint8_t)UE_id][0])&& - (phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti>0)&& - (phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->active == 1)) { - harq_pid = phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->current_harq_pid; - input_buffer_length = phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->TBS/8; + if ((eNB->dlsch_eNB[(uint8_t)UE_id][0])&& + (eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti>0)&& + (eNB->dlsch_eNB[(uint8_t)UE_id][0]->active == 1)) { + pdsch_procedures(eNB,eNB->dlsch_eNB[(uint8_t)UE_id][0],eNB->dlsch_eNB[(uint8_t)UE_id][1],&eNB->eNB_UE_stats[(uint32_t)UE_id],0,subframe,sched_subframe,num_pdcch_symbols,abstraction_flag); - LOG_D(PHY, - "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n", - phy_vars_eNB->Mod_id, phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti,harq_pid, - phy_vars_eNB->proc[sched_subframe].frame_tx, subframe, input_buffer_length, - get_G(&phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->rb_alloc, - get_Qm(phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->mcs), - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->Nl, - num_pdcch_symbols,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->mcs, - pmi2hex_2Ar1(phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->pmi_alloc), - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->round); - -#if defined(MESSAGE_CHART_GENERATOR_PHY) - MSC_LOG_TX_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")", - phy_vars_eNB->proc[sched_subframe].frame_tx, subframe, - input_buffer_length, - get_G(&phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->rb_alloc, - get_Qm(phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->mcs), - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->Nl, - num_pdcch_symbols,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->mcs, - pmi2hex_2Ar1(phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->pmi_alloc), - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->round); -#endif - - phy_vars_eNB->eNB_UE_stats[(uint8_t)UE_id].dlsch_sliding_cnt++; - - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->harq_processes[harq_pid]->round == 0) { - - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].dlsch_trials[harq_pid][0]++; - - if (phy_vars_eNB->mac_enabled==1) { - DLSCH_pdu = mac_xface->get_dlsch_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, - phy_vars_eNB->proc[sched_subframe].frame_tx, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti, - 0); - phy_vars_eNB->eNB_UE_stats[UE_id].total_TBS_MAC += phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->TBS; - } - else { - DLSCH_pdu = DLSCH_pdu_tmp; - - for (i=0; iproc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %"PRIu8"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); - smbv_configure_datalist_for_user(smbv_fname, UE_id+1, DLSCH_pdu, input_buffer_length); - } - -#endif - - -#ifdef DEBUG_PHY_PROC -#ifdef DEBUG_DLSCH - LOG_T(PHY,"eNB DLSCH SDU: \n"); - - for (i=0; idlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->TBS>>3; i++) - LOG_T(PHY,"%"PRIx8".",DLSCH_pdu[i]); - - LOG_T(PHY,"\n"); -#endif -#endif - } else { - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].dlsch_trials[harq_pid][phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->round]++; -#ifdef DEBUG_PHY_PROC -#ifdef DEBUG_DLSCH - LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n"); -#endif -#endif - } - - if (abstraction_flag==0) { - - // 36-212 - start_meas(&phy_vars_eNB->dlsch_encoding_stats); - dlsch_encoding(DLSCH_pdu, - &phy_vars_eNB->lte_frame_parms, - num_pdcch_symbols, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0], - phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - &phy_vars_eNB->dlsch_rate_matching_stats, - &phy_vars_eNB->dlsch_turbo_encoding_stats, - &phy_vars_eNB->dlsch_interleaving_stats); - stop_meas(&phy_vars_eNB->dlsch_encoding_stats); - // 36-211 - start_meas(&phy_vars_eNB->dlsch_scrambling_stats); - dlsch_scrambling(&phy_vars_eNB->lte_frame_parms, - 0, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0], - get_G(&phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->rb_alloc, - get_Qm(phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->mcs), - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->Nl, - num_pdcch_symbols,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe), - 0, - subframe<<1); - stop_meas(&phy_vars_eNB->dlsch_scrambling_stats); - start_meas(&phy_vars_eNB->dlsch_modulation_stats); - - - re_allocated = dlsch_modulation(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - AMP, - subframe, - &phy_vars_eNB->lte_frame_parms, - num_pdcch_symbols, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0], - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][1]); - - stop_meas(&phy_vars_eNB->dlsch_modulation_stats); - } - -#ifdef PHY_ABSTRACTION - else { - start_meas(&phy_vars_eNB->dlsch_encoding_stats); - dlsch_encoding_emul(phy_vars_eNB, - DLSCH_pdu, - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]); - stop_meas(&phy_vars_eNB->dlsch_encoding_stats); - } - -#endif - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->active = 0; - } - else if ((phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0])&& - (phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti>0)&& - (phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->active == 0)) { + else if ((eNB->dlsch_eNB[(uint8_t)UE_id][0])&& + (eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti>0)&& + (eNB->dlsch_eNB[(uint8_t)UE_id][0]->active == 0)) { // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->subframe_tx[subframe]=0; + eNB->dlsch_eNB[(uint8_t)UE_id][0]->subframe_tx[subframe]=0; } } @@ -1604,9 +1514,9 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e // if we have PHICH to generate - if (is_phich_subframe(&phy_vars_eNB->lte_frame_parms,subframe)) + if (is_phich_subframe(fp,subframe)) { - generate_phich_top(phy_vars_eNB, + generate_phich_top(eNB, sched_subframe, AMP, 0, @@ -1616,60 +1526,59 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e #ifdef EMOS - phy_procedures_emos_eNB_TX(subframe, phy_vars_eNB); + phy_procedures_emos_eNB_TX(subframe, eNB); #endif #if !(defined(EXMIMO) || defined(OAI_USRP) || defined (CPRIGW)) if (abstraction_flag==0) { - start_meas(&phy_vars_eNB->ofdm_mod_stats); - do_OFDM_mod(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - phy_vars_eNB->lte_eNB_common_vars.txdata[0], - phy_vars_eNB->proc[sched_subframe].frame_tx,subframe<<1, - &phy_vars_eNB->lte_frame_parms); - do_OFDM_mod(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], - phy_vars_eNB->lte_eNB_common_vars.txdata[0], - phy_vars_eNB->proc[sched_subframe].frame_tx,1+(subframe<<1), - &phy_vars_eNB->lte_frame_parms); - stop_meas(&phy_vars_eNB->ofdm_mod_stats); + start_meas(&eNB->ofdm_mod_stats); + do_OFDM_mod(eNB->lte_eNB_common_vars.txdataF[0], + eNB->lte_eNB_common_vars.txdata[0], + eNB->proc[sched_subframe].frame_tx,subframe<<1, + fp); + do_OFDM_mod(eNB->lte_eNB_common_vars.txdataF[0], + eNB->lte_eNB_common_vars.txdata[0], + eNB->proc[sched_subframe].frame_tx,1+(subframe<<1), + fp); + stop_meas(&eNB->ofdm_mod_stats); } #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,0); - stop_meas(&phy_vars_eNB->phy_proc_tx); + stop_meas(&eNB->phy_proc_tx); - (void)re_allocated; /* remove gcc warning "set but not used" */ } -void process_Msg3(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t UE_id, uint8_t harq_pid) +void process_Msg3(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t UE_id, uint8_t harq_pid) { // this prepares the demodulation of the first PUSCH of a new user, containing Msg3 - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; + int subframe = eNB->proc[sched_subframe].subframe_rx; + int frame = eNB->proc[sched_subframe].frame_rx; LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame,subframe, - UE_id,phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active, - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe, - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame); - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_flag = 0; + UE_id,eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active, + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe, + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame); + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_flag = 0; - if ((phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active == 1) && - (phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe == subframe) && - (phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame == (uint32_t)frame)) { + if ((eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active == 1) && + (eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe == subframe) && + (eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame == (uint32_t)frame)) { // harq_pid = 0; - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active = 0; - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_flag = 1; - phy_vars_eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag=1; + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active = 0; + eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_flag = 1; + eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag=1; LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame,subframe,UE_id); } } @@ -1682,39 +1591,41 @@ void process_Msg3(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t UE_i void process_HARQ_feedback(uint8_t UE_id, uint8_t sched_subframe, - PHY_VARS_eNB *phy_vars_eNB, + PHY_VARS_eNB *eNB, uint8_t pusch_flag, uint8_t *pucch_payload, uint8_t pucch_sel, uint8_t SR_payload) { + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe; - LTE_eNB_DLSCH_t *dlsch = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]; - LTE_eNB_UE_stats *ue_stats = &phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id]; + LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_eNB[(uint32_t)UE_id][0]; + LTE_eNB_UE_stats *ue_stats = &eNB->eNB_UE_stats[(uint32_t)UE_id]; LTE_DL_eNB_HARQ_t *dlsch_harq_proc; uint8_t subframe_m4,M,m; int mp; int all_ACKed=1,nb_alloc=0,nb_ACK=0; - int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - int harq_pid = subframe2harq_pid( &phy_vars_eNB->lte_frame_parms,frame,subframe); + int frame = eNB->proc[sched_subframe].frame_rx; + int subframe = eNB->proc[sched_subframe].subframe_rx; + int harq_pid = subframe2harq_pid( fp,frame,subframe); - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { //FDD + + if (fp->frame_type == FDD) { //FDD subframe_m4 = (subframe<4) ? subframe+6 : subframe-4; dl_harq_pid[0] = dlsch->harq_ids[subframe_m4]; M=1; if (pusch_flag == 1) { - dlsch_ACK[0] = phy_vars_eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; + dlsch_ACK[0] = eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; if (dlsch->subframe_tx[subframe_m4]==1) - LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUSCH for subframe %d\n",phy_vars_eNB->Mod_id, + LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUSCH for subframe %d\n",eNB->Mod_id, frame,dlsch_ACK[0],subframe_m4); } else { dlsch_ACK[0] = pucch_payload[0]; - LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",phy_vars_eNB->Mod_id, + LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id, frame,dlsch_ACK[0],subframe_m4); /* if (dlsch_ACK[0]==0) @@ -1738,7 +1649,7 @@ void process_HARQ_feedback(uint8_t UE_id, #endif } else { // TDD Handle M=1,2 cases only - M=ul_ACK_subframe2_M(&phy_vars_eNB->lte_frame_parms, + M=ul_ACK_subframe2_M(fp, subframe); // Now derive ACK information for TDD @@ -1749,10 +1660,9 @@ void process_HARQ_feedback(uint8_t UE_id, // otherwise, it depends on how many of the PDSCH in the set are scheduled, we can leave it like this, // but we have to adapt the code below. For example, if only one out of 2 are scheduled, only 1 bit o_ACK is used - dlsch_ACK[0] = phy_vars_eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; - dlsch_ACK[1] = (phy_vars_eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling) - ?phy_vars_eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]:phy_vars_eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[1]; - // printf("UE %d: ACK %d,%d\n",UE_id,dlsch_ACK[0],dlsch_ACK[1]); + dlsch_ACK[0] = eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; + dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling) + ?eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]:eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[1]; } else { // PUCCH ACK/NAK @@ -1773,7 +1683,6 @@ void process_HARQ_feedback(uint8_t UE_id, nb_ACK = 3; } } else if (pucch_sel == 2) { // bundling or M=1 - // printf("*** (%d,%d)\n",pucch_payload[0],pucch_payload[1]); dlsch_ACK[0] = pucch_payload[0]; dlsch_ACK[1] = pucch_payload[0]; } else { // multiplexing with no SR, this is table 10.1 @@ -1801,7 +1710,7 @@ void process_HARQ_feedback(uint8_t UE_id, nb_alloc = 0; for (m=0; mlte_frame_parms, + dl_subframe = ul_ACK_subframe2_dl_subframe(fp, subframe, m); @@ -1813,14 +1722,12 @@ void process_HARQ_feedback(uint8_t UE_id, all_ACKed = 1; else all_ACKed = 0; - - // printf("nb_alloc %d, all_ACKed %d\n",nb_alloc,all_ACKed); } for (m=0,mp=-1; mlte_frame_parms, + dl_subframe = ul_ACK_subframe2_dl_subframe(fp, subframe, m); @@ -1842,7 +1749,7 @@ void process_HARQ_feedback(uint8_t UE_id, if (dl_harq_pid[m]Mdlharq) { dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]]; #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",phy_vars_eNB->Mod_id, + LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id, dlsch->rnti,dl_harq_pid[m],dl_subframe, dlsch_harq_proc->status,dlsch_harq_proc->round, dlsch->harq_processes[dl_harq_pid[m]]->mcs, @@ -1858,11 +1765,10 @@ void process_HARQ_feedback(uint8_t UE_id, (dlsch_harq_proc->status == ACTIVE)) { // dl_harq_pid of DLSCH is still active - // msg("[PHY] eNB %d Process %d is active (%d)\n",phy_vars_eNB->Mod_id,dl_harq_pid[m],dlsch_ACK[m]); if ( dlsch_ACK[mp]==0) { // Received NAK #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x/%d] M = %d, m= %d, mp=%d NAK Received in round %d, requesting retransmission\n",phy_vars_eNB->Mod_id, + LOG_D(PHY,"[eNB %d][PDSCH %x/%d] M = %d, m= %d, mp=%d NAK Received in round %d, requesting retransmission\n",eNB->Mod_id, dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round); #endif @@ -1879,7 +1785,7 @@ void process_HARQ_feedback(uint8_t UE_id, if (dlsch_harq_proc->round == dlsch->Mlimit) { // This was the last round for DLSCH so reset round and increment l2_error counter #ifdef DEBUG_PHY_PROC - LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",phy_vars_eNB->Mod_id, + LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",eNB->Mod_id, dlsch->rnti,dl_harq_pid[m]); #endif #if defined(MESSAGE_CHART_GENERATOR_PHY) @@ -1896,7 +1802,7 @@ void process_HARQ_feedback(uint8_t UE_id, } } else { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",phy_vars_eNB->Mod_id, + LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id, dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round); #endif ue_stats->dlsch_ACK[dl_harq_pid[m]][dlsch_harq_proc->round]++; @@ -1908,10 +1814,10 @@ void process_HARQ_feedback(uint8_t UE_id, dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq; ue_stats->total_TBS = ue_stats->total_TBS + - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; + eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; /* ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits + - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; + eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; */ } @@ -1954,7 +1860,7 @@ void process_HARQ_feedback(uint8_t UE_id, } } -void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, +void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, uint8_t UE_id, uint8_t sched_subframe, int16_t *n1_pucch0, @@ -1963,18 +1869,17 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, int16_t *n1_pucch3) { - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&eNB->lte_frame_parms; uint8_t nCCE0,nCCE1; int sf; - int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; + int frame = eNB->proc[sched_subframe].frame_rx; + int subframe = eNB->proc[sched_subframe].subframe_rx; if (frame_parms->frame_type == FDD ) { sf = (subframe<4) ? (subframe+6) : (subframe-4); - // printf("n1_pucch_eNB: subframe %d, nCCE %d\n",sf,phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[sf]); - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[sf]>0) { - *n1_pucch0 = frame_parms->pucch_config_common.n1PUCCH_AN + phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[sf]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[sf]>0) { + *n1_pucch0 = frame_parms->pucch_config_common.n1PUCCH_AN + eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[sf]; *n1_pucch1 = -1; } else { *n1_pucch0 = -1; @@ -1985,15 +1890,15 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, switch (frame_parms->tdd_config) { case 1: // DL:S:UL:UL:DL:DL:S:UL:UL:DL if (subframe == 2) { // ACK subframes 5 and 6 - /* if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[6]>0) { - nCCE1 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[6]; + /* if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[6]>0) { + nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[6]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch1 = -1;*/ - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[5]>0) { - nCCE0 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[5]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[5]>0) { + nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[5]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -2001,8 +1906,8 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, *n1_pucch1 = -1; } else if (subframe == 3) { // ACK subframe 9 - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[9]>0) { - nCCE0 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[9]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[9]>0) { + nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[9]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -2012,8 +1917,8 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, } else if (subframe == 7) { // ACK subframes 0 and 1 //harq_ack[0].nCCE; //harq_ack[1].nCCE; - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[0]>0) { - nCCE0 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[0]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[0]>0) { + nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[0]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -2021,8 +1926,8 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, *n1_pucch1 = -1; } else if (subframe == 8) { // ACK subframes 4 //harq_ack[4].nCCE; - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[4]>0) { - nCCE0 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[4]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[4]>0) { + nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[4]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -2030,7 +1935,7 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, *n1_pucch1 = -1; } else { LOG_D(PHY,"[eNB %d] frame %d: phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame, subframe,frame_parms->tdd_config); return; @@ -2040,49 +1945,49 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, case 3: // DL:S:UL:UL:UL:DL:DL:DL:DL:DL if (subframe == 2) { // ACK subframes 5,6 and 1 (S in frame-2), forget about n-11 for the moment (S-subframe) - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[6]>0) { - nCCE1 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[6]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[6]>0) { + nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[6]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch1 = -1; - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[5]>0) { - nCCE0 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[5]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[5]>0) { + nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[5]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; } else if (subframe == 3) { // ACK subframes 7 and 8 LOG_D(PHY,"get_n1_pucch_eNB : subframe 3, subframe_tx[7] %d, subframe_tx[8] %d\n", - phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[7],phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[8]); + eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[8]); - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[8]>0) { - nCCE1 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[8]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[8]>0) { + nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[8]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; LOG_D(PHY,"nCCE1 %d, n1_pucch1 %d\n",nCCE1,*n1_pucch1); } else *n1_pucch1 = -1; - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[7]>0) { - nCCE0 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[7]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[7]>0) { + nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[7]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN; LOG_D(PHY,"nCCE0 %d, n1_pucch0 %d\n",nCCE0,*n1_pucch0); } else *n1_pucch0 = -1; } else if (subframe == 4) { // ACK subframes 9 and 0 - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[0]>0) { - nCCE1 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[0]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[0]>0) { + nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[0]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch1 = -1; - if (phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[9]>0) { - nCCE0 = phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[9]; + if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[9]>0) { + nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[9]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; } else { LOG_D(PHY,"[eNB %d] Frame %d: phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", - phy_vars_eNB->Mod_id,frame,subframe,frame_parms->tdd_config); + eNB->Mod_id,frame,subframe,frame_parms->tdd_config); return; } @@ -2095,26 +2000,27 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, } } -void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t abstraction_flag) +void prach_procedures(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t abstraction_flag) { + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; uint16_t preamble_energy_list[64],preamble_delay_list[64]; uint16_t preamble_max,preamble_energy_max; uint16_t i; int8_t UE_id; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; - uint8_t CC_id = phy_vars_eNB->CC_id; + int subframe = eNB->proc[sched_subframe].subframe_rx; + int frame = eNB->proc[sched_subframe].frame_rx; + uint8_t CC_id = eNB->CC_id; memset(&preamble_energy_list[0],0,64*sizeof(uint16_t)); memset(&preamble_delay_list[0],0,64*sizeof(uint16_t)); if (abstraction_flag == 0) { - LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",phy_vars_eNB->Mod_id, - frame,subframe,dB_fixed(signal_energy(&phy_vars_eNB->lte_eNB_common_vars.rxdata[0][0][subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti],512)) - phy_vars_eNB->rx_total_gain_eNB_dB); + LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id, + frame,subframe,dB_fixed(signal_energy(&eNB->lte_eNB_common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_eNB_dB); - rx_prach(phy_vars_eNB, + rx_prach(eNB, subframe, preamble_energy_list, preamble_delay_list, @@ -2126,12 +2032,12 @@ void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n", UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach, PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.prach_config_common.rootSequenceIndex, - phy_vars_eNB->lte_frame_parms.prach_config_common.rootSequenceIndex, + fp->prach_config_common.rootSequenceIndex, PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex); if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) && (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.prach_config_common.rootSequenceIndex == - phy_vars_eNB->lte_frame_parms.prach_config_common.rootSequenceIndex) ) { + fp->prach_config_common.rootSequenceIndex) ) { preamble_energy_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 800; preamble_delay_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 5; @@ -2158,15 +2064,15 @@ void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t if (preamble_energy_list[preamble_max] > 580) { - UE_id = find_next_ue_index(phy_vars_eNB); + UE_id = find_next_ue_index(eNB); if (UE_id>=0) { - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits + eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].sector = 0; + eNB->eNB_UE_stats[(uint32_t)UE_id].sector = 0; LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", - phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + eNB->Mod_id, + eNB->CC_id, frame, subframe, UE_id, @@ -2175,10 +2081,10 @@ void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t preamble_energy_max%10, preamble_delay_list[preamble_max]); - if (phy_vars_eNB->mac_enabled==1) { + if (eNB->mac_enabled==1) { uint8_t update_TA=4; - switch (phy_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (fp->N_RB_DL) { case 6: update_TA = 16; break; @@ -2196,8 +2102,8 @@ void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t break; } - mac_xface->initiate_ra_proc(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + mac_xface->initiate_ra_proc(eNB->Mod_id, + eNB->CC_id, frame, preamble_max, preamble_delay_list[preamble_max]*update_TA, @@ -2207,24 +2113,24 @@ void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t } else { MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many"); LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n", - phy_vars_eNB->Mod_id,frame, subframe); + eNB->Mod_id,frame, subframe); } } } -void ulsch_decoding_procedures(unsigned char subframe, unsigned int i, PHY_VARS_eNB *phy_vars_eNB, unsigned char abstraction_flag) +void ulsch_decoding_procedures(unsigned char subframe, unsigned int i, PHY_VARS_eNB *eNB, unsigned char abstraction_flag) { UNUSED(subframe); UNUSED(i); - UNUSED(phy_vars_eNB); + UNUSED(eNB); UNUSED(abstraction_flag); LOG_D(PHY,"ulsch_decoding_procedures not yet implemented. should not be called"); } -void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0}; int16_t n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3; uint8_t do_SR = 0; @@ -2233,20 +2139,20 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ ANFBmode_t bundling_flag; PUCCH_FMT_t format; - const int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - const int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; + const int subframe = eNB->proc[sched_subframe].subframe_rx; + const int frame = eNB->proc[sched_subframe].frame_rx; - if ((phy_vars_eNB->dlsch_eNB[UE_id][0]) && - (phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti>0) && - (phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { + if ((eNB->dlsch_eNB[UE_id][0]) && + (eNB->dlsch_eNB[UE_id][0]->rnti>0) && + (eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { // check SR availability - do_SR = is_SR_subframe(phy_vars_eNB,UE_id,sched_subframe); + do_SR = is_SR_subframe(eNB,UE_id,sched_subframe); // do_SR = 0; // Now ACK/NAK // First check subframe_tx flag for earlier subframes - get_n1_pucch_eNB(phy_vars_eNB, + get_n1_pucch_eNB(eNB, UE_id, sched_subframe, &n1_pucch0, @@ -2255,7 +2161,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ &n1_pucch3); LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti, + eNB->Mod_id,eNB->dlsch_eNB[UE_id][0]->rnti, frame,subframe, n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR); @@ -2264,41 +2170,41 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ // otherwise we have some PUCCH detection to do // Null out PUCCH PRBs for noise measurement - switch(phy_vars_eNB->lte_frame_parms.N_RB_UL) { + switch(fp->N_RB_UL) { case 6: - phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5 + eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5 break; case 15: - phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14 + eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14 break; case 25: - phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24 + eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24 break; case 50: - phy_vars_eNB->rb_mask_ul[0] |= 0x1; - phy_vars_eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32) + eNB->rb_mask_ul[0] |= 0x1; + eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32) break; case 75: - phy_vars_eNB->rb_mask_ul[0] |= 0x1; - phy_vars_eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64) + eNB->rb_mask_ul[0] |= 0x1; + eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64) break; case 100: - phy_vars_eNB->rb_mask_ul[0] |= 0x1; - phy_vars_eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96) + eNB->rb_mask_ul[0] |= 0x1; + eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96) break; default: - LOG_E(PHY,"Unknown number for N_RB_UL %d\n",phy_vars_eNB->lte_frame_parms.N_RB_UL); + LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL); break; } if (do_SR == 1) { - phy_vars_eNB->eNB_UE_stats[UE_id].sr_total++; + eNB->eNB_UE_stats[UE_id].sr_total++; if (abstraction_flag == 0) - metric0_SR = rx_pucch(phy_vars_eNB, + metric0_SR = rx_pucch(eNB, pucch_format1, UE_id, - phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, + eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, 0, // n2_pucch 0, // shortened format, should be use_srs flag, later &SR_payload, @@ -2307,56 +2213,56 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ #ifdef PHY_ABSTRACTION else { - metric0_SR = rx_pucch_emul(phy_vars_eNB, + metric0_SR = rx_pucch_emul(eNB, UE_id, pucch_format1, 0, &SR_payload, sched_subframe); - LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",phy_vars_eNB->Mod_id, - phy_vars_eNB->ulsch_eNB[UE_id]->rnti,frame,subframe,SR_payload,phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); + LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",eNB->Mod_id, + eNB->ulsch_eNB[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); } #endif if (SR_payload == 1) { - LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",phy_vars_eNB->Mod_id, - phy_vars_eNB->ulsch_eNB[UE_id]->rnti,frame,subframe); - phy_vars_eNB->eNB_UE_stats[UE_id].sr_received++; + LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id, + eNB->ulsch_eNB[UE_id]->rnti,frame,subframe); + eNB->eNB_UE_stats[UE_id].sr_received++; - if (phy_vars_eNB->first_sr[UE_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4 + if (eNB->first_sr[UE_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4 /* is this test necessary? */ - if (phy_vars_eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->status != SCH_IDLE) - put_harq_pid_in_freelist(phy_vars_eNB->dlsch_eNB[UE_id][0], 0); - phy_vars_eNB->first_sr[UE_id] = 0; - phy_vars_eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->round=0; - phy_vars_eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->status=SCH_IDLE; + if (eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->status != SCH_IDLE) + put_harq_pid_in_freelist(eNB->dlsch_eNB[UE_id][0], 0); + eNB->first_sr[UE_id] = 0; + eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->round=0; + eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->status=SCH_IDLE; LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n", - phy_vars_eNB->Mod_id, - phy_vars_eNB->ulsch_eNB[UE_id]->rnti,frame,subframe); + eNB->Mod_id, + eNB->ulsch_eNB[UE_id]->rnti,frame,subframe); } - if (phy_vars_eNB->mac_enabled==1) { - mac_xface->SR_indication(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + if (eNB->mac_enabled==1) { + mac_xface->SR_indication(eNB->Mod_id, + eNB->CC_id, frame, - phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti,subframe); + eNB->dlsch_eNB[UE_id][0]->rnti,subframe); } } }// do_SR==1 if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR - } else if (phy_vars_eNB->lte_frame_parms.frame_type==FDD) { // FDD + } else if (fp->frame_type==FDD) { // FDD // if SR was detected, use the n1_pucch from SR, else use n1_pucch0 - // n1_pucch0 = (SR_payload==1) ? phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0; + // n1_pucch0 = (SR_payload==1) ? eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0; - LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload); + LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload); if (abstraction_flag == 0) { - metric0 = rx_pucch(phy_vars_eNB, + metric0 = rx_pucch(eNB, pucch_format1a, UE_id, (uint16_t)n1_pucch0, @@ -2367,10 +2273,10 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ PUCCH1a_THRES); if (metric0 < metric0_SR) - metric0=rx_pucch(phy_vars_eNB, + metric0=rx_pucch(eNB, pucch_format1a, UE_id, - phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, + eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, 0, //n2_pucch 0, // shortened format pucch_payload0, @@ -2379,7 +2285,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ } else { #ifdef PHY_ABSTRACTION - metric0 = rx_pucch_emul(phy_vars_eNB,UE_id, + metric0 = rx_pucch_emul(eNB,UE_id, pucch_format1a, 0, pucch_payload0, @@ -2389,13 +2295,13 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n", - phy_vars_eNB->Mod_id, - phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti, + eNB->Mod_id, + eNB->dlsch_eNB[UE_id][0]->rnti, frame,subframe, pucch_payload0[0],metric0); #endif - process_HARQ_feedback(UE_id,sched_subframe,phy_vars_eNB, + process_HARQ_feedback(UE_id,sched_subframe,eNB, 0,// pusch_flag pucch_payload0, 2, @@ -2404,34 +2310,32 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ } // FDD else { //TDD - bundling_flag = phy_vars_eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode; + bundling_flag = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode; // fix later for 2 TB case and format1b - if ((frame_parms->frame_type==FDD) || + if ((fp->frame_type==FDD) || (bundling_flag==bundling) || - ((frame_parms->frame_type==TDD)&&(frame_parms->tdd_config==1)&&((subframe!=2)||(subframe!=7)))) { + ((fp->frame_type==TDD)&&(fp->tdd_config==1)&&((subframe!=2)||(subframe!=7)))) { format = pucch_format1a; - // msg("PUCCH 1a\n"); - } else { + } else { format = pucch_format1b; - // msg("PUCCH 1b\n"); - } + } // if SR was detected, use the n1_pucch from SR if (SR_payload==1) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",phy_vars_eNB->Mod_id, - phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti, + LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",eNB->Mod_id, + eNB->dlsch_eNB[UE_id][0]->rnti, frame,subframe, n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format); #endif if (abstraction_flag == 0) - metric0_SR = rx_pucch(phy_vars_eNB, + metric0_SR = rx_pucch(eNB, format, UE_id, - phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, + eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, 0, //n2_pucch 0, // shortened format pucch_payload0, @@ -2439,7 +2343,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ PUCCH1a_THRES); else { #ifdef PHY_ABSTRACTION - metric0 = rx_pucch_emul(phy_vars_eNB,UE_id, + metric0 = rx_pucch_emul(eNB,UE_id, format, 0, pucch_payload0, @@ -2448,8 +2352,8 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ } } else { //using n1_pucch0/n1_pucch1 resources #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",phy_vars_eNB->Mod_id, - phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti, + LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",eNB->Mod_id, + eNB->dlsch_eNB[UE_id][0]->rnti, frame,subframe, n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format); #endif @@ -2459,7 +2363,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ // Check n1_pucch0 metric if (n1_pucch0 != -1) { if (abstraction_flag == 0) - metric0 = rx_pucch(phy_vars_eNB, + metric0 = rx_pucch(eNB, format, UE_id, (uint16_t)n1_pucch0, @@ -2470,7 +2374,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ PUCCH1a_THRES); else { #ifdef PHY_ABSTRACTION - metric0 = rx_pucch_emul(phy_vars_eNB,UE_id, + metric0 = rx_pucch_emul(eNB,UE_id, format, 0, pucch_payload0, @@ -2482,7 +2386,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ // Check n1_pucch1 metric if (n1_pucch1 != -1) { if (abstraction_flag == 0) - metric1 = rx_pucch(phy_vars_eNB, + metric1 = rx_pucch(eNB, format, UE_id, (uint16_t)n1_pucch1, @@ -2493,7 +2397,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ PUCCH1a_THRES); else { #ifdef PHY_ABSTRACTION - metric1 = rx_pucch_emul(phy_vars_eNB,UE_id, + metric1 = rx_pucch_emul(eNB,UE_id, format, 1, pucch_payload1, @@ -2523,12 +2427,12 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ } #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",phy_vars_eNB->Mod_id, - phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti, + LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",eNB->Mod_id, + eNB->dlsch_eNB[UE_id][0]->rnti, frame,subframe, metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]); #endif - process_HARQ_feedback(UE_id,sched_subframe,phy_vars_eNB, + process_HARQ_feedback(UE_id,sched_subframe,eNB, 0,// pusch_flag pucch_payload, pucch_sel, @@ -2539,61 +2443,62 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_ } } -void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { uint8_t access_mode; int num_active_cba_groups; - const int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - const int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; + const int subframe = eNB->proc[sched_subframe].subframe_rx; + const int frame = eNB->proc[sched_subframe].frame_rx; uint16_t rnti=0; int ret=0; + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; - num_active_cba_groups = phy_vars_eNB->ulsch_eNB[UE_id]->num_active_cba_groups; + num_active_cba_groups = eNB->ulsch_eNB[UE_id]->num_active_cba_groups; - if ((phy_vars_eNB->ulsch_eNB[UE_id]) && + if ((eNB->ulsch_eNB[UE_id]) && (num_active_cba_groups > 0) && - (phy_vars_eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups]>0) && - (phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1)) { + (eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups]>0) && + (eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1)) { rnti=0; #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Checking PUSCH/ULSCH CBA Reception for UE %d with cba rnti %x mode %s\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe, - UE_id, (uint16_t)phy_vars_eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[phy_vars_eNB->eNB_UE_stats[UE_id].mode]); + UE_id, (uint16_t)eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->eNB_UE_stats[UE_id].mode]); #endif if (abstraction_flag==0) { - rx_ulsch(phy_vars_eNB, + rx_ulsch(eNB, sched_subframe, - phy_vars_eNB->eNB_UE_stats[UE_id].sector, // this is the effective sector id + eNB->eNB_UE_stats[UE_id].sector, // this is the effective sector id UE_id, - phy_vars_eNB->ulsch_eNB, + eNB->ulsch_eNB, 0); } #ifdef PHY_ABSTRACTION else { - rx_ulsch_emul(phy_vars_eNB, + rx_ulsch_emul(eNB, subframe, - phy_vars_eNB->eNB_UE_stats[UE_id].sector, // this is the effective sector id + eNB->eNB_UE_stats[UE_id].sector, // this is the effective sector id UE_id); } #endif if (abstraction_flag == 0) { - ret = ulsch_decoding(phy_vars_eNB, + ret = ulsch_decoding(eNB, UE_id, sched_subframe, 0, // control_only_flag - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->V_UL_DAI, - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->V_UL_DAI, + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); } #ifdef PHY_ABSTRACTION else { - ret = ulsch_decoding_emul(phy_vars_eNB, + ret = ulsch_decoding_emul(eNB, sched_subframe, UE_id, &rnti); @@ -2601,60 +2506,60 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eN #endif - if (phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) { + if (eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) { #ifdef DEBUG_PHY_PROC - print_CQI(phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o,phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->uci_format,0,phy_vars_eNB->lte_frame_parms.N_RB_DL); + print_CQI(eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o,eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL); #endif access_mode = UNKNOWN_ACCESS; - extract_CQI(phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o, - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->uci_format, - &phy_vars_eNB->eNB_UE_stats[UE_id], - phy_vars_eNB->lte_frame_parms.N_RB_DL, + extract_CQI(eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o, + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->uci_format, + &eNB->eNB_UE_stats[UE_id], + fp->N_RB_DL, &rnti, &access_mode); - phy_vars_eNB->eNB_UE_stats[UE_id].rank = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o_RI[0]; + eNB->eNB_UE_stats[UE_id].rank = eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o_RI[0]; } - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0; - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE; if ((num_active_cba_groups > 0) && (UE_id + num_active_cba_groups < NUMBER_OF_UE_MAX) && - (phy_vars_eNB->ulsch_eNB[UE_id+num_active_cba_groups]->cba_rnti[UE_id%num_active_cba_groups] > 0 ) && - (phy_vars_eNB->ulsch_eNB[UE_id+num_active_cba_groups]->num_active_cba_groups> 0)) { + (eNB->ulsch_eNB[UE_id+num_active_cba_groups]->cba_rnti[UE_id%num_active_cba_groups] > 0 ) && + (eNB->ulsch_eNB[UE_id+num_active_cba_groups]->num_active_cba_groups> 0)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d resetting the subframe_scheduling_flag for Ue %d cba groups %d members\n", - phy_vars_eNB->Mod_id,harq_pid,frame,subframe,UE_id,harq_pid, - UE_id+num_active_cba_groups, UE_id%phy_vars_eNB->ulsch_eNB[UE_id]->num_active_cba_groups); + eNB->Mod_id,harq_pid,frame,subframe,UE_id,harq_pid, + UE_id+num_active_cba_groups, UE_id%eNB->ulsch_eNB[UE_id]->num_active_cba_groups); #endif - phy_vars_eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=1; - phy_vars_eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->status= CBA_ACTIVE; - phy_vars_eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->TBS=phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS; + eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=1; + eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->status= CBA_ACTIVE; + eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->TBS=eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS; } if (ret == (1+MAX_TURBO_ITERATIONS)) { - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_round_errors[harq_pid][phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round]++; - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active = 1; - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK = 0; - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round++; + eNB->eNB_UE_stats[UE_id].ulsch_round_errors[harq_pid][eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round]++; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK = 0; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round++; } // ulsch in error else { LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe); - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active = 1; - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK = 1; - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round = 0; - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_consecutive_errors = 0; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK = 1; + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round = 0; + eNB->eNB_UE_stats[UE_id].ulsch_consecutive_errors = 0; #ifdef DEBUG_PHY_PROC #ifdef DEBUG_ULSCH LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:", frame,subframe, - harq_pid,phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3); + harq_pid,eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3); - for (j=0; julsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->b[j]); + for (j=0; julsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3; j++) + LOG_T(PHY,"%x.",eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->b[j]); LOG_T(PHY,"\n"); #endif @@ -2662,37 +2567,37 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eN if (access_mode > UNKNOWN_ACCESS) { LOG_D(PHY,"[eNB %d] Frame %d, Subframe %d : received ULSCH SDU from CBA transmission, UE (%d,%x), CBA (group %d, rnti %x)\n", - phy_vars_eNB->Mod_id, frame,subframe, - UE_id, phy_vars_eNB->ulsch_eNB[UE_id]->rnti, - UE_id % phy_vars_eNB->ulsch_eNB[UE_id]->num_active_cba_groups, phy_vars_eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups]); + eNB->Mod_id, frame,subframe, + UE_id, eNB->ulsch_eNB[UE_id]->rnti, + UE_id % eNB->ulsch_eNB[UE_id]->num_active_cba_groups, eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups]); // detect if there is a CBA collision - if (phy_vars_eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) { - mac_xface->rx_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) { + mac_xface->rx_sdu(eNB->Mod_id, + eNB->CC_id, frame,subframe, - phy_vars_eNB->ulsch_eNB[UE_id]->rnti, - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->b, - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3, + eNB->ulsch_eNB[UE_id]->rnti, + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->b, + eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3, harq_pid, NULL); - phy_vars_eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1;//(subframe); + eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1;//(subframe); } else { - if (phy_vars_eNB->cba_last_reception[UE_id%num_active_cba_groups] == 1 ) + if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 1 ) LOG_N(PHY,"[eNB%d] Frame %d subframe %d : first CBA collision detected \n ", - phy_vars_eNB->Mod_id,frame,subframe); + eNB->Mod_id,frame,subframe); LOG_N(PHY,"[eNB%d] Frame %d subframe %d : CBA collision set SR for UE %d in group %d \n ", - phy_vars_eNB->Mod_id,frame,subframe, - phy_vars_eNB->cba_last_reception[UE_id%num_active_cba_groups],UE_id%num_active_cba_groups ); + eNB->Mod_id,frame,subframe, + eNB->cba_last_reception[UE_id%num_active_cba_groups],UE_id%num_active_cba_groups ); - phy_vars_eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1; + eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1; - mac_xface->SR_indication(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + mac_xface->SR_indication(eNB->Mod_id, + eNB->CC_id, frame, - phy_vars_eNB->dlsch_eNB[UE_id][0]->rnti,subframe); + eNB->dlsch_eNB[UE_id][0]->rnti,subframe); } } // UNKNOWN_ACCESS } // ULSCH CBA not in error @@ -2700,61 +2605,61 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eN } -void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eNB,const uint8_t abstraction_flag,const relaying_type_t r_type) +void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,const uint8_t abstraction_flag,const relaying_type_t r_type) { //RX processing UNUSED(r_type); uint32_t l, ret=0,i,j,k; uint32_t harq_pid, harq_idx, round; uint8_t nPRS; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms; int sync_pos; uint16_t rnti=0; uint8_t access_mode; + LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; - const int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - const int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; + const int subframe = eNB->proc[sched_subframe].subframe_rx; + const int frame = eNB->proc[sched_subframe].frame_rx; AssertFatal(sched_subframe < NUM_ENB_THREADS, "Bad sched_subframe %d", sched_subframe); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1); - start_meas(&phy_vars_eNB->phy_proc_rx); + start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",phy_vars_eNB->Mod_id,frame, subframe); + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); #endif - phy_vars_eNB->rb_mask_ul[0]=0; - phy_vars_eNB->rb_mask_ul[1]=0; - phy_vars_eNB->rb_mask_ul[2]=0; - phy_vars_eNB->rb_mask_ul[3]=0; + eNB->rb_mask_ul[0]=0; + eNB->rb_mask_ul[1]=0; + eNB->rb_mask_ul[2]=0; + eNB->rb_mask_ul[3]=0; if (abstraction_flag == 0) { - remove_7_5_kHz(phy_vars_eNB,subframe<<1); - remove_7_5_kHz(phy_vars_eNB,(subframe<<1)+1); + remove_7_5_kHz(eNB,subframe<<1); + remove_7_5_kHz(eNB,(subframe<<1)+1); } // check if we have to detect PRACH first - if (is_prach_subframe(&phy_vars_eNB->lte_frame_parms,frame,subframe)>0) { + if (is_prach_subframe(fp,frame,subframe)>0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); - prach_procedures(phy_vars_eNB,sched_subframe,abstraction_flag); + prach_procedures(eNB,sched_subframe,abstraction_flag); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } if (abstraction_flag == 0) { - start_meas(&phy_vars_eNB->ofdm_demod_stats); + start_meas(&eNB->ofdm_demod_stats); - for (l=0; llte_frame_parms.symbols_per_tti/2; l++) { + for (l=0; lsymbols_per_tti/2; l++) { - slot_fep_ul(&phy_vars_eNB->lte_frame_parms, - &phy_vars_eNB->lte_eNB_common_vars, + slot_fep_ul(fp, + &eNB->lte_eNB_common_vars, l, subframe<<1, 0, 0 ); - slot_fep_ul(&phy_vars_eNB->lte_frame_parms, - &phy_vars_eNB->lte_eNB_common_vars, + slot_fep_ul(fp, + &eNB->lte_eNB_common_vars, l, (subframe<<1)+1, 0, @@ -2762,265 +2667,265 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ ); } - stop_meas(&phy_vars_eNB->ofdm_demod_stats); + stop_meas(&eNB->ofdm_demod_stats); } // Check for active processes in current subframe - harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms, + harq_pid = subframe2harq_pid(fp, frame,subframe); // reset the cba flag used for collision detection for (i=0; i < NUM_MAX_CBA_GROUP; i++) { - phy_vars_eNB->cba_last_reception[i]=0; + eNB->cba_last_reception[i]=0; } // Do PUCCH processing first for (i=0; imac_enabled==1) { - if (phy_vars_eNB->eNB_UE_stats[i].mode == RA_RESPONSE) { - process_Msg3(phy_vars_eNB,sched_subframe,i,harq_pid); + if (eNB->mac_enabled==1) { + if (eNB->eNB_UE_stats[i].mode == RA_RESPONSE) { + process_Msg3(eNB,sched_subframe,i,harq_pid); } } - phy_vars_eNB->pusch_stats_rb[i][(frame*10)+subframe] = -63; - phy_vars_eNB->pusch_stats_round[i][(frame*10)+subframe] = 0; - phy_vars_eNB->pusch_stats_mcs[i][(frame*10)+subframe] = -63; + eNB->pusch_stats_rb[i][(frame*10)+subframe] = -63; + eNB->pusch_stats_round[i][(frame*10)+subframe] = 0; + eNB->pusch_stats_mcs[i][(frame*10)+subframe] = -63; - if ((phy_vars_eNB->ulsch_eNB[i]) && - (phy_vars_eNB->ulsch_eNB[i]->rnti>0) && - (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) { + if ((eNB->ulsch_eNB[i]) && + (eNB->ulsch_eNB[i]->rnti>0) && + (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) { // UE is has ULSCH scheduling - round = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; + round = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; for (int rb=0; - rb<=phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; + rb<=eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; rb++) { - int rb2 = rb+phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb; - phy_vars_eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + int rb2 = rb+eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb; + eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Scheduling PUSCH/ULSCH Reception for rnti %x (UE_id %d)\n", - phy_vars_eNB->Mod_id,harq_pid, - frame,subframe,phy_vars_eNB->ulsch_eNB[i]->rnti,i); + eNB->Mod_id,harq_pid, + frame,subframe,eNB->ulsch_eNB[i]->rnti,i); #endif - if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame, subframe, - phy_vars_eNB->eNB_UE_stats[i].sector); + eNB->eNB_UE_stats[i].sector); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1); } else { LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame, subframe, i, - mode_string[phy_vars_eNB->eNB_UE_stats[i].mode]); + mode_string[eNB->eNB_UE_stats[i].mode]); } - nPRS = phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]; + nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]; - phy_vars_eNB->ulsch_eNB[i]->cyclicShift = (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2 + phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + + eNB->ulsch_eNB[i]->cyclicShift = (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + nPRS)%12; - if (frame_parms->frame_type == FDD ) { + if (fp->frame_type == FDD ) { int sf = (subframe<4) ? (subframe+6) : (subframe-4); - if (phy_vars_eNB->dlsch_eNB[i][0]->subframe_tx[sf]>0) { // we have downlink transmission - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK = 1; + if (eNB->dlsch_eNB[i][0]->subframe_tx[sf]>0) { // we have downlink transmission + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK = 1; } else { - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK = 0; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK = 0; } } LOG_D(PHY, "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, nprs %d), O_ACK %d \n", - phy_vars_eNB->Mod_id,harq_pid,frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->mcs, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rvidx, - phy_vars_eNB->ulsch_eNB[i]->cyclicShift, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2, - phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, + eNB->Mod_id,harq_pid,frame,subframe, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->mcs, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rvidx, + eNB->ulsch_eNB[i]->cyclicShift, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2, + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, nPRS, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK); - phy_vars_eNB->pusch_stats_rb[i][(frame*10)+subframe] = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; - phy_vars_eNB->pusch_stats_round[i][(frame*10)+subframe] = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; - phy_vars_eNB->pusch_stats_mcs[i][(frame*10)+subframe] = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->mcs; - start_meas(&phy_vars_eNB->ulsch_demodulation_stats); + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK); + eNB->pusch_stats_rb[i][(frame*10)+subframe] = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; + eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; + eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->mcs; + start_meas(&eNB->ulsch_demodulation_stats); if (abstraction_flag==0) { - rx_ulsch(phy_vars_eNB, + rx_ulsch(eNB, sched_subframe, - phy_vars_eNB->eNB_UE_stats[i].sector, // this is the effective sector id + eNB->eNB_UE_stats[i].sector, // this is the effective sector id i, - phy_vars_eNB->ulsch_eNB, + eNB->ulsch_eNB, 0); } #ifdef PHY_ABSTRACTION else { - rx_ulsch_emul(phy_vars_eNB, + rx_ulsch_emul(eNB, subframe, - phy_vars_eNB->eNB_UE_stats[i].sector, // this is the effective sector id + eNB->eNB_UE_stats[i].sector, // this is the effective sector id i); } #endif - stop_meas(&phy_vars_eNB->ulsch_demodulation_stats); + stop_meas(&eNB->ulsch_demodulation_stats); - start_meas(&phy_vars_eNB->ulsch_decoding_stats); + start_meas(&eNB->ulsch_decoding_stats); if (abstraction_flag == 0) { - ret = ulsch_decoding(phy_vars_eNB, + ret = ulsch_decoding(eNB, i, sched_subframe, 0, // control_only_flag - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->V_UL_DAI, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->V_UL_DAI, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); } #ifdef PHY_ABSTRACTION else { - ret = ulsch_decoding_emul(phy_vars_eNB, + ret = ulsch_decoding_emul(eNB, sched_subframe, i, &rnti); } #endif - stop_meas(&phy_vars_eNB->ulsch_decoding_stats); + stop_meas(&eNB->ulsch_decoding_stats); LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti, - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), - phy_vars_eNB->eNB_UE_stats[i].UL_rssi[0], - phy_vars_eNB->eNB_UE_stats[i].UL_rssi[1], - phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[0], - phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[1], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->ulsch_eNB[i]->rnti, + dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), + dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), + eNB->eNB_UE_stats[i].UL_rssi[0], + eNB->eNB_UE_stats[i].UL_rssi[1], + eNB->PHY_measurements_eNB->n0_power_dB[0], + eNB->PHY_measurements_eNB->n0_power_dB[1], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], ret); //compute the expected ULSCH RX power (for the stats) - phy_vars_eNB->ulsch_eNB[(uint32_t)i]->harq_processes[harq_pid]->delta_TF = - get_hundred_times_delta_IF_eNB(phy_vars_eNB,i,harq_pid, 0); // 0 means bw_factor is not considered + eNB->ulsch_eNB[(uint32_t)i]->harq_processes[harq_pid]->delta_TF = + get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered - //dump_ulsch(phy_vars_eNB, sched_subframe, i); + //dump_ulsch(eNB, sched_subframe, i); - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++; + eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++; #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d Clearing subframe_scheduling_flag\n", - phy_vars_eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid); + eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid); #endif - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0; - if (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->cqi_crc_status == 1) { + if (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->cqi_crc_status == 1) { #ifdef DEBUG_PHY_PROC - //if (((phy_vars_eNB->proc[sched_subframe].frame_tx%10) == 0) || (phy_vars_eNB->proc[sched_subframe].frame_tx < 50)) - print_CQI(phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->uci_format,0,phy_vars_eNB->lte_frame_parms.N_RB_DL); + //if (((eNB->proc[sched_subframe].frame_tx%10) == 0) || (eNB->proc[sched_subframe].frame_tx < 50)) + print_CQI(eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o,eNB->ulsch_eNB[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL); #endif - extract_CQI(phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->uci_format, - &phy_vars_eNB->eNB_UE_stats[i], - phy_vars_eNB->lte_frame_parms.N_RB_DL, + extract_CQI(eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->uci_format, + &eNB->eNB_UE_stats[i], + fp->N_RB_DL, &rnti, &access_mode); - phy_vars_eNB->eNB_UE_stats[i].rank = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_RI[0]; + eNB->eNB_UE_stats[i].rank = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_RI[0]; } - if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) + if (eNB->ulsch_eNB[i]->Msg3_flag == 1) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0); if (ret == (1+MAX_TURBO_ITERATIONS)) { - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[harq_pid][phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 0; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round++; + eNB->eNB_UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 0; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round++; - LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round); + LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round); - if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n", - phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + eNB->Mod_id, + eNB->CC_id, frame,subframe, i, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1, - phy_vars_eNB->lte_frame_parms.maxHARQ_Msg3Tx-1); + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1, + fp->maxHARQ_Msg3Tx-1); LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti, - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), - phy_vars_eNB->eNB_UE_stats[i].UL_rssi[0], - phy_vars_eNB->eNB_UE_stats[i].UL_rssi[1], - phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[0], - phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[1], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->ulsch_eNB[i]->rnti, + dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), + dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), + eNB->eNB_UE_stats[i].UL_rssi[0], + eNB->eNB_UE_stats[i].UL_rssi[1], + eNB->PHY_measurements_eNB->n0_power_dB[0], + eNB->PHY_measurements_eNB->n0_power_dB[1], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], ret); - if (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round == - phy_vars_eNB->lte_frame_parms.maxHARQ_Msg3Tx) { + if (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round == + fp->maxHARQ_Msg3Tx) { LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n", - phy_vars_eNB->Mod_id, i); - phy_vars_eNB->eNB_UE_stats[i].mode = PRACH; - if (phy_vars_eNB->mac_enabled==1) { - mac_xface->cancel_ra_proc(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + eNB->Mod_id, i); + eNB->eNB_UE_stats[i].mode = PRACH; + if (eNB->mac_enabled==1) { + mac_xface->cancel_ra_proc(eNB->Mod_id, + eNB->CC_id, frame, - phy_vars_eNB->eNB_UE_stats[i].crnti); + eNB->eNB_UE_stats[i].crnti); } - mac_phy_remove_ue(phy_vars_eNB->Mod_id,phy_vars_eNB->eNB_UE_stats[i].crnti); + mac_phy_remove_ue(eNB->Mod_id,eNB->eNB_UE_stats[i].crnti); - phy_vars_eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 0; - //phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 0; + eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 0; + //eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 0; } else { // activate retransmission for Msg3 (signalled to UE PHY by PHICH (not MAC/DCI) - phy_vars_eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 1; + eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 1; - get_Msg3_alloc_ret(&phy_vars_eNB->lte_frame_parms, + get_Msg3_alloc_ret(fp, subframe, frame, - &phy_vars_eNB->ulsch_eNB[i]->Msg3_frame, - &phy_vars_eNB->ulsch_eNB[i]->Msg3_subframe); + &eNB->ulsch_eNB[i]->Msg3_frame, + &eNB->ulsch_eNB[i]->Msg3_subframe); } LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i); } // This is Msg3 error else { //normal ULSCH LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe, i, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1, - phy_vars_eNB->ulsch_eNB[i]->Mlimit, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1]); + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1, + eNB->ulsch_eNB[i]->Mlimit, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1]); #if defined(MESSAGE_CHART_GENERATOR_PHY) MSC_LOG_RX_DISCARDED_MESSAGE( @@ -3028,51 +2933,51 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ NULL,0, "%05u:%02u ULSCH received rnti %x harq id %u round %d", frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti,harq_pid, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1 + eNB->ulsch_eNB[i]->rnti,harq_pid, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1 ); #endif - if (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round== phy_vars_eNB->ulsch_eNB[i]->Mlimit) { + if (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round== eNB->ulsch_eNB[i]->Mlimit) { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe, i, - phy_vars_eNB->ulsch_eNB[i]->Mlimit); + eNB->ulsch_eNB[i]->Mlimit); - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round=0; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[harq_pid]++; - phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors++; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round=0; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active=0; + eNB->eNB_UE_stats[i].ulsch_errors[harq_pid]++; + eNB->eNB_UE_stats[i].ulsch_consecutive_errors++; // indicate error to MAC - mac_xface->rx_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + mac_xface->rx_sdu(eNB->Mod_id, + eNB->CC_id, frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti, + eNB->ulsch_eNB[i]->rnti, NULL, 0, harq_pid, - &phy_vars_eNB->ulsch_eNB[i]->Msg3_flag); + &eNB->ulsch_eNB[i]->Msg3_flag); } } } // ulsch in error else { - if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe); LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", - phy_vars_eNB->Mod_id,harq_pid, + eNB->Mod_id,harq_pid, frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti, - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), - phy_vars_eNB->eNB_UE_stats[i].UL_rssi[0], - phy_vars_eNB->eNB_UE_stats[i].UL_rssi[1], - phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[0], - phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[1], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->ulsch_eNB[i]->rnti, + dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), + dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), + eNB->eNB_UE_stats[i].UL_rssi[0], + eNB->eNB_UE_stats[i].UL_rssi[1], + eNB->PHY_measurements_eNB->n0_power_dB[0], + eNB->PHY_measurements_eNB->n0_power_dB[1], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], ret); } #if defined(MESSAGE_CHART_GENERATOR_PHY) @@ -3081,115 +2986,115 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ NULL,0, "%05u:%02u ULSCH received rnti %x harq id %u", frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti,harq_pid + eNB->ulsch_eNB[i]->rnti,harq_pid ); #endif - for (j=0; jlte_frame_parms.nb_antennas_rx; j++) + for (j=0; jnb_antennas_rx; j++) //this is the RSSI per RB - phy_vars_eNB->eNB_UE_stats[i].UL_rssi[j] = + eNB->eNB_UE_stats[i].UL_rssi[j] = - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]* - (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb*12)/ - phy_vars_eNB->lte_frame_parms.ofdm_symbol_size) - - phy_vars_eNB->rx_total_gain_eNB_dB - - hundred_times_log10_NPRB[phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb-1]/100 - - get_hundred_times_delta_IF_eNB(phy_vars_eNB,i,harq_pid, 0)/100; + dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]* + (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb*12)/ + fp->ofdm_symbol_size) - + eNB->rx_total_gain_eNB_dB - + hundred_times_log10_NPRB[eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb-1]/100 - + get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1; - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors = 0; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1; + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0; + eNB->eNB_UE_stats[i].ulsch_consecutive_errors = 0; - if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) { - if (phy_vars_eNB->mac_enabled==1) { + if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->mac_enabled==1) { LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame,harq_pid,i); - mac_xface->rx_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + mac_xface->rx_sdu(eNB->Mod_id, + eNB->CC_id, frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3, + eNB->ulsch_eNB[i]->rnti, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3, harq_pid, - &phy_vars_eNB->ulsch_eNB[i]->Msg3_flag); + &eNB->ulsch_eNB[i]->Msg3_flag); // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI) - if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 0 ) { - phy_vars_eNB->eNB_UE_stats[i].mode = PRACH; - mac_xface->cancel_ra_proc(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + if (eNB->ulsch_eNB[i]->Msg3_flag == 0 ) { + eNB->eNB_UE_stats[i].mode = PRACH; + mac_xface->cancel_ra_proc(eNB->Mod_id, + eNB->CC_id, frame, - phy_vars_eNB->eNB_UE_stats[i].crnti); - mac_phy_remove_ue(phy_vars_eNB->Mod_id,phy_vars_eNB->eNB_UE_stats[i].crnti); - phy_vars_eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 0; + eNB->eNB_UE_stats[i].crnti); + mac_phy_remove_ue(eNB->Mod_id,eNB->eNB_UE_stats[i].crnti); + eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 0; } // Msg3_flag == 0 } // mac_enabled==1 - phy_vars_eNB->eNB_UE_stats[i].mode = PUSCH; - phy_vars_eNB->ulsch_eNB[i]->Msg3_flag = 0; + eNB->eNB_UE_stats[i].mode = PUSCH; + eNB->ulsch_eNB[i]->Msg3_flag = 0; - LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",phy_vars_eNB->Mod_id,frame,subframe,i); + LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",eNB->Mod_id,frame,subframe,i); for (k=0; k<8; k++) { //harq_processes - for (j=0; jdlsch_eNB[i][0]->Mlimit; j++) { - phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0; + for (j=0; jdlsch_eNB[i][0]->Mlimit; j++) { + eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0; + eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0; + eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0; } - phy_vars_eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[k]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0; + eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0; + eNB->eNB_UE_stats[i].ulsch_errors[k]=0; + eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0; - for (j=0; julsch_eNB[i]->Mlimit; j++) { - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0; + for (j=0; julsch_eNB[i]->Mlimit; j++) { + eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0; + eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; + eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0; + eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0; } } - phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK_round0=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_mcs_offset=0; + eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0; + eNB->eNB_UE_stats[i].dlsch_NAK_round0=0; + eNB->eNB_UE_stats[i].dlsch_mcs_offset=0; } // Msg3_flag==1 else { // Msg3_flag == 0 #ifdef DEBUG_PHY_PROC #ifdef DEBUG_ULSCH LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe, - harq_pid,phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3); + harq_pid,eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3); - for (j=0; julsch_eNB[i]->harq_processes[harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b[j]); + for (j=0; julsch_eNB[i]->harq_processes[harq_pid]->TBS>>3; j++) + LOG_T(PHY,"%x.",eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b[j]); LOG_T(PHY,"\n"); #endif #endif - if (phy_vars_eNB->mac_enabled==1) { + if (eNB->mac_enabled==1) { - mac_xface->rx_sdu(phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + mac_xface->rx_sdu(eNB->Mod_id, + eNB->CC_id, frame,subframe, - phy_vars_eNB->ulsch_eNB[i]->rnti, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3, + eNB->ulsch_eNB[i]->rnti, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3, harq_pid, NULL); #ifdef LOCALIZATION - start_meas(&phy_vars_eNB->localization_stats); - aggregate_eNB_UE_localization_stats(phy_vars_eNB, + start_meas(&eNB->localization_stats); + aggregate_eNB_UE_localization_stats(eNB, i, frame, subframe, - get_hundred_times_delta_IF_eNB(phy_vars_eNB,i,harq_pid, 1)/100); - stop_meas(&phy_vars_eNB->localization_stats); + get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100); + stop_meas(&eNB->localization_stats); #endif } // mac_enabled==1 @@ -3197,16 +3102,16 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ // estimate timing advance for MAC if (abstraction_flag == 0) { - sync_pos = lte_est_timing_advance_pusch(phy_vars_eNB,i,sched_subframe); - phy_vars_eNB->eNB_UE_stats[i].timing_advance_update = sync_pos - phy_vars_eNB->lte_frame_parms.nb_prefix_samples/4; //to check + sync_pos = lte_est_timing_advance_pusch(eNB,i,sched_subframe); + eNB->eNB_UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame, subframe, i, - phy_vars_eNB->eNB_UE_stats[i].timing_advance_update); + eNB->eNB_UE_stats[i].timing_advance_update); #endif @@ -3214,14 +3119,14 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ // process HARQ feedback #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",phy_vars_eNB->Mod_id, - phy_vars_eNB->dlsch_eNB[i][0]->rnti, + LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id, + eNB->dlsch_eNB[i][0]->rnti, frame,subframe, i); #endif process_HARQ_feedback(i, sched_subframe, - phy_vars_eNB, + eNB, 1, // pusch_flag 0, 0, @@ -3229,24 +3134,24 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d subframe %d, sect %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n", - phy_vars_eNB->Mod_id,frame,subframe, - phy_vars_eNB->eNB_UE_stats[i].sector, + eNB->Mod_id,frame,subframe, + eNB->eNB_UE_stats[i].sector, harq_pid, i, ret, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->cqi_crc_status, - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], - phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[harq_pid], - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->cqi_crc_status, + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->eNB_UE_stats[i].ulsch_errors[harq_pid], + eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); #endif // dump stats to VCD if (i==0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS0+harq_pid,phy_vars_eNB->pusch_stats_mcs[0][(frame*10)+subframe]); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB0+harq_pid,phy_vars_eNB->pusch_stats_rb[0][(frame*10)+subframe]); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND0+harq_pid,phy_vars_eNB->pusch_stats_round[0][(frame*10)+subframe]); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[0]->ulsch_power[0])); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS0+harq_pid,eNB->pusch_stats_mcs[0][(frame*10)+subframe]); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB0+harq_pid,eNB->pusch_stats_rb[0][(frame*10)+subframe]); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND0+harq_pid,eNB->pusch_stats_round[0][(frame*10)+subframe]); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->lte_eNB_pusch_vars[0]->ulsch_power[0])); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES0+harq_pid,ret); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN0+harq_pid,(frame*10)+subframe); } @@ -3256,48 +3161,48 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ // update ULSCH statistics for tracing if ((frame % 100 == 0) && (subframe == 4)) { for (harq_idx=0; harq_idx<8; harq_idx++) { - for (round=0; roundulsch_eNB[i]->Mlimit; round++) { - if ((phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]) != 0) { - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[harq_idx][round] = - (100*(phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[harq_idx][round] - - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_idx][round]))/ - (phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]); + for (round=0; roundulsch_eNB[i]->Mlimit; round++) { + if ((eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - + eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]) != 0) { + eNB->eNB_UE_stats[i].ulsch_round_fer[harq_idx][round] = + (100*(eNB->eNB_UE_stats[i].ulsch_round_errors[harq_idx][round] - + eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_idx][round]))/ + (eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - + eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]); } else { - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[harq_idx][round] = 0; + eNB->eNB_UE_stats[i].ulsch_round_fer[harq_idx][round] = 0; } - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round] = - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round]; - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_idx][round] = - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[harq_idx][round]; + eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round] = + eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round]; + eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_idx][round] = + eNB->eNB_UE_stats[i].ulsch_round_errors[harq_idx][round]; } } } if ((frame % 100 == 0) && (subframe==4)) { - phy_vars_eNB->eNB_UE_stats[i].dlsch_bitrate = (phy_vars_eNB->eNB_UE_stats[i].total_TBS - - phy_vars_eNB->eNB_UE_stats[i].total_TBS_last); + eNB->eNB_UE_stats[i].dlsch_bitrate = (eNB->eNB_UE_stats[i].total_TBS - + eNB->eNB_UE_stats[i].total_TBS_last); - phy_vars_eNB->eNB_UE_stats[i].total_TBS_last = phy_vars_eNB->eNB_UE_stats[i].total_TBS; + eNB->eNB_UE_stats[i].total_TBS_last = eNB->eNB_UE_stats[i].total_TBS; } // CBA (non-LTE) - cba_procedures(sched_subframe,phy_vars_eNB,i,harq_pid,abstraction_flag); + cba_procedures(sched_subframe,eNB,i,harq_pid,abstraction_flag); } // loop i=0 ... NUMBER_OF_UE_MAX-1 if (abstraction_flag == 0) { - lte_eNB_I0_measurements(phy_vars_eNB, + lte_eNB_I0_measurements(eNB, subframe, 0, - phy_vars_eNB->first_run_I0_measurements); - phy_vars_eNB->first_run_I0_measurements = 0; + eNB->first_run_I0_measurements); + eNB->first_run_I0_measurements = 0; } #ifdef PHY_ABSTRACTION else { - lte_eNB_I0_measurements_emul(phy_vars_eNB, + lte_eNB_I0_measurements_emul(eNB, 0); } @@ -3307,11 +3212,11 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ //} #ifdef EMOS - phy_procedures_emos_eNB_RX(subframe,phy_vars_eNB); + phy_procedures_emos_eNB_RX(subframe,eNB); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,0); - stop_meas(&phy_vars_eNB->phy_proc_rx); + stop_meas(&eNB->phy_proc_rx); } @@ -3345,8 +3250,8 @@ int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, r return do_proc; } #endif -void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **phy_vars_eNB,uint8_t abstraction_flag, - relaying_type_t r_type, PHY_VARS_RN *phy_vars_rn) +void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t abstraction_flag, + relaying_type_t r_type, PHY_VARS_RN *rn) { #if defined(ENABLE_ITTI) MessageDef *msg_p; @@ -3360,12 +3265,12 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **phy_vars_eNB,u int CC_id=0; /* - if (phy_vars_eNB->proc[sched_subframe].frame_tx >= 1000) + if (eNB->proc[sched_subframe].frame_tx >= 1000) mac_xface->macphy_exit("Exiting after 1000 Frames\n"); */ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, phy_vars_eNB[0]->proc[subframe].frame_tx); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, eNB[0]->proc[subframe].frame_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,1); - start_meas(&phy_vars_eNB[0]->phy_proc); + start_meas(&eNB[0]->phy_proc); #if defined(ENABLE_ITTI) @@ -3512,45 +3417,45 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **phy_vars_eNB,u for (CC_id=0; CC_idlte_frame_parms.frame_type == TDD)&& - (subframe_select(&phy_vars_eNB[CC_id]->lte_frame_parms,phy_vars_eNB[CC_id]->proc[subframe].subframe_tx)==SF_DL))|| - (phy_vars_eNB[CC_id]->lte_frame_parms.frame_type == FDD))) { + if ((((eNB[CC_id]->lte_frame_parms.frame_type == TDD)&& + (subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_tx)==SF_DL))|| + (eNB[CC_id]->lte_frame_parms.frame_type == FDD))) { #ifdef Rel10 - if (phy_procedures_RN_eNB_TX(phy_vars_eNB[CC_id]->proc[subframe].subframe_rx, phy_vars_eNB[CC_id]->proc[subframe].subframe_tx, r_type) != 0 ) + if (phy_procedures_RN_eNB_TX(eNB[CC_id]->proc[subframe].subframe_rx, eNB[CC_id]->proc[subframe].subframe_tx, r_type) != 0 ) #endif - phy_procedures_eNB_TX(subframe,phy_vars_eNB[CC_id],abstraction_flag,r_type,phy_vars_rn); + phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn); } - if ((((phy_vars_eNB[CC_id]->lte_frame_parms.frame_type == TDD )&& - (subframe_select(&phy_vars_eNB[CC_id]->lte_frame_parms,phy_vars_eNB[CC_id]->proc[subframe].subframe_rx)==SF_UL)) || - (phy_vars_eNB[CC_id]->lte_frame_parms.frame_type == FDD))) { - phy_procedures_eNB_RX(subframe,phy_vars_eNB[CC_id],abstraction_flag,r_type); + if ((((eNB[CC_id]->lte_frame_parms.frame_type == TDD )&& + (subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_rx)==SF_UL)) || + (eNB[CC_id]->lte_frame_parms.frame_type == FDD))) { + phy_procedures_eNB_RX(subframe,eNB[CC_id],abstraction_flag,r_type); } - if (subframe_select(&phy_vars_eNB[CC_id]->lte_frame_parms,phy_vars_eNB[CC_id]->proc[subframe].subframe_tx)==SF_S) { + if (subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_tx)==SF_S) { #ifdef Rel10 if (phy_procedures_RN_eNB_TX(subframe, subframe, r_type) != 0 ) #endif - phy_procedures_eNB_TX(subframe,phy_vars_eNB[CC_id],abstraction_flag,r_type,phy_vars_rn); + phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn); } - if ((subframe_select(&phy_vars_eNB[CC_id]->lte_frame_parms,phy_vars_eNB[CC_id]->proc[subframe].subframe_rx)==SF_S)) { - phy_procedures_eNB_S_RX(subframe,phy_vars_eNB[CC_id],abstraction_flag,r_type); + if ((subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_rx)==SF_S)) { + phy_procedures_eNB_S_RX(subframe,eNB[CC_id],abstraction_flag,r_type); } - phy_vars_eNB[CC_id]->proc[subframe].frame_tx++; - phy_vars_eNB[CC_id]->proc[subframe].frame_rx++; + eNB[CC_id]->proc[subframe].frame_tx++; + eNB[CC_id]->proc[subframe].frame_rx++; - if (phy_vars_eNB[CC_id]->proc[subframe].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h - phy_vars_eNB[CC_id]->proc[subframe].frame_tx-=MAX_FRAME_NUMBER; + if (eNB[CC_id]->proc[subframe].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h + eNB[CC_id]->proc[subframe].frame_tx-=MAX_FRAME_NUMBER; - if (phy_vars_eNB[CC_id]->proc[subframe].frame_rx>=MAX_FRAME_NUMBER) - phy_vars_eNB[CC_id]->proc[subframe].frame_rx-=MAX_FRAME_NUMBER; + if (eNB[CC_id]->proc[subframe].frame_rx>=MAX_FRAME_NUMBER) + eNB[CC_id]->proc[subframe].frame_rx-=MAX_FRAME_NUMBER; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,0); - stop_meas(&phy_vars_eNB[0]->phy_proc); + stop_meas(&eNB[0]->phy_proc); } diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index ac09ac77b3..084173248f 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -115,7 +115,7 @@ extern int rx_sig_fifo; extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; #endif -#ifdef USER_MODE + void dump_dlsch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid) { @@ -286,7 +286,7 @@ void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe) write_output("dlsch_mag1.m","dlschmag1",phy_vars_ue->lte_ue_pdsch_vars_ra[0]->dl_ch_mag0,300*nsymb,1,1); write_output("dlsch_mag2.m","dlschmag2",phy_vars_ue->lte_ue_pdsch_vars_ra[0]->dl_ch_magb0,300*nsymb,1,1); } -#endif + void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) { @@ -367,13 +367,11 @@ void process_timing_advance_rar(PHY_VARS_UE *phy_vars_ue,uint16_t timing_advance timing_advance = timing_advance - (1<<11); */ - if (openair_daq_vars.manual_timing_advance == 0) { - phy_vars_ue->timing_advance = timing_advance*4; + phy_vars_ue->timing_advance = timing_advance*4; - } #ifdef DEBUG_PHY_PROC - LOG_I(PHY,"[UE %d] Frame %d, received (rar) timing_advance %d, HW timing advance %d\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_rx, phy_vars_ue->timing_advance,openair_daq_vars.timing_advance); + LOG_I(PHY,"[UE %d] Frame %d, received (rar) timing_advance %d, HW timing advance %d\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_rx, phy_vars_ue->timing_advance); #endif } @@ -386,11 +384,8 @@ void process_timing_advance(uint8_t Mod_id,uint8_t CC_id,int16_t timing_advance) // timing advance has Q1.5 format timing_advance = timing_advance - 31; - if (openair_daq_vars.manual_timing_advance == 0) { - //if ( (frame % 100) == 0) { - //if ((timing_advance > 3) || (timing_advance < -3) ) - PHY_vars_UE_g[Mod_id][CC_id]->timing_advance = PHY_vars_UE_g[Mod_id][CC_id]->timing_advance+timing_advance*4; //this is for 25RB only!!! - } + PHY_vars_UE_g[Mod_id][CC_id]->timing_advance = PHY_vars_UE_g[Mod_id][CC_id]->timing_advance+timing_advance*4; //this is for 25RB only!!! + LOG_I(PHY,"[UE %d] Got timing advance %d from MAC, new value %d\n",Mod_id, timing_advance, PHY_vars_UE_g[Mod_id][CC_id]->timing_advance); @@ -1223,7 +1218,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case ulsch_start = (phy_vars_ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- - openair_daq_vars.timing_advance- + phy_vars_ue->hw_timing_advance- phy_vars_ue->timing_advance- phy_vars_ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); #else //this is the normal case @@ -1234,7 +1229,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra Mod_id,frame_tx,subframe_tx, ulsch_start, phy_vars_ue->rx_offset, - openair_daq_vars.timing_advance, + phy_vars_ue->hw_timing_advance, phy_vars_ue->timing_advance, phy_vars_ue->N_TA_offset); @@ -1525,14 +1520,7 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t // AGC VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_IN); -#if defined EXMIMO - if ((openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) && - (mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) ) - if (phy_vars_ue->frame_rx%100==0) - gain_control_all(dB_fixed(phy_vars_ue->PHY_measurements.rssi),0); - -#else #ifndef OAI_USRP #ifndef OAI_BLADERF #ifndef OAI_LMSSDR @@ -1540,7 +1528,7 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t #endif #endif #endif -#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); eNB_id = 0; @@ -1554,29 +1542,6 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); - /* if (openair_daq_vars.auto_freq_correction == 1) { - if (frame_rx % 100 == 0) { - if ((phy_vars_ue->lte_ue_common_vars.freq_offset>100) && (openair_daq_vars.freq_offset < 1000)) { - openair_daq_vars.freq_offset+=100; - #if defined(EXMIMO) && defined(DRIVER2013) - for (aa = 0; aa<4; aa++) { - p_exmimo_config->rf.rf_freq_rx[aa] = downlink_frequency[aa]+=openair_daq_vars.freq_offset; - p_exmimo_config->rf.rf_freq_tx[aa] = downlink_frequency[aa]+=openair_daq_vars.freq_offset; - } - #endif - } - else if ((phy_vars_ue->lte_ue_common_vars.freq_offset<-100) && (openair_daq_vars.freq_offset > -1000)) { - openair_daq_vars.freq_offset-=100; - #if defined(EXMIMO) && defined(DRIVER2013) - for (aa = 0; aa<4; aa++) { - p_exmimo_config->rf.rf_freq_rx[aa] = downlink_frequency[aa]+=openair_daq_vars.freq_offset; - p_exmimo_config->rf.rf_freq_tx[aa] = downlink_frequency[aa]+=openair_daq_vars.freq_offset; - } - #endif - } - } - }*/ - } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT); @@ -1681,9 +1646,7 @@ void restart_phy(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_fla // first_run = 1; if (abstraction_flag ==0 ) { - openair_daq_vars.mode = openair_NOT_SYNCHED; phy_vars_ue->UE_mode[eNB_id] = NOT_SYNCHED; - openair_daq_vars.sync_state=0; } else { phy_vars_ue->UE_mode[eNB_id] = PRACH; phy_vars_ue->prach_resources[eNB_id]=NULL; @@ -1691,8 +1654,8 @@ void restart_phy(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_fla phy_vars_ue->frame_rx = -1; phy_vars_ue->frame_tx = -1; - openair_daq_vars.synch_wait_cnt=0; - openair_daq_vars.sched_cnt=-1; + // phy_vars_ue->synch_wait_cnt=0; + // phy_vars_ue->sched_cnt=-1; phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq=0; phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors=0; @@ -2564,7 +2527,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if ((phy_vars_ue->transmission_mode[eNB_id] == 5) && (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (openair_daq_vars.use_ia_receiver ==1)) { + (phy_vars_ue->use_ia_receiver ==1)) { dual_stream_UE = 1; eNB_id_i = phy_vars_ue->n_connected_eNB; i_mod = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm; @@ -2975,9 +2938,9 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if (ret == (1+phy_vars_ue->dlsch_ue_ra[eNB_id]->max_turbo_iterations)) { phy_vars_ue->dlsch_ra_errors[eNB_id]++; LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received RA in error\n",phy_vars_ue->Mod_id,frame_rx,subframe_prev); -#ifdef USER_MODE - //dump_dlsch_ra(phy_vars_ue,eNB_id,subframe_prev); -#endif + + // dump_dlsch_ra(phy_vars_ue,eNB_id,subframe_prev); exit(-1); + // oai_exit=1; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); stop_meas(&phy_vars_ue->phy_proc_rx); @@ -3107,7 +3070,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if ((phy_vars_ue->transmission_mode[eNB_id] == 5) && (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (openair_daq_vars.use_ia_receiver ==1)) { + (phy_vars_ue->use_ia_receiver ==1)) { dual_stream_UE = 1; eNB_id_i = phy_vars_ue->n_connected_eNB; i_mod = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm; @@ -3176,7 +3139,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if ((phy_vars_ue->transmission_mode[eNB_id] == 5) && (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (openair_daq_vars.use_ia_receiver ==1)) { + (phy_vars_ue->use_ia_receiver ==1)) { dual_stream_UE = 1; eNB_id_i = phy_vars_ue->n_connected_eNB; i_mod = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm; diff --git a/openair1/SCHED/vars.h b/openair1/SCHED/vars.h index 532251a2f0..2c4c93cfad 100644 --- a/openair1/SCHED/vars.h +++ b/openair1/SCHED/vars.h @@ -28,7 +28,6 @@ *******************************************************************************/ #include "defs.h" -OPENAIR_DAQ_VARS openair_daq_vars; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 4d8e32b63c..62422bf9ae 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -569,17 +569,9 @@ schedule_ue_spec( eNB_UE_stats->DL_cqi[0], MIN_CQI_VALUE, MAX_CQI_VALUE); */ eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]]; - eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); + eNB_UE_stats->dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1;//cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); -#ifdef EXMIMO - - if (mac_xface->get_transmission_mode(module_idP,CC_id, rnti)==5) { - eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1,16); - } - -#endif - // store stats UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->DL_cqi[0]; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 2973bedd00..e508e24eb5 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -826,14 +826,14 @@ void schedule_ulsch_rnti(module_id_t module_idP, UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power; UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power; UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; - mcs = cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS + mcs = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS if ((cqi_req==1) && (mcs>19)) { mcs=19; } if (UE_template->pre_allocated_rb_table_index_ul >=0) { rb_table_index=UE_template->pre_allocated_rb_table_index_ul; } else { - mcs=cmin (10, openair_daq_vars.target_ue_ul_mcs); + mcs=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs); rb_table_index=5; // for PHR } @@ -1171,7 +1171,7 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f required_rbs[cba_group] = 0; num_cba_resources[cba_group]=0; active_UEs[cba_group]=0; - mcs[cba_group]=openair_daq_vars.target_ue_ul_mcs; + mcs[cba_group]=10;//openair_daq_vars.target_ue_ul_mcs; } //LOG_D(MAC, "[eNB ] CBA granted ues are %d\n",granted_UEs ); @@ -1219,7 +1219,7 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f } } - mcs[cba_group]= cmin(mcs[cba_group],openair_daq_vars.target_ue_ul_mcs); + mcs[cba_group]= mcs[cba_group];//cmin(mcs[cba_group],openair_daq_vars.target_ue_ul_mcs); if (available_rbs < min_rb_unit ) break; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index fe8fe55d44..d28614699b 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -178,7 +178,7 @@ void assign_rbs_required (module_id_t Mod_id, */ eNB_UE_stats[CC_id]->dlsch_mcs1=cqi_to_mcs[eNB_UE_stats[CC_id]->DL_cqi[0]]; - eNB_UE_stats[CC_id]->dlsch_mcs1 = cmin(eNB_UE_stats[CC_id]->dlsch_mcs1,openair_daq_vars.target_ue_dl_mcs); + eNB_UE_stats[CC_id]->dlsch_mcs1 = eNB_UE_stats[CC_id]->dlsch_mcs1;//cmin(eNB_UE_stats[CC_id]->dlsch_mcs1,openair_daq_vars.target_ue_dl_mcs); } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 822409f302..e903fd0c9a 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -114,15 +114,14 @@ unsigned short config_frames[4] = {2,9,11,13}; #endif // In lte-enb.c -int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); - +extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); extern void init_eNB(void); extern void stop_eNB(void); extern void kill_eNB_proc(void); // In lte-ue.c -int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); -void fill_ue_band_info(void); +extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); +extern void fill_ue_band_info(void); extern void init_UE(void); #ifdef XFORMS @@ -1139,6 +1138,7 @@ int main( int argc, char **argv ) memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); set_latency_target(); + // det defaults for (CC_id=0; CC_idmac_enabled = 1; - if (UE[CC_id]->mac_enabled == 0) { + if (UE[CC_id]->mac_enabled == 0) { //set default UL parameters for testing mode for (i=0; ipusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; @@ -1373,13 +1373,6 @@ int main( int argc, char **argv ) } - openair_daq_vars.manual_timing_advance = 0; - openair_daq_vars.rx_gain_mode = DAQ_AGC_ON; - openair_daq_vars.auto_freq_correction = 0; - openair_daq_vars.use_ia_receiver = 0; - - - // printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_power,tx_max_power)); } else { //this is eNB @@ -1390,12 +1383,10 @@ int main( int argc, char **argv ) PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,cooperation_flag,transmission_mode,abstraction_flag); PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id; - if (phy_test==1) - PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0; - else - PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1; + if (phy_test==1) PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0; + else PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1; - if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) { + if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) { //set default parameters for testing mode for (i=0; ipusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; @@ -1413,7 +1404,6 @@ int main( int argc, char **argv ) PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB = (int)rx_gain[CC_id][0]; - //already taken care of in lte-softmodem.c PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0; } @@ -1422,11 +1412,6 @@ int main( int argc, char **argv ) NB_eNB_INST=1; NB_INST=1; - openair_daq_vars.ue_dl_rb_alloc=0x1fff; - openair_daq_vars.target_ue_dl_mcs=target_dl_mcs; - openair_daq_vars.ue_ul_nb_rb=6; - openair_daq_vars.target_ue_ul_mcs=target_ul_mcs; - } fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); @@ -1644,11 +1629,16 @@ int main( int argc, char **argv ) // connect the TX/RX buffers if (UE_flag==1) { + + for (CC_id=0;CC_idhw_timing_advance = timing_advance; #else - openair_daq_vars.timing_advance = 160; + UE[CC_id]->hw_timing_advance = 160; #endif + } if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) { printf("Error setting up eNB buffer\n"); exit(-1); @@ -1673,7 +1663,8 @@ int main( int argc, char **argv ) } //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; } else { - openair_daq_vars.timing_advance = 0; + + if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) { printf("Error setting up eNB buffer\n"); @@ -1684,6 +1675,7 @@ int main( int argc, char **argv ) // Set LSBs for antenna switch (ExpressMIMO) for (CC_id=0; CC_idhw_timing_advance = 0; for (i=0; isamples_per_tti*10; i++) for (aa=0; aanb_antennas_tx; aa++) PHY_vars_eNB_g[0][CC_id]->lte_eNB_common_vars.txdata[0][aa][i] = 0x00010001; @@ -1730,13 +1722,16 @@ int main( int argc, char **argv ) sprintf (title, "LTE DL SCOPE UE"); fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + /* 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"); - } + }*/ + fl_set_button(form_ue[UE_id]->button_0,0); + fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); } ret = pthread_create(&forms_thread, NULL, scope_thread, NULL); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 3049fd4e02..865f257135 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -1622,7 +1622,7 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, return(-1); } - + /* if (frame_parms->frame_type == TDD) { if (frame_parms->N_RB_DL == 100) N_TA_offset = 624; @@ -1631,7 +1631,7 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, else if (frame_parms->N_RB_DL == 25) N_TA_offset = 624/4; } - + */ // replace RX signal buffers with mmaped HW versions rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c index 8a5d23afac..7c335fdd10 100644 --- a/targets/SIMU/USER/oaisim.c +++ b/targets/SIMU/USER/oaisim.c @@ -500,7 +500,7 @@ l2l1_task (void *args_p) sprintf (title, "LTE DL SCOPE eNB %d to UE %d CC_id %d", eNB_inst, UE_inst, CC_id); fl_show_form (form_ue[CC_id][UE_inst]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); - if (openair_daq_vars.use_ia_receiver == 1) { + if (PHY_vars_UE_g[UE_inst][CC_id]->use_ia_receiver == 1) { fl_set_button(form_ue[CC_id][UE_inst]->button_0,1); fl_set_object_label(form_ue[CC_id][UE_inst]->button_0, "IA Receiver ON"); fl_set_object_color(form_ue[CC_id][UE_inst]->button_0, FL_GREEN, FL_GREEN); diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index b87142c3e5..ea9d298904 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -951,22 +951,23 @@ void init_openair1(void) number_of_cards = 1; - openair_daq_vars.rx_rf_mode = 1; - openair_daq_vars.tdd = 1; - openair_daq_vars.rx_gain_mode = DAQ_AGC_ON; +// openair_daq_vars.rx_rf_mode = 1; +// openair_daq_vars.tdd = 1; +// openair_daq_vars.rx_gain_mode = DAQ_AGC_ON; - openair_daq_vars.dlsch_transmission_mode = oai_emulation.info.transmission_mode[0]; +// openair_daq_vars.dlsch_transmission_mode = oai_emulation.info.transmission_mode[0]; //#warning "NN->FK: OAI EMU channel abstraction does not work for MCS higher than" - openair_daq_vars.target_ue_dl_mcs = cmin(target_dl_mcs,16); - openair_daq_vars.target_ue_ul_mcs = target_ul_mcs; - openair_daq_vars.ue_dl_rb_alloc=0x1fff; - openair_daq_vars.ue_ul_nb_rb=6; - openair_daq_vars.dlsch_rate_adaptation = rate_adaptation_flag; - openair_daq_vars.use_ia_receiver = 0; +// openair_daq_vars.target_ue_dl_mcs = cmin(target_dl_mcs,16); +// openair_daq_vars.target_ue_ul_mcs = target_ul_mcs; +// openair_daq_vars.ue_dl_rb_alloc=0x1fff; +// openair_daq_vars.ue_ul_nb_rb=6; +// openair_daq_vars.dlsch_rate_adaptation = rate_adaptation_flag; //N_TA_offset for (CC_id=0; CC_iduse_ia_receiver = 0; + if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.frame_type == TDD) { if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.N_RB_DL == 100) PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 624; From 80b3850fa1c7ad4832328151fa5fd246dcd48316 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 16 May 2016 05:29:04 -0700 Subject: [PATCH 009/206] removal of mod_sym_t --- openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index af6c72fc6a..2a7760909c 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -140,7 +140,7 @@ uint32_t FOUR[2]={0,4}; uint32_t TWO[2]={0,2}; int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int32_t * **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -213,7 +213,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, } int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int32_t * **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -295,7 +295,7 @@ int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, } int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int32_t * **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -377,7 +377,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, } int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, - mod_sym_t **txdataF, + int32_t * **txdataF, uint32_t *jj, uint32_t *jj2, uint16_t re_offset, @@ -1514,7 +1514,7 @@ int dlsch_modulation(int32_t **txdataF, int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8]; int16_t *qam_table_s0=NULL,*qam_table_s1=NULL; int (*allocate_REs)(LTE_DL_FRAME_PARMS *, - mod_sym_t **, + int32_t * **, uint32_t*, uint32_t*, uint16_t, From d9761e7adc47a3d1bb40251f7c13f9766a0287cb Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 16 May 2016 05:47:02 -0700 Subject: [PATCH 010/206] added missing structure element in eNB_RRC_UE_t : ue_release_timer_thres --- openair2/RRC/LITE/defs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h index 7a52115440..f730a95c48 100644 --- a/openair2/RRC/LITE/defs.h +++ b/openair2/RRC/LITE/defs.h @@ -359,6 +359,7 @@ typedef struct eNB_RRC_UE_s { #endif uint32_t ul_failure_timer; uint32_t ue_release_timer; + uint32_t ue_release_timer_thres; } eNB_RRC_UE_t; typedef uid_t ue_uid_t; From b188a5cfeb6c06a215b7b1cca6ce524fe9f6b880 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 26 May 2016 15:14:57 -0700 Subject: [PATCH 011/206] changed threading (acqusition is slot based). removal of eNB_thread. timing all based on received timestamp. --- openair1/PHY/INIT/lte_init.c | 1199 +++++---- openair1/PHY/INIT/lte_param_init.c | 74 +- openair1/PHY/LTE_ESTIMATION/adjust_gain.c | 74 +- openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c | 54 +- .../lte_dl_channel_estimation.c | 158 +- .../lte_dl_mbsfn_channel_estimation.c | 114 +- .../PHY/LTE_ESTIMATION/lte_eNB_measurements.c | 122 +- .../PHY/LTE_ESTIMATION/lte_sync_timefreq.c | 6 +- .../PHY/LTE_ESTIMATION/lte_ue_measurements.c | 442 ++-- .../lte_ul_channel_estimation.c | 62 +- openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c | 46 +- openair1/PHY/LTE_REFSIG/lte_dl_mbsfn.c | 26 +- openair1/PHY/LTE_REFSIG/lte_dl_uespec.c | 40 +- openair1/PHY/LTE_TRANSPORT/dci.c | 220 +- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 152 +- openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c | 6 +- .../PHY/LTE_TRANSPORT/dlsch_demodulation.c | 628 ++--- openair1/PHY/LTE_TRANSPORT/drs_modulation.c | 22 +- openair1/PHY/LTE_TRANSPORT/initial_sync.c | 334 ++- openair1/PHY/LTE_TRANSPORT/phich.c | 126 +- openair1/PHY/LTE_TRANSPORT/pilots.c | 44 +- openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c | 10 +- openair1/PHY/LTE_TRANSPORT/pmch.c | 192 +- openair1/PHY/LTE_TRANSPORT/prach.c | 457 ++-- openair1/PHY/LTE_TRANSPORT/print_stats.c | 896 +++---- openair1/PHY/LTE_TRANSPORT/pucch.c | 100 +- openair1/PHY/LTE_TRANSPORT/rar_tools.c | 33 +- openair1/PHY/LTE_TRANSPORT/srs_modulation.c | 8 +- openair1/PHY/LTE_TRANSPORT/sss.c | 80 +- openair1/PHY/LTE_TRANSPORT/ulsch_coding.c | 88 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 132 +- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 204 +- openair1/PHY/MODULATION/slot_fep.c | 68 +- openair1/PHY/MODULATION/slot_fep_mbsfn.c | 46 +- openair1/PHY/MODULATION/ul_7_5_kHz.c | 29 +- openair1/PHY/TOOLS/lte_phy_scope.c | 56 +- openair1/PHY/defs.h | 117 +- openair1/SCHED/defs.h | 45 +- openair1/SCHED/phy_mac_stub.c | 184 +- openair1/SCHED/phy_procedures_lte_common.c | 172 +- openair1/SCHED/phy_procedures_lte_eNb.c | 1566 ++++++------ openair1/SCHED/phy_procedures_lte_ue.c | 2231 ++++++++--------- openair1/SCHED/pucch_pc.c | 38 +- openair1/SCHED/pusch_pc.c | 96 +- openair2/LAYER2/MAC/eNB_scheduler.c | 52 +- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 58 +- openair2/LAYER2/MAC/eNB_scheduler_bch.c | 28 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 16 +- openair2/LAYER2/MAC/eNB_scheduler_mch.c | 24 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 24 +- openair2/LAYER2/MAC/lte_transport_init.c | 6 +- openair2/LAYER2/MAC/main.c | 12 +- openair2/LAYER2/MAC/pre_processor.c | 10 +- openair2/LAYER2/MAC/ra_procedures.c | 4 +- openair2/LAYER2/MAC/ue_procedures.c | 16 +- openair2/PHY_INTERFACE/defs.h | 2 +- openair2/RRC/LITE/rrc_UE.c | 10 +- openair2/RRC/LITE/rrc_eNB.c | 18 +- targets/RT/USER/lte-enb.c | 732 +++--- targets/RT/USER/lte-softmodem.c | 67 +- targets/RT/USER/lte-ue.c | 134 +- targets/SIMU/USER/init_lte.c | 82 +- 62 files changed, 5977 insertions(+), 6115 deletions(-) diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 6a50c2d113..9787c476a6 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -52,7 +52,7 @@ extern uint16_t prach_root_sequence_map4[138]; uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10}; // FIXME not used anywhere -void phy_config_mib(LTE_DL_FRAME_PARMS *lte_frame_parms, +void phy_config_mib(LTE_DL_FRAME_PARMS *frame_parms, uint8_t N_RB_DL, uint8_t Nid_cell, uint8_t Ncp, @@ -61,14 +61,14 @@ void phy_config_mib(LTE_DL_FRAME_PARMS *lte_frame_parms, PHICH_CONFIG_COMMON *phich_config) { - lte_frame_parms->N_RB_DL = N_RB_DL; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = Nid_cell%6; - lte_frame_parms->Ncp = Ncp; - lte_frame_parms->frame_type = frame_type; - lte_frame_parms->nb_antennas_tx_eNB = p_eNB; - lte_frame_parms->phich_config_common.phich_resource = phich_config->phich_resource; - lte_frame_parms->phich_config_common.phich_duration = phich_config->phich_duration; + frame_parms->N_RB_DL = N_RB_DL; + frame_parms->Nid_cell = Nid_cell; + frame_parms->nushift = Nid_cell%6; + frame_parms->Ncp = Ncp; + frame_parms->frame_type = frame_type; + frame_parms->nb_antennas_tx_eNB = p_eNB; + frame_parms->phich_config_common.phich_resource = phich_config->phich_resource; + frame_parms->phich_config_common.phich_duration = phich_config->phich_duration; } void phy_config_sib1_eNB(uint8_t Mod_id, @@ -78,15 +78,15 @@ void phy_config_sib1_eNB(uint8_t Mod_id, uint16_t SIPeriod) { - LTE_DL_FRAME_PARMS *lte_frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; if (tdd_Config) { - lte_frame_parms->tdd_config = tdd_Config->subframeAssignment; - lte_frame_parms->tdd_config_S = tdd_Config->specialSubframePatterns; + frame_parms->tdd_config = tdd_Config->subframeAssignment; + frame_parms->tdd_config_S = tdd_Config->specialSubframePatterns; } - lte_frame_parms->SIwindowsize = SIwindowsize; - lte_frame_parms->SIPeriod = SIPeriod; + frame_parms->SIwindowsize = SIwindowsize; + frame_parms->SIPeriod = SIPeriod; } void phy_config_sib1_ue(uint8_t Mod_id,int CC_id, @@ -96,15 +96,15 @@ void phy_config_sib1_ue(uint8_t Mod_id,int CC_id, uint16_t SIperiod) { - LTE_DL_FRAME_PARMS *lte_frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; if (tdd_Config) { - lte_frame_parms->tdd_config = tdd_Config->subframeAssignment; - lte_frame_parms->tdd_config_S = tdd_Config->specialSubframePatterns; + frame_parms->tdd_config = tdd_Config->subframeAssignment; + frame_parms->tdd_config_S = tdd_Config->specialSubframePatterns; } - lte_frame_parms->SIwindowsize = SIwindowsize; - lte_frame_parms->SIPeriod = SIperiod; + frame_parms->SIwindowsize = SIwindowsize; + frame_parms->SIPeriod = SIperiod; } void phy_config_sib2_eNB(uint8_t Mod_id, @@ -116,132 +116,132 @@ void phy_config_sib2_eNB(uint8_t Mod_id, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList) { - LTE_DL_FRAME_PARMS *lte_frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; //LTE_eNB_UE_stats *eNB_UE_stats = PHY_vars_eNB_g[Mod_id][CC_id]->eNB_UE_stats; //int32_t rx_total_gain_eNB_dB = PHY_vars_eNB_g[Mod_id][CC_id]->rx_total_gain_eNB_dB; int i; - LOG_D(PHY,"[eNB%d] CCid %d Frame %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc[8].frame_tx); + LOG_D(PHY,"[eNB%d] CCid %d Frame %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc[0].frame_tx); - lte_frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - LOG_D(PHY,"prach_config_common.rootSequenceIndex = %d\n",lte_frame_parms->prach_config_common.rootSequenceIndex ); + frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; + LOG_D(PHY,"prach_config_common.rootSequenceIndex = %d\n",frame_parms->prach_config_common.rootSequenceIndex ); - lte_frame_parms->prach_config_common.prach_Config_enabled=1; + frame_parms->prach_config_common.prach_Config_enabled=1; - lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_ConfigIndex = %d\n",lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex); + frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_ConfigIndex = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex); - lte_frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.highSpeedFlag = %d\n",lte_frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag); - lte_frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig = %d\n",lte_frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig); - lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_FreqOffset = %d\n",lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset); - compute_prach_seq(<e_frame_parms->prach_config_common,lte_frame_parms->frame_type, + frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.highSpeedFlag = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag); + frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig); + frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_FreqOffset = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset); + compute_prach_seq(&frame_parms->prach_config_common,frame_parms->frame_type, PHY_vars_eNB_g[Mod_id][CC_id]->X_u); - lte_frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; - lte_frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; - lte_frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; - lte_frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; + frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; + frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; + frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; + frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; - lte_frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; - lte_frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; + frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; + frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; - lte_frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - LOG_D(PHY,"pusch_config_common.n_SB = %d\n",lte_frame_parms->pusch_config_common.n_SB ); + frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; + LOG_D(PHY,"pusch_config_common.n_SB = %d\n",frame_parms->pusch_config_common.n_SB ); - lte_frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - LOG_D(PHY,"pusch_config_common.hoppingMode = %d\n",lte_frame_parms->pusch_config_common.hoppingMode); + frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; + LOG_D(PHY,"pusch_config_common.hoppingMode = %d\n",frame_parms->pusch_config_common.hoppingMode); - lte_frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - LOG_D(PHY,"pusch_config_common.pusch_HoppingOffset = %d\n",lte_frame_parms->pusch_config_common.pusch_HoppingOffset); + frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; + LOG_D(PHY,"pusch_config_common.pusch_HoppingOffset = %d\n",frame_parms->pusch_config_common.pusch_HoppingOffset); - lte_frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - LOG_D(PHY,"pusch_config_common.enable64QAM = %d\n",lte_frame_parms->pusch_config_common.enable64QAM ); + frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; + LOG_D(PHY,"pusch_config_common.enable64QAM = %d\n",frame_parms->pusch_config_common.enable64QAM ); - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = %d\n",lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled); + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled); - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = %d\n",lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH); + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH); - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = %d\n",lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled); + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled); - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = %d\n",lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift); + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift); - init_ul_hopping(lte_frame_parms); + init_ul_hopping(frame_parms); - lte_frame_parms->soundingrs_ul_config_common.enabled_flag = 0; + frame_parms->soundingrs_ul_config_common.enabled_flag = 0; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) { - lte_frame_parms->soundingrs_ul_config_common.enabled_flag = 1; - lte_frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; - lte_frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; - lte_frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; + frame_parms->soundingrs_ul_config_common.enabled_flag = 1; + frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; + frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; + frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - lte_frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; + frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; else - lte_frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; + frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; } - lte_frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; - lte_frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; - lte_frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; - lte_frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; + frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; + frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; + frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; + frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; - lte_frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; + frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; // Now configure some of the Physical Channels // PUCCH - init_ncs_cell(lte_frame_parms,PHY_vars_eNB_g[Mod_id][CC_id]->ncs_cell); + init_ncs_cell(frame_parms,PHY_vars_eNB_g[Mod_id][CC_id]->ncs_cell); - init_ul_hopping(lte_frame_parms); + init_ul_hopping(frame_parms); // MBSFN if (mbsfn_SubframeConfigList != NULL) { - lte_frame_parms->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; + frame_parms->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; for (i=0; ilist.count; i++) { - lte_frame_parms->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; - lte_frame_parms->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; + frame_parms->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; + frame_parms->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { - lte_frame_parms->MBSFN_config[i].fourFrames_flag = 0; - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration + frame_parms->MBSFN_config[i].fourFrames_flag = 0; + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration - lte_frame_parms->MBSFN_config[i].fourFrames_flag = 1; - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = + frame_parms->MBSFN_config[i].fourFrames_flag = 1; + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16); LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); } } } else - lte_frame_parms->num_MBSFN_config = 0; + frame_parms->num_MBSFN_config = 0; } @@ -254,106 +254,106 @@ void phy_config_sib2_ue(uint8_t Mod_id,int CC_id, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList) { - LTE_DL_FRAME_PARMS *lte_frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; int i; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_IN); LOG_I(PHY,"[UE%d] Frame %d: Applying radioResourceConfigCommon from eNB%d\n",Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx,CH_index); - lte_frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; + frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - lte_frame_parms->prach_config_common.prach_Config_enabled=1; - lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - lte_frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; - lte_frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; + frame_parms->prach_config_common.prach_Config_enabled=1; + frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; + frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; + frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; + frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; - compute_prach_seq(<e_frame_parms->prach_config_common,lte_frame_parms->frame_type,PHY_vars_UE_g[Mod_id][CC_id]->X_u); + compute_prach_seq(&frame_parms->prach_config_common,frame_parms->frame_type,PHY_vars_UE_g[Mod_id][CC_id]->X_u); - lte_frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; - lte_frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; - lte_frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; - lte_frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; + frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; + frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; + frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; + frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; - lte_frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; - lte_frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; + frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; + frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; - lte_frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - lte_frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - lte_frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - lte_frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; + frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; + frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; + frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; + frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; - init_ul_hopping(lte_frame_parms); - lte_frame_parms->soundingrs_ul_config_common.enabled_flag = 0; + init_ul_hopping(frame_parms); + frame_parms->soundingrs_ul_config_common.enabled_flag = 0; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) { - lte_frame_parms->soundingrs_ul_config_common.enabled_flag = 1; - lte_frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; - lte_frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; - lte_frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; + frame_parms->soundingrs_ul_config_common.enabled_flag = 1; + frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; + frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; + frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - lte_frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; + frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; else - lte_frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; + frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; } - lte_frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; - lte_frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; - lte_frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; - lte_frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; + frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; + frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; + frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; + frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; - lte_frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; + frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; // Now configure some of the Physical Channels // PUCCH - init_ncs_cell(lte_frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); + init_ncs_cell(frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); - init_ul_hopping(lte_frame_parms); + init_ul_hopping(frame_parms); // MBSFN if (mbsfn_SubframeConfigList != NULL) { - lte_frame_parms->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; + frame_parms->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; for (i=0; ilist.count; i++) { - lte_frame_parms->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; - lte_frame_parms->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; + frame_parms->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; + frame_parms->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { - lte_frame_parms->MBSFN_config[i].fourFrames_flag = 0; - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration + frame_parms->MBSFN_config[i].fourFrames_flag = 0; + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration - lte_frame_parms->MBSFN_config[i].fourFrames_flag = 1; - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = + frame_parms->MBSFN_config[i].fourFrames_flag = 1; + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16); LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - lte_frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); } } } @@ -366,17 +366,17 @@ void phy_config_sib13_ue(uint8_t Mod_id,int CC_id,uint8_t CH_index,int mbsfn_Are long mbsfn_AreaId_r9) { - LTE_DL_FRAME_PARMS *lte_frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; LOG_I(PHY,"[UE%d] Frame %d: Applying MBSFN_Area_id %d for index %d\n",Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx,mbsfn_AreaId_r9,mbsfn_Area_idx); if (mbsfn_Area_idx == 0) { - lte_frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; + frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n"); } - lte_gold_mbsfn(lte_frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_mbsfn_table,lte_frame_parms->Nid_cell_mbsfn); + lte_gold_mbsfn(frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_mbsfn_table,frame_parms->Nid_cell_mbsfn); } @@ -385,56 +385,56 @@ void phy_config_sib13_eNB(uint8_t Mod_id,int CC_id,int mbsfn_Area_idx, long mbsfn_AreaId_r9) { - LTE_DL_FRAME_PARMS *lte_frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; - LOG_I(PHY,"[eNB%d] Frame %d: Applying MBSFN_Area_id %d for index %d\n",Mod_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc[8].frame_tx,mbsfn_AreaId_r9,mbsfn_Area_idx); + LOG_I(PHY,"[eNB%d] Frame %d: Applying MBSFN_Area_id %d for index %d\n",Mod_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc[0].frame_tx,mbsfn_AreaId_r9,mbsfn_Area_idx); if (mbsfn_Area_idx == 0) { - lte_frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; + frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n"); } - lte_gold_mbsfn(lte_frame_parms,PHY_vars_eNB_g[Mod_id][CC_id]->lte_gold_mbsfn_table,lte_frame_parms->Nid_cell_mbsfn); + lte_gold_mbsfn(frame_parms,PHY_vars_eNB_g[Mod_id][CC_id]->lte_gold_mbsfn_table,frame_parms->Nid_cell_mbsfn); } -void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *phy_vars_eNB) +void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB) { uint8_t UE_id; struct PhysicalConfigDedicated *physicalConfigDedicated; for (UE_id=0; UE_idphysicalConfigDedicated[UE_id]; + physicalConfigDedicated = eNB->physicalConfigDedicated[UE_id]; if (physicalConfigDedicated != NULL) { - LOG_I(PHY,"[eNB %d] Frame %d: Sent physicalConfigDedicated=%p for UE %d\n",phy_vars_eNB->Mod_id, phy_vars_eNB->proc[8].frame_tx,physicalConfigDedicated,UE_id); + LOG_I(PHY,"[eNB %d] Frame %d: Sent physicalConfigDedicated=%p for UE %d\n",eNB->Mod_id, eNB->proc[0].frame_tx,physicalConfigDedicated,UE_id); LOG_D(PHY,"------------------------------------------------------------------------\n"); if (physicalConfigDedicated->pdsch_ConfigDedicated) { - phy_vars_eNB->pdsch_config_dedicated[UE_id].p_a=physicalConfigDedicated->pdsch_ConfigDedicated->p_a; - LOG_D(PHY,"pdsch_config_dedicated.p_a %d\n",phy_vars_eNB->pdsch_config_dedicated[UE_id].p_a); + eNB->pdsch_config_dedicated[UE_id].p_a=physicalConfigDedicated->pdsch_ConfigDedicated->p_a; + LOG_D(PHY,"pdsch_config_dedicated.p_a %d\n",eNB->pdsch_config_dedicated[UE_id].p_a); LOG_D(PHY,"\n"); } if (physicalConfigDedicated->pucch_ConfigDedicated) { if (physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.present==PUCCH_ConfigDedicated__ackNackRepetition_PR_release) - phy_vars_eNB->pucch_config_dedicated[UE_id].ackNackRepetition=0; + eNB->pucch_config_dedicated[UE_id].ackNackRepetition=0; else { - phy_vars_eNB->pucch_config_dedicated[UE_id].ackNackRepetition=1; + eNB->pucch_config_dedicated[UE_id].ackNackRepetition=1; } - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { - phy_vars_eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = multiplexing; + if (eNB->frame_parms.frame_type == FDD) { + eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = multiplexing; } else { if (physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode) - phy_vars_eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = *physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode; + eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = *physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode; else - phy_vars_eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = bundling; + eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = bundling; } - if ( phy_vars_eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == multiplexing) + if ( eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == multiplexing) LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = multiplexing\n"); else LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = bundling\n"); @@ -442,13 +442,13 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *phy_vars_eNB) } if (physicalConfigDedicated->pusch_ConfigDedicated) { - phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index; - phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index; - phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index; + eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index; + eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index; + eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index; - LOG_D(PHY,"pusch_config_dedicated.betaOffset_ACK_Index %d\n",phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index); - LOG_D(PHY,"pusch_config_dedicated.betaOffset_RI_Index %d\n",phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index); - LOG_D(PHY,"pusch_config_dedicated.betaOffset_CQI_Index %d\n",phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index); + LOG_D(PHY,"pusch_config_dedicated.betaOffset_ACK_Index %d\n",eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index); + LOG_D(PHY,"pusch_config_dedicated.betaOffset_RI_Index %d\n",eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index); + LOG_D(PHY,"pusch_config_dedicated.betaOffset_CQI_Index %d\n",eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index); LOG_D(PHY,"\n"); @@ -456,43 +456,43 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *phy_vars_eNB) if (physicalConfigDedicated->uplinkPowerControlDedicated) { - phy_vars_eNB->ul_power_control_dedicated[UE_id].p0_UE_PUSCH = physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUSCH; - phy_vars_eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled= physicalConfigDedicated->uplinkPowerControlDedicated->deltaMCS_Enabled; - phy_vars_eNB->ul_power_control_dedicated[UE_id].accumulationEnabled= physicalConfigDedicated->uplinkPowerControlDedicated->accumulationEnabled; - phy_vars_eNB->ul_power_control_dedicated[UE_id].p0_UE_PUCCH= physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUCCH; - phy_vars_eNB->ul_power_control_dedicated[UE_id].pSRS_Offset= physicalConfigDedicated->uplinkPowerControlDedicated->pSRS_Offset; - phy_vars_eNB->ul_power_control_dedicated[UE_id].filterCoefficient= *physicalConfigDedicated->uplinkPowerControlDedicated->filterCoefficient; - LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUSCH %d\n",phy_vars_eNB->ul_power_control_dedicated[UE_id].p0_UE_PUSCH); - LOG_D(PHY,"ul_power_control_dedicated.deltaMCS_Enabled %d\n",phy_vars_eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled); - LOG_D(PHY,"ul_power_control_dedicated.accumulationEnabled %d\n",phy_vars_eNB->ul_power_control_dedicated[UE_id].accumulationEnabled); - LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUCCH %d\n",phy_vars_eNB->ul_power_control_dedicated[UE_id].p0_UE_PUCCH); - LOG_D(PHY,"ul_power_control_dedicated.pSRS_Offset %d\n",phy_vars_eNB->ul_power_control_dedicated[UE_id].pSRS_Offset); - LOG_D(PHY,"ul_power_control_dedicated.filterCoefficient %d\n",phy_vars_eNB->ul_power_control_dedicated[UE_id].filterCoefficient); + eNB->ul_power_control_dedicated[UE_id].p0_UE_PUSCH = physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUSCH; + eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled= physicalConfigDedicated->uplinkPowerControlDedicated->deltaMCS_Enabled; + eNB->ul_power_control_dedicated[UE_id].accumulationEnabled= physicalConfigDedicated->uplinkPowerControlDedicated->accumulationEnabled; + eNB->ul_power_control_dedicated[UE_id].p0_UE_PUCCH= physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUCCH; + eNB->ul_power_control_dedicated[UE_id].pSRS_Offset= physicalConfigDedicated->uplinkPowerControlDedicated->pSRS_Offset; + eNB->ul_power_control_dedicated[UE_id].filterCoefficient= *physicalConfigDedicated->uplinkPowerControlDedicated->filterCoefficient; + LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUSCH %d\n",eNB->ul_power_control_dedicated[UE_id].p0_UE_PUSCH); + LOG_D(PHY,"ul_power_control_dedicated.deltaMCS_Enabled %d\n",eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled); + LOG_D(PHY,"ul_power_control_dedicated.accumulationEnabled %d\n",eNB->ul_power_control_dedicated[UE_id].accumulationEnabled); + LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUCCH %d\n",eNB->ul_power_control_dedicated[UE_id].p0_UE_PUCCH); + LOG_D(PHY,"ul_power_control_dedicated.pSRS_Offset %d\n",eNB->ul_power_control_dedicated[UE_id].pSRS_Offset); + LOG_D(PHY,"ul_power_control_dedicated.filterCoefficient %d\n",eNB->ul_power_control_dedicated[UE_id].filterCoefficient); LOG_D(PHY,"\n"); } if (physicalConfigDedicated->antennaInfo) { - phy_vars_eNB->transmission_mode[UE_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode); - LOG_D(PHY,"Transmission Mode %d\n",phy_vars_eNB->transmission_mode[UE_id]); + eNB->transmission_mode[UE_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode); + LOG_D(PHY,"Transmission Mode %d\n",eNB->transmission_mode[UE_id]); LOG_D(PHY,"\n"); } if (physicalConfigDedicated->schedulingRequestConfig) { if (physicalConfigDedicated->schedulingRequestConfig->present == SchedulingRequestConfig_PR_setup) { - phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex = physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; - phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex=physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_ConfigIndex; - phy_vars_eNB->scheduling_request_config[UE_id].dsr_TransMax=physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax; + eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex = physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; + eNB->scheduling_request_config[UE_id].sr_ConfigIndex=physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_ConfigIndex; + eNB->scheduling_request_config[UE_id].dsr_TransMax=physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax; - LOG_D(PHY,"scheduling_request_config.sr_PUCCH_ResourceIndex %d\n",phy_vars_eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); - LOG_D(PHY,"scheduling_request_config.sr_ConfigIndex %d\n",phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex); - LOG_D(PHY,"scheduling_request_config.dsr_TransMax %d\n",phy_vars_eNB->scheduling_request_config[UE_id].dsr_TransMax); + LOG_D(PHY,"scheduling_request_config.sr_PUCCH_ResourceIndex %d\n",eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); + LOG_D(PHY,"scheduling_request_config.sr_ConfigIndex %d\n",eNB->scheduling_request_config[UE_id].sr_ConfigIndex); + LOG_D(PHY,"scheduling_request_config.dsr_TransMax %d\n",eNB->scheduling_request_config[UE_id].dsr_TransMax); } LOG_D(PHY,"------------------------------------------------------------\n"); } - phy_vars_eNB->physicalConfigDedicated[UE_id] = NULL; + eNB->physicalConfigDedicated[UE_id] = NULL; } } } @@ -506,13 +506,13 @@ void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, Mobility if(mobilityControlInfo!=NULL) { RadioResourceConfigCommon_t *radioResourceConfigCommon = &mobilityControlInfo->radioResourceConfigCommon; LOG_I(PHY,"radioResourceConfigCommon %p\n", radioResourceConfigCommon); - memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms_before_ho, - (void *)&PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms, + memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho, + (void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms, sizeof(LTE_DL_FRAME_PARMS)); PHY_vars_UE_g[Mod_id][CC_id]->ho_triggered = 1; //PHY_vars_UE_g[UE_id]->UE_mode[0] = PRACH; - LTE_DL_FRAME_PARMS *lte_frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; // int N_ZC; // uint8_t prach_fmt; // int u; @@ -520,98 +520,98 @@ void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, Mobility LOG_I(PHY,"[UE%d] Frame %d: Handover triggered: Applying radioResourceConfigCommon from eNB %d\n", Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx,eNB_id); - lte_frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - lte_frame_parms->prach_config_common.prach_Config_enabled=1; - lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex; - lte_frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->highSpeedFlag; - lte_frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->zeroCorrelationZoneConfig; - lte_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_FreqOffset; + frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; + frame_parms->prach_config_common.prach_Config_enabled=1; + frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex; + frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->highSpeedFlag; + frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->zeroCorrelationZoneConfig; + frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_FreqOffset; - // prach_fmt = get_prach_fmt(radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex,lte_frame_parms->frame_type); + // prach_fmt = get_prach_fmt(radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex,frame_parms->frame_type); // N_ZC = (prach_fmt <4)?839:139; - // u = (prach_fmt < 4) ? prach_root_sequence_map0_3[lte_frame_parms->prach_config_common.rootSequenceIndex] : - // prach_root_sequence_map4[lte_frame_parms->prach_config_common.rootSequenceIndex]; + // u = (prach_fmt < 4) ? prach_root_sequence_map0_3[frame_parms->prach_config_common.rootSequenceIndex] : + // prach_root_sequence_map4[frame_parms->prach_config_common.rootSequenceIndex]; //compute_prach_seq(u,N_ZC, PHY_vars_UE_g[Mod_id]->X_u); - compute_prach_seq(&PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms.prach_config_common, - lte_frame_parms->frame_type, + compute_prach_seq(&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common, + frame_parms->frame_type, PHY_vars_UE_g[Mod_id][CC_id]->X_u); - lte_frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon->deltaPUCCH_Shift; - lte_frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon->nRB_CQI; - lte_frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon->nCS_AN; - lte_frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon->n1PUCCH_AN; - lte_frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon->referenceSignalPower; - lte_frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon->p_b; + frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon->deltaPUCCH_Shift; + frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon->nRB_CQI; + frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon->nCS_AN; + frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon->n1PUCCH_AN; + frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon->referenceSignalPower; + frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon->p_b; - lte_frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - lte_frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - lte_frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - lte_frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; + frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; + frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; + frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; + frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; - init_ul_hopping(lte_frame_parms); - lte_frame_parms->soundingrs_ul_config_common.enabled_flag = 0; + init_ul_hopping(frame_parms); + frame_parms->soundingrs_ul_config_common.enabled_flag = 0; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->present==SoundingRS_UL_ConfigCommon_PR_setup) { - lte_frame_parms->soundingrs_ul_config_common.enabled_flag = 1; - lte_frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_BandwidthConfig; - lte_frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig; - lte_frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.ackNackSRS_SimultaneousTransmission; + frame_parms->soundingrs_ul_config_common.enabled_flag = 1; + frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_BandwidthConfig; + frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig; + frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.ackNackSRS_SimultaneousTransmission; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_MaxUpPts) - lte_frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; + frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; else - lte_frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; + frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; } - lte_frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUSCH; - lte_frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon->alpha; - lte_frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUCCH; - lte_frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaPreambleMsg3; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1b; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2a; - lte_frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2b; + frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUSCH; + frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon->alpha; + frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUCCH; + frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaPreambleMsg3; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1b; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2a; + frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2b; - lte_frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon->maxHARQ_Msg3Tx; + frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon->maxHARQ_Msg3Tx; // Now configure some of the Physical Channels if (radioResourceConfigCommon->antennaInfoCommon) - lte_frame_parms->nb_antennas_tx = (1<antennaInfoCommon->antennaPortsCount); + frame_parms->nb_antennas_tx = (1<antennaInfoCommon->antennaPortsCount); else - lte_frame_parms->nb_antennas_tx = 1; + frame_parms->nb_antennas_tx = 1; //PHICH if (radioResourceConfigCommon->antennaInfoCommon) { - lte_frame_parms->phich_config_common.phich_resource = radioResourceConfigCommon->phich_Config->phich_Resource; - lte_frame_parms->phich_config_common.phich_duration = radioResourceConfigCommon->phich_Config->phich_Duration; + frame_parms->phich_config_common.phich_resource = radioResourceConfigCommon->phich_Config->phich_Resource; + frame_parms->phich_config_common.phich_duration = radioResourceConfigCommon->phich_Config->phich_Duration; } //Target CellId - lte_frame_parms->Nid_cell = mobilityControlInfo->targetPhysCellId; - lte_frame_parms->nushift = lte_frame_parms->Nid_cell%6; + frame_parms->Nid_cell = mobilityControlInfo->targetPhysCellId; + frame_parms->nushift = frame_parms->Nid_cell%6; // PUCCH - init_ncs_cell(lte_frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); + init_ncs_cell(frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); - init_ul_hopping(lte_frame_parms); + init_ul_hopping(frame_parms); // RNTI - PHY_vars_UE_g[Mod_id][CC_id]->lte_ue_pdcch_vars[eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); } if(ho_failed) { LOG_D(PHY,"[UE%d] Handover failed, triggering RACH procedure\n",Mod_id); - memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms,(void *)&PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms_before_ho, sizeof(LTE_DL_FRAME_PARMS)); + memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms,(void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho, sizeof(LTE_DL_FRAME_PARMS)); PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_id] = PRACH; } } @@ -619,14 +619,14 @@ void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, Mobility void phy_config_meas_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,uint8_t n_adj_cells,unsigned int *adj_cell_id) { - PHY_MEASUREMENTS *phy_meas = &PHY_vars_UE_g[Mod_id][CC_id]->PHY_measurements; + PHY_MEASUREMENTS *phy_meas = &PHY_vars_UE_g[Mod_id][CC_id]->measurements; int i; LOG_I(PHY,"Configuring inter-cell measurements for %d cells, ids: \n",n_adj_cells); for (i=0; ilte_frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_table[i+1],adj_cell_id[i]); + lte_gold(&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_table[i+1],adj_cell_id[i]); } phy_meas->n_adj_cells = n_adj_cells; @@ -640,20 +640,20 @@ void phy_config_dedicated_eNB(uint8_t Mod_id, struct PhysicalConfigDedicated *physicalConfigDedicated) { - PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[Mod_id][CC_id]; - int8_t UE_id = find_ue(rnti,phy_vars_eNB); + PHY_VARS_eNB *eNB = PHY_vars_eNB_g[Mod_id][CC_id]; + int8_t UE_id = find_ue(rnti,eNB); if (UE_id == -1) { - LOG_E( PHY, "[eNB %"PRIu8"] Frame %d: find_ue() returns -1\n", Mod_id, phy_vars_eNB->proc[8].frame_tx ); + LOG_E( PHY, "[eNB %"PRIu8"] Frame %d: find_ue() returns -1\n", Mod_id, eNB->proc[0].frame_tx ); return; } if (physicalConfigDedicated) { - phy_vars_eNB->physicalConfigDedicated[UE_id] = physicalConfigDedicated; + eNB->physicalConfigDedicated[UE_id] = physicalConfigDedicated; LOG_I(PHY,"phy_config_dedicated_eNB: physicalConfigDedicated=%p\n",physicalConfigDedicated); } else { - LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, phy_vars_eNB->proc[8].frame_tx,UE_id); + LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, eNB->proc[0].frame_tx,UE_id); return; } @@ -672,7 +672,7 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, int CC_id) { - //PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[Mod_id][CC_id]; + //PHY_VARS_eNB *eNB = PHY_vars_eNB_g[Mod_id][CC_id]; uint8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][0]); struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10 = sCellToAddMod_r10->radioResourceConfigDedicatedSCell_r10->physicalConfigDedicatedSCell_r10; //struct RadioResourceConfigCommonSCell_r10 *physicalConfigCommonSCell_r10 = sCellToAddMod_r10->radioResourceConfigCommonSCell_r10; @@ -688,7 +688,7 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, if ((dl_CarrierFreq_r10>=36000) && (dl_CarrierFreq_r10<=36199)) { carrier_freq_local = 1900000000 + (dl_CarrierFreq_r10-36000)*100000; //band 33 from 3GPP 36.101 v 10.9 Table 5.7.3-1 - LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*phy_vars_eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); + LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); #ifdef EXMIMO #ifdef DRIVER2013 //carrier_freq[CC_id] = carrier_freq_local; @@ -704,7 +704,7 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, } else if ((dl_CarrierFreq_r10>=6150) && (dl_CarrierFreq_r10<=6449)) { carrier_freq_local = 832000000 + (dl_CarrierFreq_r10-6150)*100000; //band 20 from 3GPP 36.101 v 10.9 Table 5.7.3-1 // this is actually for the UL only, but we use it for DL too, since there is no TDD mode for this band - LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*phy_vars_eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); + LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); #ifdef EXMIMO #ifdef DRIVER2013 //carrier_freq[CC_id] = carrier_freq_local; @@ -718,15 +718,15 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, #endif #endif } else { - LOG_E(PHY,"[eNB %d] Frame %d: ARFCN %d of SCell %d for UE %d not supported\n",Mod_id,/*phy_vars_eNB->frame*/0,dl_CarrierFreq_r10,CC_id,UE_id); + LOG_E(PHY,"[eNB %d] Frame %d: ARFCN %d of SCell %d for UE %d not supported\n",Mod_id,/*eNB->frame*/0,dl_CarrierFreq_r10,CC_id,UE_id); } if (physicalConfigDedicatedSCell_r10) { -//#warning " phy_vars_eNB->physicalConfigDedicatedSCell_r10 does not exist in phy_vars_eNB" - // phy_vars_eNB->physicalConfigDedicatedSCell_r10[UE_id] = physicalConfigDedicatedSCell_r10; - LOG_I(PHY,"[eNB %d] Frame %d: Configured phyConfigDedicatedSCell with CC_id %d for UE %d\n",Mod_id,/*phy_vars_eNB->frame*/0,CC_id,UE_id); +//#warning " eNB->physicalConfigDedicatedSCell_r10 does not exist in eNB" + // eNB->physicalConfigDedicatedSCell_r10[UE_id] = physicalConfigDedicatedSCell_r10; + LOG_I(PHY,"[eNB %d] Frame %d: Configured phyConfigDedicatedSCell with CC_id %d for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,UE_id); } else { - LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated (CC_id %d, UE %d)\n",Mod_id, /*phy_vars_eNB->frame*/0,CC_id,UE_id); + LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated (CC_id %d, UE %d)\n",Mod_id, /*eNB->frame*/0,CC_id,UE_id); return; } @@ -855,18 +855,18 @@ void phy_config_cba_rnti (module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uin if (eNB_flag == 0 ) { //LOG_D(PHY,"[UE %d] configure cba group %d with rnti %x, num active cba grp %d\n", index, index, cba_rnti, num_active_cba_groups); - PHY_vars_UE_g[Mod_id][CC_id]->ulsch_ue[index]->num_active_cba_groups=num_active_cba_groups; - PHY_vars_UE_g[Mod_id][CC_id]->ulsch_ue[index]->cba_rnti[cba_group_id]=cba_rnti; + PHY_vars_UE_g[Mod_id][CC_id]->ulsch[index]->num_active_cba_groups=num_active_cba_groups; + PHY_vars_UE_g[Mod_id][CC_id]->ulsch[index]->cba_rnti[cba_group_id]=cba_rnti; } else { //for (i=index; i < NUMBER_OF_UE_MAX; i+=num_active_cba_groups){ // LOG_D(PHY,"[eNB %d] configure cba group %d with rnti %x for UE %d, num active cba grp %d\n",Mod_id, i%num_active_cba_groups, cba_rnti, i, num_active_cba_groups); - PHY_vars_eNB_g[Mod_id][CC_id]->ulsch_eNB[index]->num_active_cba_groups=num_active_cba_groups; - PHY_vars_eNB_g[Mod_id][CC_id]->ulsch_eNB[index]->cba_rnti[cba_group_id] = cba_rnti; + PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[index]->num_active_cba_groups=num_active_cba_groups; + PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[index]->cba_rnti[cba_group_id] = cba_rnti; //} } } -void phy_init_lte_top(LTE_DL_FRAME_PARMS *lte_frame_parms) +void phy_init_lte_top(LTE_DL_FRAME_PARMS *frame_parms) { crcTableInit(); @@ -888,7 +888,7 @@ void phy_init_lte_top(LTE_DL_FRAME_PARMS *lte_frame_parms) init_td16avx2(); #endif - lte_sync_time_init(lte_frame_parms); + lte_sync_time_init(frame_parms); generate_ul_ref_sigs(); generate_ul_ref_sigs_rx(); @@ -946,527 +946,460 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS } } -/*! \brief Helper function to allocate memory for DLSCH_FLP data structures. - * \param[out] pdsch_flp Pointer to the LTE_UE_PDSCH_FLP structure to initialize. - * \param[in] frame_parms LTE_DL_FRAME_PARMS structure. - * \note This function is optimistic in that it expects malloc() to succeed. - */ -void phy_init_lte_ue__PDSCH_FLP( LTE_UE_PDSCH_FLP* const pdsch_flp, const LTE_DL_FRAME_PARMS* const frame_parms ) -{ - AssertFatal( pdsch_flp, "pdsch==0" ); - pdsch_flp->llr[0] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); - pdsch_flp->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); - pdsch_flp->llr128 = (int16_t**)malloc16_clear( sizeof(int16_t*) ); - // FIXME! no further allocation for (int16_t*)pdsch_flp->llr128 !!! expect SIGSEGV - - pdsch_flp->pmi_ext = (uint8_t*)malloc16_clear( frame_parms->N_RB_DL ); - pdsch_flp->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch_flp->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch_flp->rxdataF_comp = (double**)malloc16_clear( 8*sizeof(double*) ); - pdsch_flp->dl_ch_rho_ext = (double**)malloc16_clear( 8*sizeof(double*) ); - pdsch_flp->dl_ch_mag = (double**)malloc16_clear( 8*sizeof(double*) ); - pdsch_flp->dl_ch_magb = (double**)malloc16_clear( 8*sizeof(double*) ); - pdsch_flp->rho = (double**)malloc16_clear( frame_parms->nb_antennas_rx*sizeof(double*) ); - - // the allocated memory size is fixed: - AssertFatal( frame_parms->nb_antennas_rx <= 2, "nb_antennas_rx > 2" ); - - for (int i=0; inb_antennas_rx; i++) { - pdsch_flp->rho[i] = (double*)malloc16_clear( sizeof(double)*(frame_parms->N_RB_DL*12*7*2) ); - - for (int j=0; j<4; j++) { //frame_parms->nb_antennas_tx; j++) - const int idx = (j<<1)+i; - const size_t num = 7*2*frame_parms->N_RB_DL*12; - pdsch_flp->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - pdsch_flp->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - pdsch_flp->rxdataF_comp[idx] = (double*)malloc16_clear( sizeof(double) * num ); - pdsch_flp->dl_ch_rho_ext[idx] = (double*)malloc16_clear( sizeof(double) * num ); - pdsch_flp->dl_ch_mag[idx] = (double*)malloc16_clear( sizeof(double) * num ); - pdsch_flp->dl_ch_magb[idx] = (double*)malloc16_clear( sizeof(double) * num ); - } - } -} - -int phy_init_lte_ue(PHY_VARS_UE *phy_vars_ue, +int phy_init_lte_ue(PHY_VARS_UE *ue, int nb_connected_eNB, uint8_t abstraction_flag) { // create shortcuts - LTE_DL_FRAME_PARMS* const frame_parms = &phy_vars_ue->lte_frame_parms; - LTE_UE_COMMON* const ue_common_vars = &phy_vars_ue->lte_ue_common_vars; - LTE_UE_PDSCH** const ue_pdsch_vars = phy_vars_ue->lte_ue_pdsch_vars; - LTE_UE_PDSCH_FLP** const ue_pdsch_vars_flp = phy_vars_ue->lte_ue_pdsch_vars_flp; - LTE_UE_PDSCH** const ue_pdsch_vars_SI = phy_vars_ue->lte_ue_pdsch_vars_SI; - LTE_UE_PDSCH** const ue_pdsch_vars_ra = phy_vars_ue->lte_ue_pdsch_vars_ra; - LTE_UE_PDSCH** const ue_pdsch_vars_mch = phy_vars_ue->lte_ue_pdsch_vars_MCH; - LTE_UE_PBCH** const ue_pbch_vars = phy_vars_ue->lte_ue_pbch_vars; - LTE_UE_PDCCH** const ue_pdcch_vars = phy_vars_ue->lte_ue_pdcch_vars; - LTE_UE_PRACH** const ue_prach_vars = phy_vars_ue->lte_ue_prach_vars; + LTE_DL_FRAME_PARMS* const frame_parms = &ue->frame_parms; + LTE_UE_COMMON* const common_vars = &ue->common_vars; + LTE_UE_PDSCH** const pdsch_vars = ue->pdsch_vars; + LTE_UE_PDSCH** const pdsch_vars_SI = ue->pdsch_vars_SI; + LTE_UE_PDSCH** const pdsch_vars_ra = ue->pdsch_vars_ra; + LTE_UE_PDSCH** const pdsch_vars_mch = ue->pdsch_vars_MCH; + LTE_UE_PBCH** const pbch_vars = ue->pbch_vars; + LTE_UE_PDCCH** const pdcch_vars = ue->pdcch_vars; + LTE_UE_PRACH** const prach_vars = ue->prach_vars; int i,j,k; int eNB_id; msg("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,frame_parms->nb_antennas_tx,frame_parms->nb_antennas_rx); - LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", phy_vars_ue->Mod_id+NB_eNB_INST); + LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", ue->Mod_id+NB_eNB_INST); // many memory allocation sizes are hard coded AssertFatal( frame_parms->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[eNB_id]" ); - AssertFatal( phy_vars_ue->n_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" ); -#ifndef USER_MODE - AssertFatal( frame_parms->nb_antennas_tx <= NB_ANTENNAS_TX, "nb_antennas_tx too large" ); - AssertFatal( frame_parms->nb_antennas_rx <= NB_ANTENNAS_RX, "nb_antennas_rx too large" ); -#endif + AssertFatal( ue->n_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" ); // init phy_vars_ue for (i=0; i<4; i++) { - phy_vars_ue->rx_gain_max[i] = 135; - phy_vars_ue->rx_gain_med[i] = 128; - phy_vars_ue->rx_gain_byp[i] = 120; + ue->rx_gain_max[i] = 135; + ue->rx_gain_med[i] = 128; + ue->rx_gain_byp[i] = 120; } - phy_vars_ue->n_connected_eNB = nb_connected_eNB; + ue->n_connected_eNB = nb_connected_eNB; - for(eNB_id = 0; eNB_id < phy_vars_ue->n_connected_eNB; eNB_id++) { - phy_vars_ue->total_TBS[eNB_id] = 0; - phy_vars_ue->total_TBS_last[eNB_id] = 0; - phy_vars_ue->bitrate[eNB_id] = 0; - phy_vars_ue->total_received_bits[eNB_id] = 0; + for(eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { + ue->total_TBS[eNB_id] = 0; + ue->total_TBS_last[eNB_id] = 0; + ue->bitrate[eNB_id] = 0; + ue->total_received_bits[eNB_id] = 0; } - phy_vars_ue->tx_power_dBm=-127; + ue->tx_power_dBm=-127; if (abstraction_flag == 0) { // init TX buffers - ue_common_vars->txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - ue_common_vars->txdataF = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + common_vars->txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + common_vars->txdataF = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); for (i=0; inb_antennas_tx; i++) { -#ifdef USER_MODE - ue_common_vars->txdata[i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); -#else //USER_MODE - ue_common_vars->txdata[i] = TX_DMA_BUFFER[0][i]; -#endif //USER_MODE - ue_common_vars->txdataF[i] = (int32_t *)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); + + common_vars->txdata[i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); + common_vars->txdataF[i] = (int32_t *)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); } // init RX buffers - ue_common_vars->rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - ue_common_vars->rxdataF = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - ue_common_vars->rxdataF2 = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdataF = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdataF2 = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); for (i=0; inb_antennas_rx; i++) { -#ifndef USER_MODE - ue_common_vars->rxdata[i] = (int32_t*) RX_DMA_BUFFER[0][i]; -#else //USER_MODE - ue_common_vars->rxdata[i] = (int32_t*) malloc16_clear( (FRAME_LENGTH_COMPLEX_SAMPLES+2048)*sizeof(int32_t) ); -#endif //USER_MODE - // RK 2 times because of output format of FFT! - // FIXME We should get rid of this - ue_common_vars->rxdataF[i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*(frame_parms->ofdm_symbol_size*14) ); - // RK 2 times because of output format of FFT! We should get rid of this - // FIXME We should get rid of this - ue_common_vars->rxdataF2[i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*10) ); + common_vars->rxdata[i] = (int32_t*) malloc16_clear( (FRAME_LENGTH_COMPLEX_SAMPLES+2048)*sizeof(int32_t) ); + common_vars->rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->ofdm_symbol_size*14) ); + common_vars->rxdataF2[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*10) ); } } // Channel estimates for (eNB_id=0; eNB_id<7; eNB_id++) { - ue_common_vars->dl_ch_estimates[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*)); - ue_common_vars->dl_ch_estimates_time[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*)); + common_vars->dl_ch_estimates[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*)); + common_vars->dl_ch_estimates_time[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*)); for (i=0; inb_antennas_rx; i++) for (j=0; j<4; j++) { int idx = (j<<1) + i; - ue_common_vars->dl_ch_estimates[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->symbols_per_tti*(frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) ); - ue_common_vars->dl_ch_estimates_time[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size*2 ); + common_vars->dl_ch_estimates[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->symbols_per_tti*(frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) ); + common_vars->dl_ch_estimates_time[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size*2 ); } } // DLSCH - for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) { - ue_pdsch_vars[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); -#ifdef ENABLE_FULL_FLP - ue_pdsch_vars_flp[eNB_id] = (LTE_UE_PDSCH_FLP *)malloc16_clear(sizeof(LTE_UE_PDSCH_FLP)); -#else - ue_pdsch_vars_flp[eNB_id] = 0; -#endif - ue_pdsch_vars_SI[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); - ue_pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); - ue_pdsch_vars_mch[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); - ue_pdcch_vars[eNB_id] = (LTE_UE_PDCCH *)malloc16_clear(sizeof(LTE_UE_PDCCH)); - ue_prach_vars[eNB_id] = (LTE_UE_PRACH *)malloc16_clear(sizeof(LTE_UE_PRACH)); - ue_pbch_vars[eNB_id] = (LTE_UE_PBCH *)malloc16_clear(sizeof(LTE_UE_PBCH)); + for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) { + pdsch_vars[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); + pdsch_vars_SI[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); + pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); + pdsch_vars_mch[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH)); + pdcch_vars[eNB_id] = (LTE_UE_PDCCH *)malloc16_clear(sizeof(LTE_UE_PDCCH)); + prach_vars[eNB_id] = (LTE_UE_PRACH *)malloc16_clear(sizeof(LTE_UE_PRACH)); + pbch_vars[eNB_id] = (LTE_UE_PBCH *)malloc16_clear(sizeof(LTE_UE_PBCH)); if (abstraction_flag == 0) { - phy_init_lte_ue__PDSCH( ue_pdsch_vars[eNB_id], frame_parms ); + phy_init_lte_ue__PDSCH( pdsch_vars[eNB_id], frame_parms ); - ue_pdsch_vars[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*frame_parms->N_RB_DL*12); - ue_pdsch_vars[eNB_id]->llr_shifts_p = ue_pdsch_vars[eNB_id]->llr_shifts; - ue_pdsch_vars[eNB_id]->dl_ch_mag1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - ue_pdsch_vars[eNB_id]->dl_ch_magb1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - ue_pdsch_vars[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + pdsch_vars[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*frame_parms->N_RB_DL*12); + pdsch_vars[eNB_id]->llr_shifts_p = pdsch_vars[eNB_id]->llr_shifts; + pdsch_vars[eNB_id]->dl_ch_mag1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars[eNB_id]->dl_ch_magb1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); for (k=0; k<8; k++) - ue_pdsch_vars[eNB_id]->rxdataF_comp1[k] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdsch_vars[eNB_id]->rxdataF_comp1[k] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); for (i=0; inb_antennas_rx; i++) for (j=0; j<4; j++) { int idx = (j<<1)+i; - ue_pdsch_vars[eNB_id]->dl_ch_mag1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(frame_parms->N_RB_DL*12) ); - ue_pdsch_vars[eNB_id]->dl_ch_magb1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(frame_parms->N_RB_DL*12) ); + pdsch_vars[eNB_id]->dl_ch_mag1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(frame_parms->N_RB_DL*12) ); + pdsch_vars[eNB_id]->dl_ch_magb1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(frame_parms->N_RB_DL*12) ); for (k=0; k<8; k++) - ue_pdsch_vars[eNB_id]->rxdataF_comp1[idx][k] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->N_RB_DL*12*14) ); + pdsch_vars[eNB_id]->rxdataF_comp1[idx][k] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->N_RB_DL*12*14) ); } -#ifdef ENABLE_FULL_FLP - phy_init_lte_ue__PDSCH_FLP( ue_pdsch_vars_flp[eNB_id], frame_parms ); -#endif - - phy_init_lte_ue__PDSCH( ue_pdsch_vars_SI[eNB_id], frame_parms ); - phy_init_lte_ue__PDSCH( ue_pdsch_vars_ra[eNB_id], frame_parms ); - phy_init_lte_ue__PDSCH( ue_pdsch_vars_mch[eNB_id], frame_parms ); + phy_init_lte_ue__PDSCH( pdsch_vars_SI[eNB_id], frame_parms ); + phy_init_lte_ue__PDSCH( pdsch_vars_ra[eNB_id], frame_parms ); + phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], frame_parms ); // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE - ue_pdcch_vars[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue_pdcch_vars[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue_pdcch_vars[eNB_id]->wbar = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue_pdcch_vars[eNB_id]->e_rx = (int8_t*)malloc16_clear( 4*2*100*12 ); + pdcch_vars[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars[eNB_id]->wbar = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + pdcch_vars[eNB_id]->e_rx = (int8_t*)malloc16_clear( 4*2*100*12 ); - ue_pdcch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - ue_pdcch_vars[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - ue_pdcch_vars[eNB_id]->rho = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - ue_pdcch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars[eNB_id]->rho = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pdcch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pdcch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); for (i=0; inb_antennas_rx; i++) { //ue_pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->N_RB_DL*12*7*2) ); - ue_pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) ); + pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) ); for (j=0; j<4; j++) { //frame_parms->nb_antennas_tx; j++) int idx = (j<<1)+i; // size_t num = 7*2*frame_parms->N_RB_DL*12; size_t num = 4*100*12; // 4 symbols, 100 PRBs, 12 REs per PRB - ue_pdcch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - ue_pdcch_vars[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - ue_pdcch_vars[eNB_id]->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); - ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars[eNB_id]->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); + pdcch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); } } // PBCH - ue_pbch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - ue_pbch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - ue_pbch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - ue_pbch_vars[eNB_id]->llr = (int8_t*)malloc16_clear( 1920 ); - ue_prach_vars[eNB_id]->prachF = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(frame_parms->ofdm_symbol_size*12)) ); - ue_prach_vars[eNB_id]->prach = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(frame_parms->ofdm_symbol_size*12)) ); + pbch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pbch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pbch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); + pbch_vars[eNB_id]->llr = (int8_t*)malloc16_clear( 1920 ); + prach_vars[eNB_id]->prachF = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(frame_parms->ofdm_symbol_size*12)) ); + prach_vars[eNB_id]->prach = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(frame_parms->ofdm_symbol_size*12)) ); for (i=0; inb_antennas_rx; i++) { - ue_pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); + pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); for (j=0; j<4; j++) {//frame_parms->nb_antennas_tx;j++) { int idx = (j<<1)+i; - ue_pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); - ue_pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); + pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); + pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); } } } - ue_pbch_vars[eNB_id]->decoded_output = (uint8_t*)malloc16_clear( 64 ); + pbch_vars[eNB_id]->decoded_output = (uint8_t*)malloc16_clear( 64 ); } - // initialization for the last instance of ue_pdsch_vars (used for MU-MIMO) + // initialization for the last instance of pdsch_vars (used for MU-MIMO) - ue_pdsch_vars[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) ); - ue_pdsch_vars_SI[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) ); - ue_pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) ); - ue_pdsch_vars_flp[eNB_id] = (LTE_UE_PDSCH_FLP *)malloc16_clear( sizeof(LTE_UE_PDSCH_FLP) ); + pdsch_vars[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) ); + pdsch_vars_SI[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) ); + pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) ); if (abstraction_flag == 0) { - phy_init_lte_ue__PDSCH( ue_pdsch_vars[eNB_id], frame_parms ); - ue_pdsch_vars[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + phy_init_lte_ue__PDSCH( pdsch_vars[eNB_id], frame_parms ); + pdsch_vars[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); - phy_init_lte_ue__PDSCH_FLP( ue_pdsch_vars_flp[eNB_id], frame_parms ); } else { //abstraction == 1 - phy_vars_ue->sinr_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); + ue->sinr_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); } - phy_vars_ue->sinr_CQI_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); + ue->sinr_CQI_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); - phy_vars_ue->init_averaging = 1; - phy_vars_ue->pdsch_config_dedicated->p_a = dB0; // default value until overwritten by RRCConnectionReconfiguration + ue->init_averaging = 1; + ue->pdsch_config_dedicated->p_a = dB0; // default value until overwritten by RRCConnectionReconfiguration // set channel estimation to do linear interpolation in time - phy_vars_ue->high_speed_flag = 1; - phy_vars_ue->ch_est_alpha = 24576; + ue->high_speed_flag = 1; + ue->ch_est_alpha = 24576; init_prach_tables(839); return 0; } -int phy_init_lte_eNB(PHY_VARS_eNB *phy_vars_eNB, +int phy_init_lte_eNB(PHY_VARS_eNB *eNB, unsigned char is_secondary_eNB, uint8_t cooperation_flag, unsigned char abstraction_flag) { // shortcuts - LTE_DL_FRAME_PARMS* const frame_parms = &phy_vars_eNB->lte_frame_parms; - LTE_eNB_COMMON* const eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; - LTE_eNB_PUSCH** const eNB_pusch_vars = phy_vars_eNB->lte_eNB_pusch_vars; - LTE_eNB_SRS* const eNB_srs_vars = phy_vars_eNB->lte_eNB_srs_vars; - LTE_eNB_PRACH* const eNB_prach_vars = &phy_vars_eNB->lte_eNB_prach_vars; + LTE_DL_FRAME_PARMS* const frame_parms = &eNB->frame_parms; + LTE_eNB_COMMON* const common_vars = &eNB->common_vars; + LTE_eNB_PUSCH** const pusch_vars = eNB->pusch_vars; + LTE_eNB_SRS* const srs_vars = eNB->srs_vars; + LTE_eNB_PRACH* const prach_vars = &eNB->prach_vars; int i, j, eNB_id, UE_id; - phy_vars_eNB->total_dlsch_bitrate = 0; - phy_vars_eNB->total_transmitted_bits = 0; - phy_vars_eNB->total_system_throughput = 0; - phy_vars_eNB->check_for_MUMIMO_transmissions=0; + eNB->total_dlsch_bitrate = 0; + eNB->total_transmitted_bits = 0; + eNB->total_system_throughput = 0; + eNB->check_for_MUMIMO_transmissions=0; LOG_I(PHY,"[eNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d\n", - phy_vars_eNB->Mod_id, + eNB->Mod_id, frame_parms->N_RB_DL,frame_parms->phich_config_common.phich_resource, frame_parms->phich_config_common.phich_duration); - LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_eNB][MOD %02"PRIu8"][]\n", phy_vars_eNB->Mod_id); + LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_eNB][MOD %02"PRIu8"][]\n", eNB->Mod_id); - lte_gold(frame_parms,phy_vars_eNB->lte_gold_table,frame_parms->Nid_cell); - generate_pcfich_reg_mapping(frame_parms); - generate_phich_reg_mapping(frame_parms); + if (eNB->node_function != NGFI_RRU_IF4) { + lte_gold(frame_parms,eNB->lte_gold_table,frame_parms->Nid_cell); + generate_pcfich_reg_mapping(frame_parms); + generate_phich_reg_mapping(frame_parms); + + for (UE_id=0; UE_idfirst_run_timing_advance[UE_id] = + 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. - for (UE_id=0; UE_idfirst_run_timing_advance[UE_id] = + // clear whole structure + bzero( &eNB->UE_stats[UE_id], sizeof(LTE_eNB_UE_stats) ); + + eNB->physicalConfigDedicated[UE_id] = NULL; + } + + eNB->first_run_I0_measurements = 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. - - // clear whole structure - bzero( &phy_vars_eNB->eNB_UE_stats[UE_id], sizeof(LTE_eNB_UE_stats) ); - - phy_vars_eNB->physicalConfigDedicated[UE_id] = NULL; } - - phy_vars_eNB->first_run_I0_measurements = - 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. - -#ifndef USER_MODE - AssertFatal( frame_parms->nb_antennas_tx <= NB_ANTENNAS_TX, "nb_antennas_tx too large" ); - AssertFatal( frame_parms->nb_antennas_rx <= NB_ANTENNAS_RX, "nb_antennas_rx too large" ); -#endif - - for (eNB_id=0; eNB_id<3; eNB_id++) { - + // for (eNB_id=0; eNB_id<3; eNB_id++) { + { + eNB_id=0; if (abstraction_flag==0) { - + // TX vars - eNB_common_vars->txdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - eNB_common_vars->txdataF[eNB_id] = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - + if (eNB->node_function != NGFI_RCC_IF4) + common_vars->txdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + common_vars->txdataF[eNB_id] = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + for (i=0; inb_antennas_tx; i++) { -#ifdef USER_MODE - eNB_common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); - eNB_common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); -#else // USER_MODE - eNB_common_vars->txdata[eNB_id][i] = TX_DMA_BUFFER[eNB_id][i]; - eNB_common_vars->txdataF[eNB_id][i] = (int32_t *)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); -#endif //USER_MODE + if (eNB->node_function != NGFI_RCC_IF4) + common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); + common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] lte_eNB_common_vars->txdata[%d][%d] = %p\n",eNB_id,i,eNB_common_vars->txdata[eNB_id][i]); - msg("[openair][LTE_PHY][INIT] lte_eNB_common_vars->txdataF[%d][%d] = %p (%d bytes)\n", - eNB_id,i,eNB_common_vars->txdataF[eNB_id][i], - FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + msg("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p\n",eNB_id,i,common_vars->txdata[eNB_id][i]); + msg("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%d bytes)\n", + eNB_id,i,common_vars->txdataF[eNB_id][i], + FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); #endif } - + // RX vars - eNB_common_vars->rxdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_common_vars->rxdataF[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - + if (eNB->node_function != NGFI_RCC_IF4) { + common_vars->rxdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + } + common_vars->rxdataF[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + for (i=0; inb_antennas_rx; i++) { -#ifndef USER_MODE - eNB_common_vars->rxdata[eNB_id][i] = (int32_t*)RX_DMA_BUFFER[eNB_id][i]; -#else //USER_MODE - eNB_common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); -#endif //USER_MODE - eNB_common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->samples_per_tti*sizeof(int32_t) ); - // RK 2 times because of output format of FFT! - // FIXME We should get rid of this - eNB_common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti) ); + if (eNB->node_function != NGFI_RCC_IF4) { + common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); + common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->samples_per_tti*sizeof(int32_t) ); + } + + common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti) ); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] lte_eNB_common_vars->rxdata[%d][%d] = %p\n",eNB_id,i,eNB_common_vars->rxdata[eNB_id][i]); - msg("[openair][LTE_PHY][INIT] lte_eNB_common_vars->rxdata_7_5kHz[%d][%d] = %p\n",eNB_id,i,eNB_common_vars->rxdata_7_5kHz[eNB_id][i]); + msg("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata[eNB_id][i]); + msg("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i]); #endif } - - // Channel estimates for SRS - for (UE_id=0; UE_idnb_antennas_rx*sizeof(int32_t*) ); - eNB_srs_vars[UE_id].srs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - eNB_srs_vars[UE_id].srs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size ); - eNB_srs_vars[UE_id].srs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size*2 ); - } - } //UE_id - - eNB_common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*frame_parms->samples_per_tti ); + + if (eNB->node_function != NGFI_RRU_IF4) { + // Channel estimates for SRS + for (UE_id=0; UE_idnb_antennas_rx*sizeof(int32_t*) ); + srs_vars[UE_id].srs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + + for (i=0; inb_antennas_rx; i++) { + srs_vars[UE_id].srs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size ); + srs_vars[UE_id].srs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size*2 ); + } + } //UE_id + + common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*frame_parms->samples_per_tti ); + } } else { //UPLINK abstraction = 1 - phy_vars_eNB->sinr_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); + eNB->sinr_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); } } //eNB_id - -#ifndef NO_UL_REF - + + + if (abstraction_flag==0) { - generate_ul_ref_sigs_rx(); - - // SRS - for (UE_id=0; UE_idofdm_symbol_size*sizeof(int32_t)); + if (eNB->node_function != NGFI_RRU_IF4) { + generate_ul_ref_sigs_rx(); + + // SRS + for (UE_id=0; UE_idofdm_symbol_size*sizeof(int32_t)); + } } } - -#endif - - // ULSCH VARS - - eNB_prach_vars->prachF = (int16_t*)malloc16_clear( 2*1024 /*FIXME what is the correct number?*/ *sizeof(int16_t) ); - + + + + // ULSCH VARS, skip if NFGI_RRU_IF4 + + if (eNB->node_function!=NGFI_RRU_IF4) + prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) ); + /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ - AssertFatal(frame_parms->nb_antennas_rx <= sizeof(eNB_prach_vars->rxsigF) / sizeof(eNB_prach_vars->rxsigF[0]), + AssertFatal(frame_parms->nb_antennas_rx <= sizeof(prach_vars->rxsigF) / sizeof(prach_vars->rxsigF[0]), "nb_antennas_rx too large"); for (i=0; inb_antennas_rx; i++) { - eNB_prach_vars->rxsigF[i] = (int16_t*)malloc16_clear( frame_parms->ofdm_symbol_size*12*2*sizeof(int16_t) ); + prach_vars->rxsigF[i] = (int16_t*)malloc16_clear( frame_parms->ofdm_symbol_size*12*2*sizeof(int16_t) ); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] prach_vars->rxsigF[%d] = %p\n",i,eNB_prach_vars->rxsigF[i]); + msg("[openair][LTE_PHY][INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]); #endif } - - AssertFatal(frame_parms->nb_antennas_rx <= sizeof(eNB_prach_vars->prach_ifft) / sizeof(eNB_prach_vars->prach_ifft[0]), - "nb_antennas_rx too large"); - for (i=0; inb_antennas_rx; i++) { - eNB_prach_vars->prach_ifft[i] = (int16_t*)malloc16_clear(1024*2*sizeof(int16_t)); + + if (eNB->node_function != NGFI_RRU_IF4) { + AssertFatal(frame_parms->nb_antennas_rx <= sizeof(prach_vars->prach_ifft) / sizeof(prach_vars->prach_ifft[0]), + "nb_antennas_rx too large"); + for (i=0; inb_antennas_rx; i++) { + prach_vars->prach_ifft[i] = (int16_t*)malloc16_clear(1024*2*sizeof(int16_t)); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] prach_vars->prach_ifft[%d] = %p\n",i,eNB_prach_vars->prach_ifft[i]); + msg("[openair][LTE_PHY][INIT] prach_vars->prach_ifft[%d] = %p\n",i,prach_vars->prach_ifft[i]); #endif - } - - for (UE_id=0; UE_idrxdataF_ext[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->rxdataF_ext2[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->drs_ch_estimates[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->rxdataF_comp[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->ul_ch_mag[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->ul_ch_magb[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - // RK 2 times because of output format of FFT! - // FIXME We should get rid of this - eNB_pusch_vars[UE_id]->rxdataF_ext[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - eNB_pusch_vars[UE_id]->rxdataF_ext2[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - eNB_pusch_vars[UE_id]->drs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - eNB_pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*frame_parms->ofdm_symbol_size ); - eNB_pusch_vars[UE_id]->rxdataF_comp[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - eNB_pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - eNB_pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - } - - // In case of Distributed Alamouti Collabrative scheme separate channel estimates are required for both the UEs - if (cooperation_flag == 2) { - eNB_pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // UE 0 DRS estimates - eNB_pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // UE 1 DRS estimates - - for (i=0; inb_antennas_rx; i++) { - eNB_pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - eNB_pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - } - - // Compensated data for the case of Distributed Alamouti Scheme - eNB_pusch_vars[UE_id]->rxdataF_comp_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y)*(h0*) - eNB_pusch_vars[UE_id]->rxdataF_comp_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y*)*(h1) - - for (i=0; inb_antennas_rx; i++) { - eNB_pusch_vars[UE_id]->rxdataF_comp_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - eNB_pusch_vars[UE_id]->rxdataF_comp_1[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - } - - // UE 0 - eNB_pusch_vars[UE_id]->ul_ch_mag_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->ul_ch_magb_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - eNB_pusch_vars[UE_id]->ul_ch_mag_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - eNB_pusch_vars[UE_id]->ul_ch_magb_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - } - - // UE 1 - eNB_pusch_vars[UE_id]->ul_ch_mag_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - eNB_pusch_vars[UE_id]->ul_ch_magb_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - eNB_pusch_vars[UE_id]->ul_ch_mag_1[eNB_id][i] = (int32_t*)malloc16( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - eNB_pusch_vars[UE_id]->ul_ch_magb_1[eNB_id][i] = (int32_t*)malloc16( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - } - }//cooperation_flag - } //eNB_id - - eNB_pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); - } // abstraction_flag - } //UE_id - - if (abstraction_flag==0) { - if (is_secondary_eNB) { - for (eNB_id=0; eNB_id<3; eNB_id++) { - phy_vars_eNB->dl_precoder_SeNB[eNB_id] = (int **)malloc16(4*sizeof(int*)); - - if (phy_vars_eNB->dl_precoder_SeNB[eNB_id]) { -#ifdef DEBUG_PHY - msg("[openair][SECSYS_PHY][INIT] phy_vars_eNB->dl_precoder_SeNB[%d] allocated at %p\n",eNB_id, - phy_vars_eNB->dl_precoder_SeNB[eNB_id]); -#endif - } else { - msg("[openair][SECSYS_PHY][INIT] phy_vars_eNB->dl_precoder_SeNB[%d] not allocated\n",eNB_id); - return(-1); - } - - for (j=0; jlte_frame_parms.nb_antennas_tx; j++) { - phy_vars_eNB->dl_precoder_SeNB[eNB_id][j] = (int *)malloc16(2*sizeof(int)*(phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)); // repeated format (hence the '2*') - - if (phy_vars_eNB->dl_precoder_SeNB[eNB_id][j]) { -#ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] phy_vars_eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j, - phy_vars_eNB->dl_precoder_SeNB[eNB_id][j]); -#endif - memset(phy_vars_eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)); - } else { - msg("[openair][LTE_PHY][INIT] phy_vars_eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j); - return(-1); - } - } //for(j=...nb_antennas_tx - - } //for(eNB_id... } - } - for (UE_id=0; UE_ideNB_UE_stats_ptr[UE_id] = &phy_vars_eNB->eNB_UE_stats[UE_id]; + for (UE_id=0; UE_idrxdataF_ext[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_ext2[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_comp[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_mag[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + + for (i=0; inb_antennas_rx; i++) { + // RK 2 times because of output format of FFT! + // FIXME We should get rid of this + pusch_vars[UE_id]->rxdataF_ext[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); + pusch_vars[UE_id]->rxdataF_ext2[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); + pusch_vars[UE_id]->drs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); + pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*frame_parms->ofdm_symbol_size ); + pusch_vars[UE_id]->rxdataF_comp[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); + pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + } + + // In case of Distributed Alamouti Collabrative scheme separate channel estimates are required for both the UEs + if (cooperation_flag == 2) { + pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // UE 0 DRS estimates + pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // UE 1 DRS estimates + + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + } + + // Compensated data for the case of Distributed Alamouti Scheme + pusch_vars[UE_id]->rxdataF_comp_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y)*(h0*) + pusch_vars[UE_id]->rxdataF_comp_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y*)*(h1) + + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->rxdataF_comp_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + pusch_vars[UE_id]->rxdataF_comp_1[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + } + + // UE 0 + pusch_vars[UE_id]->ul_ch_mag_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->ul_ch_mag_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + } + + // UE 1 + pusch_vars[UE_id]->ul_ch_mag_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->ul_ch_mag_1[eNB_id][i] = (int32_t*)malloc16( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb_1[eNB_id][i] = (int32_t*)malloc16( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + } + }//cooperation_flag + } //eNB_id + + pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + } // abstraction_flag + } //UE_id - phy_vars_eNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration + + if (abstraction_flag==0) { + if (is_secondary_eNB) { + for (eNB_id=0; eNB_id<3; eNB_id++) { + eNB->dl_precoder_SeNB[eNB_id] = (int **)malloc16(4*sizeof(int*)); + + if (eNB->dl_precoder_SeNB[eNB_id]) { +#ifdef DEBUG_PHY + msg("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] allocated at %p\n",eNB_id, + eNB->dl_precoder_SeNB[eNB_id]); +#endif + } else { + msg("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] not allocated\n",eNB_id); + return(-1); + } + + for (j=0; jframe_parms.nb_antennas_tx; j++) { + eNB->dl_precoder_SeNB[eNB_id][j] = (int *)malloc16(2*sizeof(int)*(eNB->frame_parms.ofdm_symbol_size)); // repeated format (hence the '2*') + + if (eNB->dl_precoder_SeNB[eNB_id][j]) { +#ifdef DEBUG_PHY + msg("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j, + eNB->dl_precoder_SeNB[eNB_id][j]); +#endif + memset(eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(eNB->frame_parms.ofdm_symbol_size)); + } else { + msg("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j); + return(-1); + } + } //for(j=...nb_antennas_tx + + } //for(eNB_id... + } + } + + for (UE_id=0; UE_idUE_stats_ptr[UE_id] = &eNB->UE_stats[UE_id]; + + eNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration - init_prach_tables(839); + init_prach_tables(839); + } // node_function != NGFI_RRU_IF4 return (0); } diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c index 0db51e8b17..d13b624cfd 100644 --- a/openair1/PHY/INIT/lte_param_init.c +++ b/openair1/PHY/INIT/lte_param_init.c @@ -25,7 +25,7 @@ void lte_param_init(unsigned char N_tx, uint32_t perfect_ce) { - LTE_DL_FRAME_PARMS *lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms; int i; @@ -39,64 +39,64 @@ void lte_param_init(unsigned char N_tx, randominit(0); set_taus_seed(0); - lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); + frame_parms = &(PHY_vars_eNB->frame_parms); - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->threequarter_fs = threequarter_fs; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Ncp_UL = extended_prefix_flag; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = Nid_cell%6; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - lte_frame_parms->nb_antennas_tx_eNB = N_tx; - lte_frame_parms->phich_config_common.phich_resource = one; - lte_frame_parms->tdd_config = tdd_config; - lte_frame_parms->frame_type = frame_type; - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0;44 - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; + frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz + frame_parms->N_RB_UL = N_RB_DL; + frame_parms->threequarter_fs = threequarter_fs; + frame_parms->Ncp = extended_prefix_flag; + frame_parms->Ncp_UL = extended_prefix_flag; + frame_parms->Nid_cell = Nid_cell; + frame_parms->nushift = Nid_cell%6; + frame_parms->nb_antennas_tx = N_tx; + frame_parms->nb_antennas_rx = N_rx; + frame_parms->nb_antennas_tx_eNB = N_tx; + frame_parms->phich_config_common.phich_resource = one; + frame_parms->tdd_config = tdd_config; + frame_parms->frame_type = frame_type; + // frame_parms->Csrs = 2; + // frame_parms->Bsrs = 0; + // frame_parms->kTC = 0;44 + // frame_parms->n_RRC = 0; + frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - init_frame_parms(lte_frame_parms,osf); + init_frame_parms(frame_parms,osf); - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); + //copy_lte_parms_to_phy_framing(frame_parms, &(PHY_config->PHY_framing)); - // phy_init_top(lte_frame_parms); //allocation + // phy_init_top(frame_parms); //allocation PHY_vars_UE->is_secondary_ue = 0; - PHY_vars_UE->lte_frame_parms = *lte_frame_parms; - PHY_vars_eNB->lte_frame_parms = *lte_frame_parms; + PHY_vars_UE->frame_parms = *frame_parms; + PHY_vars_eNB->frame_parms = *frame_parms; - phy_init_lte_top(lte_frame_parms); - dump_frame_parms(lte_frame_parms); + phy_init_lte_top(frame_parms); + dump_frame_parms(frame_parms); - PHY_vars_UE->PHY_measurements.n_adj_cells=0; - PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; - PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; + PHY_vars_UE->measurements.n_adj_cells=0; + PHY_vars_UE->measurements.adj_cell_id[0] = Nid_cell+1; + PHY_vars_UE->measurements.adj_cell_id[1] = Nid_cell+2; for (i=0; i<3; i++) - lte_gold(lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); + lte_gold(frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); phy_init_lte_ue(PHY_vars_UE,1,0); phy_init_lte_eNB(PHY_vars_eNB,0,0,0); - generate_pcfich_reg_mapping(&PHY_vars_UE->lte_frame_parms); - generate_phich_reg_mapping(&PHY_vars_UE->lte_frame_parms); + generate_pcfich_reg_mapping(&PHY_vars_UE->frame_parms); + generate_phich_reg_mapping(&PHY_vars_UE->frame_parms); // DL power control init if (transmission_mode == 1) { PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_eNB->lte_frame_parms).pdsch_config_common).p_b = 0; + ((PHY_vars_eNB->frame_parms).pdsch_config_common).p_b = 0; PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_UE->lte_frame_parms).pdsch_config_common).p_b = 0; + ((PHY_vars_UE->frame_parms).pdsch_config_common).p_b = 0; } else { // rho_a = rhob PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_eNB->lte_frame_parms).pdsch_config_common).p_b = 1; + ((PHY_vars_eNB->frame_parms).pdsch_config_common).p_b = 1; PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_UE->lte_frame_parms).pdsch_config_common).p_b = 1; + ((PHY_vars_UE->frame_parms).pdsch_config_common).p_b = 1; } PHY_vars_UE->perfect_ce = perfect_ce; diff --git a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c index af72bce967..48339de4cd 100644 --- a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c +++ b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c @@ -36,7 +36,7 @@ extern int card; #endif void -phy_adjust_gain (PHY_VARS_UE *phy_vars_ue, uint32_t rx_power_fil_dB, uint8_t eNB_id) +phy_adjust_gain (PHY_VARS_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id) { #ifdef EXMIMO @@ -46,72 +46,72 @@ phy_adjust_gain (PHY_VARS_UE *phy_vars_ue, uint32_t rx_power_fil_dB, uint8_t eNB LOG_D(PHY,"Gain control: rssi %d (%d,%d)\n", rx_power_fil_dB, - phy_vars_ue->PHY_measurements.rssi, - phy_vars_ue->PHY_measurements.rx_power_avg_dB[eNB_id] + ue->measurements.rssi, + ue->measurements.rx_power_avg_dB[eNB_id] ); // Gain control with hysterisis - // Adjust gain in phy_vars_ue->rx_vars[0].rx_total_gain_dB + // Adjust gain in ue->rx_vars[0].rx_total_gain_dB - if (rx_power_fil_dB < TARGET_RX_POWER - 5) //&& (phy_vars_ue->rx_total_gain_dB < MAX_RF_GAIN) ) - phy_vars_ue->rx_total_gain_dB+=5; - else if (rx_power_fil_dB > TARGET_RX_POWER + 5) //&& (phy_vars_ue->rx_total_gain_dB > MIN_RF_GAIN) ) - phy_vars_ue->rx_total_gain_dB-=5; + if (rx_power_fil_dB < TARGET_RX_POWER - 5) //&& (ue->rx_total_gain_dB < MAX_RF_GAIN) ) + ue->rx_total_gain_dB+=5; + else if (rx_power_fil_dB > TARGET_RX_POWER + 5) //&& (ue->rx_total_gain_dB > MIN_RF_GAIN) ) + ue->rx_total_gain_dB-=5; - if (phy_vars_ue->rx_total_gain_dB>MAX_RF_GAIN) { + if (ue->rx_total_gain_dB>MAX_RF_GAIN) { /* if ((openair_daq_vars.rx_rf_mode==0) && (openair_daq_vars.mode == openair_NOT_SYNCHED)) { openair_daq_vars.rx_rf_mode=1; - phy_vars_ue->rx_total_gain_dB = max(MIN_RF_GAIN,MAX_RF_GAIN-25); + ue->rx_total_gain_dB = max(MIN_RF_GAIN,MAX_RF_GAIN-25); } else { */ - phy_vars_ue->rx_total_gain_dB = MAX_RF_GAIN; - } else if (phy_vars_ue->rx_total_gain_dBrx_total_gain_dB = MAX_RF_GAIN; + } else if (ue->rx_total_gain_dBrx_total_gain_dB = min(MAX_RF_GAIN,MIN_RF_GAIN+25); + ue->rx_total_gain_dB = min(MAX_RF_GAIN,MIN_RF_GAIN+25); } else { */ - phy_vars_ue->rx_total_gain_dB = MIN_RF_GAIN; + ue->rx_total_gain_dB = MIN_RF_GAIN; } - LOG_D(PHY,"Gain control: rx_total_gain_dB = %d (max %d,rxpf %d)\n",phy_vars_ue->rx_total_gain_dB,MAX_RF_GAIN,rx_power_fil_dB); + LOG_D(PHY,"Gain control: rx_total_gain_dB = %d (max %d,rxpf %d)\n",ue->rx_total_gain_dB,MAX_RF_GAIN,rx_power_fil_dB); #ifdef EXMIMO - if (phy_vars_ue->rx_total_gain_dB>phy_vars_ue->rx_gain_max[0]) { - phy_vars_ue->rx_total_gain_dB = phy_vars_ue->rx_gain_max[0]; + if (ue->rx_total_gain_dB>ue->rx_gain_max[0]) { + ue->rx_total_gain_dB = ue->rx_gain_max[0]; - for (i=0; ilte_frame_parms.nb_antennas_rx; i++) { + for (i=0; iframe_parms.nb_antennas_rx; i++) { p_exmimo_config->rf.rx_gain[i][0] = 30; } - } else if (phy_vars_ue->rx_total_gain_dB<(phy_vars_ue->rx_gain_max[0]-30)) { + } else if (ue->rx_total_gain_dB<(ue->rx_gain_max[0]-30)) { // for the moment we stay in max gain mode - phy_vars_ue->rx_total_gain_dB = phy_vars_ue->rx_gain_max[0] - 30; + ue->rx_total_gain_dB = ue->rx_gain_max[0] - 30; - for (i=0; ilte_frame_parms.nb_antennas_rx; i++) { + for (i=0; iframe_parms.nb_antennas_rx; i++) { p_exmimo_config->rf.rx_gain[i][0] = 0; } /* - phy_vars_ue->rx_gain_mode[0] = byp; - phy_vars_ue->rx_gain_mode[1] = byp; + ue->rx_gain_mode[0] = byp; + ue->rx_gain_mode[1] = byp; exmimo_pci_interface->rf.rf_mode0 = 22991; //bypass exmimo_pci_interface->rf.rf_mode1 = 22991; //bypass - if (phy_vars_ue->rx_total_gain_dB<(phy_vars_ue->rx_gain_byp[0]-50)) { + if (ue->rx_total_gain_dB<(ue->rx_gain_byp[0]-50)) { exmimo_pci_interface->rf.rx_gain00 = 0; exmimo_pci_interface->rf.rx_gain10 = 0; } */ } else { - for (i=0; ilte_frame_parms.nb_antennas_rx; i++) { - p_exmimo_config->rf.rx_gain[i][0] = 30 - phy_vars_ue->rx_gain_max[0] + phy_vars_ue->rx_total_gain_dB; + for (i=0; iframe_parms.nb_antennas_rx; i++) { + p_exmimo_config->rf.rx_gain[i][0] = 30 - ue->rx_gain_max[0] + ue->rx_total_gain_dB; } } @@ -119,28 +119,28 @@ phy_adjust_gain (PHY_VARS_UE *phy_vars_ue, uint32_t rx_power_fil_dB, uint8_t eNB break; case med_gain: case byp_gain: - if (phy_vars_ue->rx_total_gain_dB>phy_vars_ue->rx_gain_byp[0]) { - phy_vars_ue->rx_gain_mode[0] = max_gain; - phy_vars_ue->rx_gain_mode[1] = max_gain; + if (ue->rx_total_gain_dB>ue->rx_gain_byp[0]) { + ue->rx_gain_mode[0] = max_gain; + ue->rx_gain_mode[1] = max_gain; exmimo_pci_interface->rf.rf_mode0 = 55759; //max gain exmimo_pci_interface->rf.rf_mode1 = 55759; //max gain - if (phy_vars_ue->rx_total_gain_dB>phy_vars_ue->rx_gain_max[0]) { + if (ue->rx_total_gain_dB>ue->rx_gain_max[0]) { exmimo_pci_interface->rf.rx_gain00 = 50; exmimo_pci_interface->rf.rx_gain10 = 50; } else { - exmimo_pci_interface->rf.rx_gain00 = 50 - phy_vars_ue->rx_gain_max[0] + phy_vars_ue->rx_total_gain_dB; - exmimo_pci_interface->rf.rx_gain10 = 50 - phy_vars_ue->rx_gain_max[1] + phy_vars_ue->rx_total_gain_dB; + exmimo_pci_interface->rf.rx_gain00 = 50 - ue->rx_gain_max[0] + ue->rx_total_gain_dB; + exmimo_pci_interface->rf.rx_gain10 = 50 - ue->rx_gain_max[1] + ue->rx_total_gain_dB; } } - else if (phy_vars_ue->rx_total_gain_dB<(phy_vars_ue->rx_gain_byp[0]-50)) { + else if (ue->rx_total_gain_dB<(ue->rx_gain_byp[0]-50)) { exmimo_pci_interface->rf.rx_gain00 = 0; exmimo_pci_interface->rf.rx_gain10 = 0; } else { - exmimo_pci_interface->rf.rx_gain00 = 50 - phy_vars_ue->rx_gain_byp[0] + phy_vars_ue->rx_total_gain_dB; - exmimo_pci_interface->rf.rx_gain10 = 50 - phy_vars_ue->rx_gain_byp[1] + phy_vars_ue->rx_total_gain_dB; + exmimo_pci_interface->rf.rx_gain00 = 50 - ue->rx_gain_byp[0] + ue->rx_total_gain_dB; + exmimo_pci_interface->rf.rx_gain10 = 50 - ue->rx_gain_byp[1] + ue->rx_total_gain_dB; } break; default: @@ -152,9 +152,9 @@ phy_adjust_gain (PHY_VARS_UE *phy_vars_ue, uint32_t rx_power_fil_dB, uint8_t eNB #endif #ifdef DEBUG_PHY - /* if ((phy_vars_ue->frame%100==0) || (phy_vars_ue->frame < 10)) + /* if ((ue->frame%100==0) || (ue->frame < 10)) msg("[PHY][ADJUST_GAIN] frame %d, rx_power = %d, rx_power_fil = %d, rx_power_fil_dB = %d, coef=%d, ncoef=%d, rx_total_gain_dB = %d (%d,%d,%d)\n", - phy_vars_ue->frame,rx_power,rx_power_fil,rx_power_fil_dB,coef,ncoef,phy_vars_ue->rx_total_gain_dB, + ue->frame,rx_power,rx_power_fil,rx_power_fil_dB,coef,ncoef,ue->rx_total_gain_dB, TARGET_RX_POWER,MAX_RF_GAIN,MIN_RF_GAIN); */ #endif //DEBUG_PHY diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c index 059119c605..7467dd38a5 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c @@ -37,7 +37,7 @@ // last channel estimate of the receiver void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, - PHY_VARS_UE *phy_vars_ue, + PHY_VARS_UE *ue, unsigned char eNB_id, unsigned char clear, short coef) @@ -51,7 +51,7 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, ncoef = 32767 - coef; #ifdef DEBUG_PHY - LOG_D(PHY,"frame %d, slot %d: rx_offset (before) = %d\n",phy_vars_ue->frame_rx,phy_vars_ue->slot_rx,phy_vars_ue->rx_offset); + LOG_D(PHY,"frame %d, slot %d: rx_offset (before) = %d\n",ue->frame_rx,ue->slot_rx,ue->rx_offset); #endif //DEBUG_PHY @@ -60,8 +60,8 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, temp = 0; for (aa=0; aanb_antennas_rx; aa++) { - Re = ((int16_t*)phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_id][aa])[(i<<2)]; - Im = ((int16_t*)phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_id][aa])[1+(i<<2)]; + Re = ((int16_t*)ue->common_vars.dl_ch_estimates_time[eNB_id][aa])[(i<<2)]; + Im = ((int16_t*)ue->common_vars.dl_ch_estimates_time[eNB_id][aa])[1+(i<<2)]; temp += (Re*Re/2) + (Im*Im/2); } @@ -81,21 +81,21 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, diff = max_pos_fil - frame_parms->nb_prefix_samples/8; if ( diff > SYNCH_HYST ) - phy_vars_ue->rx_offset++; + ue->rx_offset++; else if (diff < -SYNCH_HYST) - phy_vars_ue->rx_offset--; + ue->rx_offset--; - if ( phy_vars_ue->rx_offset < 0 ) - phy_vars_ue->rx_offset += FRAME_LENGTH_COMPLEX_SAMPLES; + if ( ue->rx_offset < 0 ) + ue->rx_offset += FRAME_LENGTH_COMPLEX_SAMPLES; - if ( phy_vars_ue->rx_offset >= FRAME_LENGTH_COMPLEX_SAMPLES ) - phy_vars_ue->rx_offset -= FRAME_LENGTH_COMPLEX_SAMPLES; + if ( ue->rx_offset >= FRAME_LENGTH_COMPLEX_SAMPLES ) + ue->rx_offset -= FRAME_LENGTH_COMPLEX_SAMPLES; #ifdef DEBUG_PHY LOG_D(PHY,"frame %d: rx_offset (after) = %d : max_pos = %d,max_pos_fil = %d (peak %d)\n", - phy_vars_ue->frame_rx,phy_vars_ue->rx_offset,max_pos,max_pos_fil,temp); + ue->frame_rx,ue->rx_offset,max_pos,max_pos_fil,temp); #endif //DEBUG_PHY @@ -103,7 +103,7 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, - LTE_eNB_SRS *lte_eNb_srs, + LTE_eNB_SRS *lte_eNB_srs, unsigned int *eNB_id, unsigned char clear, unsigned char number_of_cards, @@ -133,23 +133,23 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, // do ifft of channel estimate switch(frame_parms->N_RB_DL) { case 6: - dft128((int16_t*) <e_eNb_srs->srs_ch_estimates[ind][aa][0], - (int16_t*) lte_eNb_srs->srs_ch_estimates_time[ind][aa], + dft128((int16_t*) <e_eNB_srs->srs_ch_estimates[ind][aa][0], + (int16_t*) lte_eNB_srs->srs_ch_estimates_time[ind][aa], 1); break; case 25: - dft512((int16_t*) <e_eNb_srs->srs_ch_estimates[ind][aa][0], - (int16_t*) lte_eNb_srs->srs_ch_estimates_time[ind][aa], + dft512((int16_t*) <e_eNB_srs->srs_ch_estimates[ind][aa][0], + (int16_t*) lte_eNB_srs->srs_ch_estimates_time[ind][aa], 1); break; case 50: - dft1024((int16_t*) <e_eNb_srs->srs_ch_estimates[ind][aa][0], - (int16_t*) lte_eNb_srs->srs_ch_estimates_time[ind][aa], + dft1024((int16_t*) <e_eNB_srs->srs_ch_estimates[ind][aa][0], + (int16_t*) lte_eNB_srs->srs_ch_estimates_time[ind][aa], 1); break; case 100: - dft2048((int16_t*) <e_eNb_srs->srs_ch_estimates[ind][aa][0], - (int16_t*) lte_eNb_srs->srs_ch_estimates_time[ind][aa], + dft2048((int16_t*) <e_eNB_srs->srs_ch_estimates[ind][aa][0], + (int16_t*) lte_eNB_srs->srs_ch_estimates_time[ind][aa], 1); break; } @@ -157,7 +157,7 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, #ifdef DEBUG_PHY sprintf(fname,"srs_ch_estimates_time_%d%d.m",ind,aa); sprintf(vname,"srs_time_%d%d",ind,aa); - write_output(fname,vname,lte_eNb_srs->srs_ch_estimates_time[ind][aa],frame_parms->ofdm_symbol_size*2,2,1); + write_output(fname,vname,lte_eNB_srs->srs_ch_estimates_time[ind][aa],frame_parms->ofdm_symbol_size*2,2,1); #endif #endif } @@ -168,8 +168,8 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, temp = 0; for (aa=0; aanb_antennas_rx; aa++) { - Re = ((int16_t*)lte_eNb_srs->srs_ch_estimates_time[ind][aa])[(i<<1)]; - Im = ((int16_t*)lte_eNb_srs->srs_ch_estimates_time[ind][aa])[1+(i<<1)]; + Re = ((int16_t*)lte_eNB_srs->srs_ch_estimates_time[ind][aa])[(i<<1)]; + Im = ((int16_t*)lte_eNB_srs->srs_ch_estimates_time[ind][aa])[1+(i<<1)]; temp += (Re*Re/2) + (Im*Im/2); } @@ -195,7 +195,7 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, } -int lte_est_timing_advance_pusch(PHY_VARS_eNB* phy_vars_eNB,uint8_t UE_id,uint8_t sched_subframe) +int lte_est_timing_advance_pusch(PHY_VARS_eNB* eNB,uint8_t UE_id,uint8_t thread_id) { static int first_run=1; static int max_pos_fil2=0; @@ -203,8 +203,8 @@ int lte_est_timing_advance_pusch(PHY_VARS_eNB* phy_vars_eNB,uint8_t UE_id,uint8_ short Re,Im,coef=24576; short ncoef = 32768 - coef; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; - LTE_eNB_PUSCH *eNB_pusch_vars = phy_vars_eNB->lte_eNB_pusch_vars[UE_id]; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + LTE_eNB_PUSCH *eNB_pusch_vars = eNB->pusch_vars[UE_id]; int32_t **ul_ch_estimates_time= eNB_pusch_vars->drs_ch_estimates_time[0]; uint8_t cyclic_shift = 0; int sync_pos = (frame_parms->ofdm_symbol_size-cyclic_shift*frame_parms->ofdm_symbol_size/12)%(frame_parms->ofdm_symbol_size); @@ -236,7 +236,7 @@ int lte_est_timing_advance_pusch(PHY_VARS_eNB* phy_vars_eNB,uint8_t UE_id,uint8_ max_pos_fil2 = ((max_pos_fil2 * coef) + (max_pos * ncoef)) >> 15; #ifdef DEBUG_PHY - LOG_D(PHY,"frame %d: max_pos = %d, max_pos_fil = %d, sync_pos=%d\n",phy_vars_eNB->proc[sched_subframe].frame_rx,max_pos,max_pos_fil2,sync_pos); + LOG_D(PHY,"frame %d: max_pos = %d, max_pos_fil = %d, sync_pos=%d\n",eNB->proc[thread_id].frame_rx,max_pos,max_pos_fil2,sync_pos); #endif //DEBUG_PHY return(max_pos_fil2-sync_pos); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c index bfbe94bb61..b8baec980a 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c @@ -34,7 +34,7 @@ #include "filt96_32.h" //#define DEBUG_CH -int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, +int lte_dl_channel_estimation(PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t eNB_offset, unsigned char Ns, @@ -54,13 +54,13 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, // unsigned int n; // int i; - uint16_t Nid_cell = (eNB_offset == 0) ? phy_vars_ue->lte_frame_parms.Nid_cell : phy_vars_ue->PHY_measurements.adj_cell_id[eNB_offset-1]; + uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; uint8_t nushift,pilot1,pilot2,pilot3; - int **dl_ch_estimates=phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset]; - int **rxdataF=phy_vars_ue->lte_ue_common_vars.rxdataF; + int **dl_ch_estimates=ue->common_vars.dl_ch_estimates[eNB_offset]; + int **rxdataF=ue->common_vars.rxdataF; - if (phy_vars_ue->lte_frame_parms.Ncp == 0) { // normal prefix + if (ue->frame_parms.Ncp == 0) { // normal prefix pilot1 = 4; pilot2 = 7; pilot3 = 11; @@ -87,19 +87,19 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, } - //ch_offset = (l*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)); - if (phy_vars_ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = phy_vars_ue->lte_frame_parms.ofdm_symbol_size ; + //ch_offset = (l*(ue->frame_parms.ofdm_symbol_size)); + if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage + ch_offset = ue->frame_parms.ofdm_symbol_size ; else - ch_offset = phy_vars_ue->lte_frame_parms.ofdm_symbol_size*symbol; + ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; - symbol_offset = phy_vars_ue->lte_frame_parms.ofdm_symbol_size*symbol; + symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; k = (nu + nushift)%6; #ifdef DEBUG_CH - printf("Channel Estimation : eNB_offset %d cell_id %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d\n",eNB_offset,Nid_cell,ch_offset,phy_vars_ue->lte_frame_parms.ofdm_symbol_size, - phy_vars_ue->lte_frame_parms.Ncp,l,Ns,k); + printf("Channel Estimation : eNB_offset %d cell_id %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d\n",eNB_offset,Nid_cell,ch_offset,ue->frame_parms.ofdm_symbol_size, + ue->frame_parms.Ncp,l,Ns,k); #endif switch (k) { @@ -182,7 +182,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, // generate pilot - lte_dl_cell_spec_rx(phy_vars_ue, + lte_dl_cell_spec_rx(ue, eNB_offset, &pilot[p][0], Ns, @@ -190,25 +190,25 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, p); - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { pil = (int16_t *)&pilot[p][0]; - rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+k+phy_vars_ue->lte_frame_parms.first_carrier_offset))]; + rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+k+ue->frame_parms.first_carrier_offset))]; dl_ch = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset]; // if (eNb_id==0) - memset(dl_ch,0,4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)); - if (phy_vars_ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha - multadd_complex_vector_real_scalar(dl_ch-(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1), - phy_vars_ue->ch_est_alpha,dl_ch-(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1), - 1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size)); + if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha + multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), + ue->ch_est_alpha,dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), + 1,ue->frame_parms.ofdm_symbol_size); #ifdef DEBUG_CH - printf("k %d, first_carrier %d\n",k,phy_vars_ue->lte_frame_parms.first_carrier_offset); + printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset); #endif - if ((phy_vars_ue->lte_frame_parms.N_RB_DL==6) || - (phy_vars_ue->lte_frame_parms.N_RB_DL==50) || - (phy_vars_ue->lte_frame_parms.N_RB_DL==100)) { + if ((ue->frame_parms.N_RB_DL==6) || + (ue->frame_parms.N_RB_DL==50) || + (ue->frame_parms.N_RB_DL==100)) { //First half of pilots // Treat first 2 pilots specially (left edge) @@ -238,7 +238,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, rxF+=12; dl_ch+=16; - for (pilot_cnt=2; pilot_cnt<((phy_vars_ue->lte_frame_parms.N_RB_DL)-1); pilot_cnt+=2) { + for (pilot_cnt=2; pilot_cnt<((ue->frame_parms.N_RB_DL)-1); pilot_cnt+=2) { @@ -285,7 +285,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, #ifdef DEBUG_CH printf("second half k %d\n",k); #endif - for (pilot_cnt=0; pilot_cnt<((phy_vars_ue->lte_frame_parms.N_RB_DL)-3); pilot_cnt+=2) { + for (pilot_cnt=0; pilot_cnt<((ue->frame_parms.N_RB_DL)-3); pilot_cnt+=2) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -342,7 +342,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, } - else if (phy_vars_ue->lte_frame_parms.N_RB_DL==25) { + else if (ue->frame_parms.N_RB_DL==25) { //printf("Channel estimation\n"); // Treat first 2 pilots specially (left edge) @@ -385,7 +385,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, for (pilot_cnt=2; pilot_cnt<24; pilot_cnt+=2) { // printf("pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]); - // printf("rx[%d][%d] -> (%d,%d)\n",p,phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p),rxF[0],rxF[1]); + // printf("rx[%d][%d] -> (%d,%d)\n",p,ue->frame_parms.first_carrier_offset + ue->frame_parms.nushift + 6*rb+(3*p),rxF[0],rxF[1]); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -466,7 +466,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, for (pilot_cnt=0; pilot_cnt<22; pilot_cnt+=2) { // printf("* pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]); - // printf("rx[%d][%d] -> (%d,%d)\n",p,phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p),rxF[0],rxF[1]); + // printf("rx[%d][%d] -> (%d,%d)\n",p,ue->frame_parms.first_carrier_offset + ue->frame_parms.nushift + 6*rb+(3*p),rxF[0],rxF[1]); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -539,7 +539,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, dl_ch, 24); - } else if (phy_vars_ue->lte_frame_parms.N_RB_DL==15) { + } else if (ue->frame_parms.N_RB_DL==15) { //printf("First Half\n"); for (rb=0; rb<28; rb+=4) { @@ -547,7 +547,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, //printf("aarx=%d\n",aarx); //printf("pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]); //printf("rx[%d][%d] -> (%d,%d)\n",p, - // phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p), + // ue->frame_parms.first_carrier_offset + ue->frame_parms.nushift + 6*rb+(3*p), // rxF[0], // rxF[1]); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -602,7 +602,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, //printf("aarx=%d\n",aarx); //printf("pilot[%d][%d] (%d,%d)\n",p,rb,pil[0],pil[1]); //printf("rx[%d][%d] -> (%d,%d)\n",p, - // phy_vars_ue->lte_frame_parms.first_carrier_offset + phy_vars_ue->lte_frame_parms.nushift + 6*rb+(3*p), + // ue->frame_parms.first_carrier_offset + ue->frame_parms.nushift + 6*rb+(3*p), // rxF[0], // rxF[1]); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -629,78 +629,78 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, } } else { - msg("channel estimation not implemented for phy_vars_ue->lte_frame_parms.N_RB_DL = %d\n",phy_vars_ue->lte_frame_parms.N_RB_DL); + msg("channel estimation not implemented for ue->frame_parms.N_RB_DL = %d\n",ue->frame_parms.N_RB_DL); } - if (phy_vars_ue->perfect_ce == 0) { + if (ue->perfect_ce == 0) { // Temporal Interpolation // printf("ch_offset %d\n",ch_offset); dl_ch = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset]; - if (phy_vars_ue->high_speed_flag == 0) { + if (ue->high_speed_flag == 0) { multadd_complex_vector_real_scalar(dl_ch, - 32767-phy_vars_ue->ch_est_alpha, - dl_ch-(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + 32767-ue->ch_est_alpha, + dl_ch-(ue->frame_parms.ofdm_symbol_size<<1),0,ue->frame_parms.ofdm_symbol_size); } else { // high_speed_flag == 1 if (symbol == 0) { - // printf("Interpolating %d->0\n",4-phy_vars_ue->lte_frame_parms.Ncp); - // dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][(4-phy_vars_ue->lte_frame_parms.Ncp)*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot3*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; + // printf("Interpolating %d->0\n",4-ue->frame_parms.Ncp); + // dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][(4-ue->frame_parms.Ncp)*(ue->frame_parms.ofdm_symbol_size)]; + dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot3*(ue->frame_parms.ofdm_symbol_size)]; - multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); } // this is 1/3,2/3 combination for pilots spaced by 3 symbols else if (symbol == pilot1) { dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][0]; - if (phy_vars_ue->lte_frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) - multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + if (ue->frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) + multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); } else { - multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)<<1),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); } // pilot spacing 3 symbols (1/3,2/3 combination) } else if (symbol == pilot2) { - dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot1*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; + dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot1*(ue->frame_parms.ofdm_symbol_size)]; - multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); } else { // symbol == pilot3 - // printf("Interpolating 0->%d\n",4-phy_vars_ue->lte_frame_parms.Ncp); - dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; + // printf("Interpolating 0->%d\n",4-ue->frame_parms.Ncp); + dl_ch_prev = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][pilot2*(ue->frame_parms.ofdm_symbol_size)]; - if (phy_vars_ue->lte_frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) - multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + if (ue->frame_parms.Ncp==0) {// pilot spacing 4 symbols (1/4,1/2,3/4 combination) + multadd_complex_vector_real_scalar(dl_ch_prev,24576,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,8192,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,16384,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,8192,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,24576,dl_ch_prev+(3*2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); } else { - multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,10923,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size)<<1)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch_prev,21845,dl_ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)<<1),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(dl_ch,10923,dl_ch_prev+(2*((ue->frame_parms.ofdm_symbol_size)<<1)),0,ue->frame_parms.ofdm_symbol_size); } // pilot spacing 3 symbols (1/3,2/3 combination) } @@ -710,7 +710,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, void (*idft)(int16_t *,int16_t *, int); - switch (phy_vars_ue->lte_frame_parms.ofdm_symbol_size) { + switch (ue->frame_parms.ofdm_symbol_size) { case 128: idft = idft128; break; @@ -741,11 +741,11 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, } // do ifft of channel estimate - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) - for (p=0; plte_frame_parms.nb_antennas_tx_eNB; p++) { - if (phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx]) - idft((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx][8], - (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1); + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) + for (p=0; pframe_parms.nb_antennas_tx_eNB; p++) { + if (ue->common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx]) + idft((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx][8], + (int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1); } return(0); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c index f257678c2c..5d9074ea73 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c @@ -33,7 +33,7 @@ #include "PHY/defs.h" //#define DEBUG_CH -int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, +int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t eNB_offset, int subframe, @@ -51,28 +51,16 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, // unsigned int n; // int i; - int **dl_ch_estimates=phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[0]; - int **rxdataF=phy_vars_ue->lte_ue_common_vars.rxdataF; + int **dl_ch_estimates=ue->common_vars.dl_ch_estimates[0]; + int **rxdataF=ue->common_vars.rxdataF; - ch_offset = (l*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)); + ch_offset = (l*(ue->frame_parms.ofdm_symbol_size)); symbol_offset = ch_offset;//phy_vars_ue->lte_frame_parms.ofdm_symbol_size*l; - // printf("dl_mbsfn_channel_estimation.c: symbol %d (%d)\n",l,ch_offset); - // m=phy_vars_ue->lte_frame_parms.N_RB_DL*6; - /* - if ((l==2) || (l==10)) - k = 0;//m<<1; - else if (l==6) - k = 1;//+(m<<1); - else { - msg("lte_dl_mbsfn: l %d -> ERROR\n",l); - return(-1); - } - */ - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { // generate pilot if ((l==2)||(l==6)||(l==10)) { - lte_dl_mbsfn_rx(phy_vars_ue, + lte_dl_mbsfn_rx(ue, &pilot[0], subframe, l>>2); @@ -81,16 +69,16 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, pil = (short *)&pilot[0]; - rxF = (short *)&rxdataF[aarx][((symbol_offset+phy_vars_ue->lte_frame_parms.first_carrier_offset))]; + rxF = (short *)&rxdataF[aarx][((symbol_offset+ue->frame_parms.first_carrier_offset))]; ch = (short *)&dl_ch_estimates[aarx][ch_offset]; // if (eNb_id==0) - memset(ch,0,4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)); + memset(ch,0,4*(ue->frame_parms.ofdm_symbol_size)); //*********************************************************************** - if ((phy_vars_ue->lte_frame_parms.N_RB_DL==6) || - (phy_vars_ue->lte_frame_parms.N_RB_DL==50) || - (phy_vars_ue->lte_frame_parms.N_RB_DL==100)) { + if ((ue->frame_parms.N_RB_DL==6) || + (ue->frame_parms.N_RB_DL==50) || + (ue->frame_parms.N_RB_DL==100)) { // Interpolation and extrapolation; if (l==6) { @@ -99,10 +87,10 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, rxF+=2; } - for (rb=0; rblte_frame_parms.N_RB_DL; rb++) { + for (rb=0; rbframe_parms.N_RB_DL; rb++) { // ------------------------1st pilot------------------------ - if (rb==(phy_vars_ue->lte_frame_parms.N_RB_DL>>1)) { + if (rb==(ue->frame_parms.N_RB_DL>>1)) { rxF = (short *)&rxdataF[aarx][symbol_offset+1]; if (l==6) @@ -117,7 +105,7 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, /* printf("rb %d: pil0 (%d,%d) x (%d,%d) = (%d,%d)\n", rb,pil[0],pil[1],rxF[0],rxF[1],ch[0],ch[1]);*/ - if ((rb>0)&&(rb!=(phy_vars_ue->lte_frame_parms.N_RB_DL>>1))) { + if ((rb>0)&&(rb!=(ue->frame_parms.N_RB_DL>>1))) { ch[-2] += ch[2]; ch[-1] += ch[3]; } else { @@ -165,8 +153,8 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, ch[20] = (short)(((int)pil[10]*rxF[20] - (int)pil[11]*rxF[21])>>15); ch[21] = (short)(((int)pil[10]*rxF[21] + (int)pil[11]*rxF[20])>>15); - if ((rb<(phy_vars_ue->lte_frame_parms.N_RB_DL-1))&& - (rb!=((phy_vars_ue->lte_frame_parms.N_RB_DL>>1)-1))) { + if ((rb<(ue->frame_parms.N_RB_DL-1))&& + (rb!=((ue->frame_parms.N_RB_DL>>1)-1))) { ch[22] = ch[20]>>1; ch[23] = ch[21]>>1; ch[18] += ch[22]; @@ -188,7 +176,7 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, } //********************************************************************* - else if (phy_vars_ue->lte_frame_parms.N_RB_DL==25) { + else if (ue->frame_parms.N_RB_DL==25) { //printf("Channel estimation\n"); //------------------------ loop over first 12 RBs------------------------ if (l==6) { @@ -712,72 +700,72 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *phy_vars_ue, if (l==6) { ch = (short *)&dl_ch_estimates[aarx][ch_offset]; // printf("Interpolating ch 2,6 => %d\n",ch_offset); - ch_prev = (short *)&dl_ch_estimates[aarx][2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - ch0 = (short *)&dl_ch_estimates[aarx][0*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - memcpy(ch0,ch_prev,4*phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + ch_prev = (short *)&dl_ch_estimates[aarx][2*(ue->frame_parms.ofdm_symbol_size)]; + ch0 = (short *)&dl_ch_estimates[aarx][0*(ue->frame_parms.ofdm_symbol_size)]; + memcpy(ch0,ch_prev,4*ue->frame_parms.ofdm_symbol_size); - ch1 = (short *)&dl_ch_estimates[aarx][1*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - memcpy(ch1,ch_prev,4*phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + ch1 = (short *)&dl_ch_estimates[aarx][1*(ue->frame_parms.ofdm_symbol_size)]; + memcpy(ch1,ch_prev,4*ue->frame_parms.ofdm_symbol_size); // 3/4 ch2 + 1/4 ch6 => ch3 - multadd_complex_vector_real_scalar(ch_prev,24576,ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(ch,8192,ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch_prev,24576,ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch,8192,ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); // 1/2 ch2 + 1/2 ch6 => ch4 - multadd_complex_vector_real_scalar(ch_prev,16384,ch_prev+(4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(ch,16384,ch_prev+(4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch_prev,16384,ch_prev+(4*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch,16384,ch_prev+(4*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); // 1/4 ch2 + 3/4 ch6 => ch5 - multadd_complex_vector_real_scalar(ch_prev,8192,ch_prev+(6*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size))),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(ch,24576,ch_prev+(6*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size))),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch_prev,8192,ch_prev+(6*((ue->frame_parms.ofdm_symbol_size))),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch,24576,ch_prev+(6*((ue->frame_parms.ofdm_symbol_size))),0,ue->frame_parms.ofdm_symbol_size); } if (l==10) { ch = (short *)&dl_ch_estimates[aarx][ch_offset]; - ch_prev = (short *)&dl_ch_estimates[aarx][6*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; + ch_prev = (short *)&dl_ch_estimates[aarx][6*(ue->frame_parms.ofdm_symbol_size)]; // 3/4 ch6 + 1/4 ch10 => ch7 - multadd_complex_vector_real_scalar(ch_prev,24576,ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(ch,8192,ch_prev+(2*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch_prev,24576,ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch,8192,ch_prev+(2*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); // 1/2 ch6 + 1/2 ch10 => ch8 - multadd_complex_vector_real_scalar(ch_prev,16384,ch_prev+(4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(ch,16384,ch_prev+(4*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch_prev,16384,ch_prev+(4*(ue->frame_parms.ofdm_symbol_size)),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch,16384,ch_prev+(4*(ue->frame_parms.ofdm_symbol_size)),0,ue->frame_parms.ofdm_symbol_size); // 1/4 ch6 + 3/4 ch10 => ch9 - multadd_complex_vector_real_scalar(ch_prev,8192,ch_prev+(6*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size))),1,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - multadd_complex_vector_real_scalar(ch,24576,ch_prev+(6*((phy_vars_ue->lte_frame_parms.ofdm_symbol_size))),0,phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch_prev,8192,ch_prev+(6*((ue->frame_parms.ofdm_symbol_size))),1,ue->frame_parms.ofdm_symbol_size); + multadd_complex_vector_real_scalar(ch,24576,ch_prev+(6*((ue->frame_parms.ofdm_symbol_size))),0,ue->frame_parms.ofdm_symbol_size); // 5/4 ch10 - 1/4 ch6 => ch11 // Ch11 - ch_prev = (short *)&dl_ch_estimates[aarx][10*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - ch11 = (short *)&dl_ch_estimates[aarx][11*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - memcpy(ch11,ch_prev,4*phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + ch_prev = (short *)&dl_ch_estimates[aarx][10*(ue->frame_parms.ofdm_symbol_size)]; + ch11 = (short *)&dl_ch_estimates[aarx][11*(ue->frame_parms.ofdm_symbol_size)]; + memcpy(ch11,ch_prev,4*ue->frame_parms.ofdm_symbol_size); } } // do ifft of channel estimate - for (aa=0; aalte_frame_parms.nb_antennas_rx*phy_vars_ue->lte_frame_parms.nb_antennas_tx; aa++) { - if (phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa]) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + for (aa=0; aaframe_parms.nb_antennas_rx*ue->frame_parms.nb_antennas_tx; aa++) { + if (ue->common_vars.dl_ch_estimates[eNB_offset][aa]) { + switch (ue->frame_parms.N_RB_DL) { case 6: - idft128((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], - (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], + idft128((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][aa][8], + (int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; case 25: - idft512((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], - (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], + idft512((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][aa][8], + (int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; case 50: - idft1024((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], - (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], + idft1024((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][aa][8], + (int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; case 75: - idft1536((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], - (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], + idft1536((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][aa][8], + (int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; case 100: - idft2048((int16_t*) &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_offset][aa][8], - (int16_t*) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_offset][aa], + idft2048((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][aa][8], + (int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][aa], 1); break; default: diff --git a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c index 8b5c1a1806..5750733edf 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c @@ -39,16 +39,16 @@ int32_t rx_power_avg_eNB[3][3]; -void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, +void lte_eNB_I0_measurements(PHY_VARS_eNB *eNB, int subframe, unsigned char eNB_id, unsigned char clear) { - LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; - PHY_MEASUREMENTS_eNB *phy_measurements = &phy_vars_eNB->PHY_measurements_eNB[eNB_id]; - uint32_t *rb_mask = phy_vars_eNB->rb_mask_ul; + LTE_eNB_COMMON *common_vars = &eNB->common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + PHY_MEASUREMENTS_eNB *measurements = &eNB->measurements[eNB_id]; + uint32_t *rb_mask = eNB->rb_mask_ul; uint32_t aarx /* ,rx_power_correction */; uint32_t rb; @@ -59,24 +59,24 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, // noise measurements // for the moment we measure the noise on the 7th OFDM symbol (in S subframe) - phy_measurements->n0_power_tot = 0; + measurements->n0_power_tot = 0; for (aarx=0; aarxnb_antennas_rx; aarx++) { if (clear == 1) - phy_measurements->n0_power[aarx]=0; + measurements->n0_power[aarx]=0; - phy_measurements->n0_power[aarx] = ((k1*signal_energy(&eNB_common_vars->rxdata[eNB_id][aarx][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size], - frame_parms->ofdm_symbol_size)) + k2*phy_measurements->n0_power[aarx])>>10; - //phy_measurements->n0_power[aarx] = (phy_measurements->n0_power[aarx]) * 12*frame_parms->N_RB_DL)/(frame_parms->ofdm_symbol_size); - phy_measurements->n0_power_dB[aarx] = (unsigned short) dB_fixed(phy_measurements->n0_power[aarx]); - phy_measurements->n0_power_tot += phy_measurements->n0_power[aarx]; + measurements->n0_power[aarx] = ((k1*signal_energy(&common_vars->rxdata[eNB_id][aarx][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size)) + k2*measurements->n0_power[aarx])>>10; + //measurements->n0_power[aarx] = (measurements->n0_power[aarx]) * 12*frame_parms->N_RB_DL)/(frame_parms->ofdm_symbol_size); + measurements->n0_power_dB[aarx] = (unsigned short) dB_fixed(measurements->n0_power[aarx]); + measurements->n0_power_tot += measurements->n0_power[aarx]; } - phy_measurements->n0_power_tot_dB = (unsigned short) dB_fixed(phy_measurements->n0_power_tot); + measurements->n0_power_tot_dB = (unsigned short) dB_fixed(measurements->n0_power_tot); - phy_measurements->n0_power_tot_dBm = phy_measurements->n0_power_tot_dB - phy_vars_eNB->rx_total_gain_eNB_dB; - // printf("n0_power %d\n",phy_measurements->n0_power_tot_dB); + measurements->n0_power_tot_dBm = measurements->n0_power_tot_dB - eNB->rx_total_gain_dB; + // printf("n0_power %d\n",measurements->n0_power_tot_dB); for (rb=0; rbN_RB_UL; rb++) { @@ -88,7 +88,7 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, // select the 7th symbol in an uplink subframe offset = (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; offset += (7*frame_parms->ofdm_symbol_size); - ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][offset]; + ul_ch = &common_vars->rxdataF[eNB_id][aarx][offset]; len = 12; // just do first half of middle PRB for odd number of PRBs if (((frame_parms->N_RB_UL&1) == 1) && @@ -96,36 +96,36 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, len=6; } if (clear == 1) - phy_measurements->n0_subband_power[aarx][rb]=0; + measurements->n0_subband_power[aarx][rb]=0; AssertFatal(ul_ch, "RX signal buffer (freq) problem"); - phy_measurements->n0_subband_power[aarx][rb] = signal_energy_nodc(ul_ch,len); + measurements->n0_subband_power[aarx][rb] = signal_energy_nodc(ul_ch,len); //((k1*(signal_energy_nodc(ul_ch,len))) - // + (k2*phy_measurements->n0_subband_power[aarx][rb])); + // + (k2*measurements->n0_subband_power[aarx][rb])); - phy_measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(phy_measurements->n0_subband_power[aarx][rb]); - // printf("subframe %d (%d): eNb %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), - // phy_measurements->n0_subband_power_dB[aarx][rb]); - n0_power_tot += phy_measurements->n0_subband_power[aarx][rb]; + measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(measurements->n0_subband_power[aarx][rb]); + // printf("subframe %d (%d): eNB %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), + // measurements->n0_subband_power_dB[aarx][rb]); + n0_power_tot += measurements->n0_subband_power[aarx][rb]; } - phy_measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); - phy_measurements->n0_subband_power_tot_dBm[rb] = phy_measurements->n0_subband_power_tot_dB[rb] - phy_vars_eNB->rx_total_gain_eNB_dB - dB_fixed(frame_parms->N_RB_UL); + measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); + measurements->n0_subband_power_tot_dBm[rb] = measurements->n0_subband_power_tot_dB[rb] - eNB->rx_total_gain_dB - dB_fixed(frame_parms->N_RB_UL); } } } -void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, unsigned char eNB_id, unsigned char UE_id, unsigned char init_averaging) { - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNb->lte_frame_parms; - PHY_MEASUREMENTS_eNB *phy_measurements = &phy_vars_eNb->PHY_measurements_eNB[eNB_id]; - LTE_eNB_SRS *eNB_srs_vars = &phy_vars_eNb->lte_eNB_srs_vars[UE_id]; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + PHY_MEASUREMENTS_eNB *measurements = &eNB->measurements[eNB_id]; + LTE_eNB_SRS *srs_vars = &eNB->srs_vars[UE_id]; int32_t aarx,rx_power_correction; int32_t rx_power; @@ -151,39 +151,39 @@ void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNb, for (aarx=0; aarxnb_antennas_rx; aarx++) { - phy_measurements->rx_spatial_power[UE_id][0][aarx] = - ((signal_energy_nodc(&eNB_srs_vars->srs_ch_estimates[eNB_id][aarx][frame_parms->first_carrier_offset], + measurements->rx_spatial_power[UE_id][0][aarx] = + ((signal_energy_nodc(&srs_vars->srs_ch_estimates[eNB_id][aarx][frame_parms->first_carrier_offset], (frame_parms->N_RB_DL*6)) + - signal_energy_nodc(&eNB_srs_vars->srs_ch_estimates[eNB_id][aarx][1], + signal_energy_nodc(&srs_vars->srs_ch_estimates[eNB_id][aarx][1], (frame_parms->N_RB_DL*6)))*rx_power_correction) - - phy_measurements->n0_power[aarx]; + measurements->n0_power[aarx]; - phy_measurements->rx_spatial_power[UE_id][0][aarx]<<=1; // because of noise only in odd samples + measurements->rx_spatial_power[UE_id][0][aarx]<<=1; // because of noise only in odd samples - phy_measurements->rx_spatial_power_dB[UE_id][0][aarx] = (unsigned short) dB_fixed(phy_measurements->rx_spatial_power[UE_id][0][aarx]); + measurements->rx_spatial_power_dB[UE_id][0][aarx] = (unsigned short) dB_fixed(measurements->rx_spatial_power[UE_id][0][aarx]); - phy_measurements->wideband_cqi[UE_id][aarx] = phy_measurements->rx_spatial_power[UE_id][0][aarx]; + measurements->wideband_cqi[UE_id][aarx] = measurements->rx_spatial_power[UE_id][0][aarx]; - // phy_measurements->rx_power[UE_id][aarx]/=frame_parms->nb_antennas_tx; - phy_measurements->wideband_cqi_dB[UE_id][aarx] = (unsigned short) dB_fixed(phy_measurements->wideband_cqi[UE_id][aarx]); - rx_power += phy_measurements->wideband_cqi[UE_id][aarx]; - // phy_measurements->rx_avg_power_dB[UE_id] += phy_measurements->rx_power_dB[UE_id][aarx]; + // measurements->rx_power[UE_id][aarx]/=frame_parms->nb_antennas_tx; + measurements->wideband_cqi_dB[UE_id][aarx] = (unsigned short) dB_fixed(measurements->wideband_cqi[UE_id][aarx]); + rx_power += measurements->wideband_cqi[UE_id][aarx]; + // measurements->rx_avg_power_dB[UE_id] += measurements->rx_power_dB[UE_id][aarx]; } - // phy_measurements->rx_avg_power_dB[UE_id]/=frame_parms->nb_antennas_rx; + // measurements->rx_avg_power_dB[UE_id]/=frame_parms->nb_antennas_rx; if (init_averaging == 0) rx_power_avg_eNB[UE_id][eNB_id] = ((k1*rx_power_avg_eNB[UE_id][eNB_id]) + (k2*rx_power))>>10; else rx_power_avg_eNB[UE_id][eNB_id] = rx_power; - phy_measurements->wideband_cqi_tot[UE_id] = dB_fixed2(rx_power,2*phy_measurements->n0_power_tot); + measurements->wideband_cqi_tot[UE_id] = dB_fixed2(rx_power,2*measurements->n0_power_tot); // times 2 since we have noise only in the odd carriers of the srs comb - phy_measurements->rx_rssi_dBm[UE_id] = (int32_t)dB_fixed(rx_power_avg_eNB[UE_id][eNB_id])-phy_vars_eNb->rx_total_gain_eNB_dB; + measurements->rx_rssi_dBm[UE_id] = (int32_t)dB_fixed(rx_power_avg_eNB[UE_id][eNB_id])-eNB->rx_total_gain_dB; @@ -193,52 +193,52 @@ void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNb, for (rb=0; rbN_RB_DL; rb++) { - // printf("eNB_common_vars->srs_ch_estimates[0] => %x\n",eNB_common_vars->srs_ch_estimates[0]); + // printf("common_vars->srs_ch_estimates[0] => %x\n",common_vars->srs_ch_estimates[0]); if (rb < 12) - ul_ch = &eNB_srs_vars->srs_ch_estimates[eNB_id][aarx][frame_parms->first_carrier_offset + (rb*12)]; + ul_ch = &srs_vars->srs_ch_estimates[eNB_id][aarx][frame_parms->first_carrier_offset + (rb*12)]; else if (rb>12) - ul_ch = &eNB_srs_vars->srs_ch_estimates[eNB_id][aarx][6 + (rb-13)*12]; + ul_ch = &srs_vars->srs_ch_estimates[eNB_id][aarx][6 + (rb-13)*12]; else { - phy_measurements->subband_cqi_dB[UE_id][aarx][rb] = 0; + measurements->subband_cqi_dB[UE_id][aarx][rb] = 0; continue; } // cqi if (aarx==0) - phy_measurements->subband_cqi_tot[UE_id][rb]=0; + measurements->subband_cqi_tot[UE_id][rb]=0; - phy_measurements->subband_cqi[UE_id][aarx][rb] = (signal_energy_nodc(ul_ch,12))*rx_power_correction - phy_measurements->n0_power[aarx]; + measurements->subband_cqi[UE_id][aarx][rb] = (signal_energy_nodc(ul_ch,12))*rx_power_correction - measurements->n0_power[aarx]; - if (phy_measurements->subband_cqi[UE_id][aarx][rb] < 0) - phy_measurements->subband_cqi[UE_id][aarx][rb]=0; + if (measurements->subband_cqi[UE_id][aarx][rb] < 0) + measurements->subband_cqi[UE_id][aarx][rb]=0; - phy_measurements->subband_cqi_tot[UE_id][rb] += phy_measurements->subband_cqi[UE_id][aarx][rb]; - phy_measurements->subband_cqi_dB[UE_id][aarx][rb] = dB_fixed2(phy_measurements->subband_cqi[UE_id][aarx][rb], - 2*phy_measurements->n0_power[aarx]); + measurements->subband_cqi_tot[UE_id][rb] += measurements->subband_cqi[UE_id][aarx][rb]; + measurements->subband_cqi_dB[UE_id][aarx][rb] = dB_fixed2(measurements->subband_cqi[UE_id][aarx][rb], + 2*measurements->n0_power[aarx]); // 2*n0_power since we have noise from the odd carriers in the comb of the srs - // msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,rb,phy_measurements->subband_cqi[eNB_id][aarx][rb],phy_measurements->subband_cqi_dB[eNB_id][aarx][rb]); + // msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,rb,measurements->subband_cqi[eNB_id][aarx][rb],measurements->subband_cqi_dB[eNB_id][aarx][rb]); } } for (rb=0; rbN_RB_DL; rb++) { - phy_measurements->subband_cqi_tot_dB[UE_id][rb] = dB_fixed2(phy_measurements->subband_cqi_tot[UE_id][rb], - phy_measurements->n0_power_tot); + measurements->subband_cqi_tot_dB[UE_id][rb] = dB_fixed2(measurements->subband_cqi_tot[UE_id][rb], + measurements->n0_power_tot); /* - if (phy_measurements->subband_cqi_tot_dB[UE_id][rb] == 65) - msg("eNB meas error *****subband_cqi_tot[%d][%d] %d => %d dB (n0 %d)\n",UE_id,rb,phy_measurements->subband_cqi_tot[UE_id][rb],phy_measurements->subband_cqi_tot_dB[UE_id][rb],phy_measurements->n0_power_tot); + if (measurements->subband_cqi_tot_dB[UE_id][rb] == 65) + msg("eNB meas error *****subband_cqi_tot[%d][%d] %d => %d dB (n0 %d)\n",UE_id,rb,measurements->subband_cqi_tot[UE_id][rb],measurements->subband_cqi_tot_dB[UE_id][rb],measurements->n0_power_tot); */ } } -void lte_eNB_I0_measurements_emul(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_I0_measurements_emul(PHY_VARS_eNB *eNB, uint8_t sect_id) { - LOG_D(PHY,"EMUL lte_eNB_IO_measurements_emul: eNB %d, sect %d\n",phy_vars_eNb->Mod_id,sect_id); + LOG_D(PHY,"EMUL lte_eNB_IO_measurements_emul: eNB %d, sect %d\n",eNB->Mod_id,sect_id); } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c index 74b46c5eb6..f3c9b973ea 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c @@ -82,7 +82,7 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq) //compute frequency-domain representation of 6144-sample chunk - rxp = &ue->lte_ue_common_vars.rxdata[0][i]; + rxp = &ue->common_vars.rxdata[0][i]; sp=spectrum; while (1) { @@ -341,8 +341,8 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq) } // loop on pss index } - if (rxp == &ue->lte_ue_common_vars.rxdata[0][i+38400*4]) { - rxp = &ue->lte_ue_common_vars.rxdata[0][i+38400*4]; + if (rxp == &ue->common_vars.rxdata[0][i+38400*4]) { + rxp = &ue->common_vars.rxdata[0][i+38400*4]; sp=spectrum_p5ms; } else { break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c index 3bc26ad7e8..ae484092b8 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c @@ -66,36 +66,36 @@ void print_ints(char *s,int *x) int16_t get_PL(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; /* int RSoffset; - if (phy_vars_ue->lte_frame_parms.mode1_flag == 1) + if (ue->frame_parms.mode1_flag == 1) RSoffset = 6; else RSoffset = 3; */ - LOG_D(PHY,"get_PL : Frame %d : rsrp %f dBm/RE (%f), eNB power %d dBm/RE\n", phy_vars_ue->frame_rx, - (1.0*dB_fixed_times10(phy_vars_ue->PHY_measurements.rsrp[eNB_index])-(10.0*phy_vars_ue->rx_total_gain_dB))/10.0, - 10*log10((double)phy_vars_ue->PHY_measurements.rsrp[eNB_index]), - phy_vars_ue->lte_frame_parms.pdsch_config_common.referenceSignalPower); + LOG_D(PHY,"get_PL : Frame %d : rsrp %f dBm/RE (%f), eNB power %d dBm/RE\n", ue->frame_rx, + (1.0*dB_fixed_times10(ue->measurements.rsrp[eNB_index])-(10.0*ue->rx_total_gain_dB))/10.0, + 10*log10((double)ue->measurements.rsrp[eNB_index]), + ue->frame_parms.pdsch_config_common.referenceSignalPower); - return((int16_t)(((10*phy_vars_ue->rx_total_gain_dB) - - dB_fixed_times10(phy_vars_ue->PHY_measurements.rsrp[eNB_index])+ - // dB_fixed_times10(RSoffset*12*PHY_vars_UE_g[Mod_id][CC_id]->lte_frame_parms.N_RB_DL) + - (phy_vars_ue->lte_frame_parms.pdsch_config_common.referenceSignalPower*10))/10)); + return((int16_t)(((10*ue->rx_total_gain_dB) - + dB_fixed_times10(ue->measurements.rsrp[eNB_index])+ + // dB_fixed_times10(RSoffset*12*ue_g[Mod_id][CC_id]->frame_parms.N_RB_DL) + + (ue->frame_parms.pdsch_config_common.referenceSignalPower*10))/10)); } uint8_t get_n_adj_cells (uint8_t Mod_id,uint8_t CC_id) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - if (phy_vars_ue) - return phy_vars_ue->PHY_measurements.n_adj_cells; + if (ue) + return ue->measurements.n_adj_cells; else return 0; } @@ -103,30 +103,30 @@ uint8_t get_n_adj_cells (uint8_t Mod_id,uint8_t CC_id) uint32_t get_rx_total_gain_dB (uint8_t Mod_id,uint8_t CC_id) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - if (phy_vars_ue) - return phy_vars_ue->rx_total_gain_dB; + if (ue) + return ue->rx_total_gain_dB; return 0xFFFFFFFF; } uint32_t get_RSSI (uint8_t Mod_id,uint8_t CC_id) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - if (phy_vars_ue) - return phy_vars_ue->PHY_measurements.rssi; + if (ue) + return ue->measurements.rssi; return 0xFFFFFFFF; } uint32_t get_RSRP(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - if (phy_vars_ue) - return phy_vars_ue->PHY_measurements.rsrp[eNB_index]; + if (ue) + return ue->measurements.rsrp[eNB_index]; return 0xFFFFFFFF; } @@ -134,10 +134,10 @@ uint32_t get_RSRP(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) uint32_t get_RSRQ(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - if (phy_vars_ue) - return phy_vars_ue->PHY_measurements.rsrq[eNB_index]; + if (ue) + return ue->measurements.rsrq[eNB_index]; return 0xFFFFFFFF; } @@ -145,10 +145,10 @@ uint32_t get_RSRQ(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) int8_t set_RSRP_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - if (phy_vars_ue) { - phy_vars_ue->PHY_measurements.rsrp_filtered[eNB_index]=rsrp; + if (ue) { + ue->measurements.rsrp_filtered[eNB_index]=rsrp; return 0; } @@ -159,10 +159,10 @@ int8_t set_RSRP_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rs int8_t set_RSRQ_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrq) { - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - if (phy_vars_ue) { - phy_vars_ue->PHY_measurements.rsrq_filtered[eNB_index]=rsrq; + if (ue) { + ue->measurements.rsrq_filtered[eNB_index]=rsrq; return 0; } @@ -171,7 +171,7 @@ int8_t set_RSRQ_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rs } -void ue_rrc_measurements(PHY_VARS_UE *phy_vars_ue, +void ue_rrc_measurements(PHY_VARS_UE *ue, uint8_t slot, uint8_t abstraction_flag) { @@ -179,95 +179,95 @@ void ue_rrc_measurements(PHY_VARS_UE *phy_vars_ue, int aarx,rb; int16_t *rxF,*rxF_pss,*rxF_sss; - uint16_t Nid_cell = phy_vars_ue->lte_frame_parms.Nid_cell; + uint16_t Nid_cell = ue->frame_parms.Nid_cell; uint8_t eNB_offset,nu,l,nushift,k; uint16_t off; - for (eNB_offset = 0; eNB_offset<1+phy_vars_ue->PHY_measurements.n_adj_cells; eNB_offset++) { + for (eNB_offset = 0; eNB_offset<1+ue->measurements.n_adj_cells; eNB_offset++) { if (eNB_offset==0) { - phy_vars_ue->PHY_measurements.rssi = 0; - phy_vars_ue->PHY_measurements.n0_power_tot = 0; + ue->measurements.rssi = 0; + ue->measurements.n0_power_tot = 0; if (abstraction_flag == 0) { - if ((phy_vars_ue->lte_frame_parms.frame_type == FDD) && + if ((ue->frame_parms.frame_type == FDD) && ((slot == 0) || (slot == 10))) { // FDD PSS/SSS, compute noise in DTX REs - if (phy_vars_ue->lte_frame_parms.Ncp==NORMAL) { - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { + if (ue->frame_parms.Ncp==NORMAL) { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - rxF_sss = (int16_t *)&phy_vars_ue->lte_ue_common_vars.rxdataF[aarx][(5*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - rxF_pss = (int16_t *)&phy_vars_ue->lte_ue_common_vars.rxdataF[aarx][(6*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; + rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(5*ue->frame_parms.ofdm_symbol_size)]; + rxF_pss = (int16_t *)&ue->common_vars.rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)]; //-ve spectrum from SSS // printf("slot %d: SSS DTX: %d,%d, non-DTX %d,%d\n",slot,rxF_pss[-72],rxF_pss[-71],rxF_pss[-36],rxF_pss[-35]); - // phy_vars_ue->PHY_measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); - // printf("sssn36 %d\n",phy_vars_ue->PHY_measurements.n0_power[aarx]); - phy_vars_ue->PHY_measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); - // printf("sssm32 %d\n",phy_vars_ue->PHY_measurements.n0_power[aarx]); + // ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); + // printf("sssn36 %d\n",ue->measurements.n0_power[aarx]); + ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); + // printf("sssm32 %d\n",ue->measurements.n0_power[aarx]); //+ve spectrum from SSS - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65])); - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63])); - // printf("sssp32 %d\n",phy_vars_ue->PHY_measurements.n0_power[aarx]); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63])); + // printf("sssp32 %d\n",ue->measurements.n0_power[aarx]); //+ve spectrum from PSS - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+70]*rxF_pss[2+70])+((int32_t)rxF_pss[2+69]*rxF_pss[2+69])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+68]*rxF_pss[2+68])+((int32_t)rxF_pss[2+67]*rxF_pss[2+67])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+66]*rxF_pss[2+66])+((int32_t)rxF_pss[2+65]*rxF_pss[2+65])); - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+64]*rxF_pss[2+64])+((int32_t)rxF_pss[2+63]*rxF_pss[2+63])); - // printf("pss32 %d\n",phy_vars_ue->PHY_measurements.n0_power[aarx]); //-ve spectrum from PSS - rxF_pss = (int16_t *)&phy_vars_ue->lte_ue_common_vars.rxdataF[aarx][(7*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); - // printf("pssm36 %d\n",phy_vars_ue->PHY_measurements.n0_power[aarx]); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); - // printf("pssm32 %d\n",phy_vars_ue->PHY_measurements.n0_power[aarx]); - phy_vars_ue->PHY_measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(phy_vars_ue->PHY_measurements.n0_power[aarx]/12); - phy_vars_ue->PHY_measurements.n0_power_tot += phy_vars_ue->PHY_measurements.n0_power[aarx]; + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+70]*rxF_pss[2+70])+((int32_t)rxF_pss[2+69]*rxF_pss[2+69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+68]*rxF_pss[2+68])+((int32_t)rxF_pss[2+67]*rxF_pss[2+67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+66]*rxF_pss[2+66])+((int32_t)rxF_pss[2+65]*rxF_pss[2+65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+64]*rxF_pss[2+64])+((int32_t)rxF_pss[2+63]*rxF_pss[2+63])); + // printf("pss32 %d\n",ue->measurements.n0_power[aarx]); //-ve spectrum from PSS + rxF_pss = (int16_t *)&ue->common_vars.rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)]; + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); + // printf("pssm36 %d\n",ue->measurements.n0_power[aarx]); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); + // printf("pssm32 %d\n",ue->measurements.n0_power[aarx]); + ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/12); + ue->measurements.n0_power_tot += ue->measurements.n0_power[aarx]; } - phy_vars_ue->PHY_measurements.n0_power_tot_dB = (unsigned short) dB_fixed(phy_vars_ue->PHY_measurements.n0_power_tot/(12*aarx)); - phy_vars_ue->PHY_measurements.n0_power_tot_dBm = phy_vars_ue->PHY_measurements.n0_power_tot_dB - phy_vars_ue->rx_total_gain_dB - dB_fixed(phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(12*aarx)); + ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size); } } - else if ((phy_vars_ue->lte_frame_parms.frame_type == TDD) && + else if ((ue->frame_parms.frame_type == TDD) && (slot == 1)) { // TDD SSS, compute noise in DTX REs - if (phy_vars_ue->lte_frame_parms.Ncp==NORMAL) { - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { + if (ue->frame_parms.Ncp==NORMAL) { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - rxF_sss = (int16_t *)&phy_vars_ue->lte_ue_common_vars.rxdataF[aarx][(6*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; + rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)]; // note this is a dummy pointer, the pss is not really there! // in FDD the pss is in the symbol after the sss, but not in TDD - rxF_pss = (int16_t *)&phy_vars_ue->lte_ue_common_vars.rxdataF[aarx][(7*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; + rxF_pss = (int16_t *)&ue->common_vars.rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)]; //-ve spectrum from SSS - // phy_vars_ue->PHY_measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); - phy_vars_ue->PHY_measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); + // ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71])); + ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63])); //+ve spectrum from SSS - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+72]*rxF_sss[2+72])+((int32_t)rxF_sss[2+71]*rxF_sss[2+71])); - phy_vars_ue->PHY_measurements.n0_power[aarx] = (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67])); - phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65])); - // phy_vars_ue->PHY_measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+72]*rxF_sss[2+72])+((int32_t)rxF_sss[2+71]*rxF_sss[2+71])); + ue->measurements.n0_power[aarx] = (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67])); + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65])); + // ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63])); - phy_vars_ue->PHY_measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(phy_vars_ue->PHY_measurements.n0_power[aarx]/(6)); - phy_vars_ue->PHY_measurements.n0_power_tot += phy_vars_ue->PHY_measurements.n0_power[aarx]; + ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/(6)); + ue->measurements.n0_power_tot += ue->measurements.n0_power[aarx]; } - phy_vars_ue->PHY_measurements.n0_power_tot_dB = (unsigned short) dB_fixed(phy_vars_ue->PHY_measurements.n0_power_tot/(6*aarx)); - phy_vars_ue->PHY_measurements.n0_power_tot_dBm = phy_vars_ue->PHY_measurements.n0_power_tot_dB - phy_vars_ue->rx_total_gain_dB - dB_fixed(phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(6*aarx)); + ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size); } @@ -275,58 +275,58 @@ void ue_rrc_measurements(PHY_VARS_UE *phy_vars_ue, } } // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation - // printf("[PHY][UE %d] Frame %d slot %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, Nid2 %d, nushift %d, eNB_offset %d)\n",phy_vars_ue->Mod_id,phy_vars_ue->frame,slot,Nid_cell,Nid2,nushift,eNB_offset); + // printf("[PHY][UE %d] Frame %d slot %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, Nid2 %d, nushift %d, eNB_offset %d)\n",ue->Mod_id,ue->frame,slot,Nid_cell,Nid2,nushift,eNB_offset); if (eNB_offset > 0) - Nid_cell = phy_vars_ue->PHY_measurements.adj_cell_id[eNB_offset-1]; + Nid_cell = ue->measurements.adj_cell_id[eNB_offset-1]; nushift = Nid_cell%6; - phy_vars_ue->PHY_measurements.rsrp[eNB_offset] = 0; + ue->measurements.rsrp[eNB_offset] = 0; if (abstraction_flag == 0) { // compute RSRP using symbols 0 and 4-frame_parms->Ncp - for (l=0,nu=0; l<=(4-phy_vars_ue->lte_frame_parms.Ncp); l+=(4-phy_vars_ue->lte_frame_parms.Ncp),nu=3) { + for (l=0,nu=0; l<=(4-ue->frame_parms.Ncp); l+=(4-ue->frame_parms.Ncp),nu=3) { k = (nu + nushift)%6; #ifdef DEBUG_MEAS - LOG_I(PHY,"[UE %d] Frame %d slot %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, nushift %d, eNB_offset %d, k %d, l %d)\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_rx,slot,Nid_cell,nushift, + LOG_I(PHY,"[UE %d] Frame %d slot %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, nushift %d, eNB_offset %d, k %d, l %d)\n",ue->Mod_id,ue->frame_rx,slot,Nid_cell,nushift, eNB_offset,k,l); #endif - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { - rxF = (int16_t *)&phy_vars_ue->lte_ue_common_vars.rxdataF[aarx][(l*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)]; - off = (phy_vars_ue->lte_frame_parms.first_carrier_offset+k)<<1; + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + rxF = (int16_t *)&ue->common_vars.rxdataF[aarx][(l*ue->frame_parms.ofdm_symbol_size)]; + off = (ue->frame_parms.first_carrier_offset+k)<<1; - if (l==(4-phy_vars_ue->lte_frame_parms.Ncp)) { - for (rb=0; rblte_frame_parms.N_RB_DL; rb++) { + if (l==(4-ue->frame_parms.Ncp)) { + for (rb=0; rbframe_parms.N_RB_DL; rb++) { // printf("rb %d, off %d, off2 %d\n",rb,off,off2); - phy_vars_ue->PHY_measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])); + ue->measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])); // printf("rb %d, off %d : %d\n",rb,off,((((int32_t)rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1]))); - // if ((phy_vars_ue->frame_rx&0x3ff) == 0) + // if ((ue->frame_rx&0x3ff) == 0) // printf("rb %d, off %d : %d\n",rb,off,((rxF[off]*rxF[off])+(rxF[off+1]*rxF[off+1]))); off+=12; - if (off>=(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1)) + if (off>=(ue->frame_parms.ofdm_symbol_size<<1)) off = (1+k)<<1; - phy_vars_ue->PHY_measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])); + ue->measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])); // printf("rb %d, off %d : %d\n",rb,off,(((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1]))); /* - if ((phy_vars_ue->frame_rx&0x3ff) == 0) + if ((ue->frame_rx&0x3ff) == 0) printf("rb %d, off %d : %d\n",rb,off,((rxF[off]*rxF[off])+(rxF[off+1]*rxF[off+1]))); */ off+=12; - if (off>=(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<1)) + if (off>=(ue->frame_parms.ofdm_symbol_size<<1)) off = (1+k)<<1; } @@ -334,40 +334,40 @@ void ue_rrc_measurements(PHY_VARS_UE *phy_vars_ue, /* if ((eNB_offset==0)&&(l==0)) { for (i=0;i<6;i++,off2+=4) - phy_vars_ue->PHY_measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1])); - if (off2==(phy_vars_ue->lte_frame_parms.ofdm_symbol_size<<2)) + ue->measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1])); + if (off2==(ue->frame_parms.ofdm_symbol_size<<2)) off2=4; for (i=0;i<6;i++,off2+=4) - phy_vars_ue->PHY_measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1])); + ue->measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1])); } */ - // printf("slot %d, rb %d => rsrp %d, rssi %d\n",slot,rb,phy_vars_ue->PHY_measurements.rsrp[eNB_offset],phy_vars_ue->PHY_measurements.rssi); + // printf("slot %d, rb %d => rsrp %d, rssi %d\n",slot,rb,ue->measurements.rsrp[eNB_offset],ue->measurements.rssi); } } } // 2 RE per PRB - // phy_vars_ue->PHY_measurements.rsrp[eNB_offset]/=(24*phy_vars_ue->lte_frame_parms.N_RB_DL); - phy_vars_ue->PHY_measurements.rsrp[eNB_offset]/=(2*phy_vars_ue->lte_frame_parms.N_RB_DL*phy_vars_ue->lte_frame_parms.ofdm_symbol_size); - // LOG_I(PHY,"eNB: %d, RSRP: %d \n",eNB_offset,phy_vars_ue->PHY_measurements.rsrp[eNB_offset]); + // ue->measurements.rsrp[eNB_offset]/=(24*ue->frame_parms.N_RB_DL); + ue->measurements.rsrp[eNB_offset]/=(2*ue->frame_parms.N_RB_DL*ue->frame_parms.ofdm_symbol_size); + // LOG_I(PHY,"eNB: %d, RSRP: %d \n",eNB_offset,ue->measurements.rsrp[eNB_offset]); if (eNB_offset == 0) { - // phy_vars_ue->PHY_measurements.rssi/=(24*phy_vars_ue->lte_frame_parms.N_RB_DL); - // phy_vars_ue->PHY_measurements.rssi*=rx_power_correction; - // phy_vars_ue->PHY_measurements.rssi=phy_vars_ue->PHY_measurements.rsrp[0]*24/2; - phy_vars_ue->PHY_measurements.rssi=phy_vars_ue->PHY_measurements.rsrp[0]*(12*phy_vars_ue->lte_frame_parms.N_RB_DL); + // ue->measurements.rssi/=(24*ue->frame_parms.N_RB_DL); + // ue->measurements.rssi*=rx_power_correction; + // ue->measurements.rssi=ue->measurements.rsrp[0]*24/2; + ue->measurements.rssi=ue->measurements.rsrp[0]*(12*ue->frame_parms.N_RB_DL); } - if (phy_vars_ue->PHY_measurements.rssi>0) - phy_vars_ue->PHY_measurements.rsrq[eNB_offset] = 100*phy_vars_ue->PHY_measurements.rsrp[eNB_offset]*phy_vars_ue->lte_frame_parms.N_RB_DL/phy_vars_ue->PHY_measurements.rssi; + if (ue->measurements.rssi>0) + ue->measurements.rsrq[eNB_offset] = 100*ue->measurements.rsrp[eNB_offset]*ue->frame_parms.N_RB_DL/ue->measurements.rssi; else - phy_vars_ue->PHY_measurements.rsrq[eNB_offset] = -12000; + ue->measurements.rsrq[eNB_offset] = -12000; - //((200*phy_vars_ue->PHY_measurements.rsrq[eNB_offset]) + ((1024-200)*100*phy_vars_ue->PHY_measurements.rsrp[eNB_offset]*phy_vars_ue->lte_frame_parms.N_RB_DL/phy_vars_ue->PHY_measurements.rssi))>>10; + //((200*ue->measurements.rsrq[eNB_offset]) + ((1024-200)*100*ue->measurements.rsrp[eNB_offset]*ue->frame_parms.N_RB_DL/ue->measurements.rssi))>>10; } else { // Do abstraction of RSRP and RSRQ - phy_vars_ue->PHY_measurements.rssi = phy_vars_ue->PHY_measurements.rx_power_avg[0]; + ue->measurements.rssi = ue->measurements.rx_power_avg[0]; // dummay value for the moment - phy_vars_ue->PHY_measurements.rsrp[eNB_offset] = -93 ; - phy_vars_ue->PHY_measurements.rsrq[eNB_offset] = 3; + ue->measurements.rsrp[eNB_offset] = -93 ; + ue->measurements.rsrq[eNB_offset] = 3; } @@ -376,24 +376,24 @@ void ue_rrc_measurements(PHY_VARS_UE *phy_vars_ue, // if (slot == 0) { if (eNB_offset == 0) - LOG_I(PHY,"[UE %d] Frame %d, slot %d RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB, gain %d), N0 %d dBm\n",phy_vars_ue->Mod_id, - phy_vars_ue->frame_rx,slot,10*log10(phy_vars_ue->PHY_measurements.rssi)-phy_vars_ue->rx_total_gain_dB, - 10*log10(phy_vars_ue->PHY_measurements.rssi), - phy_vars_ue->rx_total_gain_dB, - phy_vars_ue->PHY_measurements.n0_power_tot_dBm); + LOG_I(PHY,"[UE %d] Frame %d, slot %d RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB, gain %d), N0 %d dBm\n",ue->Mod_id, + ue->frame_rx,slot,10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, + 10*log10(ue->measurements.rssi), + ue->rx_total_gain_dB, + ue->measurements.n0_power_tot_dBm); LOG_I(PHY,"[UE %d] Frame %d, slot %d RRC Measurements (idx %d, Cell id %d) => rsrp: %3.1f dBm/RE (%d), rsrq: %3.1f dB\n", - phy_vars_ue->Mod_id, - phy_vars_ue->frame_rx,slot,eNB_offset, - (eNB_offset>0) ? phy_vars_ue->PHY_measurements.adj_cell_id[eNB_offset-1] : phy_vars_ue->lte_frame_parms.Nid_cell, - 10*log10(phy_vars_ue->PHY_measurements.rsrp[eNB_offset])-phy_vars_ue->rx_total_gain_dB, - phy_vars_ue->PHY_measurements.rsrp[eNB_offset], - (10*log10(phy_vars_ue->PHY_measurements.rsrq[eNB_offset]))); - //LOG_D(PHY,"RSRP_total_dB: %3.2f \n",(dB_fixed_times10(phy_vars_ue->PHY_measurements.rsrp[eNB_offset])/10.0)-phy_vars_ue->rx_total_gain_dB-dB_fixed(phy_vars_ue->lte_frame_parms.N_RB_DL*12)); + ue->Mod_id, + ue->frame_rx,slot,eNB_offset, + (eNB_offset>0) ? ue->measurements.adj_cell_id[eNB_offset-1] : ue->frame_parms.Nid_cell, + 10*log10(ue->measurements.rsrp[eNB_offset])-ue->rx_total_gain_dB, + ue->measurements.rsrp[eNB_offset], + (10*log10(ue->measurements.rsrq[eNB_offset]))); + //LOG_D(PHY,"RSRP_total_dB: %3.2f \n",(dB_fixed_times10(ue->measurements.rsrp[eNB_offset])/10.0)-ue->rx_total_gain_dB-dB_fixed(ue->frame_parms.N_RB_DL*12)); - //LOG_D(PHY,"RSRP_dB: %3.2f \n",(dB_fixed_times10(phy_vars_ue->PHY_measurements.rsrp[eNB_offset])/10.0)); - //LOG_D(PHY,"gain_loss_dB: %d \n",phy_vars_ue->rx_total_gain_dB); - //LOG_D(PHY,"gain_fixed_dB: %d \n",dB_fixed(phy_vars_ue->lte_frame_parms.N_RB_DL*12)); + //LOG_D(PHY,"RSRP_dB: %3.2f \n",(dB_fixed_times10(ue->measurements.rsrp[eNB_offset])/10.0)); + //LOG_D(PHY,"gain_loss_dB: %d \n",ue->rx_total_gain_dB); + //LOG_D(PHY,"gain_fixed_dB: %d \n",dB_fixed(ue->frame_parms.N_RB_DL*12)); // } @@ -402,7 +402,7 @@ void ue_rrc_measurements(PHY_VARS_UE *phy_vars_ue, } -void lte_ue_measurements(PHY_VARS_UE *phy_vars_ue, +void lte_ue_measurements(PHY_VARS_UE *ue, unsigned int subframe_offset, unsigned char N0_symbol, unsigned char abstraction_flag) @@ -419,7 +419,7 @@ void lte_ue_measurements(PHY_VARS_UE *phy_vars_ue, int16x8_t *dl_ch0_128, *dl_ch1_128; #endif int *dl_ch0,*dl_ch1; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; int nb_subbands,subband_size,last_subband_size; int N_RB_DL = frame_parms->N_RB_DL; @@ -451,121 +451,121 @@ void lte_ue_measurements(PHY_VARS_UE *phy_vars_ue, } // signal measurements - for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) { + for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) { for (aarx=0; aarxnb_antennas_rx; aarx++) { for (aatx=0; aatxnb_antennas_tx_eNB; aatx++) { - phy_vars_ue->PHY_measurements.rx_spatial_power[eNB_id][aatx][aarx] = - (signal_energy_nodc(&phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][(aatx<<1) + aarx][0], + ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] = + (signal_energy_nodc(&ue->common_vars.dl_ch_estimates[eNB_id][(aatx<<1) + aarx][0], (N_RB_DL*12))); - //- phy_vars_ue->PHY_measurements.n0_power[aarx]; + //- ue->measurements.n0_power[aarx]; - if (phy_vars_ue->PHY_measurements.rx_spatial_power[eNB_id][aatx][aarx]<0) - phy_vars_ue->PHY_measurements.rx_spatial_power[eNB_id][aatx][aarx] = 0; //phy_vars_ue->PHY_measurements.n0_power[aarx]; + if (ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]<0) + ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] = 0; //ue->measurements.n0_power[aarx]; - phy_vars_ue->PHY_measurements.rx_spatial_power_dB[eNB_id][aatx][aarx] = (unsigned short) dB_fixed(phy_vars_ue->PHY_measurements.rx_spatial_power[eNB_id][aatx][aarx]); + ue->measurements.rx_spatial_power_dB[eNB_id][aatx][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]); if (aatx==0) - phy_vars_ue->PHY_measurements.rx_power[eNB_id][aarx] = phy_vars_ue->PHY_measurements.rx_spatial_power[eNB_id][aatx][aarx]; + ue->measurements.rx_power[eNB_id][aarx] = ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]; else - phy_vars_ue->PHY_measurements.rx_power[eNB_id][aarx] += phy_vars_ue->PHY_measurements.rx_spatial_power[eNB_id][aatx][aarx]; + ue->measurements.rx_power[eNB_id][aarx] += ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]; } //aatx - phy_vars_ue->PHY_measurements.rx_power_dB[eNB_id][aarx] = (unsigned short) dB_fixed(phy_vars_ue->PHY_measurements.rx_power[eNB_id][aarx]); + ue->measurements.rx_power_dB[eNB_id][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_power[eNB_id][aarx]); if (aarx==0) - phy_vars_ue->PHY_measurements.rx_power_tot[eNB_id] = phy_vars_ue->PHY_measurements.rx_power[eNB_id][aarx]; + ue->measurements.rx_power_tot[eNB_id] = ue->measurements.rx_power[eNB_id][aarx]; else - phy_vars_ue->PHY_measurements.rx_power_tot[eNB_id] += phy_vars_ue->PHY_measurements.rx_power[eNB_id][aarx]; + ue->measurements.rx_power_tot[eNB_id] += ue->measurements.rx_power[eNB_id][aarx]; } //aarx - phy_vars_ue->PHY_measurements.rx_power_tot_dB[eNB_id] = (unsigned short) dB_fixed(phy_vars_ue->PHY_measurements.rx_power_tot[eNB_id]); + ue->measurements.rx_power_tot_dB[eNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[eNB_id]); } //eNB_id // filter to remove jitter - if (phy_vars_ue->init_averaging == 0) { - for (eNB_id = 0; eNB_id < phy_vars_ue->n_connected_eNB; eNB_id++) - phy_vars_ue->PHY_measurements.rx_power_avg[eNB_id] = (int) - (((k1*((long long int)(phy_vars_ue->PHY_measurements.rx_power_avg[eNB_id]))) + - (k2*((long long int)(phy_vars_ue->PHY_measurements.rx_power_tot[eNB_id]))))>>10); + if (ue->init_averaging == 0) { + for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) + ue->measurements.rx_power_avg[eNB_id] = (int) + (((k1*((long long int)(ue->measurements.rx_power_avg[eNB_id]))) + + (k2*((long long int)(ue->measurements.rx_power_tot[eNB_id]))))>>10); - phy_vars_ue->PHY_measurements.n0_power_avg = (int) - (((k1*((long long int) (phy_vars_ue->PHY_measurements.n0_power_avg))) + - (k2*((long long int) (phy_vars_ue->PHY_measurements.n0_power_tot))))>>10); + ue->measurements.n0_power_avg = (int) + (((k1*((long long int) (ue->measurements.n0_power_avg))) + + (k2*((long long int) (ue->measurements.n0_power_tot))))>>10); } else { - for (eNB_id = 0; eNB_id < phy_vars_ue->n_connected_eNB; eNB_id++) - phy_vars_ue->PHY_measurements.rx_power_avg[eNB_id] = phy_vars_ue->PHY_measurements.rx_power_tot[eNB_id]; + for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) + ue->measurements.rx_power_avg[eNB_id] = ue->measurements.rx_power_tot[eNB_id]; - phy_vars_ue->PHY_measurements.n0_power_avg = phy_vars_ue->PHY_measurements.n0_power_tot; - phy_vars_ue->init_averaging = 0; + ue->measurements.n0_power_avg = ue->measurements.n0_power_tot; + ue->init_averaging = 0; } - for (eNB_id = 0; eNB_id < phy_vars_ue->n_connected_eNB; eNB_id++) { - phy_vars_ue->PHY_measurements.rx_power_avg_dB[eNB_id] = dB_fixed( phy_vars_ue->PHY_measurements.rx_power_avg[eNB_id]); - phy_vars_ue->PHY_measurements.wideband_cqi_tot[eNB_id] = dB_fixed2(phy_vars_ue->PHY_measurements.rx_power_tot[eNB_id],phy_vars_ue->PHY_measurements.n0_power_tot); - phy_vars_ue->PHY_measurements.wideband_cqi_avg[eNB_id] = dB_fixed2(phy_vars_ue->PHY_measurements.rx_power_avg[eNB_id],phy_vars_ue->PHY_measurements.n0_power_avg); - phy_vars_ue->PHY_measurements.rx_rssi_dBm[eNB_id] = phy_vars_ue->PHY_measurements.rx_power_avg_dB[eNB_id] - phy_vars_ue->rx_total_gain_dB; + for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { + ue->measurements.rx_power_avg_dB[eNB_id] = dB_fixed( ue->measurements.rx_power_avg[eNB_id]); + ue->measurements.wideband_cqi_tot[eNB_id] = dB_fixed2(ue->measurements.rx_power_tot[eNB_id],ue->measurements.n0_power_tot); + ue->measurements.wideband_cqi_avg[eNB_id] = dB_fixed2(ue->measurements.rx_power_avg[eNB_id],ue->measurements.n0_power_avg); + ue->measurements.rx_rssi_dBm[eNB_id] = ue->measurements.rx_power_avg_dB[eNB_id] - ue->rx_total_gain_dB; #ifdef DEBUG_MEAS LOG_I(PHY,"[eNB %d] lte_ue_measurements: RSSI %d dBm, RSSI (digital) %d dB\n", - eNB_id,phy_vars_ue->PHY_measurements.rx_rssi_dBm[eNB_id], - phy_vars_ue->PHY_measurements.rx_power_avg_dB[eNB_id]); + eNB_id,ue->measurements.rx_rssi_dBm[eNB_id], + ue->measurements.rx_power_avg_dB[eNB_id]); #endif } - phy_vars_ue->PHY_measurements.n0_power_avg_dB = dB_fixed( phy_vars_ue->PHY_measurements.n0_power_avg); + ue->measurements.n0_power_avg_dB = dB_fixed( ue->measurements.n0_power_avg); - for (eNB_id = 0; eNB_id < phy_vars_ue->n_connected_eNB; eNB_id++) { + for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { if (frame_parms->mode1_flag==0) { // cqi/pmi information for (aarx=0; aarxnb_antennas_rx; aarx++) { - dl_ch0 = &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][aarx][4]; - dl_ch1 = &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][2+aarx][4]; + dl_ch0 = &ue->common_vars.dl_ch_estimates[eNB_id][aarx][4]; + dl_ch1 = &ue->common_vars.dl_ch_estimates[eNB_id][2+aarx][4]; for (subband=0; subbandPHY_measurements.subband_cqi_tot[eNB_id][subband]=0; + ue->measurements.subband_cqi_tot[eNB_id][subband]=0; if ((subband<(nb_subbands-1))||(N_RB_DL==6)) { /*for (i=0;i<48;i++) msg("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]); */ - phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband] = + ue->measurements.subband_cqi[eNB_id][aarx][subband] = (signal_energy_nodc(dl_ch0,subband_size) + signal_energy_nodc(dl_ch1,subband_size)); - if ( phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband] < 0) - phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband]=0; + if ( ue->measurements.subband_cqi[eNB_id][aarx][subband] < 0) + ue->measurements.subband_cqi[eNB_id][aarx][subband]=0; /* else - phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband]-=phy_vars_ue->PHY_measurements.n0_power[aarx]; + ue->measurements.subband_cqi[eNB_id][aarx][subband]-=ue->measurements.n0_power[aarx]; */ - phy_vars_ue->PHY_measurements.subband_cqi_tot[eNB_id][subband] += phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband]; - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband], - phy_vars_ue->PHY_measurements.n0_power[aarx]); + ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband]; + ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband], + ue->measurements.n0_power[aarx]); } else { // this is for the last subband which is smaller in size // for (i=0;i<12;i++) // printf("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]); - phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband] = (signal_energy_nodc(dl_ch0,last_subband_size) + - signal_energy_nodc(dl_ch1,last_subband_size)); // - phy_vars_ue->PHY_measurements.n0_power[aarx]; - phy_vars_ue->PHY_measurements.subband_cqi_tot[eNB_id][subband] += phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband]; - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband], - phy_vars_ue->PHY_measurements.n0_power[aarx]); + ue->measurements.subband_cqi[eNB_id][aarx][subband] = (signal_energy_nodc(dl_ch0,last_subband_size) + + signal_energy_nodc(dl_ch1,last_subband_size)); // - ue->measurements.n0_power[aarx]; + ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband]; + ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband], + ue->measurements.n0_power[aarx]); } dl_ch1+=subband_size; dl_ch0+=subband_size; - // msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,subband,phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband],phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][aarx][subband]); + // msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,subband,ue->measurements.subband_cqi[eNB_id][aarx][subband],ue->measurements.subband_cqi_dB[eNB_id][aarx][subband]); } } for (subband=0; subbandPHY_measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(phy_vars_ue->PHY_measurements.subband_cqi_tot[eNB_id][subband],phy_vars_ue->PHY_measurements.n0_power_tot); - // msg("subband_cqi_tot[%d][%d] => %d dB (n0 %d)\n",eNB_id,subband,phy_vars_ue->PHY_measurements.subband_cqi_tot_dB[eNB_id][subband],phy_vars_ue->PHY_measurements.n0_power_tot); + ue->measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(ue->measurements.subband_cqi_tot[eNB_id][subband],ue->measurements.n0_power_tot); + // msg("subband_cqi_tot[%d][%d] => %d dB (n0 %d)\n",eNB_id,subband,ue->measurements.subband_cqi_tot_dB[eNB_id][subband],ue->measurements.n0_power_tot); } for (aarx=0; aarxnb_antennas_rx; aarx++) { @@ -574,13 +574,13 @@ void lte_ue_measurements(PHY_VARS_UE *phy_vars_ue, #if defined(__x86_64__) || defined(__i386__) __m128i pmi128_re,pmi128_im,mmtmpPMI0,mmtmpPMI1 /* ,mmtmpPMI2,mmtmpPMI3 */ ; - dl_ch0_128 = (__m128i *)&phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][aarx][4]; - dl_ch1_128 = (__m128i *)&phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][2+aarx][4]; + dl_ch0_128 = (__m128i *)&ue->common_vars.dl_ch_estimates[eNB_id][aarx][4]; + dl_ch1_128 = (__m128i *)&ue->common_vars.dl_ch_estimates[eNB_id][2+aarx][4]; #elif defined(__arm__) int32x4_t pmi128_re,pmi128_im,mmtmpPMI0,mmtmpPMI1,mmtmpPMI0b,mmtmpPMI1b; - dl_ch0_128 = (int16x8_t *)&phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][aarx][4]; - dl_ch1_128 = (int16x8_t *)&phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][2+aarx][4]; + dl_ch0_128 = (int16x8_t *)&ue->common_vars.dl_ch_estimates[eNB_id][aarx][4]; + dl_ch1_128 = (int16x8_t *)&ue->common_vars.dl_ch_estimates[eNB_id][2+aarx][4]; #endif for (subband=0; subbandPHY_measurements.subband_pmi_re[eNB_id][subband][aarx] = (((int *)&pmi128_re)[0] + ((int *)&pmi128_re)[1] + ((int *)&pmi128_re)[2] + ((int *)&pmi128_re)[3])>>2; - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB_id][subband][aarx] = (((int *)&pmi128_im)[0] + ((int *)&pmi128_im)[1] + ((int *)&pmi128_im)[2] + ((int *)&pmi128_im)[3])>>2; - phy_vars_ue->PHY_measurements.wideband_pmi_re[eNB_id][aarx] += phy_vars_ue->PHY_measurements.subband_pmi_re[eNB_id][subband][aarx]; - phy_vars_ue->PHY_measurements.wideband_pmi_im[eNB_id][aarx] += phy_vars_ue->PHY_measurements.subband_pmi_im[eNB_id][subband][aarx]; + ue->measurements.subband_pmi_re[eNB_id][subband][aarx] = (((int *)&pmi128_re)[0] + ((int *)&pmi128_re)[1] + ((int *)&pmi128_re)[2] + ((int *)&pmi128_re)[3])>>2; + ue->measurements.subband_pmi_im[eNB_id][subband][aarx] = (((int *)&pmi128_im)[0] + ((int *)&pmi128_im)[1] + ((int *)&pmi128_im)[2] + ((int *)&pmi128_im)[3])>>2; + ue->measurements.wideband_pmi_re[eNB_id][aarx] += ue->measurements.subband_pmi_re[eNB_id][subband][aarx]; + ue->measurements.wideband_pmi_im[eNB_id][aarx] += ue->measurements.subband_pmi_im[eNB_id][subband][aarx]; } // subband loop } // rx antenna loop } // if frame_parms->mode1_flag == 0 else { // cqi information only for mode 1 for (aarx=0; aarxnb_antennas_rx; aarx++) { - dl_ch0 = &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][aarx][4]; + dl_ch0 = &ue->common_vars.dl_ch_estimates[eNB_id][aarx][4]; for (subband=0; subband<7; subband++) { // cqi if (aarx==0) - phy_vars_ue->PHY_measurements.subband_cqi_tot[eNB_id][subband]=0; + ue->measurements.subband_cqi_tot[eNB_id][subband]=0; if (subband<6) { // for (i=0;i<48;i++) // printf("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]); - phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband] = - (signal_energy_nodc(dl_ch0,48) ) - phy_vars_ue->PHY_measurements.n0_power[aarx]; + ue->measurements.subband_cqi[eNB_id][aarx][subband] = + (signal_energy_nodc(dl_ch0,48) ) - ue->measurements.n0_power[aarx]; - phy_vars_ue->PHY_measurements.subband_cqi_tot[eNB_id][subband] += phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband]; - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband], - phy_vars_ue->PHY_measurements.n0_power[aarx]); + ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband]; + ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband], + ue->measurements.n0_power[aarx]); } else { // for (i=0;i<12;i++) // printf("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]); - phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband] = (signal_energy_nodc(dl_ch0,12) ) - phy_vars_ue->PHY_measurements.n0_power[aarx]; - phy_vars_ue->PHY_measurements.subband_cqi_tot[eNB_id][subband] += phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband]; - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband], - phy_vars_ue->PHY_measurements.n0_power[aarx]); + ue->measurements.subband_cqi[eNB_id][aarx][subband] = (signal_energy_nodc(dl_ch0,12) ) - ue->measurements.n0_power[aarx]; + ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband]; + ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband], + ue->measurements.n0_power[aarx]); } dl_ch1+=48; - // msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,subband,phy_vars_ue->PHY_measurements.subband_cqi[eNB_id][aarx][subband],phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][aarx][subband]); + // msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,subband,ue->measurements.subband_cqi[eNB_id][aarx][subband],ue->measurements.subband_cqi_dB[eNB_id][aarx][subband]); } } for (subband=0; subbandPHY_measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(phy_vars_ue->PHY_measurements.subband_cqi_tot[eNB_id][subband],phy_vars_ue->PHY_measurements.n0_power_tot); + ue->measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(ue->measurements.subband_cqi_tot[eNB_id][subband],ue->measurements.n0_power_tot); } } - phy_vars_ue->PHY_measurements.rank[eNB_id] = 0; + ue->measurements.rank[eNB_id] = 0; for (i=0; iPHY_measurements.selected_rx_antennas[eNB_id][i] = 0; + ue->measurements.selected_rx_antennas[eNB_id][i] = 0; if (frame_parms->nb_antennas_rx>1) { - if (phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][0][i] >= phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB_id][1][i]) - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB_id][i] = 0; + if (ue->measurements.subband_cqi_dB[eNB_id][0][i] >= ue->measurements.subband_cqi_dB[eNB_id][1][i]) + ue->measurements.selected_rx_antennas[eNB_id][i] = 0; else - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB_id][i] = 1; + ue->measurements.selected_rx_antennas[eNB_id][i] = 1; } else - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB_id][i] = 0; + ue->measurements.selected_rx_antennas[eNB_id][i] = 0; } // if(eNB_id==0) - // printf("in lte_ue_measurements: selected rx_antenna[eNB_id==0]:%u\n", phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB_id][i]); + // printf("in lte_ue_measurements: selected rx_antenna[eNB_id==0]:%u\n", ue->measurements.selected_rx_antennas[eNB_id][i]); } // eNB_id loop #if defined(__x86_64__) || defined(__i386__) @@ -699,7 +699,7 @@ void lte_ue_measurements(PHY_VARS_UE *phy_vars_ue, } -void lte_ue_measurements_emul(PHY_VARS_UE *phy_vars_ue,uint8_t last_slot,uint8_t eNB_id) +void lte_ue_measurements_emul(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) { msg("[PHY] EMUL UE lte_ue_measurements_emul last slot %d, eNB_id %d\n",last_slot,eNB_id); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 1eb663ec89..723b143d26 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -52,29 +52,29 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32 #define SCALE 0x3FFF -int32_t lte_ul_channel_estimation(PHY_VARS_eNB *phy_vars_eNB, +int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, uint8_t eNB_id, uint8_t UE_id, - uint8_t sched_subframe, + uint8_t thread_id, unsigned char l, unsigned char Ns, uint8_t cooperation_flag) { - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; - LTE_eNB_PUSCH *eNB_pusch_vars = phy_vars_eNB->lte_eNB_pusch_vars[UE_id]; - int32_t **ul_ch_estimates=eNB_pusch_vars->drs_ch_estimates[eNB_id]; - int32_t **ul_ch_estimates_time= eNB_pusch_vars->drs_ch_estimates_time[eNB_id]; - int32_t **ul_ch_estimates_0= eNB_pusch_vars->drs_ch_estimates_0[eNB_id]; - int32_t **ul_ch_estimates_1= eNB_pusch_vars->drs_ch_estimates_1[eNB_id]; - int32_t **rxdataF_ext= eNB_pusch_vars->rxdataF_ext[eNB_id]; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - uint8_t harq_pid = subframe2harq_pid(frame_parms,phy_vars_eNB->proc[sched_subframe].frame_rx,subframe); + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + LTE_eNB_PUSCH *pusch_vars = eNB->pusch_vars[UE_id]; + int32_t **ul_ch_estimates=pusch_vars->drs_ch_estimates[eNB_id]; + int32_t **ul_ch_estimates_time= pusch_vars->drs_ch_estimates_time[eNB_id]; + int32_t **ul_ch_estimates_0= pusch_vars->drs_ch_estimates_0[eNB_id]; + int32_t **ul_ch_estimates_1= pusch_vars->drs_ch_estimates_1[eNB_id]; + int32_t **rxdataF_ext= pusch_vars->rxdataF_ext[eNB_id]; + int subframe = eNB->proc[thread_id].subframe_rx; + uint8_t harq_pid = subframe2harq_pid(frame_parms,eNB->proc[thread_id].frame_rx,subframe); int16_t delta_phase = 0; int16_t *ru1 = ru_90; int16_t *ru2 = ru_90; int16_t current_phase1,current_phase2; - uint16_t N_rb_alloc = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb; + uint16_t N_rb_alloc = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb; uint16_t aa,Msc_RS,Msc_RS_idx; uint16_t * Msc_idx_ptr; int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp; @@ -116,7 +116,7 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *phy_vars_eNB, Msc_RS = N_rb_alloc*12; cyclic_shift = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->n_DMRS2 + + eNB->ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS2 + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+Ns]) % 12; #if defined(USER_MODE) @@ -669,11 +669,11 @@ extern uint16_t transmission_offset_tdd[16]; #define DEBUG_SRS int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, - LTE_eNB_COMMON *eNb_common_vars, - LTE_eNB_SRS *eNb_srs_vars, + LTE_eNB_COMMON *common_vars, + LTE_eNB_SRS *srs_vars, SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, unsigned char sub_frame_number, - unsigned char eNb_id) + unsigned char eNB_id) { int T_SFC,aa; @@ -690,7 +690,7 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, T_SFC = (Ssrs<=7 ? 5 : 10); /* - msg("SRS channel estimation eNb %d, subframs %d, %d %d %d %d %d\n",eNb_id,sub_frame_number, + msg("SRS channel estimation eNB %d, subframs %d, %d %d %d %d %d\n",eNB_id,sub_frame_number, SRS_parms->Csrs, SRS_parms->Bsrs, SRS_parms->kTC, @@ -702,34 +702,34 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, if (generate_srs_rx(frame_parms, soundingrs_ul_config_dedicated, - eNb_srs_vars->srs)==-1) { + srs_vars->srs)==-1) { msg("lte_srs_channel_estimation: Error in generate_srs_rx\n"); return(-1); } for (aa=0; aarxdataF[eNb_id][aa][2*frame_parms->ofdm_symbol_size*symbol], - eNb_srs_vars->srs, - eNb_srs_vars->srs_ch_estimates[eNb_id][aa]); + msg("SRS channel estimation eNB %d, subframs %d, aarx %d, %p, %p, %p\n",eNB_id,sub_frame_number,aa, + &common_vars->rxdataF[eNB_id][aa][2*frame_parms->ofdm_symbol_size*symbol], + srs_vars->srs, + srs_vars->srs_ch_estimates[eNB_id][aa]); #endif - //write_output("eNb_rxF.m","rxF",&eNb_common_vars->rxdataF[0][aa][2*frame_parms->ofdm_symbol_size*symbol],2*(frame_parms->ofdm_symbol_size),2,1); - //write_output("eNb_srs.m","srs_eNb",eNb_common_vars->srs,(frame_parms->ofdm_symbol_size),1,1); + //write_output("eNB_rxF.m","rxF",&common_vars->rxdataF[0][aa][2*frame_parms->ofdm_symbol_size*symbol],2*(frame_parms->ofdm_symbol_size),2,1); + //write_output("eNB_srs.m","srs_eNB",common_vars->srs,(frame_parms->ofdm_symbol_size),1,1); - mult_cpx_conj_vector((int16_t*) &eNb_common_vars->rxdataF[eNb_id][aa][2*frame_parms->ofdm_symbol_size*symbol], - (int16_t*) eNb_srs_vars->srs, - (int16_t*) eNb_srs_vars->srs_ch_estimates[eNb_id][aa], + mult_cpx_conj_vector((int16_t*) &common_vars->rxdataF[eNB_id][aa][2*frame_parms->ofdm_symbol_size*symbol], + (int16_t*) srs_vars->srs, + (int16_t*) srs_vars->srs_ch_estimates[eNB_id][aa], frame_parms->ofdm_symbol_size, 15); //msg("SRS channel estimation cmult out\n"); #ifdef USER_MODE #ifdef DEBUG_SRS - sprintf(fname,"eNB_id%d_an%d_srs_ch_est.m",eNb_id,aa); - sprintf(vname,"eNB%d_%d_srs_ch_est",eNb_id,aa); - write_output(fname,vname,eNb_srs_vars->srs_ch_estimates[eNb_id][aa],frame_parms->ofdm_symbol_size,1,1); + sprintf(fname,"eNB_id%d_an%d_srs_ch_est.m",eNB_id,aa); + sprintf(vname,"eNB%d_%d_srs_ch_est",eNB_id,aa); + write_output(fname,vname,srs_vars->srs_ch_estimates[eNB_id][aa],frame_parms->ofdm_symbol_size,1,1); #endif #endif } @@ -738,7 +738,7 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, /* else { for (aa=0;aasrs_ch_estimates[eNb_id][aa],frame_parms->ofdm_symbol_size*sizeof(int)); + bzero(srs_vars->srs_ch_estimates[eNB_id][aa],frame_parms->ofdm_symbol_size*sizeof(int)); } */ return(0); diff --git a/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c b/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c index 9ffda3a83d..17b57bc085 100644 --- a/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c +++ b/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c @@ -40,7 +40,7 @@ //Calibration -int lte_dl_cell_spec_SS(PHY_VARS_eNB *phy_vars_eNB, +int lte_dl_cell_spec_SS(PHY_VARS_eNB *eNB, int32_t *output, short amp, unsigned char Ns, @@ -76,27 +76,27 @@ int lte_dl_cell_spec_SS(PHY_VARS_eNB *phy_vars_eNB, return(-1); } - mprime = 110 - phy_vars_eNB->lte_frame_parms.N_RB_DL; + mprime = 110 - eNB->frame_parms.N_RB_DL; - k = (nu + phy_vars_eNB->lte_frame_parms.nushift); + k = (nu + eNB->frame_parms.nushift); if (k > 6)//b k -=6;//b - k+=phy_vars_eNB->lte_frame_parms.first_carrier_offset; + k+=eNB->frame_parms.first_carrier_offset; - for (m=0; mlte_frame_parms.N_RB_DL<<1; m++) { // loop over pilots in one slot/symbol, 2*N_RB_DL pilots + for (m=0; mframe_parms.N_RB_DL<<1; m++) { // loop over pilots in one slot/symbol, 2*N_RB_DL pilots mprime_dword = mprime>>4; mprime_qpsk_symb = mprime&0xf; // this is r_mprime from 3GPP 36-211 6.10.1.2 - output[k] = qpsk[(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; + output[k] = qpsk[(eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; //output[k] = (lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3; #ifdef DEBUG_DL_CELL_SPEC printf("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - printf("index = %d (k %d)\n",(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); + printf("index = %d (k %d)\n",(eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); #endif mprime++; @@ -108,9 +108,9 @@ int lte_dl_cell_spec_SS(PHY_VARS_eNB *phy_vars_eNB, #endif k+=6;//b - if (k >= phy_vars_eNB->lte_frame_parms.ofdm_symbol_size) { + if (k >= eNB->frame_parms.ofdm_symbol_size) { k++; // skip DC carrier - k-=phy_vars_eNB->lte_frame_parms.ofdm_symbol_size; + k-=eNB->frame_parms.ofdm_symbol_size; } // printf("** k %d\n",k); @@ -120,7 +120,7 @@ int lte_dl_cell_spec_SS(PHY_VARS_eNB *phy_vars_eNB, } -int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB, +int lte_dl_cell_spec(PHY_VARS_eNB *eNB, int32_t *output, short amp, unsigned char Ns, @@ -155,31 +155,31 @@ int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB, return(-1); } - mprime = 110 - phy_vars_eNB->lte_frame_parms.N_RB_DL; + mprime = 110 - eNB->frame_parms.N_RB_DL; - k = (nu + phy_vars_eNB->lte_frame_parms.nushift); + k = (nu + eNB->frame_parms.nushift); if (k > 5) k -=6; - k+=phy_vars_eNB->lte_frame_parms.first_carrier_offset; + k+=eNB->frame_parms.first_carrier_offset; DevAssert( Ns < 20 ); DevAssert( l < 2 ); DevAssert( mprime>>4 < 14 ); - for (m=0; mlte_frame_parms.N_RB_DL<<1; m++) { + for (m=0; mframe_parms.N_RB_DL<<1; m++) { mprime_dword = mprime>>4; mprime_qpsk_symb = mprime&0xf; // this is r_mprime from 3GPP 36-211 6.10.1.2 - output[k] = qpsk[(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; + output[k] = qpsk[(eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; //output[k] = (lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3; #ifdef DEBUG_DL_CELL_SPEC printf("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - printf("index = %d (k %d)\n",(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); + printf("index = %d (k %d)\n",(eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); #endif mprime++; @@ -191,9 +191,9 @@ int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB, #endif k+=6; - if (k >= phy_vars_eNB->lte_frame_parms.ofdm_symbol_size) { + if (k >= eNB->frame_parms.ofdm_symbol_size) { k++; // skip DC carrier - k-=phy_vars_eNB->lte_frame_parms.ofdm_symbol_size; + k-=eNB->frame_parms.ofdm_symbol_size; } // printf("** k %d\n",k); @@ -202,7 +202,7 @@ int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB, return(0); } -int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue, +int lte_dl_cell_spec_rx(PHY_VARS_UE *ue, uint8_t eNB_offset, int *output, unsigned char Ns, @@ -230,19 +230,19 @@ int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue, ((short *)&qpsk[3])[0] = -pamp; ((short *)&qpsk[3])[1] = pamp; - mprime = 110 - phy_vars_ue->lte_frame_parms.N_RB_DL; + mprime = 110 - ue->frame_parms.N_RB_DL; - for (m=0; mlte_frame_parms.N_RB_DL<<1; m++) { + for (m=0; mframe_parms.N_RB_DL<<1; m++) { mprime_dword = mprime>>4; mprime_qpsk_symb = mprime&0xf; // this is r_mprime from 3GPP 36-211 6.10.1.2 - output[k] = qpsk[(phy_vars_ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; + output[k] = qpsk[(ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; #ifdef DEBUG_DL_CELL_SPEC printf("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - printf("index = %d (k %d)\n",(phy_vars_ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); + printf("index = %d (k %d)\n",(ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); #endif mprime++; diff --git a/openair1/PHY/LTE_REFSIG/lte_dl_mbsfn.c b/openair1/PHY/LTE_REFSIG/lte_dl_mbsfn.c index 9c3269b863..06edf4a5f5 100644 --- a/openair1/PHY/LTE_REFSIG/lte_dl_mbsfn.c +++ b/openair1/PHY/LTE_REFSIG/lte_dl_mbsfn.c @@ -39,7 +39,7 @@ //extern unsigned int lte_gold_table[10][3][42]; //#define DEBUG_DL_MBSFN -int lte_dl_mbsfn(PHY_VARS_eNB *phy_vars_eNB, int32_t *output, +int lte_dl_mbsfn(PHY_VARS_eNB *eNB, int32_t *output, short amp, int subframe, unsigned char l) @@ -62,9 +62,9 @@ int lte_dl_mbsfn(PHY_VARS_eNB *phy_vars_eNB, int32_t *output, ((short *)&qpsk[3])[1] = -a; - mprime = 3*(110 - phy_vars_eNB->lte_frame_parms.N_RB_DL); + mprime = 3*(110 - eNB->frame_parms.N_RB_DL); - for (m=0; mlte_frame_parms.N_RB_DL*6; m++) { + for (m=0; mframe_parms.N_RB_DL*6; m++) { if ((l==0) || (l==2)) k = m<<1; @@ -75,24 +75,24 @@ int lte_dl_mbsfn(PHY_VARS_eNB *phy_vars_eNB, int32_t *output, return(-1); } - k+=phy_vars_eNB->lte_frame_parms.first_carrier_offset; + k+=eNB->frame_parms.first_carrier_offset; mprime_dword = mprime>>4; mprime_qpsk_symb = mprime&0xf; - if (k >= phy_vars_eNB->lte_frame_parms.ofdm_symbol_size) { + if (k >= eNB->frame_parms.ofdm_symbol_size) { k++; // skip DC carrier - k-=phy_vars_eNB->lte_frame_parms.ofdm_symbol_size; + k-=eNB->frame_parms.ofdm_symbol_size; } - output[k] = qpsk[(phy_vars_eNB->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; + output[k] = qpsk[(eNB->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; //output[k] = (lte_gold_table[eNB_offset][subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3; #ifdef DEBUG_DL_MBSFN msg("subframe %d, l %d, m %d, mprime %d, mprime_dword %d, mprime_qpsk_symbol %d\n", subframe,l,m,mprime,mprime_dword,mprime_qpsk_symb); - msg("index = %d (k %d)(%x)\n",(phy_vars_eNB->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k,phy_vars_eNB->lte_gold_mbsfn_table[subframe][l][mprime_dword]); + msg("index = %d (k %d)(%x)\n",(eNB->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k,eNB->lte_gold_mbsfn_table[subframe][l][mprime_dword]); #endif mprime++; @@ -110,7 +110,7 @@ int lte_dl_mbsfn(PHY_VARS_eNB *phy_vars_eNB, int32_t *output, -int lte_dl_mbsfn_rx(PHY_VARS_UE *phy_vars_ue, +int lte_dl_mbsfn_rx(PHY_VARS_UE *ue, int *output, int subframe, unsigned char l) @@ -131,20 +131,20 @@ int lte_dl_mbsfn_rx(PHY_VARS_UE *phy_vars_ue, ((short *)&qpsk[3])[0] = -ONE_OVER_SQRT2_Q15; ((short *)&qpsk[3])[1] = ONE_OVER_SQRT2_Q15; - mprime = 3*(110 - phy_vars_ue->lte_frame_parms.N_RB_DL); + mprime = 3*(110 - ue->frame_parms.N_RB_DL); - for (m=0; mlte_frame_parms.N_RB_DL*6; m++) { + for (m=0; mframe_parms.N_RB_DL*6; m++) { mprime_dword = mprime>>4; mprime_qpsk_symb = mprime&0xf; // this is r_mprime from 3GPP 36-211 6.10.1.2 - output[k] = qpsk[(phy_vars_ue->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; + output[k] = qpsk[(ue->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; #ifdef DEBUG_DL_MBSFN printf("subframe %d, l %d, m %d, mprime %d, mprime_dword %d, mprime_qpsk_symbol %d\n", subframe,l,m,mprime, mprime_dword,mprime_qpsk_symb); - printf("index = %d (k %d) (%x)\n",(phy_vars_ue->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k,phy_vars_ue->lte_gold_mbsfn_table[subframe][l][mprime_dword]); + printf("index = %d (k %d) (%x)\n",(ue->lte_gold_mbsfn_table[subframe][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k,ue->lte_gold_mbsfn_table[subframe][l][mprime_dword]); #endif mprime++; diff --git a/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c b/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c index 9b094393c7..ae971c4c6c 100644 --- a/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c +++ b/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c @@ -52,7 +52,7 @@ int Wbar_NCP[8][4] = {{1,1,1,1},{1,-1,1,-1},{1,1,1,1},{1,-1,1,-1},{1,1,-1,-1},{-1,-1,1,1},{1,-1,-1,1},{-1,1,1,-1}}; -int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, +int lte_dl_ue_spec(PHY_VARS_eNB *eNB, uint8_t UE_id, int32_t *output, short amp, @@ -64,7 +64,7 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, int32_t qpsk[4],nqpsk[4],*qpsk_p,*output_p; int16_t a; int w,lprime,ind,l,ind_dword,ind_qpsk_symb,nPRB; - // LTE_eNB_DLSCH_t *dlsch = phy_vars_eNB->dlsch_eNB[UE_id][0]; + // LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_eNB[UE_id][0]; a = (amp*ONE_OVER_SQRT2_Q15)>>15; ((short *)&qpsk[0])[0] = a; @@ -87,13 +87,13 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, if (p>=7) { if (SS_flag==0) { - if (phy_vars_eNB->lte_frame_parms.Ncp == NORMAL) { + if (eNB->frame_parms.Ncp == NORMAL) { // this is 3GPP 36-211 6.10.3.2, NORMAL CP, p>=7 // position output pointer to 5th symbol in slot - output_p = output+(60*phy_vars_eNB->lte_frame_parms.N_RB_DL); + output_p = output+(60*eNB->frame_parms.N_RB_DL); // shift to 2nd RE in PRB for p=7,8,11,13 if ((p==7) || (p==8) || (p==11) || (p==13)) output_p++; @@ -101,12 +101,12 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, for (lprime=0; lprime<2; lprime++) { - ind = 3*lprime*phy_vars_eNB->lte_frame_parms.N_RB_DL; + ind = 3*lprime*eNB->frame_parms.N_RB_DL; l = lprime + ((Ns&1)<<1); // loop over pairs of PRBs, this is the periodicity of the W_bar_NCP sequence // unroll the computations for the 6 pilots, select qpsk or nqpsk as function of W_bar_NCP - for (nPRB=0; nPRBlte_frame_parms.N_RB_DL; nPRB+=2) { + for (nPRB=0; nPRBframe_parms.N_RB_DL; nPRB+=2) { // First pilot w = Wbar_NCP[p-7][l]; @@ -116,13 +116,13 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, ind_dword = ind>>4; ind_qpsk_symb = ind&0xf; - *output_p = qpsk_p[(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; + *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; #ifdef DEBUG_DL_UESPEC LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - LOG_D(PHY,"index = %d\n",(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); + LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); #endif output_p+=5; @@ -135,12 +135,12 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, ind_dword = ind>>4; ind_qpsk_symb = ind&0xf; - *output_p = qpsk_p[(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; + *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; #ifdef DEBUG_DL_UESPEC LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - LOG_D(PHY,"index = %d\n",(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); + LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); #endif output_p+=5; @@ -152,12 +152,12 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, ind_dword = ind>>4; ind_qpsk_symb = ind&0xf; - *output_p = qpsk_p[(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; + *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; #ifdef DEBUG_DL_UESPEC LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - LOG_D(PHY,"index = %d\n",(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); + LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); #endif output_p+=2; @@ -171,13 +171,13 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, ind_dword = ind>>4; ind_qpsk_symb = ind&0xf; - *output_p = qpsk_p[(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; + *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; #ifdef DEBUG_DL_UESPEC LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - LOG_D(PHY,"index = %d\n",(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); + LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); #endif output_p+=5; @@ -190,12 +190,12 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, ind_dword = ind>>4; ind_qpsk_symb = ind&0xf; - *output_p = qpsk_p[(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; + *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; #ifdef DEBUG_DL_UESPEC LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - LOG_D(PHY,"index = %d\n",(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); + LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); #endif output_p+=5; @@ -207,12 +207,12 @@ int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB, ind_dword = ind>>4; ind_qpsk_symb = ind&0xf; - *output_p = qpsk_p[(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; + *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3]; #ifdef DEBUG_DL_UESPEC LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - LOG_D(PHY,"index = %d\n",(phy_vars_eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); + LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); #endif output_p+=2; @@ -260,9 +260,9 @@ int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue, ((short *)&qpsk[3])[0] = -pamp; ((short *)&qpsk[3])[1] = pamp; - mprime = 110 - phy_vars_ue->lte_frame_parms.N_RB_DL; + mprime = 110 - phy_vars_ue->frame_parms.N_RB_DL; - for (m=0;mlte_frame_parms.N_RB_DL<<1;m++) { + for (m=0;mframe_parms.N_RB_DL<<1;m++) { mprime_dword = mprime>>4; mprime_qpsk_symb = mprime&0xf; diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index e79f603a49..c0ea61d48e 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -1686,8 +1686,8 @@ void pdcch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, int32_t avgP[4]; -int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, - LTE_UE_PDCCH **lte_ue_pdcch_vars, +int32_t rx_pdcch(LTE_UE_COMMON *common_vars, + LTE_UE_PDCCH **pdcch_vars, LTE_DL_FRAME_PARMS *frame_parms, uint8_t subframe, uint8_t eNB_id, @@ -1701,49 +1701,49 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, uint8_t eNB_id_i=eNB_id+1;//add 1 to eNB_id to separate from wanted signal, chosen as the B/F'd pilots from the SeNB are shifted by 1 #endif int32_t avgs,s; - uint8_t n_pdcch_symbols = 3; //lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols; + uint8_t n_pdcch_symbols = 3; //pdcch_vars[eNB_id]->num_pdcch_symbols; uint8_t mi = get_mi(frame_parms,subframe); // printf("In rx_pdcch, subframe %d, eNB_id %d\n",subframe,eNB_id); for (s=0; srxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id+1], //add 1 to eNB_id to compensate for the shifted B/F'd pilots from the SeNB - lte_ue_pdcch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_extract_rbs_single(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id+1], //add 1 to eNB_id to compensate for the shifted B/F'd pilots from the SeNB + pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, s, high_speed_flag, frame_parms); #ifdef MU_RECEIVER - pdcch_extract_rbs_single(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id_i - 1],//subtract 1 to eNB_id_i to compensate for the non-shifted pilots from the PeNB - lte_ue_pdcch_vars[eNB_id_i]->rxdataF_ext,//shift by two to simulate transmission from a second antenna - lte_ue_pdcch_vars[eNB_id_i]->dl_ch_estimates_ext,//shift by two to simulate transmission from a second antenna + pdcch_extract_rbs_single(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id_i - 1],//subtract 1 to eNB_id_i to compensate for the non-shifted pilots from the PeNB + pdcch_vars[eNB_id_i]->rxdataF_ext,//shift by two to simulate transmission from a second antenna + pdcch_vars[eNB_id_i]->dl_ch_estimates_ext,//shift by two to simulate transmission from a second antenna s, high_speed_flag, frame_parms); #endif //MU_RECEIVER } else if (frame_parms->nb_antennas_tx_eNB>1) { - pdcch_extract_rbs_dual(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id], - lte_ue_pdcch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_extract_rbs_dual(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id], + pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, s, high_speed_flag, frame_parms); } else { - pdcch_extract_rbs_single(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id], - lte_ue_pdcch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_extract_rbs_single(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id], + pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, s, high_speed_flag, frame_parms); } } - pdcch_channel_level(lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_channel_level(pdcch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avgP, frame_parms->N_RB_DL); @@ -1761,10 +1761,10 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, for (s=0; srxdataF_ext, - lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdcch_vars[eNB_id]->rxdataF_comp, - (aatx>1) ? lte_ue_pdcch_vars[eNB_id]->rho : NULL, + pdcch_channel_compensation(pdcch_vars[eNB_id]->rxdataF_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_vars[eNB_id]->rxdataF_comp, + (aatx>1) ? pdcch_vars[eNB_id]->rho : NULL, frame_parms, s, log2_maxh); // log2_maxh+I0_shift @@ -1773,7 +1773,7 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, #ifdef DEBUG_PHY if (subframe==5) - write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_d.m","rxF_c_d",&pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif @@ -1781,21 +1781,21 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, if (is_secondary_ue) { //get MF output for interfering stream - pdcch_channel_compensation(lte_ue_pdcch_vars[eNB_id_i]->rxdataF_ext, - lte_ue_pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, - lte_ue_pdcch_vars[eNB_id_i]->rxdataF_comp, - (aatx>1) ? lte_ue_pdcch_vars[eNB_id_i]->rho : NULL, + pdcch_channel_compensation(pdcch_vars[eNB_id_i]->rxdataF_ext, + pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdcch_vars[eNB_id_i]->rxdataF_comp, + (aatx>1) ? pdcch_vars[eNB_id_i]->rho : NULL, frame_parms, s, log2_maxh); // log2_maxh+I0_shift #ifdef DEBUG_PHY - write_output("rxF_comp_i.m","rxF_c_i",<e_ue_pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_i.m","rxF_c_i",&pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif pdcch_dual_stream_correlation(frame_parms, s, - lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, - lte_ue_pdcch_vars[eNB_id]->dl_ch_rho_ext, + pdcch_vars[eNB_id]->dl_ch_estimates_ext, + pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdcch_vars[eNB_id]->dl_ch_rho_ext, log2_maxh); } @@ -1807,54 +1807,54 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, if (is_secondary_ue) { pdcch_detection_mrc_i(frame_parms, - lte_ue_pdcch_vars[eNB_id]->rxdataF_comp, - lte_ue_pdcch_vars[eNB_id_i]->rxdataF_comp, - lte_ue_pdcch_vars[eNB_id]->rho, - lte_ue_pdcch_vars[eNB_id]->dl_ch_rho_ext, + pdcch_vars[eNB_id]->rxdataF_comp, + pdcch_vars[eNB_id_i]->rxdataF_comp, + pdcch_vars[eNB_id]->rho, + pdcch_vars[eNB_id]->dl_ch_rho_ext, s); #ifdef DEBUG_PHY - write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - write_output("rxF_comp_i.m","rxF_c_i",<e_ue_pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_d.m","rxF_c_d",&pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_i.m","rxF_c_i",&pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif } else #endif //MU_RECEIVER pdcch_detection_mrc(frame_parms, - lte_ue_pdcch_vars[eNB_id]->rxdataF_comp, + pdcch_vars[eNB_id]->rxdataF_comp, s); } if (mimo_mode == SISO) - pdcch_siso(frame_parms,lte_ue_pdcch_vars[eNB_id]->rxdataF_comp,s); + pdcch_siso(frame_parms,pdcch_vars[eNB_id]->rxdataF_comp,s); else - pdcch_alamouti(frame_parms,lte_ue_pdcch_vars[eNB_id]->rxdataF_comp,s); + pdcch_alamouti(frame_parms,pdcch_vars[eNB_id]->rxdataF_comp,s); #ifdef MU_RECEIVER if (is_secondary_ue) { pdcch_qpsk_qpsk_llr(frame_parms, - lte_ue_pdcch_vars[eNB_id]->rxdataF_comp, - lte_ue_pdcch_vars[eNB_id_i]->rxdataF_comp, - lte_ue_pdcch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdcch_vars[eNB_id]->llr16, //subsequent function require 16 bit llr, but output must be 8 bit (actually clipped to 4, because of the Viterbi decoder) - lte_ue_pdcch_vars[eNB_id]->llr, + pdcch_vars[eNB_id]->rxdataF_comp, + pdcch_vars[eNB_id_i]->rxdataF_comp, + pdcch_vars[eNB_id]->dl_ch_rho_ext, + pdcch_vars[eNB_id]->llr16, //subsequent function require 16 bit llr, but output must be 8 bit (actually clipped to 4, because of the Viterbi decoder) + pdcch_vars[eNB_id]->llr, s); /* #ifdef DEBUG_PHY if (subframe==5) { - write_output("llr8_seq.m","llr8",<e_ue_pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); - write_output("llr16_seq.m","llr16",<e_ue_pdcch_vars[eNB_id]->llr16[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); + write_output("llr8_seq.m","llr8",&pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); + write_output("llr16_seq.m","llr16",&pdcch_vars[eNB_id]->llr16[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); } #endif*/ } else { #endif //MU_RECEIVER pdcch_llr(frame_parms, - lte_ue_pdcch_vars[eNB_id]->rxdataF_comp, - (char *)lte_ue_pdcch_vars[eNB_id]->llr, + pdcch_vars[eNB_id]->rxdataF_comp, + (char *)pdcch_vars[eNB_id]->llr, s); /*#ifdef DEBUG_PHY - write_output("llr8_seq.m","llr8",<e_ue_pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); + write_output("llr8_seq.m","llr8",&pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); #endif*/ #ifdef MU_RECEIVER } @@ -1866,7 +1866,7 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, // decode pcfich here n_pdcch_symbols = rx_pcfich(frame_parms, subframe, - lte_ue_pdcch_vars[eNB_id], + pdcch_vars[eNB_id], mimo_mode); if (n_pdcch_symbols>3) @@ -1879,24 +1879,24 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, printf("demapping: subframe %d, mi %d, tdd_config %d\n",subframe,get_mi(frame_parms,subframe),frame_parms->tdd_config); #endif - pdcch_demapping(lte_ue_pdcch_vars[eNB_id]->llr, - lte_ue_pdcch_vars[eNB_id]->wbar, + pdcch_demapping(pdcch_vars[eNB_id]->llr, + pdcch_vars[eNB_id]->wbar, frame_parms, n_pdcch_symbols, get_mi(frame_parms,subframe)); pdcch_deinterleaving(frame_parms, - (uint16_t*)lte_ue_pdcch_vars[eNB_id]->e_rx, - lte_ue_pdcch_vars[eNB_id]->wbar, + (uint16_t*)pdcch_vars[eNB_id]->e_rx, + pdcch_vars[eNB_id]->wbar, n_pdcch_symbols, mi); pdcch_unscrambling(frame_parms, subframe, - lte_ue_pdcch_vars[eNB_id]->e_rx, + pdcch_vars[eNB_id]->e_rx, get_nCCE(n_pdcch_symbols,frame_parms,mi)*72); - lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols = n_pdcch_symbols; + pdcch_vars[eNB_id]->num_pdcch_symbols = n_pdcch_symbols; return(0); } @@ -2356,7 +2356,7 @@ uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB, LTE_eNB_DLSCH_t *dlsch_eNB; uint8_t num_pdcch_symbols = get_num_pdcch_symbols(num_ue_spec_dci+num_common_dci, dci_alloc, - &phy_vars_eNB->lte_frame_parms, + &phy_vars_eNB->frame_parms, subframe); eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].cntl.cfi=num_pdcch_symbols; @@ -2542,8 +2542,8 @@ uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int sub // check for eNB only ! return(get_nCCE(num_pdcch_symbols, - &PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms, - get_mi(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe))); + &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms, + get_mi(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,subframe))); } @@ -2647,7 +2647,7 @@ int get_nCCE_offset_l1(int *CCE_table, } -void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, +void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, int do_common, uint8_t subframe, DCI_ALLOC_t *dci_alloc, @@ -2676,7 +2676,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, unsigned int Yk,nb_candidates = 0,i,m; unsigned int CCEmap_cand; - nCCE = get_nCCE(lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols,frame_parms,mi); + nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols,frame_parms,mi); if (nCCE > get_nCCE(3,frame_parms,1)) return; @@ -2691,7 +2691,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, // Find first available in ue specific search space // according to procedure in Section 9.1.1 of 36.213 (v. 8.6) // compute Yk - Yk = (unsigned int)lte_ue_pdcch_vars[eNB_id]->crnti; + Yk = (unsigned int)pdcch_vars[eNB_id]->crnti; for (i=0; i<=subframe; i++) Yk = (Yk*39827)%65537; @@ -2777,7 +2777,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, dci_decoding(sizeof_bits, L, - <e_ue_pdcch_vars[eNB_id]->e_rx[CCEind*72], + &pdcch_vars[eNB_id]->e_rx[CCEind*72], dci_decoded_output); /* for (i=0;i<3+(sizeof_bits>>3);i++) @@ -2790,7 +2790,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, if (((L>1) && ((crc == si_rnti)|| (crc == ra_rnti)))|| - (crc == lte_ue_pdcch_vars[eNB_id]->crnti)) { + (crc == pdcch_vars[eNB_id]->crnti)) { dci_alloc[*dci_cnt].dci_length = sizeof_bits; dci_alloc[*dci_cnt].rnti = crc; dci_alloc[*dci_cnt].L = L; @@ -2826,28 +2826,28 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, } else if (crc==ra_rnti) { dci_alloc[*dci_cnt].format = format_ra; // store first nCCE of group for PUCCH transmission of ACK/NAK - lte_ue_pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; + pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; *dci_cnt = *dci_cnt+1; - } else if (crc==lte_ue_pdcch_vars[eNB_id]->crnti) { + } else if (crc==pdcch_vars[eNB_id]->crnti) { if ((format_c == format0)&&((dci_decoded_output[0]&0x80)==0)) {// check if pdu is format 0 or 1A if (*format0_found == 0) { dci_alloc[*dci_cnt].format = format0; *format0_found = 1; *dci_cnt = *dci_cnt+1; - lte_ue_pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; + pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; } } else if (format_c == format0) { // this is a format 1A DCI dci_alloc[*dci_cnt].format = format1A; *dci_cnt = *dci_cnt+1; - lte_ue_pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; + pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; } else { // store first nCCE of group for PUCCH transmission of ACK/NAK if (*format_c_found == 0) { dci_alloc[*dci_cnt].format = format_c; *dci_cnt = *dci_cnt+1; *format_c_found = 1; - lte_ue_pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; + pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; } } } @@ -2881,14 +2881,14 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, #endif - // if (crc==lte_ue_pdcch_vars[eNB_id]->crnti) + // if (crc==pdcch_vars[eNB_id]->crnti) // return; } // rnti match } // CCEmap_cand == 0 } // candidate loop } -uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, +uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, DCI_ALLOC_t *dci_alloc, int do_common, int16_t eNB_id, @@ -2897,12 +2897,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, uint8_t dci_cnt=0,old_dci_cnt=0; uint32_t CCEmap0=0,CCEmap1=0,CCEmap2=0; - LTE_UE_PDCCH **lte_ue_pdcch_vars = phy_vars_ue->lte_ue_pdcch_vars; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - uint8_t mi = get_mi(&phy_vars_ue->lte_frame_parms,subframe); + LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint8_t mi = get_mi(&ue->frame_parms,subframe); uint16_t ra_rnti=99; uint8_t format0_found=0,format_c_found=0; - uint8_t tmode = phy_vars_ue->transmission_mode[eNB_id]; + uint8_t tmode = ue->transmission_mode[eNB_id]; uint8_t frame_type = frame_parms->frame_type; uint8_t format1A_size_bits=0,format1A_size_bytes=0; uint8_t format1C_size_bits=0,format1C_size_bytes=0; @@ -3107,12 +3107,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, printf("[DCI search] doing common search/format0 aggregation 4\n"); #endif - if (phy_vars_ue->prach_resources[eNB_id]) - ra_rnti = phy_vars_ue->prach_resources[eNB_id]->ra_RNTI; + if (ue->prach_resources[eNB_id]) + ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; // First check common search spaces at aggregation 4 (SI_RNTI and RA_RNTI format 0/1A), // and UE_SPEC format0 (PUSCH) too while we're at it - dci_decoding_procedure0(lte_ue_pdcch_vars,1,subframe, + dci_decoding_procedure0(pdcch_vars,1,subframe, dci_alloc, eNB_id, frame_parms, @@ -3138,7 +3138,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // Now check common search spaces at aggregation 4 (SI_RNTI and RA_RNTI and C-RNTI format 1C), // and UE_SPEC format0 (PUSCH) too while we're at it - dci_decoding_procedure0(lte_ue_pdcch_vars,1,subframe, + dci_decoding_procedure0(pdcch_vars,1,subframe, dci_alloc, eNB_id, frame_parms, @@ -3168,7 +3168,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, #ifdef DEBUG_DCI_DECODING printf("[DCI search] doing common search/format0 aggregation 8\n"); #endif - dci_decoding_procedure0(lte_ue_pdcch_vars,1,subframe, + dci_decoding_procedure0(pdcch_vars,1,subframe, dci_alloc, eNB_id, frame_parms, @@ -3194,7 +3194,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // Now check common search spaces at aggregation 8 (SI_RNTI and RA_RNTI and C-RNTI format 1C), // and UE_SPEC format0 (PUSCH) too while we're at it - dci_decoding_procedure0(lte_ue_pdcch_vars,1,subframe, + dci_decoding_procedure0(pdcch_vars,1,subframe, dci_alloc, eNB_id, frame_parms, @@ -3217,15 +3217,15 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, } - if (phy_vars_ue->UE_mode[eNB_id] <= PRACH) + if (ue->UE_mode[eNB_id] <= PRACH) return(dci_cnt); - if (phy_vars_ue->prach_resources[eNB_id]) - ra_rnti = phy_vars_ue->prach_resources[eNB_id]->ra_RNTI; + if (ue->prach_resources[eNB_id]) + ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; // Now check UE_SPEC format0/1A ue_spec search spaces at aggregation 8 // printf("[DCI search] Format 0/1A aggregation 8\n"); - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3252,7 +3252,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // printf("[DCI search] Format 0 aggregation 4\n"); // Now check UE_SPEC format 0 search spaces at aggregation 4 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3283,7 +3283,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // printf("[DCI search] Format 0 aggregation 2\n"); // Now check UE_SPEC format 0 search spaces at aggregation 2 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3310,7 +3310,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // printf("[DCI search] Format 0 aggregation 4\n"); // Now check UE_SPEC format 0 search spaces at aggregation 1 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3342,7 +3342,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, if (tmode < 3) { // Now check UE_SPEC format 1 search spaces at aggregation 1 old_dci_cnt=dci_cnt; - dci_decoding_procedure0(lte_ue_pdcch_vars,0,subframe, + dci_decoding_procedure0(pdcch_vars,0,subframe, dci_alloc, eNB_id, frame_parms, @@ -3371,7 +3371,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // Now check UE_SPEC format 1 search spaces at aggregation 2 old_dci_cnt=dci_cnt; - dci_decoding_procedure0(lte_ue_pdcch_vars,0,subframe, + dci_decoding_procedure0(pdcch_vars,0,subframe, dci_alloc, eNB_id, frame_parms, @@ -3401,7 +3401,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // Now check UE_SPEC format 1 search spaces at aggregation 4 old_dci_cnt=dci_cnt; - dci_decoding_procedure0(lte_ue_pdcch_vars,0,subframe, + dci_decoding_procedure0(pdcch_vars,0,subframe, dci_alloc, eNB_id, frame_parms, @@ -3431,7 +3431,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 1 search spaces at aggregation 8 old_dci_cnt=dci_cnt; - dci_decoding_procedure0(lte_ue_pdcch_vars,0,subframe, + dci_decoding_procedure0(pdcch_vars,0,subframe, dci_alloc, eNB_id, frame_parms, @@ -3463,7 +3463,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, // Now check UE_SPEC format 2A_2A search spaces at aggregation 1 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3492,7 +3492,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, return(dci_cnt); // Now check UE_SPEC format 2 search spaces at aggregation 2 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3521,7 +3521,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, return(dci_cnt); // Now check UE_SPEC format 2_2A search spaces at aggregation 4 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3551,7 +3551,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 2_2A search spaces at aggregation 8 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3575,7 +3575,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, } else if (tmode == 4) { // Now check UE_SPEC format 2_2A search spaces at aggregation 1 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3604,7 +3604,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, return(dci_cnt); // Now check UE_SPEC format 2 search spaces at aggregation 2 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3633,7 +3633,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, return(dci_cnt); // Now check UE_SPEC format 2_2A search spaces at aggregation 4 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3663,7 +3663,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 2_2A search spaces at aggregation 8 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3690,7 +3690,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, #ifdef DEBUG_DCI_DECODING LOG_I(PHY," MU-MIMO check UE_SPEC format 1E_2A_M10PRB\n"); #endif - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3720,7 +3720,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, return(dci_cnt); // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 2 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3749,7 +3749,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, return(dci_cnt); // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 4 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3780,7 +3780,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 1E_2A_M10PRB search spaces at aggregation 8 - dci_decoding_procedure0(lte_ue_pdcch_vars,0, + dci_decoding_procedure0(pdcch_vars,0, subframe, dci_alloc, eNB_id, @@ -3816,7 +3816,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, } #ifdef PHY_ABSTRACTION -uint16_t dci_decoding_procedure_emul(LTE_UE_PDCCH **lte_ue_pdcch_vars, +uint16_t dci_decoding_procedure_emul(LTE_UE_PDCCH **pdcch_vars, uint8_t num_ue_spec_dci, uint8_t num_common_dci, DCI_ALLOC_t *dci_alloc_tx, @@ -3831,10 +3831,10 @@ uint16_t dci_decoding_procedure_emul(LTE_UE_PDCCH **lte_ue_pdcch_vars, LOG_D(PHY,"[DCI][EMUL] : num_common_dci %d\n",num_common_dci); for (i=num_common_dci; i<(num_ue_spec_dci+num_common_dci); i++) { - LOG_D(PHY,"[DCI][EMUL] Checking dci %d => %x format %d (bit 0 %d)\n",i,lte_ue_pdcch_vars[eNB_id]->crnti,dci_alloc_tx[i].format, + LOG_D(PHY,"[DCI][EMUL] Checking dci %d => %x format %d (bit 0 %d)\n",i,pdcch_vars[eNB_id]->crnti,dci_alloc_tx[i].format, dci_alloc_tx[i].dci_pdu[0]&0x80); - if (dci_alloc_tx[i].rnti == lte_ue_pdcch_vars[eNB_id]->crnti) { + if (dci_alloc_tx[i].rnti == pdcch_vars[eNB_id]->crnti) { memcpy(dci_alloc_rx+dci_cnt,dci_alloc_tx+i,sizeof(DCI_ALLOC_t)); dci_cnt++; } diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index a163225f03..90c67ed70f 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -6235,7 +6235,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, uint16_t rnti, uint8_t subframe, DCI_format_t dci_format, - PHY_VARS_UE *phy_vars_ue, + PHY_VARS_UE *ue, uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, @@ -6245,13 +6245,13 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, { uint8_t harq_pid; - uint8_t transmission_mode = phy_vars_ue->transmission_mode[eNB_id]; - ANFBmode_t AckNackFBMode = phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; - LTE_UE_ULSCH_t *ulsch = phy_vars_ue->ulsch_ue[eNB_id]; - // LTE_UE_DLSCH_t **dlsch = phy_vars_ue->dlsch_ue[0]; - PHY_MEASUREMENTS *meas = &phy_vars_ue->PHY_measurements; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - // uint32_t current_dlsch_cqi = phy_vars_ue->current_dlsch_cqi[eNB_id]; + uint8_t transmission_mode = ue->transmission_mode[eNB_id]; + ANFBmode_t AckNackFBMode = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; + LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; + // LTE_UE_DLSCH_t **dlsch = ue->dlsch[0]; + PHY_MEASUREMENTS *meas = &ue->measurements; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + // uint32_t current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id]; uint32_t cqi_req; uint32_t dai=0; @@ -6269,12 +6269,12 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, harq_pid = 0; else harq_pid = subframe2harq_pid(frame_parms, - pdcch_alloc2ul_frame(frame_parms,phy_vars_ue->frame_rx,subframe), + pdcch_alloc2ul_frame(frame_parms,ue->frame_rx,subframe), pdcch_alloc2ul_subframe(frame_parms,subframe)); if (harq_pid == 255) { LOG_E(PHY, "frame %d, subframe %d, rnti %x, format %d: illegal harq_pid!\n", - phy_vars_ue->frame_rx, subframe, rnti, dci_format); + ue->frame_rx, subframe, rnti, dci_format); return(-1); } @@ -6401,7 +6401,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, if (rballoc > RIV_max) { LOG_E(PHY,"frame %d, subframe %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc > RIV_max\n", - phy_vars_ue->frame_rx, subframe, rnti, dci_format); + ue->frame_rx, subframe, rnti, dci_format); return(-1); } @@ -6414,18 +6414,18 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->harq_processes[harq_pid]->TPC = TPC; - if (phy_vars_ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) { + if (ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) { LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d: f_pusch (ACC) %d, adjusting by %d (TPC %d)\n", - phy_vars_ue->Mod_id,harq_pid,phy_vars_ue->frame_rx,subframe,ulsch->f_pusch, - delta_PUSCH_acc[phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TPC], - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TPC); - ulsch->f_pusch += delta_PUSCH_acc[phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TPC]; + ue->Mod_id,harq_pid,ue->frame_rx,subframe,ulsch->f_pusch, + delta_PUSCH_acc[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC); + ulsch->f_pusch += delta_PUSCH_acc[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC]; } else { LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d: f_pusch (ABS) %d, adjusting to %d (TPC %d)\n", - phy_vars_ue->Mod_id,harq_pid,phy_vars_ue->frame_rx,subframe,ulsch->f_pusch, - delta_PUSCH_abs[phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TPC], - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TPC); - ulsch->f_pusch = delta_PUSCH_abs[phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TPC]; + ue->Mod_id,harq_pid,ue->frame_rx,subframe,ulsch->f_pusch, + delta_PUSCH_abs[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC); + ulsch->f_pusch = delta_PUSCH_abs[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC]; } if (ulsch->harq_processes[harq_pid]->first_tx==1) { @@ -6495,7 +6495,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, // The aperiodic CQI reporting mode is fixed for every transmission mode instead of being configured by higher layer signaling case 1: if ((rnti >= cba_rnti) && (rnti < p_rnti)) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; break; @@ -6516,7 +6516,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_mcs_CBA; ulsch->o_RI[0] = 0; } else if(meas->rank[eNB_id] == 0) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6537,7 +6537,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_nopmi; ulsch->o_RI[0] = 0; } else { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6563,7 +6563,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, case 2: if ((rnti >= cba_rnti) && (rnti < p_rnti)) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; break; @@ -6584,7 +6584,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_mcs_CBA; ulsch->o_RI[0] = 0; } else if(meas->rank[eNB_id] == 0) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6605,7 +6605,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_nopmi; ulsch->o_RI[0] = 0; } else { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6631,7 +6631,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, case 3: if ((rnti >= cba_rnti) && (rnti < p_rnti)) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; break; @@ -6652,7 +6652,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_mcs_CBA; ulsch->o_RI[0] = 0; } else if(meas->rank[eNB_id] == 0) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6673,7 +6673,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_nopmi; ulsch->o_RI[0] = 0; } else { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6699,7 +6699,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, case 4: if ((rnti >= cba_rnti) && (rnti < p_rnti)) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; break; @@ -6720,7 +6720,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_mcs_CBA; ulsch->o_RI[0] = 0; } else if(meas->rank[eNB_id] == 0) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_wideband_cqi_rank1_2A_1_5MHz; break; @@ -6741,7 +6741,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = wideband_cqi_rank1_2A; ulsch->o_RI[0] = 0; } else { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_wideband_cqi_rank2_2A_1_5MHz; break; @@ -6767,7 +6767,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, case 5: if ((rnti >= cba_rnti) && (rnti < p_rnti)) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; break; @@ -6788,7 +6788,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_mcs_CBA; ulsch->o_RI[0] = 0; } else if(meas->rank[eNB_id] == 0) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_wideband_cqi_rank1_2A_1_5MHz; break; @@ -6809,7 +6809,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = wideband_cqi_rank1_2A; ulsch->o_RI[0] = 0; } else { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_wideband_cqi_rank2_2A_1_5MHz; break; @@ -6835,7 +6835,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, case 6: if ((rnti >= cba_rnti) && (rnti < p_rnti)) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; break; @@ -6856,7 +6856,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_mcs_CBA; ulsch->o_RI[0] = 0; } else if(meas->rank[eNB_id] == 0) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_wideband_cqi_rank1_2A_1_5MHz; break; @@ -6877,7 +6877,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = wideband_cqi_rank1_2A; ulsch->o_RI[0] = 0; } else { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_wideband_cqi_rank2_2A_1_5MHz; break; @@ -6903,7 +6903,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, case 7: if ((rnti >= cba_rnti) && (rnti < p_rnti)) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz; break; @@ -6924,7 +6924,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_mcs_CBA; ulsch->o_RI[0] = 0; } else if(meas->rank[eNB_id] == 0) { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6945,7 +6945,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_nopmi; ulsch->o_RI[0] = 0; } else { - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: ulsch->O = sizeof_HLC_subband_cqi_nopmi_1_5MHz; break; @@ -6979,23 +6979,13 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->uci_format = HLC_subband_cqi_nopmi; } - print_CQI(ulsch->o,ulsch->uci_format,eNB_id,phy_vars_ue->lte_frame_parms.N_RB_DL); + print_CQI(ulsch->o,ulsch->uci_format,eNB_id,ue->frame_parms.N_RB_DL); - //FK: moved this part to ulsch_coding to be more recent - /* - fill_CQI(ulsch->o,ulsch->uci_format,meas,eNB_id,transmission_mode); - print_CQI(ulsch->o,ulsch->uci_format,eNB_id); - // save PUSCH pmi for later (transmission modes 4,5,6) - // msg("ulsch: saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi)); - dlsch[0]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi; - */ - - // check this (see comment in generate_ue_ulsch_params_from_dci) if (frame_parms->frame_type == FDD) { int dl_subframe = (subframe<4) ? (subframe+6) : (subframe-4); - if (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[dl_subframe].send_harq_status>0) { // we have downlink transmission + if (ue->dlsch[eNB_id][0]->harq_ack[dl_subframe].send_harq_status>0) { // we have downlink transmission ulsch->harq_processes[harq_pid]->O_ACK = 1; } else { ulsch->harq_processes[harq_pid]->O_ACK = 0; @@ -7009,9 +6999,9 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, // ulsch->harq_processes[harq_pid]->V_UL_DAI = dai+1; } - ulsch->beta_offset_cqi_times8 = beta_cqi[phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index];//18; - ulsch->beta_offset_ri_times8 = beta_ri[phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index];//10; - ulsch->beta_offset_harqack_times8 = beta_ack[phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index];//16; + ulsch->beta_offset_cqi_times8 = beta_cqi[ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index];//18; + ulsch->beta_offset_ri_times8 = beta_ri[ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index];//10; + ulsch->beta_offset_harqack_times8 = beta_ack[ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index];//16; ulsch->Nsymb_pusch = 12-(frame_parms->Ncp<<1)-(use_srs==0?0:1); ulsch->srs_active = use_srs; @@ -7044,8 +7034,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->harq_processes[harq_pid]->round = 0; // a Ndi=1 automatically acknowledges previous PUSCH transmission - if (phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] == 1) - phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] = 0; + if (ue->ulsch_Msg3_active[eNB_id] == 1) + ue->ulsch_Msg3_active[eNB_id] = 0; } else { // printf("Ndi = 0 : Setting RVidx from mcs %d\n",((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->mcs); if (mcs>28) ulsch->harq_processes[harq_pid]->rvidx = mcs - 28; @@ -7054,7 +7044,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, } LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d), nb_rb %d, first_rb %d, mcs %d, round %d, rv %d\n", - phy_vars_ue->Mod_id,harq_pid,phy_vars_ue->frame_rx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift,ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb, + ue->Mod_id,harq_pid,ue->frame_rx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift,ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb, ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->round,ulsch->harq_processes[harq_pid]->rvidx); // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift; @@ -7081,7 +7071,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, return(0); } else { LOG_E(PHY,"frame %d, subframe %d: FATAL ERROR, generate_ue_ulsch_params_from_dci, Illegal dci_format %d\n", - phy_vars_ue->frame_rx, subframe,dci_format); + ue->frame_rx, subframe,dci_format); return(-1); } @@ -7089,10 +7079,10 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, int generate_eNB_ulsch_params_from_dci(void *dci_pdu, uint16_t rnti, - uint8_t sched_subframe, + uint8_t thread_id, DCI_format_t dci_format, uint8_t UE_id, - PHY_VARS_eNB *phy_vars_eNB, + PHY_VARS_eNB *eNB, uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, @@ -7102,11 +7092,11 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, uint8_t harq_pid; uint32_t rb_alloc; - uint8_t transmission_mode=phy_vars_eNB->transmission_mode[UE_id]; - ANFBmode_t AckNackFBMode = phy_vars_eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode; - LTE_eNB_ULSCH_t *ulsch=phy_vars_eNB->ulsch_eNB[UE_id]; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_tx; + uint8_t transmission_mode=eNB->transmission_mode[UE_id]; + ANFBmode_t AckNackFBMode = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode; + LTE_eNB_ULSCH_t *ulsch=eNB->ulsch[UE_id]; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + int subframe = eNB->proc[thread_id].subframe_tx; uint32_t cqi_req = 0; uint32_t dai = 0; @@ -7127,11 +7117,11 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, harq_pid = subframe2harq_pid(frame_parms, pdcch_alloc2ul_frame(frame_parms, - phy_vars_eNB->proc[sched_subframe].frame_tx, + eNB->proc[thread_id].frame_tx, subframe), pdcch_alloc2ul_subframe(frame_parms,subframe)); - // printf("eNB: sched_subframe %d, subframe %d, frame_tx %d\n",sched_subframe,subframe,phy_vars_eNB->proc[sched_subframe].frame_tx); + // printf("eNB: thread_id %d, subframe %d, frame_tx %d\n",thread_id,subframe,eNB->proc[thread_id].frame_tx); switch (frame_parms->N_RB_DL) { case 6: @@ -7607,7 +7597,7 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, if (frame_parms->frame_type == FDD) { int dl_subframe = (subframe<4) ? (subframe+6) : (subframe-4); - if (phy_vars_eNB->dlsch_eNB[UE_id][0]->subframe_tx[dl_subframe]>0) { // we have downlink transmission + if (eNB->dlsch[UE_id][0]->subframe_tx[dl_subframe]>0) { // we have downlink transmission ulsch->harq_processes[harq_pid]->O_ACK = 1; } else { ulsch->harq_processes[harq_pid]->O_ACK = 0; @@ -7621,9 +7611,9 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, ulsch->harq_processes[harq_pid]->V_UL_DAI = dai+1; } - ulsch->beta_offset_cqi_times8 = beta_cqi[phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index];//18; - ulsch->beta_offset_ri_times8 = beta_ri[phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index];//10; - ulsch->beta_offset_harqack_times8 = beta_ack[phy_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index];//16; + ulsch->beta_offset_cqi_times8 = beta_cqi[eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index];//18; + ulsch->beta_offset_ri_times8 = beta_ri[eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index];//10; + ulsch->beta_offset_harqack_times8 = beta_ack[eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index];//16; ulsch->harq_processes[harq_pid]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)-(use_srs==0?0:1); ulsch->harq_processes[harq_pid]->srs_active = use_srs; @@ -7649,7 +7639,7 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d)\n", - phy_vars_eNB->Mod_id,harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift); + eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift); @@ -7716,15 +7706,15 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, } -double sinr_eff_cqi_calc(PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id) +double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id) { - uint8_t transmission_mode = phy_vars_ue->transmission_mode[eNB_id]; - PHY_MEASUREMENTS *meas = &phy_vars_ue->PHY_measurements; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - int32_t **dl_channel_est = phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id]; + uint8_t transmission_mode = ue->transmission_mode[eNB_id]; + PHY_MEASUREMENTS *meas = &ue->measurements; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int32_t **dl_channel_est = ue->common_vars.dl_ch_estimates[eNB_id]; double *s_dB; - s_dB = phy_vars_ue->sinr_CQI_dB; - // LTE_UE_ULSCH_t *ulsch = phy_vars_ue->ulsch_ue[eNB_id]; + s_dB = ue->sinr_CQI_dB; + // LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; //for the calculation of SINR_eff for CQI calculation int count,a_rx,a_tx; double abs_channel=0; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c index 2e8d70102f..0739d772f5 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c @@ -188,7 +188,8 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, #ifdef DEBUG_DLSCH_DECODING uint16_t i; #endif -#ifdef __AVX2__ + //#ifdef __AVX2__ +#if 0 int Kr_last,skipped_last=0; uint8_t (*tc_2cw)(int16_t *y, int16_t *y2, @@ -249,7 +250,8 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, } if (llr8_flag == 0) { -#ifdef __AVX2__ + //#ifdef __AVX2__ +#if 0 tc_2cw = phy_threegpplte_turbo_decoder16avx2; #endif tc = phy_threegpplte_turbo_decoder16; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c index 19ce6b9edc..c41262727f 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c @@ -78,10 +78,10 @@ unsigned char offset_mumimo_llr_drange[29][3]= {{0, 6, 5},{0, 4, 5},{0, 4, 5},{0 extern void print_shorts(char *s,int16_t *x); -int rx_pdsch(PHY_VARS_UE *phy_vars_ue, +int rx_pdsch(PHY_VARS_UE *ue, PDSCH_t type, unsigned char eNB_id, - unsigned char eNB_id_i, //if this == phy_vars_ue->n_connected_eNB, we assume MU interference + unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference uint8_t subframe, unsigned char symbol, unsigned char first_symbol_flag, @@ -90,11 +90,11 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, unsigned char harq_pid) { - LTE_UE_COMMON *lte_ue_common_vars = &phy_vars_ue->lte_ue_common_vars; - LTE_UE_PDSCH **lte_ue_pdsch_vars; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - PHY_MEASUREMENTS *phy_measurements = &phy_vars_ue->PHY_measurements; - LTE_UE_DLSCH_t **dlsch_ue; + LTE_UE_COMMON *common_vars = &ue->common_vars; + LTE_UE_PDSCH **pdsch_vars; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + PHY_MEASUREMENTS *phy_measurements = &ue->measurements; + LTE_UE_DLSCH_t **dlsch; unsigned char aatx,aarx; unsigned short nb_rb; @@ -104,26 +104,26 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, switch (type) { case SI_PDSCH: - lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]; - dlsch_ue = &phy_vars_ue->dlsch_ue_SI[eNB_id]; - dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; + pdsch_vars = &ue->pdsch_vars_SI[eNB_id]; + dlsch = &ue->dlsch_SI[eNB_id]; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; break; case RA_PDSCH: - lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars_ra[eNB_id]; - dlsch_ue = &phy_vars_ue->dlsch_ue_ra[eNB_id]; - dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; + pdsch_vars = &ue->pdsch_vars_ra[eNB_id]; + dlsch = &ue->dlsch_ra[eNB_id]; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; break; case PDSCH: - lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars[eNB_id]; - dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id]; - dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; - dlsch1_harq = dlsch_ue[1]->harq_processes[harq_pid]; + pdsch_vars = &ue->pdsch_vars[eNB_id]; + dlsch = ue->dlsch[eNB_id]; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch1_harq = dlsch[1]->harq_processes[harq_pid]; break; default: - LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",phy_vars_ue->frame_rx,subframe,type); + LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",ue->frame_rx,subframe,type); return(-1); break; } @@ -134,23 +134,23 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, return(-1); } - if (!lte_ue_common_vars) { - LOG_W(PHY,"dlsch_demodulation.c: Null lte_ue_common_vars\n"); + if (!common_vars) { + LOG_W(PHY,"dlsch_demodulation.c: Null common_vars\n"); return(-1); } - if (!dlsch_ue[0]) { - LOG_W(PHY,"dlsch_demodulation.c: Null dlsch_ue pointer\n"); + if (!dlsch[0]) { + LOG_W(PHY,"dlsch_demodulation.c: Null dlsch pointer\n"); return(-1); } - if (!lte_ue_pdsch_vars) { - LOG_W(PHY,"dlsch_demodulation.c: Null lte_ue_pdsch_vars pointer\n"); + if (!pdsch_vars) { + LOG_W(PHY,"dlsch_demodulation.c: Null pdsch_vars pointer\n"); return(-1); } if (!frame_parms) { - LOG_W(PHY,"dlsch_demodulation.c: Null lte_frame_parms\n"); + LOG_W(PHY,"dlsch_demodulation.c: Null frame_parms\n"); return(-1); } @@ -163,84 +163,84 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, if (frame_parms->nb_antennas_tx_eNB>1) { #ifdef DEBUG_DLSCH_MOD - LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch_ue[0],dlsch0_harq->rb_alloc_even[0]); + LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch[0],dlsch0_harq->rb_alloc_even[0]); #endif - nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id], - lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, + nb_rb = dlsch_extract_rbs_dual(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id], + pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - lte_ue_pdsch_vars[eNB_id]->pmi_ext, + pdsch_vars[eNB_id]->pmi_ext, rballoc, symbol, subframe, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_parms); if (dual_stream_flag==1) { - if (eNB_id_in_connected_eNB) - nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id_i], - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + if (eNB_id_in_connected_eNB) + nb_rb = dlsch_extract_rbs_dual(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id_i], + pdsch_vars[eNB_id_i]->rxdataF_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, + pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_parms); else - nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id], - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + nb_rb = dlsch_extract_rbs_dual(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id], + pdsch_vars[eNB_id_i]->rxdataF_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, + pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_parms); } } // if n_tx>1 else { - nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id], - lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, + nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id], + pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - lte_ue_pdsch_vars[eNB_id]->pmi_ext, + pdsch_vars[eNB_id]->pmi_ext, rballoc, symbol, subframe, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_parms); if (dual_stream_flag==1) { - if (eNB_id_in_connected_eNB) - nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id_i], - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + if (eNB_id_in_connected_eNB) + nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id_i], + pdsch_vars[eNB_id_i]->rxdataF_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, + pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_parms); - nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id], - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id], + pdsch_vars[eNB_id_i]->rxdataF_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, + pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_parms); } } //else n_tx>1 @@ -253,14 +253,14 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, /* // DL power control: Scaling of Channel estimates for PDSCH - dlsch_scale_channel(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, + dlsch_scale_channel(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, - dlsch_ue, + dlsch, symbol, nb_rb); */ if (first_symbol_flag==1) { - dlsch_channel_level(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, + dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avg, symbol, @@ -281,14 +281,14 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, // avgs = cmax(avgs,avg[(aarx<<1)+aatx]); - lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1; + pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1; // + log2_approx(frame_parms->nb_antennas_tx_eNB-1) //-1 because log2_approx counts the number of bits // + log2_approx(frame_parms->nb_antennas_rx-1); if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) && (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->dl_power_off==1)) // we are in TM 6 - lte_ue_pdsch_vars[eNB_id]->log2_maxh++; + pdsch_vars[eNB_id]->log2_maxh++; // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above /* K = Nb_rx in TM1 @@ -301,11 +301,11 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, (dlsch0_harq->dl_power_off==1)) // we are in TM 6 K *= frame_parms->nb_antennas_tx_eNB; - lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2); + pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2); */ #ifdef DEBUG_PHY - LOG_D(PHY,"[DLSCH] log2_maxh = %d (%d,%d)\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs); + LOG_D(PHY,"[DLSCH] log2_maxh = %d (%d,%d)\n",pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs); LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode); #endif } @@ -315,47 +315,47 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, if (dlsch0_harq->mimo_moderxdataF_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - (aatx>1) ? lte_ue_pdsch_vars[eNB_id]->rho : NULL, + dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, frame_parms, symbol, first_symbol_flag, dlsch0_harq->Qm, nb_rb, - lte_ue_pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[eNB_id]->log2_maxh, phy_measurements); // log2_maxh+I0_shift #ifdef DEBUG_PHY if (symbol==5) - write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif if ((dual_stream_flag==1) && - (eNB_id_in_connected_eNB)) { + (eNB_id_in_connected_eNB)) { // get MF output for interfering stream - dlsch_channel_compensation(lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - (aatx>1) ? lte_ue_pdsch_vars[eNB_id_i]->rho : NULL, + dlsch_channel_compensation(pdsch_vars[eNB_id_i]->rxdataF_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id_i]->dl_ch_magb0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + (aatx>1) ? pdsch_vars[eNB_id_i]->rho : NULL, frame_parms, symbol, first_symbol_flag, i_mod, nb_rb, - lte_ue_pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[eNB_id]->log2_maxh, phy_measurements); // log2_maxh+I0_shift #ifdef DEBUG_PHY if (symbol == 5) { - write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - write_output("rxF_comp_i.m","rxF_c_i",<e_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } #endif @@ -364,29 +364,29 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->log2_maxh); } } else if (dlsch0_harq->mimo_mode == LARGE_CDD) { // TM3 // LOG_I(PHY,"Running PDSCH RX for TM3\n"); if (frame_parms->nb_antennas_tx_eNB == 2) { if (first_symbol_flag==1) { // effective channel of desired user is always stronger than interfering eff. channel - dlsch_channel_level_TM3(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, + dlsch_channel_level_TM3(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avg, symbol, nb_rb); // LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->mcs>>1)-1]); avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->Qm>>1)-1]; - lte_ue_pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); - // printf("log2_maxh =%d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); + // printf("log2_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh); } dlsch_channel_compensation_TM3(frame_parms, - lte_ue_pdsch_vars[eNB_id], + pdsch_vars[eNB_id], phy_measurements, eNB_id, symbol, @@ -394,23 +394,23 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, dlsch1_harq->Qm, dlsch0_harq->round, nb_rb, - lte_ue_pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->log2_maxh); // compute correlation between signal and interference channels (rho12 and rho21) dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - &(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->log2_maxh); dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, - &(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho2_ext, - lte_ue_pdsch_vars[eNB_id]->log2_maxh); - //printf("TM3 log2_maxh : %d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh); + &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->log2_maxh); + //printf("TM3 log2_maxh : %d\n",pdsch_vars[eNB_id]->log2_maxh); } else { LOG_E(PHY, "only 2 tx antennas supported for TM3\n"); @@ -418,90 +418,90 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, } else if (dlsch0_harq->mimo_moden_connected_eNB)) { // TM5 two-user + if ((dual_stream_flag==1) && (eNB_id_i==ue->n_connected_eNB)) { // TM5 two-user // Scale the channel estimates for interfering stream - dlsch_scale_channel(lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, frame_parms, - dlsch_ue, + dlsch, symbol, nb_rb); /* compute new log2_maxh for effective channel */ if (first_symbol_flag==1) { // effective channel of desired user is always stronger than interfering eff. channel - dlsch_channel_level_TM56(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, lte_ue_pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb); + dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb); // LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]); avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]; - lte_ue_pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); - //printf("log1_maxh =%d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); + //printf("log1_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh); } - dlsch_channel_compensation_TM56(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->pmi_ext, + dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->pmi_ext, frame_parms, phy_measurements, eNB_id, symbol, dlsch0_harq->Qm, nb_rb, - lte_ue_pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[eNB_id]->log2_maxh, dlsch0_harq->dl_power_off); // if interference source is MU interference, assume opposite precoder was used at eNB // calculate opposite PMI for (rb=0; rbpmi_ext[rb]) { + switch(pdsch_vars[eNB_id]->pmi_ext[rb]) { case 0: - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=1; + pdsch_vars[eNB_id_i]->pmi_ext[rb]=1; break; case 1: - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=0; + pdsch_vars[eNB_id_i]->pmi_ext[rb]=0; break; case 2: - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=3; + pdsch_vars[eNB_id_i]->pmi_ext[rb]=3; break; case 3: - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=2; + pdsch_vars[eNB_id_i]->pmi_ext[rb]=2; break; } // if (rb==0) - // printf("pmi %d, pmi_i %d\n",lte_ue_pdsch_vars[eNB_id]->pmi_ext[rb],lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]); + // printf("pmi %d, pmi_i %d\n",pdsch_vars[eNB_id]->pmi_ext[rb],pdsch_vars[eNB_id_i]->pmi_ext[rb]); } - dlsch_channel_compensation_TM56(lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, + dlsch_channel_compensation_TM56(pdsch_vars[eNB_id_i]->rxdataF_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id_i]->dl_ch_magb0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->pmi_ext, frame_parms, phy_measurements, eNB_id_i, symbol, i_mod, nb_rb, - lte_ue_pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[eNB_id]->log2_maxh, dlsch0_harq->dl_power_off); #ifdef DEBUG_PHY if (symbol==5) { - write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - write_output("rxF_comp_i.m","rxF_c_i",<e_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } #endif @@ -509,25 +509,25 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->log2_maxh); } else { - dlsch_channel_compensation_TM56(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->pmi_ext, + dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->pmi_ext, frame_parms, phy_measurements, eNB_id, symbol, dlsch0_harq->Qm, nb_rb, - lte_ue_pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[eNB_id]->log2_maxh, 1); } } @@ -537,14 +537,14 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, if (dlsch0_harq->mimo_mode == LARGE_CDD) { if (frame_parms->nb_antennas_tx_eNB == 2) { dlsch_detection_mrc(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->rho, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag1, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb1, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->rho, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->dl_ch_mag1, + pdsch_vars[eNB_id]->dl_ch_magb1, symbol, nb_rb, dual_stream_flag); @@ -552,14 +552,14 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, } else { dlsch_detection_mrc(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->rho, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->rho, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id_i]->dl_ch_magb0, symbol, nb_rb, dual_stream_flag); @@ -573,17 +573,17 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, /* dlsch_siso(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, + pdsch_vars[eNB_id]->rxdataF_comp, + pdsch_vars[eNB_id_i]->rxdataF_comp, symbol, nb_rb); */ } else if (dlsch0_harq->mimo_mode == ALAMOUTI) { dlsch_alamouti(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, symbol, nb_rb); @@ -603,40 +603,40 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, if (dlsch0_harq->mimo_mode != LARGE_CDD) { if (dual_stream_flag == 0) dlsch_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); else if (i_mod == 2) { dlsch_qpsk_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else if (i_mod == 4) { dlsch_qpsk_16qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else { dlsch_qpsk_64qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } } else { // TM3 @@ -644,48 +644,48 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, if (dlsch1_harq->Qm == 2) { /* dlsch_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); */ dlsch_qpsk_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); dlsch_qpsk_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho2_ext, - lte_ue_pdsch_vars[eNB_id]->llr[1], + pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[eNB_id]->llr128_2ndstream); } else if (dlsch1_harq->Qm == 4) { dlsch_qpsk_16qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag1, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], + pdsch_vars[eNB_id]->dl_ch_mag1, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else { dlsch_qpsk_64qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag1, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round], + pdsch_vars[eNB_id]->dl_ch_mag1, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } } @@ -695,44 +695,44 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, case 4 : if (dual_stream_flag == 0) { dlsch_16qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->llr[0], - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else if (i_mod == 2) { dlsch_16qam_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else if (i_mod == 4) { dlsch_16qam_16qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else { dlsch_16qam_64qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } break; @@ -740,46 +740,46 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue, case 6 : if (dual_stream_flag == 0) { dlsch_64qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->llr[0], - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else if (i_mod == 2) { dlsch_64qam_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else if (i_mod == 4) { dlsch_64qam_16qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } else { dlsch_64qam_64qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id_i]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id_i]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext, + pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); } break; @@ -1843,8 +1843,8 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, } void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, - LTE_UE_PDSCH *lte_ue_pdsch_vars, - PHY_MEASUREMENTS *phy_measurements, + LTE_UE_PDSCH *pdsch_vars, + PHY_MEASUREMENTS *measurements, int eNB_id, unsigned char symbol, unsigned char mod_order0, @@ -1861,14 +1861,14 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, unsigned char aarx=0,symbol_mod,pilots=0; int precoded_signal_strength0=0,precoded_signal_strength1=0; - int **rxdataF_ext = lte_ue_pdsch_vars->rxdataF_ext; - int **dl_ch_estimates_ext = lte_ue_pdsch_vars->dl_ch_estimates_ext; - int **dl_ch_mag0 = lte_ue_pdsch_vars->dl_ch_mag0; - int **dl_ch_mag1 = lte_ue_pdsch_vars->dl_ch_mag1; - int **dl_ch_magb0 = lte_ue_pdsch_vars->dl_ch_magb0; - int **dl_ch_magb1 = lte_ue_pdsch_vars->dl_ch_magb1; - int **rxdataF_comp0 = lte_ue_pdsch_vars->rxdataF_comp0; - int **rxdataF_comp1 = lte_ue_pdsch_vars->rxdataF_comp1[round]; //? + int **rxdataF_ext = pdsch_vars->rxdataF_ext; + int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; + int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; + int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1; + int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; + int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1; + int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; + int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[round]; //? __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp0_128,QAM_amp0_128b,QAM_amp1_128,QAM_amp1_128b; @@ -2178,16 +2178,16 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, Nre = (pilots==0) ? 12 : 8; precoded_signal_strength0 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (phy_measurements->n0_power[aarx])); + (nb_rb*Nre))) - (measurements->n0_power[aarx])); precoded_signal_strength1 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx+2][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (phy_measurements->n0_power[aarx])); + (nb_rb*Nre))) - (measurements->n0_power[aarx])); - phy_measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,phy_measurements->n0_power_tot); - phy_measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,phy_measurements->n0_power_tot); + measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,measurements->n0_power_tot); + measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,measurements->n0_power_tot); //printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, - // phy_measurements->precoded_cqi_dB[eNB_id][0]); + // measurements->precoded_cqi_dB[eNB_id][0]); _mm_empty(); _m_empty(); @@ -2206,14 +2206,14 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, int16x8_t QAM_amp0_128,QAM_amp0_128b,QAM_amp1_128,QAM_amp1_128b; int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift); - int **rxdataF_ext = lte_ue_pdsch_vars->rxdataF_ext; - int **dl_ch_estimates_ext = lte_ue_pdsch_vars->dl_ch_estimates_ext; - int **dl_ch_mag0 = lte_ue_pdsch_vars->dl_ch_mag0; - int **dl_ch_mag1 = lte_ue_pdsch_vars->dl_ch_mag1; - int **dl_ch_magb0 = lte_ue_pdsch_vars->dl_ch_magb0; - int **dl_ch_magb1 = lte_ue_pdsch_vars->dl_ch_magb1; - int **rxdataF_comp0 = lte_ue_pdsch_vars->rxdataF_comp0; - int **rxdataF_comp1 = lte_ue_pdsch_vars->rxdataF_comp1[round]; //? + int **rxdataF_ext = pdsch_vars->rxdataF_ext; + int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; + int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; + int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1; + int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; + int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1; + int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; + int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[round]; //? int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1}; @@ -2461,14 +2461,14 @@ void dlsch_channel_compensation_TM3(LTE_DL_FRAME_PARMS *frame_parms, Nre = (pilots==0) ? 12 : 8; precoded_signal_strength0 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (phy_measurements->n0_power[aarx])); + (nb_rb*Nre))) - (measurements->n0_power[aarx])); precoded_signal_strength1 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx+2][symbol*frame_parms->N_RB_DL*Nre], - (nb_rb*Nre))) - (phy_measurements->n0_power[aarx])); + (nb_rb*Nre))) - (measurements->n0_power[aarx])); - phy_measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,phy_measurements->n0_power_tot); - phy_measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,phy_measurements->n0_power_tot); + measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,measurements->n0_power_tot); + measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,measurements->n0_power_tot); #endif } @@ -2717,7 +2717,7 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, void dlsch_scale_channel(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, - LTE_UE_DLSCH_t **dlsch_ue, + LTE_UE_DLSCH_t **dlsch, uint8_t symbol, unsigned short nb_rb) { @@ -2738,7 +2738,7 @@ void dlsch_scale_channel(int **dl_ch_estimates_ext, } // Determine scaling amplitude based the symbol - ch_amp = ((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); + ch_amp = ((pilots) ? (dlsch[0]->sqrt_rho_b) : (dlsch[0]->sqrt_rho_a)); // LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); @@ -4197,74 +4197,74 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF, #ifdef USER_MODE -void dump_dlsch2(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int round) +void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int round) { - unsigned int nsymb = (phy_vars_ue->lte_frame_parms.Ncp == 0) ? 14 : 12; + unsigned int nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; char fname[32],vname[32]; - int N_RB_DL=phy_vars_ue->lte_frame_parms.N_RB_DL; + int N_RB_DL=ue->frame_parms.N_RB_DL; sprintf(fname,"dlsch%d_rxF_r%d_ext0.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_ext0",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1); - if (phy_vars_ue->lte_frame_parms.nb_antennas_rx >1) { + if (ue->frame_parms.nb_antennas_rx >1) { sprintf(fname,"dlsch%d_rxF_r%d_ext1.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_ext1",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1); } sprintf(fname,"dlsch%d_ch_r%d_ext00.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext00",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); - if (phy_vars_ue->lte_frame_parms.nb_antennas_rx == 2) { + if (ue->frame_parms.nb_antennas_rx == 2) { sprintf(fname,"dlsch%d_ch_r%d_ext01.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext01",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); } - if (phy_vars_ue->lte_frame_parms.nb_antennas_tx_eNB == 2) { + if (ue->frame_parms.nb_antennas_tx_eNB == 2) { sprintf(fname,"dlsch%d_ch_r%d_ext10.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext10",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); - if (phy_vars_ue->lte_frame_parms.nb_antennas_rx == 2) { + if (ue->frame_parms.nb_antennas_rx == 2) { sprintf(fname,"dlsch%d_ch_r%d_ext11.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext11",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); } } /* - write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); - write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); - write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); + write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); + write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); + write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); */ sprintf(fname,"dlsch%d_r%d_rho.m",eNB_id,round); sprintf(vname,"dl_rho_r%d_%d",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext[0],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_rho_ext[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_rxF_r%d_comp0.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_comp0",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1); - if (phy_vars_ue->lte_frame_parms.nb_antennas_tx_eNB == 2) { + write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1); + if (ue->frame_parms.nb_antennas_tx_eNB == 2) { sprintf(fname,"dlsch%d_rxF_r%d_comp1.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_comp1",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[0][round],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_comp1[0][round],12*N_RB_DL*nsymb,1,1); } sprintf(fname,"dlsch%d_rxF_r%d_llr.m",eNB_id,round); sprintf(vname,"dl%d_r%d_llr",eNB_id,round); - write_output(fname,vname, phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->llr[0],coded_bits_per_codeword,1,0); + write_output(fname,vname, ue->pdsch_vars[eNB_id]->llr[0],coded_bits_per_codeword,1,0); sprintf(fname,"dlsch%d_r%d_mag1.m",eNB_id,round); sprintf(vname,"dl%d_r%d_mag1",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_r%d_mag2.m",eNB_id,round); sprintf(vname,"dl%d_r%d_mag2",eNB_id,round); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb,1,1); - // printf("log2_maxh = %d\n",phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->log2_maxh); + // printf("log2_maxh = %d\n",ue->pdsch_vars[eNB_id]->log2_maxh); } #endif diff --git a/openair1/PHY/LTE_TRANSPORT/drs_modulation.c b/openair1/PHY/LTE_TRANSPORT/drs_modulation.c index 097bcdd691..2d3b9d3b23 100644 --- a/openair1/PHY/LTE_TRANSPORT/drs_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/drs_modulation.c @@ -42,7 +42,7 @@ #include "PHY/sse_intrin.h" //#define DEBUG_DRS -int generate_drs_pusch(PHY_VARS_UE *phy_vars_ue, +int generate_drs_pusch(PHY_VARS_UE *ue, uint8_t eNB_id, short amp, unsigned int subframe, @@ -62,26 +62,26 @@ int generate_drs_pusch(PHY_VARS_UE *phy_vars_ue, int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384}; uint8_t cyclic_shift,cyclic_shift0,cyclic_shift1; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - int32_t *txdataF = phy_vars_ue->lte_ue_common_vars.txdataF[ant]; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int32_t *txdataF = ue->common_vars.txdataF[ant]; uint32_t u,v,alpha_ind; uint32_t u0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]; uint32_t u1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]; uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; int32_t ref_re,ref_im; - uint8_t harq_pid = subframe2harq_pid(frame_parms,phy_vars_ue->frame_tx,subframe); + uint8_t harq_pid = subframe2harq_pid(frame_parms,ue->frame_tx,subframe); cyclic_shift0 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->n_DMRS2 + - phy_vars_ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]+ - ((phy_vars_ue->ulsch_ue[0]->cooperation_flag==2)?10:0)+ + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 + + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]+ + ((ue->ulsch[0]->cooperation_flag==2)?10:0)+ ant*6) % 12; - // printf("PUSCH.cyclicShift %d, n_DMRS2 %d, nPRS %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,phy_vars_ue->ulsch_ue[eNB_id]->n_DMRS2,phy_vars_ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]); + // printf("PUSCH.cyclicShift %d, n_DMRS2 %d, nPRS %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,ue->ulsch[eNB_id]->n_DMRS2,ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]); cyclic_shift1 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->n_DMRS2 + - phy_vars_ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+1]+ - ((phy_vars_ue->ulsch_ue[0]->cooperation_flag==2)?10:0)+ + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 + + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+1]+ + ((ue->ulsch[0]->cooperation_flag==2)?10:0)+ ant*6) % 12; // cyclic_shift0 = 0; diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c index 5a8463a861..673b7a4348 100644 --- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c @@ -44,101 +44,98 @@ #include "SCHED/extern.h" #include "defs.h" #include "extern.h" -#ifdef EXMIMO -#include "gain_control.h" -#endif -#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_LMSSDR) + #include "common_lib.h" extern openair0_config_t openair0_cfg[]; -#endif -#define DEBUG_INITIAL_SYNCH -int pbch_detection(PHY_VARS_UE *phy_vars_ue, runmode_t mode) +//#define DEBUG_INITIAL_SYNCH + +int pbch_detection(PHY_VARS_UE *ue, runmode_t mode) { -uint8_t l,pbch_decoded,frame_mod4,pbch_tx_ant,dummy; -LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; -char phich_resource[6]; - + uint8_t l,pbch_decoded,frame_mod4,pbch_tx_ant,dummy; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + char phich_resource[6]; + #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",phy_vars_ue->Mod_id, - phy_vars_ue->rx_offset); + LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id, + ue->rx_offset); #endif for (l=0; lsymbols_per_tti/2; l++) { - slot_fep(phy_vars_ue, + slot_fep(ue, l, 0, - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); } for (l=0; lsymbols_per_tti/2; l++) { - slot_fep(phy_vars_ue, + slot_fep(ue, l, 1, - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); } - slot_fep(phy_vars_ue, + slot_fep(ue, 0, 2, - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); - lte_ue_measurements(phy_vars_ue, - phy_vars_ue->rx_offset, + lte_ue_measurements(ue, + ue->rx_offset, 0, 0); - if (phy_vars_ue->lte_frame_parms.frame_type == TDD) { - ue_rrc_measurements(phy_vars_ue, + if (ue->frame_parms.frame_type == TDD) { + ue_rrc_measurements(ue, 1, 0); } else { - ue_rrc_measurements(phy_vars_ue, + ue_rrc_measurements(ue, 0, 0); } #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE %d] RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), avg rx power %d dB (%d lin), RX gain %d dB\n", - phy_vars_ue->Mod_id, - phy_vars_ue->PHY_measurements.rx_rssi_dBm[0] - ((phy_vars_ue->lte_frame_parms.nb_antennas_rx==2) ? 3 : 0), - phy_vars_ue->PHY_measurements.rx_power_dB[0][0], - phy_vars_ue->PHY_measurements.rx_power_dB[0][1], - phy_vars_ue->PHY_measurements.rx_power[0][0], - phy_vars_ue->PHY_measurements.rx_power[0][1], - phy_vars_ue->PHY_measurements.rx_power_avg_dB[0], - phy_vars_ue->PHY_measurements.rx_power_avg[0], - phy_vars_ue->rx_total_gain_dB); + ue->Mod_id, + ue->measurements.rx_rssi_dBm[0] - ((ue->frame_parms.nb_antennas_rx==2) ? 3 : 0), + ue->measurements.rx_power_dB[0][0], + ue->measurements.rx_power_dB[0][1], + ue->measurements.rx_power[0][0], + ue->measurements.rx_power[0][1], + ue->measurements.rx_power_avg_dB[0], + ue->measurements.rx_power_avg[0], + ue->rx_total_gain_dB); LOG_I(PHY,"[UE %d] N0 %d dBm digital (%d, %d) dB, linear (%d, %d), avg noise power %d dB (%d lin)\n", - phy_vars_ue->Mod_id, - phy_vars_ue->PHY_measurements.n0_power_tot_dBm, - phy_vars_ue->PHY_measurements.n0_power_dB[0], - phy_vars_ue->PHY_measurements.n0_power_dB[1], - phy_vars_ue->PHY_measurements.n0_power[0], - phy_vars_ue->PHY_measurements.n0_power[1], - phy_vars_ue->PHY_measurements.n0_power_avg_dB, - phy_vars_ue->PHY_measurements.n0_power_avg); + ue->Mod_id, + ue->measurements.n0_power_tot_dBm, + ue->measurements.n0_power_dB[0], + ue->measurements.n0_power_dB[1], + ue->measurements.n0_power[0], + ue->measurements.n0_power[1], + ue->measurements.n0_power_avg_dB, + ue->measurements.n0_power_avg); #endif pbch_decoded = 0; for (frame_mod4=0; frame_mod4<4; frame_mod4++) { - pbch_tx_ant = rx_pbch(&phy_vars_ue->lte_ue_common_vars, - phy_vars_ue->lte_ue_pbch_vars[0], + pbch_tx_ant = rx_pbch(&ue->common_vars, + ue->pbch_vars[0], frame_parms, 0, SISO, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_mod4); if ((pbch_tx_ant>0) && (pbch_tx_ant<=2)) { @@ -146,12 +143,12 @@ char phich_resource[6]; break; } - pbch_tx_ant = rx_pbch(&phy_vars_ue->lte_ue_common_vars, - phy_vars_ue->lte_ue_pbch_vars[0], + pbch_tx_ant = rx_pbch(&ue->common_vars, + ue->pbch_vars[0], frame_parms, 0, ALAMOUTI, - phy_vars_ue->high_speed_flag, + ue->high_speed_flag, frame_mod4); if ((pbch_tx_ant>0) && (pbch_tx_ant<=2)) { @@ -171,12 +168,12 @@ char phich_resource[6]; // flip byte endian on 24-bits for MIB - // dummy = phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[0]; - // phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[0] = phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[2]; - // phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[2] = dummy; + // dummy = ue->pbch_vars[0]->decoded_output[0]; + // ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2]; + // ue->pbch_vars[0]->decoded_output[2] = dummy; // now check for Bandwidth of Cell - dummy = (phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[2]>>5)&7; + dummy = (ue->pbch_vars[0]->decoded_output[2]>>5)&7; switch (dummy) { @@ -205,15 +202,15 @@ char phich_resource[6]; break; default: - LOG_E(PHY,"[UE%d] Initial sync: PBCH decoding: Unknown N_RB_DL\n",phy_vars_ue->Mod_id); + LOG_E(PHY,"[UE%d] Initial sync: PBCH decoding: Unknown N_RB_DL\n",ue->Mod_id); return -1; break; } // now check for PHICH parameters - frame_parms->phich_config_common.phich_duration = (PHICH_DURATION_t)((phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[2]>>4)&1); - dummy = (phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[2]>>2)&3; + frame_parms->phich_config_common.phich_duration = (PHICH_DURATION_t)((ue->pbch_vars[0]->decoded_output[2]>>4)&1); + dummy = (ue->pbch_vars[0]->decoded_output[2]>>2)&3; switch (dummy) { case 0: @@ -237,25 +234,25 @@ char phich_resource[6]; break; default: - LOG_E(PHY,"[UE%d] Initial sync: Unknown PHICH_DURATION\n",phy_vars_ue->Mod_id); + LOG_E(PHY,"[UE%d] Initial sync: Unknown PHICH_DURATION\n",ue->Mod_id); return -1; break; } - phy_vars_ue->frame_rx = (((phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[2]&3)<<6) + (phy_vars_ue->lte_ue_pbch_vars[0]->decoded_output[1]>>2))<<2; - phy_vars_ue->frame_rx += frame_mod4; + ue->frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2; + ue->frame_rx += frame_mod4; #ifndef USER_MODE // one frame delay - phy_vars_ue->frame_rx ++; + ue->frame_rx ++; #endif - phy_vars_ue->frame_tx = phy_vars_ue->frame_rx; + ue->frame_tx = ue->frame_rx; #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully mode1_flag %d, tx_ant %d, frame %d, N_RB_DL %d, phich_duration %d, phich_resource %s!\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_parms->mode1_flag, pbch_tx_ant, - phy_vars_ue->frame_rx, + ue->frame_rx, frame_parms->N_RB_DL, frame_parms->phich_config_common.phich_duration, phich_resource); //frame_parms->phich_config_common.phich_resource); @@ -271,7 +268,7 @@ char phich_string[13][4] = {"","1/6","","1/2","","","one","","","","","","two"}; char duplex_string[2][4] = {"FDD","TDD"}; char prefix_string[2][9] = {"NORMAL","EXTENDED"}; -int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) +int initial_sync(PHY_VARS_UE *ue, runmode_t mode) { int32_t sync_pos,sync_pos2,sync_pos_slot; @@ -279,7 +276,7 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) uint8_t phase_fdd_ncp,phase_fdd_ecp,phase_tdd_ncp,phase_tdd_ecp; uint8_t flip_fdd_ncp,flip_fdd_ecp,flip_tdd_ncp,flip_tdd_ecp; // uint16_t Nid_cell_fdd_ncp=0,Nid_cell_fdd_ecp=0,Nid_cell_tdd_ncp=0,Nid_cell_tdd_ecp=0; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; int ret=-1; int aarx,rx_power=0; /*#ifdef OAI_USRP @@ -291,21 +288,21 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) frame_parms->frame_type=FDD; init_frame_parms(frame_parms,1); /* - write_output("rxdata0.m","rxd0",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); exit(-1); */ - sync_pos = lte_sync_time(phy_vars_ue->lte_ue_common_vars.rxdata, + sync_pos = lte_sync_time(ue->common_vars.rxdata, frame_parms, - (int *)&phy_vars_ue->lte_ue_common_vars.eNb_id); + (int *)&ue->common_vars.eNb_id); - // write_output("rxdata1.m","rxd1",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + // write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); if (sync_pos >= frame_parms->nb_prefix_samples) sync_pos2 = sync_pos - frame_parms->nb_prefix_samples; else sync_pos2 = sync_pos + FRAME_LENGTH_COMPLEX_SAMPLES - frame_parms->nb_prefix_samples; #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n",phy_vars_ue->Mod_id,sync_pos,phy_vars_ue->lte_ue_common_vars.eNb_id); + LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n",ue->Mod_id,sync_pos,ue->common_vars.eNb_id); #endif // SSS detection @@ -314,25 +311,25 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) sync_pos_slot = (frame_parms->samples_per_tti>>1) - frame_parms->ofdm_symbol_size - frame_parms->nb_prefix_samples; if (sync_pos2 >= sync_pos_slot) - phy_vars_ue->rx_offset = sync_pos2 - sync_pos_slot; + ue->rx_offset = sync_pos2 - sync_pos_slot; else - phy_vars_ue->rx_offset = FRAME_LENGTH_COMPLEX_SAMPLES + sync_pos2 - sync_pos_slot; + ue->rx_offset = FRAME_LENGTH_COMPLEX_SAMPLES + sync_pos2 - sync_pos_slot; if (((sync_pos2 - sync_pos_slot) >=0 ) && ((sync_pos2 - sync_pos_slot) < ((FRAME_LENGTH_COMPLEX_SAMPLES-frame_parms->samples_per_tti/2)))) { #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"Calling sss detection (FDD normal CP)\n"); #endif - rx_sss(phy_vars_ue,&metric_fdd_ncp,&flip_fdd_ncp,&phase_fdd_ncp); + rx_sss(ue,&metric_fdd_ncp,&flip_fdd_ncp,&phase_fdd_ncp); frame_parms->nushift = frame_parms->Nid_cell%6; if (flip_fdd_ncp==1) - phy_vars_ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); + ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); - init_frame_parms(&phy_vars_ue->lte_frame_parms,1); - lte_gold(frame_parms,phy_vars_ue->lte_gold_table[0],frame_parms->Nid_cell); - ret = pbch_detection(phy_vars_ue,mode); - // write_output("rxdata2.m","rxd2",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + init_frame_parms(&ue->frame_parms,1); + lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell); + ret = pbch_detection(ue,mode); + // write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"FDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n", @@ -361,25 +358,25 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) sync_pos_slot = (frame_parms->samples_per_tti>>1) - frame_parms->ofdm_symbol_size - (frame_parms->nb_prefix_samples); if (sync_pos2 >= sync_pos_slot) - phy_vars_ue->rx_offset = sync_pos2 - sync_pos_slot; + ue->rx_offset = sync_pos2 - sync_pos_slot; else - phy_vars_ue->rx_offset = FRAME_LENGTH_COMPLEX_SAMPLES + sync_pos2 - sync_pos_slot; + ue->rx_offset = FRAME_LENGTH_COMPLEX_SAMPLES + sync_pos2 - sync_pos_slot; - //msg("nb_prefix_samples %d, rx_offset %d\n",frame_parms->nb_prefix_samples,phy_vars_ue->rx_offset); + //msg("nb_prefix_samples %d, rx_offset %d\n",frame_parms->nb_prefix_samples,ue->rx_offset); if (((sync_pos2 - sync_pos_slot) >=0 ) && ((sync_pos2 - sync_pos_slot) < ((FRAME_LENGTH_COMPLEX_SAMPLES-frame_parms->samples_per_tti/2)))) { - rx_sss(phy_vars_ue,&metric_fdd_ecp,&flip_fdd_ecp,&phase_fdd_ecp); + rx_sss(ue,&metric_fdd_ecp,&flip_fdd_ecp,&phase_fdd_ecp); frame_parms->nushift = frame_parms->Nid_cell%6; if (flip_fdd_ecp==1) - phy_vars_ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); + ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); - init_frame_parms(&phy_vars_ue->lte_frame_parms,1); - lte_gold(frame_parms,phy_vars_ue->lte_gold_table[0],frame_parms->Nid_cell); - ret = pbch_detection(phy_vars_ue,mode); - // write_output("rxdata3.m","rxd3",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + init_frame_parms(&ue->frame_parms,1); + lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell); + ret = pbch_detection(ue,mode); + // write_output("rxdata3.m","rxd3",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"FDD Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n", frame_parms->Nid_cell,metric_fdd_ecp,phase_fdd_ecp,flip_fdd_ecp,ret); @@ -408,37 +405,26 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) (frame_parms->nb_prefix_samples); if (sync_pos2 >= sync_pos_slot) - phy_vars_ue->rx_offset = sync_pos2 - sync_pos_slot; + ue->rx_offset = sync_pos2 - sync_pos_slot; else - phy_vars_ue->rx_offset = (FRAME_LENGTH_COMPLEX_SAMPLES>>1) + sync_pos2 - sync_pos_slot; + ue->rx_offset = (FRAME_LENGTH_COMPLEX_SAMPLES>>1) + sync_pos2 - sync_pos_slot; - /*if (((sync_pos2 - sync_pos_slot) >=0 ) && - ((sync_pos2 - sync_pos_slot) < ((FRAME_LENGTH_COMPLEX_SAMPLES-frame_parms->samples_per_tti/2)))) {*/ - - - rx_sss(phy_vars_ue,&metric_tdd_ncp,&flip_tdd_ncp,&phase_tdd_ncp); + rx_sss(ue,&metric_tdd_ncp,&flip_tdd_ncp,&phase_tdd_ncp); if (flip_tdd_ncp==1) - phy_vars_ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); + ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); frame_parms->nushift = frame_parms->Nid_cell%6; - init_frame_parms(&phy_vars_ue->lte_frame_parms,1); + init_frame_parms(&ue->frame_parms,1); - lte_gold(frame_parms,phy_vars_ue->lte_gold_table[0],frame_parms->Nid_cell); - ret = pbch_detection(phy_vars_ue,mode); - // write_output("rxdata4.m","rxd4",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell); + ret = pbch_detection(ue,mode); + // write_output("rxdata4.m","rxd4",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"TDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n", frame_parms->Nid_cell,metric_tdd_ncp,phase_tdd_ncp,flip_tdd_ncp,ret); #endif - /*} - else { - #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"TDD Normal prefix: SSS error condition: sync_pos %d, sync_pos_slot %d\n", sync_pos, sync_pos_slot); - #endif - }*/ - if (ret==-1) { // Now TDD extended prefix @@ -456,35 +442,25 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) sync_pos_slot = frame_parms->samples_per_tti + (frame_parms->ofdm_symbol_size<<1) + (frame_parms->nb_prefix_samples<<1); if (sync_pos2 >= sync_pos_slot) - phy_vars_ue->rx_offset = sync_pos2 - sync_pos_slot; + ue->rx_offset = sync_pos2 - sync_pos_slot; else - phy_vars_ue->rx_offset = (FRAME_LENGTH_COMPLEX_SAMPLES>>1) + sync_pos2 - sync_pos_slot; + ue->rx_offset = (FRAME_LENGTH_COMPLEX_SAMPLES>>1) + sync_pos2 - sync_pos_slot; - /*if (((sync_pos2 - sync_pos_slot) >=0 ) && - ((sync_pos2 - sync_pos_slot) < ((FRAME_LENGTH_COMPLEX_SAMPLES-frame_parms->samples_per_tti/2)))) {*/ - - rx_sss(phy_vars_ue,&metric_tdd_ecp,&flip_tdd_ecp,&phase_tdd_ecp); + rx_sss(ue,&metric_tdd_ecp,&flip_tdd_ecp,&phase_tdd_ecp); frame_parms->nushift = frame_parms->Nid_cell%6; if (flip_tdd_ecp==1) - phy_vars_ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); + ue->rx_offset += (FRAME_LENGTH_COMPLEX_SAMPLES>>1); - init_frame_parms(&phy_vars_ue->lte_frame_parms,1); - lte_gold(frame_parms,phy_vars_ue->lte_gold_table[0],frame_parms->Nid_cell); - ret = pbch_detection(phy_vars_ue,mode); + init_frame_parms(&ue->frame_parms,1); + lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell); + ret = pbch_detection(ue,mode); - // write_output("rxdata5.m","rxd5",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + // write_output("rxdata5.m","rxd5",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"TDD Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n", frame_parms->Nid_cell,metric_tdd_ecp,phase_tdd_ecp,flip_tdd_ecp,ret); #endif - /*} - else { - #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"TDD Extended prefix: SSS error condition: sync_pos %d, sync_pos_slot %d\n", sync_pos, sync_pos_slot); - #endif - }*/ - } } } @@ -492,74 +468,73 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] In synch, rx_offset %d samples\n",phy_vars_ue->Mod_id, phy_vars_ue->rx_offset); + LOG_I(PHY,"[UE%d] In synch, rx_offset %d samples\n",ue->Mod_id, ue->rx_offset); #endif - if (phy_vars_ue->UE_scan_carrier == 0) { - if (phy_vars_ue->mac_enabled==1) { - LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",phy_vars_ue->Mod_id); + if (ue->UE_scan_carrier == 0) { + if (ue->mac_enabled==1) { + LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); //mac_resynch(); - mac_xface->dl_phy_sync_success(phy_vars_ue->Mod_id,phy_vars_ue->frame_rx,0,1);//phy_vars_ue->lte_ue_common_vars.eNb_id); - phy_vars_ue->UE_mode[0] = PRACH; + mac_xface->dl_phy_sync_success(ue->Mod_id,ue->frame_rx,0,1);//ue->common_vars.eNb_id); + ue->UE_mode[0] = PRACH; } else { - phy_vars_ue->UE_mode[0] = PUSCH; + ue->UE_mode[0] = PUSCH; } generate_pcfich_reg_mapping(frame_parms); generate_phich_reg_mapping(frame_parms); - // init_prach625(frame_parms); - //phy_vars_ue->lte_ue_pbch_vars[0]->pdu_errors=0; - phy_vars_ue->lte_ue_pbch_vars[0]->pdu_errors_conseq=0; - //phy_vars_ue->lte_ue_pbch_vars[0]->pdu_errors_last=0; + + ue->pbch_vars[0]->pdu_errors_conseq=0; + } - LOG_I(PHY,"[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",phy_vars_ue->Mod_id, - phy_vars_ue->frame_rx, - 10*log10(phy_vars_ue->PHY_measurements.rssi)-phy_vars_ue->rx_total_gain_dB, - 10*log10(phy_vars_ue->PHY_measurements.rssi), - phy_vars_ue->rx_total_gain_dB, - phy_vars_ue->PHY_measurements.n0_power_tot_dBm, - 10*log10(phy_vars_ue->PHY_measurements.rsrp[0])-phy_vars_ue->rx_total_gain_dB, - (10*log10(phy_vars_ue->PHY_measurements.rsrq[0]))); + LOG_I(PHY,"[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, + ue->frame_rx, + 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, + 10*log10(ue->measurements.rssi), + ue->rx_total_gain_dB, + ue->measurements.n0_power_tot_dBm, + 10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB, + (10*log10(ue->measurements.rsrq[0]))); LOG_I(PHY,"[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d\n", - phy_vars_ue->Mod_id, - phy_vars_ue->frame_rx, - duplex_string[phy_vars_ue->lte_frame_parms.frame_type], - prefix_string[phy_vars_ue->lte_frame_parms.Ncp], - phy_vars_ue->lte_frame_parms.Nid_cell, - phy_vars_ue->lte_frame_parms.N_RB_DL, - phy_vars_ue->lte_frame_parms.phich_config_common.phich_duration, - phich_string[phy_vars_ue->lte_frame_parms.phich_config_common.phich_resource], - phy_vars_ue->lte_frame_parms.nb_antennas_tx_eNB); -#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_LMSSDR) + ue->Mod_id, + ue->frame_rx, + duplex_string[ue->frame_parms.frame_type], + prefix_string[ue->frame_parms.Ncp], + ue->frame_parms.Nid_cell, + ue->frame_parms.N_RB_DL, + ue->frame_parms.phich_config_common.phich_duration, + phich_string[ue->frame_parms.phich_config_common.phich_resource], + ue->frame_parms.nb_antennas_tx_eNB); + LOG_I(PHY,"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", - phy_vars_ue->Mod_id, - phy_vars_ue->frame_rx, - openair0_cfg[0].rx_freq[0]-phy_vars_ue->lte_ue_common_vars.freq_offset, - phy_vars_ue->lte_ue_common_vars.freq_offset); -#endif + ue->Mod_id, + ue->frame_rx, + openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, + ue->common_vars.freq_offset); + } else { #ifdef DEBUG_INITIAL_SYNC - LOG_I(PHY,"[UE%d] Initial sync : PBCH not ok\n",phy_vars_ue->Mod_id); - LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n",phy_vars_ue->Mod_id,sync_pos,phy_vars_ue->lte_ue_common_vars.eNb_id); + LOG_I(PHY,"[UE%d] Initial sync : PBCH not ok\n",ue->Mod_id); + LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n",ue->Mod_id,sync_pos,ue->common_vars.eNb_id); /* LOG_I(PHY,"[UE%d] Initial sync: (metric fdd_ncp %d (%d), metric fdd_ecp %d (%d), metric_tdd_ncp %d (%d), metric_tdd_ecp %d (%d))\n", - phy_vars_ue->Mod_id, + ue->Mod_id, metric_fdd_ncp,Nid_cell_fdd_ncp, metric_fdd_ecp,Nid_cell_fdd_ecp, metric_tdd_ncp,Nid_cell_tdd_ncp, metric_tdd_ecp,Nid_cell_tdd_ecp);*/ - LOG_I(PHY,"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d\n",phy_vars_ue->Mod_id, + LOG_I(PHY,"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d\n",ue->Mod_id, frame_parms->Nid_cell,frame_parms->frame_type); #endif - phy_vars_ue->UE_mode[0] = NOT_SYNCHED; - phy_vars_ue->lte_ue_pbch_vars[0]->pdu_errors_last=phy_vars_ue->lte_ue_pbch_vars[0]->pdu_errors; - phy_vars_ue->lte_ue_pbch_vars[0]->pdu_errors++; - phy_vars_ue->lte_ue_pbch_vars[0]->pdu_errors_conseq++; + ue->UE_mode[0] = NOT_SYNCHED; + ue->pbch_vars[0]->pdu_errors_last=ue->pbch_vars[0]->pdu_errors; + ue->pbch_vars[0]->pdu_errors++; + ue->pbch_vars[0]->pdu_errors_conseq++; } @@ -569,57 +544,44 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) // do a measurement on the best guess of the PSS for (aarx=0; aarxnb_antennas_rx; aarx++) - rx_power += signal_energy(&phy_vars_ue->lte_ue_common_vars.rxdata[aarx][sync_pos2], + rx_power += signal_energy(&ue->common_vars.rxdata[aarx][sync_pos2], frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); /* // do a measurement on the full frame for (aarx=0; aarxnb_antennas_rx; aarx++) - rx_power += signal_energy(&phy_vars_ue->lte_ue_common_vars.rxdata[aarx][0], + rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0], frame_parms->samples_per_tti*10); */ // we might add a low-pass filter here later - phy_vars_ue->PHY_measurements.rx_power_avg[0] = rx_power/frame_parms->nb_antennas_rx; + ue->measurements.rx_power_avg[0] = rx_power/frame_parms->nb_antennas_rx; - phy_vars_ue->PHY_measurements.rx_power_avg_dB[0] = dB_fixed(phy_vars_ue->PHY_measurements.rx_power_avg[0]); + ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]); #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] Initial sync : Estimated power: %d dB\n",phy_vars_ue->Mod_id,phy_vars_ue->PHY_measurements.rx_power_avg_dB[0] ); + LOG_I(PHY,"[UE%d] Initial sync : Estimated power: %d dB\n",ue->Mod_id,ue->measurements.rx_power_avg_dB[0] ); #endif -#ifdef EXMIMO - if ((openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) && - (mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) ) - //phy_adjust_gain(phy_vars_ue,0); - gain_control_all(phy_vars_ue->PHY_measurements.rx_power_avg_dB[0],0); - -#else #ifndef OAI_USRP #ifndef OAI_BLADERF #ifndef OAI_LMSSDR - phy_adjust_gain(phy_vars_ue,phy_vars_ue->PHY_measurements.rx_power_avg_dB[0],0); -#endif + phy_adjust_gain(ue,ue->measurements.rx_power_avg_dB[0],0); #endif #endif #endif + } else { -#ifdef EXMIMO - if ((openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) && - (mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) ) - //phy_adjust_gain(phy_vars_ue,0); - gain_control_all(dB_fixed(phy_vars_ue->PHY_measurements.rssi),0); -#else #ifndef OAI_USRP #ifndef OAI_BLADERF #ifndef OAI_LMSSDR - phy_adjust_gain(phy_vars_ue,dB_fixed(phy_vars_ue->PHY_measurements.rssi),0); -#endif + phy_adjust_gain(ue,dB_fixed(ue->measurements.rssi),0); #endif #endif #endif + } // exit_fun("debug exit"); diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index 8b3a6c8758..e46fb1756a 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -1052,18 +1052,18 @@ void generate_phich(LTE_DL_FRAME_PARMS *frame_parms, // This routine demodulates the PHICH and updates PUSCH/ULSCH parameters -void rx_phich(PHY_VARS_UE *phy_vars_ue, +void rx_phich(PHY_VARS_UE *ue, uint8_t subframe, uint8_t eNB_id) { - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; - LTE_UE_PDCCH **lte_ue_pdcch_vars = phy_vars_ue->lte_ue_pdcch_vars; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars; // uint8_t HI; - uint8_t harq_pid = phich_subframe_to_harq_pid(frame_parms,phy_vars_ue->frame_rx,subframe); - LTE_UE_ULSCH_t *ulsch = phy_vars_ue->ulsch_ue[eNB_id]; + uint8_t harq_pid = phich_subframe_to_harq_pid(frame_parms,ue->frame_rx,subframe); + LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; int16_t phich_d[24],*phich_d_ptr,HI16; // unsigned int i,aa; int8_t d[24],*dp; @@ -1074,16 +1074,16 @@ void rx_phich(PHY_VARS_UE *phy_vars_ue, uint8_t reset = 1; int16_t cs[12]; uint32_t i,i2,i3,phich_quad; - int32_t **rxdataF_comp = lte_ue_pdcch_vars[eNB_id]->rxdataF_comp; + int32_t **rxdataF_comp = pdcch_vars[eNB_id]->rxdataF_comp; uint8_t Ngroup_PHICH,ngroup_PHICH,nseq_PHICH; uint8_t NSF_PHICH = 4; uint8_t pusch_subframe; // check if we're expecting a PHICH in this subframe - LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX\n",phy_vars_ue->Mod_id,harq_pid,phy_vars_ue->frame_rx,subframe); + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX\n",ue->Mod_id,harq_pid,ue->frame_rx,subframe); if (ulsch->harq_processes[harq_pid]->status == ACTIVE) { - LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",phy_vars_ue->Mod_id,harq_pid,phy_vars_ue->frame_rx,subframe); + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",ue->Mod_id,harq_pid,ue->frame_rx,subframe); Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48; if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0) @@ -1344,35 +1344,35 @@ void rx_phich(PHY_VARS_UE *phy_vars_ue, #endif if (HI16>0) { //NACK - if (phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] == 1) { + if (ue->ulsch_Msg3_active[eNB_id] == 1) { LOG_D(PHY,"[UE %d][PUSCH %d][RAPROC] Frame %d subframe %d Msg3 PHICH, received NAK (%d) nseq %d, ngroup %d\n", - phy_vars_ue->Mod_id,harq_pid, - phy_vars_ue->frame_rx, + ue->Mod_id,harq_pid, + ue->frame_rx, subframe, HI16, nseq_PHICH, ngroup_PHICH); - get_Msg3_alloc_ret(&phy_vars_ue->lte_frame_parms, + get_Msg3_alloc_ret(&ue->frame_parms, subframe, - phy_vars_ue->frame_rx, - &phy_vars_ue->ulsch_ue_Msg3_frame[eNB_id], - &phy_vars_ue->ulsch_ue_Msg3_subframe[eNB_id]); + ue->frame_rx, + &ue->ulsch_Msg3_frame[eNB_id], + &ue->ulsch_Msg3_subframe[eNB_id]); ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1; // ulsch->harq_processes[harq_pid]->Ndi = 0; ulsch->harq_processes[harq_pid]->round++; ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3]; - if (ulsch->harq_processes[harq_pid]->round>=phy_vars_ue->lte_frame_parms.maxHARQ_Msg3Tx) { + if (ulsch->harq_processes[harq_pid]->round>=ue->frame_parms.maxHARQ_Msg3Tx) { ulsch->harq_processes[harq_pid]->subframe_scheduling_flag =0; ulsch->harq_processes[harq_pid]->status = IDLE; // inform MAC that Msg3 transmission has failed - phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] = 0; + ue->ulsch_Msg3_active[eNB_id] = 0; } } else { //#ifdef DEBUG_PHICH LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received NAK (%d) nseq %d, ngroup %d\n", - phy_vars_ue->Mod_id,harq_pid, - phy_vars_ue->frame_rx, + ue->Mod_id,harq_pid, + ue->frame_rx, subframe, HI16, nseq_PHICH, @@ -1389,18 +1389,18 @@ void rx_phich(PHY_VARS_UE *phy_vars_ue, } else { //ACK - if (phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] == 1) { + if (ue->ulsch_Msg3_active[eNB_id] == 1) { LOG_D(PHY,"[UE %d][PUSCH %d][RAPROC] Frame %d subframe %d Msg3 PHICH, received ACK (%d) nseq %d, ngroup %d\n\n", - phy_vars_ue->Mod_id,harq_pid, - phy_vars_ue->frame_rx, + ue->Mod_id,harq_pid, + ue->frame_rx, subframe, HI16, nseq_PHICH,ngroup_PHICH); } else { //#ifdef PHICH_DEBUG LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received ACK (%d) nseq %d, ngroup %d\n\n", - phy_vars_ue->Mod_id,harq_pid, - phy_vars_ue->frame_rx, + ue->Mod_id,harq_pid, + ue->frame_rx, subframe, HI16, nseq_PHICH,ngroup_PHICH); //#endif @@ -1410,29 +1410,29 @@ void rx_phich(PHY_VARS_UE *phy_vars_ue, ulsch->harq_processes[harq_pid]->status = IDLE; ulsch->harq_processes[harq_pid]->round = 0; // inform MAC? - phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] = 0; + ue->ulsch_Msg3_active[eNB_id] = 0; } } -void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, - unsigned char sched_subframe, +void generate_phich_top(PHY_VARS_eNB *eNB, + unsigned char thread_id, int16_t amp, uint8_t sect_id, uint8_t abstraction_flag) { - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms; - LTE_eNB_ULSCH_t **ulsch_eNB = phy_vars_eNB->ulsch_eNB; - int32_t **txdataF = phy_vars_eNB->lte_eNB_common_vars.txdataF[sect_id]; + LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms; + LTE_eNB_ULSCH_t **ulsch = eNB->ulsch; + int32_t **txdataF = eNB->common_vars.txdataF[sect_id]; uint8_t harq_pid; uint8_t Ngroup_PHICH,ngroup_PHICH,nseq_PHICH; uint8_t NSF_PHICH = 4; uint8_t pusch_subframe; uint8_t UE_id; uint32_t pusch_frame; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_tx; + int subframe = eNB->proc[thread_id].subframe_tx; // compute Ngroup_PHICH (see formula at beginning of Section 6.9 in 36-211 @@ -1444,19 +1444,19 @@ void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, if (frame_parms->Ncp == 1) NSF_PHICH = 2; - pusch_frame = phich_frame2_pusch_frame(frame_parms,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); + pusch_frame = phich_frame2_pusch_frame(frame_parms,eNB->proc[thread_id].frame_tx,subframe); pusch_subframe = phich_subframe2_pusch_subframe(frame_parms,subframe); harq_pid = subframe2harq_pid(frame_parms,pusch_frame,pusch_subframe); for (UE_id=0; UE_idrnti>0)) { - if (ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active == 1) { + if ((ulsch[UE_id])&&(ulsch[UE_id]->rnti>0)) { + if (ulsch[UE_id]->harq_processes[harq_pid]->phich_active == 1) { LOG_D(PHY,"[eNB][PUSCH %d/%x] Frame %d subframe %d (pusch_subframe %d,pusch_frame %d) phich active %d\n", - harq_pid,ulsch_eNB[UE_id]->rnti,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,pusch_subframe,pusch_frame,ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active); + harq_pid,ulsch[UE_id]->rnti,eNB->proc[thread_id].frame_tx,subframe,pusch_subframe,pusch_frame,ulsch[UE_id]->harq_processes[harq_pid]->phich_active); - ngroup_PHICH = (ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb + - ulsch_eNB[UE_id]->harq_processes[harq_pid]->n_DMRS)%Ngroup_PHICH; + ngroup_PHICH = (ulsch[UE_id]->harq_processes[harq_pid]->first_rb + + ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%Ngroup_PHICH; if ((frame_parms->tdd_config == 0) && (frame_parms->frame_type == TDD) ) { @@ -1464,20 +1464,20 @@ void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, ngroup_PHICH += Ngroup_PHICH; } - nseq_PHICH = ((ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb/Ngroup_PHICH) + - ulsch_eNB[UE_id]->harq_processes[harq_pid]->n_DMRS)%(2*NSF_PHICH); + nseq_PHICH = ((ulsch[UE_id]->harq_processes[harq_pid]->first_rb/Ngroup_PHICH) + + ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%(2*NSF_PHICH); LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Generating PHICH, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d dci_alloc %d)\n", - phy_vars_eNB->Mod_id,harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx, + eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx, subframe,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH, - ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK, - ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb, - ulsch_eNB[UE_id]->harq_processes[harq_pid]->dci_alloc); + ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, + ulsch[UE_id]->harq_processes[harq_pid]->first_rb, + ulsch[UE_id]->harq_processes[harq_pid]->dci_alloc); - if (ulsch_eNB[UE_id]->Msg3_active == 1) { + if (ulsch[UE_id]->Msg3_active == 1) { LOG_D(PHY,"[eNB %d][PUSCH %d][RAPROC] Frame %d, subframe %d: Generating Msg3 PHICH for UE %d, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d\n", - phy_vars_eNB->Mod_id,harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - UE_id,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK, - ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb); + eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe, + UE_id,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, + ulsch[UE_id]->harq_processes[harq_pid]->first_rb); } if (abstraction_flag == 0) { @@ -1485,7 +1485,7 @@ void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, amp,//amp*2, nseq_PHICH, ngroup_PHICH, - ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK, + ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, subframe, txdataF); } else { @@ -1493,7 +1493,7 @@ void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, generate_phich_emul(frame_parms, //nseq_PHICH, //ngroup_PHICH, - ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK, + ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, subframe); */ } @@ -1501,27 +1501,27 @@ void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, // if no format0 DCI was transmitted by MAC, prepare the // MCS parameters for the retransmission - if ((ulsch_eNB[UE_id]->harq_processes[harq_pid]->dci_alloc == 0) && - (ulsch_eNB[UE_id]->harq_processes[harq_pid]->rar_alloc == 0) ) { - if (ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK==0 ) { + if ((ulsch[UE_id]->harq_processes[harq_pid]->dci_alloc == 0) && + (ulsch[UE_id]->harq_processes[harq_pid]->rar_alloc == 0) ) { + if (ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK==0 ) { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d, subframe %d : PHICH NACK / (no format0 DCI) Setting subframe_scheduling_flag\n", - phy_vars_eNB->Mod_id,harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; - ulsch_eNB[UE_id]->harq_processes[harq_pid]->rvidx = rv_table[ulsch_eNB[UE_id]->harq_processes[harq_pid]->round&3]; - ulsch_eNB[UE_id]->harq_processes[harq_pid]->O_RI = 0; - ulsch_eNB[UE_id]->harq_processes[harq_pid]->Or2 = 0; - ulsch_eNB[UE_id]->harq_processes[harq_pid]->Or1 = 0; - ulsch_eNB[UE_id]->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_nopmi; + eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe); + ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + ulsch[UE_id]->harq_processes[harq_pid]->rvidx = rv_table[ulsch[UE_id]->harq_processes[harq_pid]->round&3]; + ulsch[UE_id]->harq_processes[harq_pid]->O_RI = 0; + ulsch[UE_id]->harq_processes[harq_pid]->Or2 = 0; + ulsch[UE_id]->harq_processes[harq_pid]->Or1 = 0; + ulsch[UE_id]->harq_processes[harq_pid]->uci_format = HLC_subband_cqi_nopmi; } else { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d PHICH ACK (no format0 DCI) Clearing subframe_scheduling_flag, setting round to 0\n", - phy_vars_eNB->Mod_id,harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; - ulsch_eNB[UE_id]->harq_processes[harq_pid]->round=0; + eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe); + ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + ulsch[UE_id]->harq_processes[harq_pid]->round=0; } } - ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active=0; + ulsch[UE_id]->harq_processes[harq_pid]->phich_active=0; } // phich_active==1 } //ulsch_ue[UE_id] is non-null }// UE loop diff --git a/openair1/PHY/LTE_TRANSPORT/pilots.c b/openair1/PHY/LTE_TRANSPORT/pilots.c index 66e32fcb49..3e84c83747 100644 --- a/openair1/PHY/LTE_TRANSPORT/pilots.c +++ b/openair1/PHY/LTE_TRANSPORT/pilots.c @@ -40,13 +40,13 @@ //#include "defs.h" #include "PHY/defs.h" -void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, +void generate_pilots(PHY_VARS_eNB *eNB, int32_t **txdataF, int16_t amp, uint16_t Ntti) { - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; uint32_t tti,tti_offset,slot_offset,Nsymb,samples_per_symbol; uint8_t second_pilot; @@ -71,7 +71,7 @@ void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, //Generate Pilots //antenna 0 symbol 0 slot 0 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[0][tti_offset], + lte_dl_cell_spec(eNB,&txdataF[0][tti_offset], amp, slot_offset, 0, @@ -80,7 +80,7 @@ void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, // printf("tti %d : second_pilot offset %d \n",tti,tti_offset+(second_pilot*samples_per_symbol)); //antenna 0 symbol 3/4 slot 0 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[0][tti_offset+(second_pilot*samples_per_symbol)], + lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+(second_pilot*samples_per_symbol)], amp, slot_offset, 1, @@ -88,7 +88,7 @@ void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, // printf("tti %d : third_pilot offset %d \n",tti,tti_offset+((Nsymb>>1)*samples_per_symbol)); //antenna 0 symbol 0 slot 1 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[0][tti_offset+((Nsymb>>1)*samples_per_symbol)], + lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+((Nsymb>>1)*samples_per_symbol)], amp, 1+slot_offset, 0, @@ -96,7 +96,7 @@ void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, // printf("tti %d : third_pilot offset %d \n",tti,tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)); //antenna 0 symbol 3/4 slot 1 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[0][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)], + lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)], amp, 1+slot_offset, 1, @@ -106,28 +106,28 @@ void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, if (frame_parms->nb_antennas_tx > 1) { if (frame_parms->mode1_flag) { // antenna 1 symbol 0 slot 0 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset], amp, slot_offset, 0, 0); // antenna 1 symbol 3 slot 0 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)], amp, slot_offset, 1, 0); //antenna 1 symbol 0 slot 1 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol], amp, 1+slot_offset, 0, 0); // antenna 1 symbol 3 slot 1 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)], amp, 1+slot_offset, 1, @@ -136,28 +136,28 @@ void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, } else { // antenna 1 symbol 0 slot 0 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset], amp, slot_offset, 0, 1); // antenna 1 symbol 3 slot 0 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)], amp, slot_offset, 1, 1); //antenna 1 symbol 0 slot 1 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol], amp, 1+slot_offset, 0, 1); // antenna 1 symbol 3 slot 1 - lte_dl_cell_spec(phy_vars_eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)], + lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)], amp, 1+slot_offset, 1, @@ -167,14 +167,14 @@ void generate_pilots(PHY_VARS_eNB *phy_vars_eNB, } } -int generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, +int generate_pilots_slot(PHY_VARS_eNB *eNB, int32_t **txdataF, int16_t amp, uint16_t slot, int first_pilot_only) { - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; uint32_t slot_offset,Nsymb,samples_per_symbol; uint8_t second_pilot; @@ -194,7 +194,7 @@ int generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, //Generate Pilots //antenna 0 symbol 0 slot 0 - lte_dl_cell_spec(phy_vars_eNB, + lte_dl_cell_spec(eNB, &txdataF[0][slot_offset], amp, slot, @@ -204,7 +204,7 @@ int generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, if (first_pilot_only==0) { //antenna 0 symbol 3 slot 0 - lte_dl_cell_spec(phy_vars_eNB, + lte_dl_cell_spec(eNB, &txdataF[0][slot_offset+(second_pilot*samples_per_symbol)], amp, slot, @@ -215,7 +215,7 @@ int generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, if (frame_parms->nb_antennas_tx > 1) { if (frame_parms->mode1_flag) { // antenna 1 symbol 0 slot 0 - lte_dl_cell_spec(phy_vars_eNB, + lte_dl_cell_spec(eNB, &txdataF[1][slot_offset], amp, slot, @@ -224,7 +224,7 @@ int generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, if (first_pilot_only==0) { // antenna 1 symbol 3 slot 0 - lte_dl_cell_spec(phy_vars_eNB, + lte_dl_cell_spec(eNB, &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)], amp, slot, @@ -234,7 +234,7 @@ int generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, } else { // antenna 1 symbol 0 slot 0 - lte_dl_cell_spec(phy_vars_eNB, + lte_dl_cell_spec(eNB, &txdataF[1][slot_offset], amp, slot, @@ -243,7 +243,7 @@ int generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, if (first_pilot_only == 0) { // antenna 1 symbol 3 slot 0 - lte_dl_cell_spec(phy_vars_eNB, + lte_dl_cell_spec(eNB, &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)], amp, slot, diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c index 168f3db17c..4e0d6bba02 100644 --- a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c +++ b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c @@ -41,13 +41,13 @@ #include "PHY/defs.h" -int generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB, +int generate_mbsfn_pilot(PHY_VARS_eNB *eNB, int32_t **txdataF, int16_t amp, uint16_t subframe) { - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; uint32_t subframe_offset,Nsymb,samples_per_symbol; @@ -66,7 +66,7 @@ int generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB, //Generate Pilots //antenna 4 symbol 2 Slot 0 - lte_dl_mbsfn(phy_vars_eNB, + lte_dl_mbsfn(eNB, &txdataF[0][subframe_offset+(2*samples_per_symbol)], amp, subframe, @@ -75,14 +75,14 @@ int generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB, //antenna 4 symbol 0 slot 1 - lte_dl_mbsfn(phy_vars_eNB, + lte_dl_mbsfn(eNB, &txdataF[0][subframe_offset+(6*samples_per_symbol)], amp, subframe, 1); //antenna 4 symbol 4 slot 1 - lte_dl_mbsfn(phy_vars_eNB, + lte_dl_mbsfn(eNB, &txdataF[0][subframe_offset+(10*samples_per_symbol)], amp, subframe, diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 7b93201dd0..56a01b940e 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -48,50 +48,50 @@ -void dump_mch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int subframe) +void dump_mch(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int subframe) { unsigned int nsymb_pmch=12; char fname[32],vname[32]; - int N_RB_DL=phy_vars_ue->lte_frame_parms.N_RB_DL; + int N_RB_DL=ue->frame_parms.N_RB_DL; sprintf(fname,"mch_rxF_ext0.m"); sprintf(vname,"pmch_rxF_ext0"); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars_MCH[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb_pmch,1,1); + write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb_pmch,1,1); sprintf(fname,"mch_ch_ext00.m"); sprintf(vname,"pmch_ch_ext00"); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars_MCH[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb_pmch,1,1); + write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb_pmch,1,1); /* - write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb_pmch,1,1); - write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb_pmch,1,1); - write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb_pmch,1,1); - write_output("dlsch%d_rho.m","dl_rho",lte_ue_pdsch_vars[eNB_id]->rho[0],12*N_RB_DL*nsymb_pmch,1,1); + write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb_pmch,1,1); + write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb_pmch,1,1); + write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb_pmch,1,1); + write_output("dlsch%d_rho.m","dl_rho",pdsch_vars[eNB_id]->rho[0],12*N_RB_DL*nsymb_pmch,1,1); */ sprintf(fname,"mch_rxF_comp0.m"); sprintf(vname,"pmch_rxF_comp0"); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars_MCH[eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb_pmch,1,1); + write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb_pmch,1,1); sprintf(fname,"mch_rxF_llr.m"); sprintf(vname,"pmch_llr"); - write_output(fname,vname, phy_vars_ue->lte_ue_pdsch_vars_MCH[eNB_id]->llr[0],coded_bits_per_codeword,1,0); + write_output(fname,vname, ue->pdsch_vars_MCH[eNB_id]->llr[0],coded_bits_per_codeword,1,0); sprintf(fname,"mch_mag1.m"); sprintf(vname,"pmch_mag1"); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars_MCH[eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb_pmch,1,1); + write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb_pmch,1,1); sprintf(fname,"mch_mag2.m"); sprintf(vname,"pmch_mag2"); - write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars_MCH[eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb_pmch,1,1); + write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb_pmch,1,1); write_output("mch00_ch0.m","pmch00_ch0", - &(phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][0][0]), - phy_vars_ue->lte_frame_parms.ofdm_symbol_size*12,1,1); + &(ue->common_vars.dl_ch_estimates[eNB_id][0][0]), + ue->frame_parms.ofdm_symbol_size*12,1,1); write_output("rxsig_mch.m","rxs_mch", - &phy_vars_ue->lte_ue_common_vars.rxdata[0][subframe*phy_vars_ue->lte_frame_parms.samples_per_tti], - phy_vars_ue->lte_frame_parms.samples_per_tti,1,1); + &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_tti], + ue->frame_parms.samples_per_tti,1,1); if (PHY_vars_eNB_g) write_output("txsig_mch.m","txs_mch", - &PHY_vars_eNB_g[0][0]->lte_eNB_common_vars.txdata[0][0][subframe*phy_vars_ue->lte_frame_parms.samples_per_tti], - phy_vars_ue->lte_frame_parms.samples_per_tti,1,1); + &PHY_vars_eNB_g[0][0]->common_vars.txdata[0][0][subframe*ue->frame_parms.samples_per_tti], + ue->frame_parms.samples_per_tti,1,1); } int is_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms) @@ -190,11 +190,11 @@ int is_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_par return(0); } -void fill_eNB_dlsch_MCH(PHY_VARS_eNB *phy_vars_eNB,int mcs,int ndi,int rvidx, int abstraction_flag) +void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx, int abstraction_flag) { - LTE_eNB_DLSCH_t *dlsch = phy_vars_eNB->dlsch_eNB_MCH; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms; + LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_MCH; + LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms; // dlsch->rnti = M_RNTI; dlsch->harq_processes[0]->mcs = mcs; @@ -228,23 +228,23 @@ void fill_eNB_dlsch_MCH(PHY_VARS_eNB *phy_vars_eNB,int mcs,int ndi,int rvidx, in } if (abstraction_flag) { - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].cntl.pmch_flag=1; - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_pmch=1; // assumption: there is always one pmch in each SF - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_common_dci=0; - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_ue_spec_dci=0; - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[0]=5;// put at the reserved position for PMCH - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[0]=0; - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].ue_id[0]=255;//broadcast - eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[0]=dlsch->harq_processes[0]->TBS>>3; + eNB_transport_info[eNB->Mod_id][eNB->CC_id].cntl.pmch_flag=1; + eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_pmch=1; // assumption: there is always one pmch in each SF + eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_common_dci=0; + eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_ue_spec_dci=0; + eNB_transport_info[eNB->Mod_id][eNB->CC_id].dlsch_type[0]=5;// put at the reserved position for PMCH + eNB_transport_info[eNB->Mod_id][eNB->CC_id].harq_pid[0]=0; + eNB_transport_info[eNB->Mod_id][eNB->CC_id].ue_id[0]=255;//broadcast + eNB_transport_info[eNB->Mod_id][eNB->CC_id].tbs[0]=dlsch->harq_processes[0]->TBS>>3; } } -void fill_UE_dlsch_MCH(PHY_VARS_UE *phy_vars_ue,int mcs,int ndi,int rvidx,int eNB_id) +void fill_UE_dlsch_MCH(PHY_VARS_UE *ue,int mcs,int ndi,int rvidx,int eNB_id) { - LTE_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch_ue_MCH[eNB_id]; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; + LTE_UE_DLSCH_t *dlsch = ue->dlsch_MCH[eNB_id]; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; // dlsch->rnti = M_RNTI; dlsch->harq_processes[0]->mcs = mcs; @@ -286,59 +286,59 @@ void fill_UE_dlsch_MCH(PHY_VARS_UE *phy_vars_ue,int mcs,int ndi,int rvidx,int eN } } -void generate_mch(PHY_VARS_eNB *phy_vars_eNB,int sched_subframe,uint8_t *a,int abstraction_flag) +void generate_mch(PHY_VARS_eNB *eNB,int thread_id,uint8_t *a,int abstraction_flag) { int G; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_tx; + int subframe = eNB->proc[thread_id].subframe_tx; if (abstraction_flag != 0) { - if (eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]!=0) - printf("[PHY][EMU] PMCH transport block position is different than zero %d \n", eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]); + if (eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]!=0) + printf("[PHY][EMU] PMCH transport block position is different than zero %d \n", eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]); - memcpy(phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->b, + memcpy(eNB->dlsch_MCH->harq_processes[0]->b, a, - phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3); + eNB->dlsch_MCH->harq_processes[0]->TBS>>3); LOG_D(PHY, "[eNB %d] dlsch_encoding_emul pmch , tbs is %d \n", - phy_vars_eNB->Mod_id, - phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3); + eNB->Mod_id, + eNB->dlsch_MCH->harq_processes[0]->TBS>>3); - memcpy(&eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].transport_blocks[eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]], + memcpy(&eNB_transport_info[eNB->Mod_id][eNB->CC_id].transport_blocks[eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]], a, - phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3); - eNB_transport_info_TB_index[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]+= phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3;//=eNB_transport_info[phy_vars_eNB->Mod_id].tbs[0]; + eNB->dlsch_MCH->harq_processes[0]->TBS>>3); + eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]+= eNB->dlsch_MCH->harq_processes[0]->TBS>>3;//=eNB_transport_info[eNB->Mod_id].tbs[0]; } else { - G = get_G(&phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->lte_frame_parms.N_RB_DL, - phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->rb_alloc, - get_Qm(phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->mcs),1, - 2,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); + G = get_G(&eNB->frame_parms, + eNB->frame_parms.N_RB_DL, + eNB->dlsch_MCH->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1, + 2,eNB->proc[thread_id].frame_tx,subframe); - generate_mbsfn_pilot(phy_vars_eNB, - phy_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_mbsfn_pilot(eNB, + eNB->common_vars.txdataF[0], AMP, subframe); if (dlsch_encoding(a, - &phy_vars_eNB->lte_frame_parms, + &eNB->frame_parms, 1, - phy_vars_eNB->dlsch_eNB_MCH, - phy_vars_eNB->proc[sched_subframe].frame_tx, + eNB->dlsch_MCH, + eNB->proc[thread_id].frame_tx, subframe, - &phy_vars_eNB->dlsch_rate_matching_stats, - &phy_vars_eNB->dlsch_turbo_encoding_stats, - &phy_vars_eNB->dlsch_interleaving_stats + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_interleaving_stats )<0) mac_xface->macphy_exit("problem in dlsch_encoding"); - dlsch_scrambling(&phy_vars_eNB->lte_frame_parms,1,phy_vars_eNB->dlsch_eNB_MCH,G,0,subframe<<1); + dlsch_scrambling(&eNB->frame_parms,1,eNB->dlsch_MCH,G,0,subframe<<1); - mch_modulation(phy_vars_eNB->lte_eNB_common_vars.txdataF[0], + mch_modulation(eNB->common_vars.txdataF[0], AMP, subframe, - &phy_vars_eNB->lte_frame_parms, - phy_vars_eNB->dlsch_eNB_MCH); + &eNB->frame_parms, + eNB->dlsch_MCH); } } @@ -962,30 +962,30 @@ void mch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, } int avg_pmch[4]; -int rx_pmch(PHY_VARS_UE *phy_vars_ue, +int rx_pmch(PHY_VARS_UE *ue, unsigned char eNB_id, uint8_t subframe, unsigned char symbol) { - LTE_UE_COMMON *lte_ue_common_vars = &phy_vars_ue->lte_ue_common_vars; - LTE_UE_PDSCH **lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars_MCH[eNB_id]; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - LTE_UE_DLSCH_t **dlsch_ue = &phy_vars_ue->dlsch_ue_MCH[eNB_id]; + LTE_UE_COMMON *common_vars = &ue->common_vars; + LTE_UE_PDSCH **pdsch_vars = &ue->pdsch_vars_MCH[eNB_id]; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + LTE_UE_DLSCH_t **dlsch = &ue->dlsch_MCH[eNB_id]; int avgs,aarx; //printf("*********************mch: symbol %d\n",symbol); - mch_extract_rbs(lte_ue_common_vars->rxdataF, - lte_ue_common_vars->dl_ch_estimates[eNB_id], - lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, + mch_extract_rbs(common_vars->rxdataF, + common_vars->dl_ch_estimates[eNB_id], + pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_ch_estimates_ext, symbol, subframe, frame_parms); if (symbol == 2) { - mch_channel_level(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, + mch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avg_pmch, symbol, @@ -997,55 +997,55 @@ int rx_pmch(PHY_VARS_UE *phy_vars_ue, for (aarx=0; aarxnb_antennas_rx; aarx++) avgs = cmax(avgs,avg_pmch[aarx]); - if (get_Qm(dlsch_ue[0]->harq_processes[0]->mcs)==2) - lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2) ;// + 2 + if (get_Qm(dlsch[0]->harq_processes[0]->mcs)==2) + pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2) ;// + 2 else - lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2); // + 5;// + 2 + pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2); // + 5;// + 2 - mch_channel_compensation(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, + mch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext, + pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, frame_parms, symbol, - get_Qm(dlsch_ue[0]->harq_processes[0]->mcs), - lte_ue_pdsch_vars[eNB_id]->log2_maxh); + get_Qm(dlsch[0]->harq_processes[0]->mcs), + pdsch_vars[eNB_id]->log2_maxh); if (frame_parms->nb_antennas_rx > 1) mch_detection_mrc(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, symbol); - switch (get_Qm(dlsch_ue[0]->harq_processes[0]->mcs)) { + switch (get_Qm(dlsch[0]->harq_processes[0]->mcs)) { case 2 : mch_qpsk_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], symbol, - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); break; case 4: mch_16qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->llr[0], - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, symbol, - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); break; case 6: mch_64qam_llr(frame_parms, - lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0, - lte_ue_pdsch_vars[eNB_id]->llr[0], - lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0, - lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, symbol, - lte_ue_pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr128); break; } diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 5e58b13737..c18982f170 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -595,23 +595,23 @@ int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t su return(2==1); } -int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subframe, uint16_t Nf ) +int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint16_t Nf ) { - lte_frame_type_t frame_type = phy_vars_ue->lte_frame_parms.frame_type; - //uint8_t tdd_config = phy_vars_ue->lte_frame_parms.tdd_config; - uint16_t rootSequenceIndex = phy_vars_ue->lte_frame_parms.prach_config_common.rootSequenceIndex; - uint8_t prach_ConfigIndex = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - uint8_t Ncs_config = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; - uint8_t restricted_set = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag; - //uint8_t n_ra_prboffset = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset; - uint8_t preamble_index = phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex; - uint8_t tdd_mapindex = phy_vars_ue->prach_resources[eNB_id]->ra_TDD_map_index; - int16_t *prachF = phy_vars_ue->lte_ue_prach_vars[eNB_id]->prachF; + lte_frame_type_t frame_type = ue->frame_parms.frame_type; + //uint8_t tdd_config = ue->frame_parms.tdd_config; + uint16_t rootSequenceIndex = ue->frame_parms.prach_config_common.rootSequenceIndex; + uint8_t prach_ConfigIndex = ue->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex; + uint8_t Ncs_config = ue->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; + uint8_t restricted_set = ue->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag; + //uint8_t n_ra_prboffset = ue->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset; + uint8_t preamble_index = ue->prach_resources[eNB_id]->ra_PreambleIndex; + uint8_t tdd_mapindex = ue->prach_resources[eNB_id]->ra_TDD_map_index; + int16_t *prachF = ue->prach_vars[eNB_id]->prachF; static int16_t prach_tmp[45600*2] __attribute__((aligned(32))); int16_t *prach = prach_tmp; int16_t *prach2; - int16_t amp = phy_vars_ue->lte_ue_prach_vars[eNB_id]->amp; + int16_t amp = ue->prach_vars[eNB_id]->amp; int16_t Ncp; uint8_t n_ra_prb; uint16_t NCS; @@ -634,23 +634,20 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra int i, prach_len; uint16_t first_nonzero_root_idx=0; -#ifdef BIT8_TX - prach_start = ((subframe*phy_vars_ue->lte_frame_parms.samples_per_tti)<<1)-phy_vars_ue->N_TA_offset; -#else #if defined(EXMIMO) || defined(OAI_USRP) - prach_start = (phy_vars_ue->rx_offset+subframe*phy_vars_ue->lte_frame_parms.samples_per_tti-phy_vars_ue->hw_timing_advance-phy_vars_ue->N_TA_offset); + prach_start = (ue->rx_offset+subframe*ue->frame_parms.samples_per_tti-ue->hw_timing_advance-ue->N_TA_offset); if (prach_start<0) - prach_start+=(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); + prach_start+=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); - if (prach_start>=(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) - prach_start-=(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); + if (prach_start>=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) + prach_start-=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); #else //normal case (simulation) - prach_start = subframe*phy_vars_ue->lte_frame_parms.samples_per_tti-phy_vars_ue->N_TA_offset; -#endif + prach_start = subframe*ue->frame_parms.samples_per_tti-ue->N_TA_offset; #endif + // First compute physical root sequence if (restricted_set == 0) { if (Ncs_config > 15) { @@ -670,7 +667,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra NCS = NCS_restricted[Ncs_config]; } - n_ra_prb = get_prach_prb_offset(&(phy_vars_ue->lte_frame_parms), tdd_mapindex, Nf); + n_ra_prb = get_prach_prb_offset(&(ue->frame_parms), tdd_mapindex, Nf); prach_root_sequence_map = (prach_fmt<4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; /* @@ -678,7 +675,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra if (frame_type == TDD) { // TDD if (tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach==0) { - LOG_E( PHY, "[PHY][UE %"PRIu8"] Illegal prach_ConfigIndex %"PRIu8" for ", phy_vars_ue->Mod_id, prach_ConfigIndex ); + LOG_E( PHY, "[PHY][UE %"PRIu8"] Illegal prach_ConfigIndex %"PRIu8" for ", ue->Mod_id, prach_ConfigIndex ); } // adjust n_ra_prboffset for frequency multiplexing (p.36 36.211) @@ -688,7 +685,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra if ((f_ra&1) == 0) { n_ra_prb = n_ra_prboffset + 6*(f_ra>>1); } else { - n_ra_prb = phy_vars_ue->lte_frame_parms.N_RB_UL - 6 - n_ra_prboffset + 6*(f_ra>>1); + n_ra_prb = ue->frame_parms.N_RB_UL - 6 - n_ra_prboffset + 6*(f_ra>>1); } } else { if ((tdd_config >2) && (tdd_config<6)) @@ -699,7 +696,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra if ((((Nf&1)*(2-Nsp)+t1_ra)&1) == 0) { n_ra_prb = 6*f_ra; } else { - n_ra_prb = phy_vars_ue->lte_frame_parms.N_RB_UL - 6*(f_ra+1); + n_ra_prb = ue->frame_parms.N_RB_UL - 6*(f_ra+1); } } } @@ -715,7 +712,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra } else { // This is the high-speed case #ifdef PRACH_DEBUG - LOG_D(PHY,"[UE %d] High-speed mode, NCS_config %d\n",phy_vars_ue->Mod_id,Ncs_config); + LOG_D(PHY,"[UE %d] High-speed mode, NCS_config %d\n",ue->Mod_id,Ncs_config); #endif not_found = 1; @@ -785,24 +782,24 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra // nsymb = (frame_parms->Ncp==0) ? 14:12; // subframe_offset = (unsigned int)frame_parms->ofdm_symbol_size*subframe*nsymb; - k = (12*n_ra_prb) - 6*phy_vars_ue->lte_frame_parms.N_RB_UL; + k = (12*n_ra_prb) - 6*ue->frame_parms.N_RB_UL; if (k<0) - k+=phy_vars_ue->lte_frame_parms.ofdm_symbol_size; + k+=ue->frame_parms.ofdm_symbol_size; k*=12; k+=13; - Xu = (int16_t*)phy_vars_ue->X_u[preamble_offset-first_nonzero_root_idx]; + Xu = (int16_t*)ue->X_u[preamble_offset-first_nonzero_root_idx]; /* - k+=(12*phy_vars_ue->lte_frame_parms.first_carrier_offset); - if (k>(12*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)) - k-=(12*phy_vars_ue->lte_frame_parms.ofdm_symbol_size); + k+=(12*ue->frame_parms.first_carrier_offset); + if (k>(12*ue->frame_parms.ofdm_symbol_size)) + k-=(12*ue->frame_parms.ofdm_symbol_size); */ k*=2; - switch (phy_vars_ue->lte_frame_parms.N_RB_UL) { + switch (ue->frame_parms.N_RB_UL) { case 6: memset((void*)prachF,0,4*1536); break; @@ -838,7 +835,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra prachF[k++]= ((Xu_re*ru[offset2<<1]) - (Xu_im*ru[1+(offset2<<1)]))>>15; prachF[k++]= ((Xu_im*ru[offset2<<1]) + (Xu_re*ru[1+(offset2<<1)]))>>15; - if (k==(12*2*phy_vars_ue->lte_frame_parms.ofdm_symbol_size)) + if (k==(12*2*ue->frame_parms.ofdm_symbol_size)) k=0; } @@ -865,7 +862,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra break; } - switch (phy_vars_ue->lte_frame_parms.N_RB_UL) { + switch (ue->frame_parms.N_RB_UL) { case 6: Ncp>>=4; prach+=4; // makes prach2 aligned to 128-bit @@ -891,7 +888,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra prach2 = prach+(Ncp<<1); // do IDFT - switch (phy_vars_ue->lte_frame_parms.N_RB_UL) { + switch (ue->frame_parms.N_RB_UL) { case 6: if (prach_fmt == 4) { idft256(prachF,prach2,1); @@ -1015,34 +1012,34 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra } else { #if defined(EXMIMO) || defined(OAI_USRP) int j; - int overflow = prach_start + prach_len - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_ue->lte_frame_parms.samples_per_tti; + int overflow = prach_start + prach_len - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*ue->frame_parms.samples_per_tti; LOG_D( PHY, "prach_start=%d, overflow=%d\n", prach_start, overflow ); - for (i=prach_start,j=0; ilte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,prach_start+prach_len); i++,j++) { - ((int16_t*)phy_vars_ue->lte_ue_common_vars.txdata[0])[2*i] = prach[2*j]<<4; - ((int16_t*)phy_vars_ue->lte_ue_common_vars.txdata[0])[2*i+1] = prach[2*j+1]<<4; + for (i=prach_start,j=0; iframe_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,prach_start+prach_len); i++,j++) { + ((int16_t*)ue->common_vars.txdata[0])[2*i] = prach[2*j]<<4; + ((int16_t*)ue->common_vars.txdata[0])[2*i+1] = prach[2*j+1]<<4; } for (i=0; ilte_ue_common_vars.txdata[0])[2*i] = prach[2*j]<<4; - ((int16_t*)phy_vars_ue->lte_ue_common_vars.txdata[0])[2*i+1] = prach[2*j+1]<<4; + ((int16_t*)ue->common_vars.txdata[0])[2*i] = prach[2*j]<<4; + ((int16_t*)ue->common_vars.txdata[0])[2*i+1] = prach[2*j+1]<<4; } #if defined(EXMIMO) // handle switch before 1st TX subframe, guarantee that the slot prior to transmission is switch on - for (k=prach_start - (phy_vars_ue->lte_frame_parms.samples_per_tti>>1) ; kframe_parms.samples_per_tti>>1) ; klte_ue_common_vars.txdata[0][k+phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; - else if (k>(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) - phy_vars_ue->lte_ue_common_vars.txdata[0][k-phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + ue->common_vars.txdata[0][k+ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + else if (k>(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) + ue->common_vars.txdata[0][k-ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; else - phy_vars_ue->lte_ue_common_vars.txdata[0][k] &= 0xFFFEFFFE; + ue->common_vars.txdata[0][k] &= 0xFFFEFFFE; } #endif #else for (i=0; ilte_ue_common_vars.txdata[0][prach_start]))[2*i] = prach[2*i]; - ((int16_t*)(&phy_vars_ue->lte_ue_common_vars.txdata[0][prach_start]))[2*i+1] = prach[2*i+1]; + ((int16_t*)(&ue->common_vars.txdata[0][prach_start]))[2*i] = prach[2*i]; + ((int16_t*)(&ue->common_vars.txdata[0][prach_start]))[2*i+1] = prach[2*i+1]; } #endif @@ -1058,7 +1055,7 @@ int32_t generate_prach( PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, uint8_t subfra } //__m128i mmtmpX0,mmtmpX1,mmtmpX2,mmtmpX3; -void rx_prach(PHY_VARS_eNB *phy_vars_eNB, +void rx_prach(PHY_VARS_eNB *eNB, uint8_t subframe, uint16_t *preamble_energy_list, uint16_t *preamble_delay_list, @@ -1067,16 +1064,16 @@ void rx_prach(PHY_VARS_eNB *phy_vars_eNB, { int i; - lte_frame_type_t frame_type = phy_vars_eNB->lte_frame_parms.frame_type; + lte_frame_type_t frame_type = eNB->frame_parms.frame_type; - uint16_t rootSequenceIndex = phy_vars_eNB->lte_frame_parms.prach_config_common.rootSequenceIndex; - uint8_t prach_ConfigIndex = phy_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - uint8_t Ncs_config = phy_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; - uint8_t restricted_set = phy_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag; - int16_t *prachF = phy_vars_eNB->lte_eNB_prach_vars.prachF; - int16_t **rxsigF = phy_vars_eNB->lte_eNB_prach_vars.rxsigF; - int16_t **prach_ifft = phy_vars_eNB->lte_eNB_prach_vars.prach_ifft; - int16_t *prach[4]; + uint16_t rootSequenceIndex = eNB->frame_parms.prach_config_common.rootSequenceIndex; + uint8_t prach_ConfigIndex = eNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex; + uint8_t Ncs_config = eNB->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; + uint8_t restricted_set = eNB->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag; + int16_t *prachF = eNB->prach_vars.prachF; + int16_t **rxsigF = eNB->prach_vars.rxsigF; + int16_t **prach_ifft = eNB->prach_vars.prach_ifft; + int16_t *prach[eNB->frame_parms.nb_antennas_rx]; int16_t *prach2; uint8_t n_ra_prb; uint8_t preamble_index; @@ -1102,10 +1099,10 @@ void rx_prach(PHY_VARS_eNB *phy_vars_eNB, int32_t lev; int16_t levdB; int fft_size,log2_ifft_size; - uint8_t nb_ant_rx = 1; //phy_vars_eNB->lte_frame_parms.nb_antennas_rx; + uint8_t nb_ant_rx = 1; //eNB->frame_parms.nb_antennas_rx; for (aa=0; aalte_eNB_common_vars.rxdata[0][aa][subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti-phy_vars_eNB->N_TA_offset]; + prach[aa] = (int16_t*)&eNB->common_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_tti-eNB->N_TA_offset]; } // First compute physical root sequence @@ -1127,9 +1124,9 @@ void rx_prach(PHY_VARS_eNB *phy_vars_eNB, NCS = NCS_restricted[Ncs_config]; } - start_meas(&phy_vars_eNB->rx_prach); + start_meas(&eNB->rx_prach); - n_ra_prb = get_prach_prb_offset(&(phy_vars_eNB->lte_frame_parms),tdd_mapindex,Nf); + n_ra_prb = get_prach_prb_offset(&(eNB->frame_parms),tdd_mapindex,Nf); prach_root_sequence_map = (prach_fmt < 4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; // PDP is oversampled, e.g. 1024 sample instead of 839 @@ -1162,7 +1159,7 @@ void rx_prach(PHY_VARS_eNB *phy_vars_eNB, break; } - switch (phy_vars_eNB->lte_frame_parms.N_RB_UL) { + switch (eNB->frame_parms.N_RB_UL) { case 6: Ncp>>=4; break; @@ -1184,23 +1181,123 @@ void rx_prach(PHY_VARS_eNB *phy_vars_eNB, break; } + + if ((eNB->node_function == eNodeB_3GPP) || + (eNB->node_function == NGFI_RRU_IF4)) { // compute the DFTs of the PRACH temporal resources + // Do forward transform + for (aa=0; aaframe_parms.N_RB_UL) { + case 6: + if (prach_fmt == 4) { + dft256(prach2,rxsigF[aa],1); + } else { + dft1536(prach2,rxsigF[aa],1); + + if (prach_fmt>1) + dft1536(prach2+3072,rxsigF[aa]+3072,1); + } + + break; + + case 15: + if (prach_fmt == 4) { + dft256(prach2,rxsigF[aa],1); + } else { + dft3072(prach2,rxsigF[aa]); + + if (prach_fmt>1) + dft3072(prach2+6144,rxsigF[aa]+6144); + } + + break; + + case 25: + default: + if (prach_fmt == 4) { + dft1024(prach2,rxsigF[aa],1); + fft_size = 1024; + } else { + dft6144(prach2,rxsigF[aa]); + + if (prach_fmt>1) + dft6144(prach2+12288,rxsigF[aa]+12288); + + fft_size = 6144; + } + + break; + + case 50: + if (prach_fmt == 4) { + dft2048(prach2,rxsigF[aa],1); + } else { + dft12288(prach2,rxsigF[aa]); + + if (prach_fmt>1) + dft12288(prach2+24576,rxsigF[aa]+24576); + } + + break; + + case 75: + if (prach_fmt == 4) { + dft3072(prach2,rxsigF[aa]); + } else { + dft18432(prach2,rxsigF[aa]); + + if (prach_fmt>1) + dft18432(prach2+36864,rxsigF[aa]+36864); + } + + break; + + case 100: + if (prach_fmt == 4) { + dft4096(prach2,rxsigF[aa],1); + } else { + dft24576(prach2,rxsigF[aa]); + + if (prach_fmt>1) + dft24576(prach2+49152,rxsigF[aa]+49152); + } + + break; + } + } + } + + if (eNB->node_function == NGFI_RRU_IF4) { + //send prachF to RCC + return; + } + else if (eNB->node_function == NGFI_RCC_IF4) { + //wait for prachF from RRU and continue with PRACH processing + } + + + + // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4 + preamble_offset_old = 99; for (preamble_index=0 ; preamble_index<64 ; preamble_index++) { if (restricted_set == 0) { // This is the relative offset in the root sequence table (5.7.2-4 from 36.211) for the given preamble index preamble_offset = ((NCS==0)? preamble_index : (preamble_index/(N_ZC/NCS))); - + if (preamble_offset != preamble_offset_old) { preamble_offset_old = preamble_offset; new_dft = 1; // This is the \nu corresponding to the preamble index preamble_shift = 0; } - + else { preamble_shift -= NCS; - + if (preamble_shift < 0) preamble_shift+=N_ZC; } @@ -1277,187 +1374,111 @@ void rx_prach(PHY_VARS_eNB *phy_vars_eNB, if (new_dft == 1) { new_dft = 0; - Xu=(int16_t*)phy_vars_eNB->X_u[preamble_offset-first_nonzero_root_idx]; + Xu=(int16_t*)eNB->X_u[preamble_offset-first_nonzero_root_idx]; + - for (aa=0; aalte_frame_parms.N_RB_UL; + + k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; + + if (k<0) + k+=(eNB->frame_parms.ofdm_symbol_size); + + k*=12; + k+=13; // phi + K/2 + // k+=(12*eNB->frame_parms.first_carrier_offset); + // if (k>(12*eNB->frame_parms.ofdm_symbol_size)) + // k-=(12*eNB->frame_parms.ofdm_symbol_size); + + // printf("First prach carrier : k %d\n",k); + k*=2; + - if (k<0) - k+=(phy_vars_eNB->lte_frame_parms.ofdm_symbol_size); - - k*=12; - k+=13; // phi + K/2 - // k+=(12*phy_vars_eNB->lte_frame_parms.first_carrier_offset); - // if (k>(12*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)) - // k-=(12*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size); - - // printf("First prach carrier : k %d\n",k); - k*=2; - - // do DFT - switch (phy_vars_eNB->lte_frame_parms.N_RB_UL) { - case 6: - if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); - } else { - dft1536(prach2,rxsigF[aa],1); - - if (prach_fmt>1) - dft1536(prach2+3072,rxsigF[aa]+3072,1); - } - - break; - - case 15: - if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); - } else { - dft3072(prach2,rxsigF[aa]); - - if (prach_fmt>1) - dft3072(prach2+6144,rxsigF[aa]+6144); - } - - break; - - case 25: - default: - if (prach_fmt == 4) { - dft1024(prach2,rxsigF[aa],1); - fft_size = 1024; - } else { - dft6144(prach2,rxsigF[aa]); - - if (prach_fmt>1) - dft6144(prach2+12288,rxsigF[aa]+12288); - - fft_size = 6144; - } - - break; - - case 50: - if (prach_fmt == 4) { - dft2048(prach2,rxsigF[aa],1); - } else { - dft12288(prach2,rxsigF[aa]); - - if (prach_fmt>1) - dft12288(prach2+24576,rxsigF[aa]+24576); - } - - break; - - case 75: - if (prach_fmt == 4) { - dft3072(prach2,rxsigF[aa]); - } else { - dft18432(prach2,rxsigF[aa]); - - if (prach_fmt>1) - dft18432(prach2+36864,rxsigF[aa]+36864); - } - - break; - - case 100: - if (prach_fmt == 4) { - dft4096(prach2,rxsigF[aa],1); - } else { - dft24576(prach2,rxsigF[aa]); - - if (prach_fmt>1) - dft24576(prach2+49152,rxsigF[aa]+49152); - } - - break; - } - - memset( prachF, 0, sizeof(int16_t)*2*1024 ); + + memset( prachF, 0, sizeof(int16_t)*2*1024 ); #ifdef PRACH_DEBUG - write_output("prach_rx0.m","prach_rx0",prach[0],6144+792,1,1); + write_output("prach_rx0.m","prach_rx0",prach[0],6144+792,1,1); #endif - // write_output("prach_rx1.m","prach_rx1",prach[1],6144+792,1,1); - // write_output("prach_rxF0.m","prach_rxF0",rxsigF[0],24576,1,1); - // write_output("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1); + // write_output("prach_rx1.m","prach_rx1",prach[1],6144+792,1,1); + // write_output("prach_rxF0.m","prach_rxF0",rxsigF[0],24576,1,1); + // write_output("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1); - // Do componentwise product with Xu* - for (offset=0; offset<(N_ZC<<1); offset+=2) { - prachF[offset] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][k] + (int32_t)Xu[offset+1]*rxsigF[aa][k+1])>>15); - prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][k+1] - (int32_t)Xu[offset+1]*rxsigF[aa][k])>>15); - /* - if (offset<16) - printf("Xu[%d] %d %d, rxsigF[%d][%d] %d %d\n",offset,Xu[offset],Xu[offset+1],aa,k,rxsigF[aa][k],rxsigF[aa][k+1]); - */ - /* - mmtmpX0 = _mm_madd_epi16(*(__m128i*)&Xu[offset],*(__m128i*)&rxsigF[aa][k<<1]); - mmtmpX1 = _mm_shufflelo_epi16(*(__m128i*)&Xu[offset],_MM_SHUFFLE(2,3,0,1)); - mmtmpX1 = _mm_shufflehi_epi16(mmtmpX1,_MM_SHUFFLE(2,3,0,1)); - mmtmpX1 = _mm_sign_epi16(mmtmpX1,*(__m128i*)&conjugate[0]); - mmtmpX1 = _mm_madd_epi16(mmtmpX1,*(__m128i*)&rxsigF[aa][k<<1]); - mmtmpX0 = _mm_srai_epi32(mmtmpX0,15); - mmtmpX1 = _mm_srai_epi32(mmtmpX1,15); - mmtmpX2 = _mm_unpacklo_epi32(mmtmpX0,mmtmpX1); - mmtmpX3 = _mm_unpackhi_epi32(mmtmpX0,mmtmpX1); - *(__m128i*)&prachF[offset] = _mm_packs_epi32(mmtmpX2,mmtmpX3); - */ - k+=2; - - if (k==(12*2*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)) - k=0; - } - - // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) - if (N_ZC == 839) { - log2_ifft_size = 10; - idft1024(prachF,prach_ifft[aa],1); - } else { - idft256(prachF,prach_ifft[aa],1); - log2_ifft_size = 8; - } + for (aa=0;aa>15); + prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][k+1] - (int32_t)Xu[offset+1]*rxsigF[aa][k])>>15); + /* + if (offset<16) + printf("Xu[%d] %d %d, rxsigF[%d][%d] %d %d\n",offset,Xu[offset],Xu[offset+1],aa,k,rxsigF[aa][k],rxsigF[aa][k+1]); + */ + /* + mmtmpX0 = _mm_madd_epi16(*(__m128i*)&Xu[offset],*(__m128i*)&rxsigF[aa][k<<1]); + mmtmpX1 = _mm_shufflelo_epi16(*(__m128i*)&Xu[offset],_MM_SHUFFLE(2,3,0,1)); + mmtmpX1 = _mm_shufflehi_epi16(mmtmpX1,_MM_SHUFFLE(2,3,0,1)); + mmtmpX1 = _mm_sign_epi16(mmtmpX1,*(__m128i*)&conjugate[0]); + mmtmpX1 = _mm_madd_epi16(mmtmpX1,*(__m128i*)&rxsigF[aa][k<<1]); + mmtmpX0 = _mm_srai_epi32(mmtmpX0,15); + mmtmpX1 = _mm_srai_epi32(mmtmpX1,15); + mmtmpX2 = _mm_unpacklo_epi32(mmtmpX0,mmtmpX1); + mmtmpX3 = _mm_unpackhi_epi32(mmtmpX0,mmtmpX1); + *(__m128i*)&prachF[offset] = _mm_packs_epi32(mmtmpX2,mmtmpX3); + */ + k+=2; + + if (k==(12*2*eNB->frame_parms.ofdm_symbol_size)) + k=0; + } + + // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) + if (N_ZC == 839) { + log2_ifft_size = 10; + idft1024(prachF,prach_ifft[aa],1); + } else { + idft256(prachF,prach_ifft[aa],1); + log2_ifft_size = 8; + } #ifdef PRACH_DEBUG - write_output("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); + if (aa==0) write_output("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); #endif - // write_output("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1); - + // if (aa=1) write_output("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1); }// antennas_rx #ifdef PRACH_DEBUG write_output("prach_ifft0.m","prach_t0",prach_ifft[0],2048,1,1); #endif // write_output("prach_ifft1.m","prach_t1",prach_ifft[1],2048,1,1); - + } // new dft - + // check energy in nth time shift preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<preamble_energy_list[preamble_index] ) { - preamble_energy_list[preamble_index] = levdB; - preamble_delay_list[preamble_index] = (i*fft_size)>>log2_ifft_size; + preamble_energy_list[preamble_index] = levdB; + preamble_delay_list[preamble_index] = (i*fft_size)>>log2_ifft_size; } } - + #ifdef PRACH_DEBUG LOG_D(PHY,"[RAPROC] Preamble %d => %d dB, %d (shift %d (%d), NCS2 %d(%d), Ncp %d)\n",preamble_index,preamble_energy_list[preamble_index],preamble_delay_list[preamble_index],preamble_shift2, - preamble_shift, NCS2,NCS,Ncp); + preamble_shift, NCS2,NCS,Ncp); #endif // exit(-1); }// preamble_index - - stop_meas(&phy_vars_eNB->rx_prach); - + + stop_meas(&eNB->rx_prach); + } void init_prach_tables(int N_ZC) diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 16cc75b290..9297d91376 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -55,7 +55,7 @@ extern int mac_get_rrc_status(uint8_t Mod_id,uint8_t eNB_flag,uint8_t index); extern openair0_config_t openair0_cfg[]; #endif -int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t mode, int input_level_dBm) +int dump_ue_stats(PHY_VARS_UE *ue, char* buffer, int length, runmode_t mode, int input_level_dBm) { uint8_t eNB=0; @@ -63,493 +63,493 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t int len=length; int harq_pid,round; - if (phy_vars_ue==NULL) + if (ue==NULL) return 0; if ((mode == normal_txrx) || (mode == no_L2_connect)) { - len += sprintf(&buffer[len], "[UE_PROC] UE %d, RNTI %x\n",phy_vars_ue->Mod_id, phy_vars_ue->lte_ue_pdcch_vars[0]->crnti); + len += sprintf(&buffer[len], "[UE_PROC] UE %d, RNTI %x\n",ue->Mod_id, ue->pdcch_vars[0]->crnti); len += sprintf(&buffer[len],"[UE PROC] RSRP[0] %.2f dBm/RE, RSSI %.2f dBm, RSRQ[0] %.2f dB, N0 %d dBm/RE (NF %.1f dB)\n", - 10*log10(phy_vars_ue->PHY_measurements.rsrp[0])-phy_vars_ue->rx_total_gain_dB, - 10*log10(phy_vars_ue->PHY_measurements.rssi)-phy_vars_ue->rx_total_gain_dB, - 10*log10(phy_vars_ue->PHY_measurements.rsrq[0]), - phy_vars_ue->PHY_measurements.n0_power_tot_dBm, - (double)phy_vars_ue->PHY_measurements.n0_power_tot_dBm+132.24); + 10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB, + 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, + 10*log10(ue->measurements.rsrq[0]), + ue->measurements.n0_power_tot_dBm, + (double)ue->measurements.n0_power_tot_dBm+132.24); /* len += sprintf(&buffer[len], "[UE PROC] Frame count: %d\neNB0 RSSI %d dBm/RE (%d dB, %d dB)\neNB1 RSSI %d dBm/RE (%d dB, %d dB)neNB2 RSSI %d dBm/RE (%d dB, %d dB)\nN0 %d dBm/RE, %f dBm/%dPRB (%d dB, %d dB)\n", - phy_vars_ue->frame_rx, - phy_vars_ue->PHY_measurements.rx_rssi_dBm[0], - phy_vars_ue->PHY_measurements.rx_power_dB[0][0], - phy_vars_ue->PHY_measurements.rx_power_dB[0][1], - phy_vars_ue->PHY_measurements.rx_rssi_dBm[1], - phy_vars_ue->PHY_measurements.rx_power_dB[1][0], - phy_vars_ue->PHY_measurements.rx_power_dB[1][1], - phy_vars_ue->PHY_measurements.rx_rssi_dBm[2], - phy_vars_ue->PHY_measurements.rx_power_dB[2][0], - phy_vars_ue->PHY_measurements.rx_power_dB[2][1], - phy_vars_ue->PHY_measurements.n0_power_tot_dBm, - phy_vars_ue->PHY_measurements.n0_power_tot_dBm+10*log10(12*phy_vars_ue->lte_frame_parms.N_RB_DL), - phy_vars_ue->lte_frame_parms.N_RB_DL, - phy_vars_ue->PHY_measurements.n0_power_dB[0], - phy_vars_ue->PHY_measurements.n0_power_dB[1]); + ue->frame_rx, + ue->measurements.rx_rssi_dBm[0], + ue->measurements.rx_power_dB[0][0], + ue->measurements.rx_power_dB[0][1], + ue->measurements.rx_rssi_dBm[1], + ue->measurements.rx_power_dB[1][0], + ue->measurements.rx_power_dB[1][1], + ue->measurements.rx_rssi_dBm[2], + ue->measurements.rx_power_dB[2][0], + ue->measurements.rx_power_dB[2][1], + ue->measurements.n0_power_tot_dBm, + ue->measurements.n0_power_tot_dBm+10*log10(12*ue->frame_parms.N_RB_DL), + ue->frame_parms.N_RB_DL, + ue->measurements.n0_power_dB[0], + ue->measurements.n0_power_dB[1]); */ #ifdef EXMIMO - len += sprintf(&buffer[len], "[UE PROC] RX Gain %d dB (LNA %d, vga %d dB)\n",phy_vars_ue->rx_total_gain_dB, openair0_cfg[0].rxg_mode[0],(int)openair0_cfg[0].rx_gain[0]); + len += sprintf(&buffer[len], "[UE PROC] RX Gain %d dB (LNA %d, vga %d dB)\n",ue->rx_total_gain_dB, openair0_cfg[0].rxg_mode[0],(int)openair0_cfg[0].rx_gain[0]); #endif #if defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - len += sprintf(&buffer[len], "[UE PROC] RX Gain %d dB\n",phy_vars_ue->rx_total_gain_dB); + len += sprintf(&buffer[len], "[UE PROC] RX Gain %d dB\n",ue->rx_total_gain_dB); #endif #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - len += sprintf(&buffer[len], "[UE_PROC] Frequency offset %d Hz, estimated carrier frequency %f Hz\n",phy_vars_ue->lte_ue_common_vars.freq_offset,openair0_cfg[0].rx_freq[0]-phy_vars_ue->lte_ue_common_vars.freq_offset); + len += sprintf(&buffer[len], "[UE_PROC] Frequency offset %d Hz, estimated carrier frequency %f Hz\n",ue->common_vars.freq_offset,openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset); #endif - len += sprintf(&buffer[len], "[UE PROC] UE mode = %s (%d)\n",mode_string[phy_vars_ue->UE_mode[0]],phy_vars_ue->UE_mode[0]); - len += sprintf(&buffer[len], "[UE PROC] timing_advance = %d\n",phy_vars_ue->timing_advance); - if (phy_vars_ue->UE_mode[0]==PUSCH) { + len += sprintf(&buffer[len], "[UE PROC] UE mode = %s (%d)\n",mode_string[ue->UE_mode[0]],ue->UE_mode[0]); + len += sprintf(&buffer[len], "[UE PROC] timing_advance = %d\n",ue->timing_advance); + if (ue->UE_mode[0]==PUSCH) { len += sprintf(&buffer[len], "[UE PROC] Po_PUSCH = %d dBm (PL %d dB, Po_NOMINAL_PUSCH %d dBm, PHR %d dB)\n", - phy_vars_ue->ulsch_ue[0]->Po_PUSCH, - get_PL(phy_vars_ue->Mod_id,phy_vars_ue->CC_id,0), - phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUSCH, - phy_vars_ue->ulsch_ue[0]->PHR); + ue->ulsch[0]->Po_PUSCH, + get_PL(ue->Mod_id,ue->CC_id,0), + ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH, + ue->ulsch[0]->PHR); len += sprintf(&buffer[len], "[UE PROC] Po_PUCCH = %d dBm (Po_NOMINAL_PUCCH %d dBm, g_pucch %d dB)\n", - get_PL(phy_vars_ue->Mod_id,phy_vars_ue->CC_id,0)+ - phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH+ - phy_vars_ue->dlsch_ue[0][0]->g_pucch, - phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - phy_vars_ue->dlsch_ue[0][0]->g_pucch); + get_PL(ue->Mod_id,ue->CC_id,0)+ + ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+ + ue->dlsch[0][0]->g_pucch, + ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, + ue->dlsch[0][0]->g_pucch); } //for (eNB=0;eNBPHY_measurements.rx_spatial_power_dB[eNB][0][0], - phy_vars_ue->PHY_measurements.rx_spatial_power_dB[eNB][0][1], - phy_vars_ue->PHY_measurements.rx_spatial_power_dB[eNB][1][0], - phy_vars_ue->PHY_measurements.rx_spatial_power_dB[eNB][1][1]); + ue->measurements.rx_spatial_power_dB[eNB][0][0], + ue->measurements.rx_spatial_power_dB[eNB][0][1], + ue->measurements.rx_spatial_power_dB[eNB][1][0], + ue->measurements.rx_spatial_power_dB[eNB][1][1]); - len += sprintf(&buffer[len], "[UE PROC] RX total power eNB%d: %d dB, avg: %d dB\n",eNB,phy_vars_ue->PHY_measurements.rx_power_tot_dB[eNB],phy_vars_ue->PHY_measurements.rx_power_avg_dB[eNB]); - len += sprintf(&buffer[len], "[UE PROC] RX total power lin: %d, avg: %d, RX total noise lin: %d, avg: %d\n",phy_vars_ue->PHY_measurements.rx_power_tot[eNB], - phy_vars_ue->PHY_measurements.rx_power_avg[eNB], phy_vars_ue->PHY_measurements.n0_power_tot, phy_vars_ue->PHY_measurements.n0_power_avg); - len += sprintf(&buffer[len], "[UE PROC] effective SINR %.2f dB\n",phy_vars_ue->sinr_eff); - len += sprintf(&buffer[len], "[UE PROC] Wideband CQI eNB %d: %d dB, avg: %d dB\n",eNB,phy_vars_ue->PHY_measurements.wideband_cqi_tot[eNB],phy_vars_ue->PHY_measurements.wideband_cqi_avg[eNB]); + len += sprintf(&buffer[len], "[UE PROC] RX total power eNB%d: %d dB, avg: %d dB\n",eNB,ue->measurements.rx_power_tot_dB[eNB],ue->measurements.rx_power_avg_dB[eNB]); + len += sprintf(&buffer[len], "[UE PROC] RX total power lin: %d, avg: %d, RX total noise lin: %d, avg: %d\n",ue->measurements.rx_power_tot[eNB], + ue->measurements.rx_power_avg[eNB], ue->measurements.n0_power_tot, ue->measurements.n0_power_avg); + len += sprintf(&buffer[len], "[UE PROC] effective SINR %.2f dB\n",ue->sinr_eff); + len += sprintf(&buffer[len], "[UE PROC] Wideband CQI eNB %d: %d dB, avg: %d dB\n",eNB,ue->measurements.wideband_cqi_tot[eNB],ue->measurements.wideband_cqi_avg[eNB]); - switch (phy_vars_ue->lte_frame_parms.N_RB_DL) { + switch (ue->frame_parms.N_RB_DL) { case 6: len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 0): [%d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][5]); + ue->measurements.subband_cqi_dB[eNB][0][0], + ue->measurements.subband_cqi_dB[eNB][0][1], + ue->measurements.subband_cqi_dB[eNB][0][2], + ue->measurements.subband_cqi_dB[eNB][0][3], + ue->measurements.subband_cqi_dB[eNB][0][4], + ue->measurements.subband_cqi_dB[eNB][0][5]); len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 1): [%d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][5]); + ue->measurements.subband_cqi_dB[eNB][1][0], + ue->measurements.subband_cqi_dB[eNB][1][1], + ue->measurements.subband_cqi_dB[eNB][1][2], + ue->measurements.subband_cqi_dB[eNB][1][3], + ue->measurements.subband_cqi_dB[eNB][1][4], + ue->measurements.subband_cqi_dB[eNB][1][5]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 0): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][0]); + ue->measurements.subband_pmi_re[eNB][0][0], + ue->measurements.subband_pmi_im[eNB][0][0], + ue->measurements.subband_pmi_re[eNB][1][0], + ue->measurements.subband_pmi_im[eNB][1][0], + ue->measurements.subband_pmi_re[eNB][2][0], + ue->measurements.subband_pmi_im[eNB][2][0], + ue->measurements.subband_pmi_re[eNB][3][0], + ue->measurements.subband_pmi_im[eNB][3][0], + ue->measurements.subband_pmi_re[eNB][4][0], + ue->measurements.subband_pmi_im[eNB][4][0], + ue->measurements.subband_pmi_re[eNB][5][0], + ue->measurements.subband_pmi_im[eNB][5][0]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 1): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][1]); + ue->measurements.subband_pmi_re[eNB][0][1], + ue->measurements.subband_pmi_im[eNB][0][1], + ue->measurements.subband_pmi_re[eNB][1][1], + ue->measurements.subband_pmi_im[eNB][1][1], + ue->measurements.subband_pmi_re[eNB][2][1], + ue->measurements.subband_pmi_im[eNB][2][1], + ue->measurements.subband_pmi_re[eNB][3][1], + ue->measurements.subband_pmi_im[eNB][3][1], + ue->measurements.subband_pmi_re[eNB][4][1], + ue->measurements.subband_pmi_im[eNB][4][1], + ue->measurements.subband_pmi_re[eNB][5][1], + ue->measurements.subband_pmi_im[eNB][5][1]); len += sprintf(&buffer[len], "[UE PROC] PMI Antenna selection eNB%d : [%d %d %d %d %d %d]\n", eNB, - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][0], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][1], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][2], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][3], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][4], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][5]); + ue->measurements.selected_rx_antennas[eNB][0], + ue->measurements.selected_rx_antennas[eNB][1], + ue->measurements.selected_rx_antennas[eNB][2], + ue->measurements.selected_rx_antennas[eNB][3], + ue->measurements.selected_rx_antennas[eNB][4], + ue->measurements.selected_rx_antennas[eNB][5]); - len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&phy_vars_ue->PHY_measurements,eNB,6))); + len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&ue->measurements,eNB,6))); len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (both): %jx,%jx\n",eNB, - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,0,6)), - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,1,6))); + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,0,6)), + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,1,6))); break; case 25: len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 0): [%d %d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][5], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][6]); + ue->measurements.subband_cqi_dB[eNB][0][0], + ue->measurements.subband_cqi_dB[eNB][0][1], + ue->measurements.subband_cqi_dB[eNB][0][2], + ue->measurements.subband_cqi_dB[eNB][0][3], + ue->measurements.subband_cqi_dB[eNB][0][4], + ue->measurements.subband_cqi_dB[eNB][0][5], + ue->measurements.subband_cqi_dB[eNB][0][6]); len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 1): [%d %d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][5], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][6]); + ue->measurements.subband_cqi_dB[eNB][1][0], + ue->measurements.subband_cqi_dB[eNB][1][1], + ue->measurements.subband_cqi_dB[eNB][1][2], + ue->measurements.subband_cqi_dB[eNB][1][3], + ue->measurements.subband_cqi_dB[eNB][1][4], + ue->measurements.subband_cqi_dB[eNB][1][5], + ue->measurements.subband_cqi_dB[eNB][1][6]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 0): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][6][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][6][0]); + ue->measurements.subband_pmi_re[eNB][0][0], + ue->measurements.subband_pmi_im[eNB][0][0], + ue->measurements.subband_pmi_re[eNB][1][0], + ue->measurements.subband_pmi_im[eNB][1][0], + ue->measurements.subband_pmi_re[eNB][2][0], + ue->measurements.subband_pmi_im[eNB][2][0], + ue->measurements.subband_pmi_re[eNB][3][0], + ue->measurements.subband_pmi_im[eNB][3][0], + ue->measurements.subband_pmi_re[eNB][4][0], + ue->measurements.subband_pmi_im[eNB][4][0], + ue->measurements.subband_pmi_re[eNB][5][0], + ue->measurements.subband_pmi_im[eNB][5][0], + ue->measurements.subband_pmi_re[eNB][6][0], + ue->measurements.subband_pmi_im[eNB][6][0]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 1): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][6][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][6][1]); + ue->measurements.subband_pmi_re[eNB][0][1], + ue->measurements.subband_pmi_im[eNB][0][1], + ue->measurements.subband_pmi_re[eNB][1][1], + ue->measurements.subband_pmi_im[eNB][1][1], + ue->measurements.subband_pmi_re[eNB][2][1], + ue->measurements.subband_pmi_im[eNB][2][1], + ue->measurements.subband_pmi_re[eNB][3][1], + ue->measurements.subband_pmi_im[eNB][3][1], + ue->measurements.subband_pmi_re[eNB][4][1], + ue->measurements.subband_pmi_im[eNB][4][1], + ue->measurements.subband_pmi_re[eNB][5][1], + ue->measurements.subband_pmi_im[eNB][5][1], + ue->measurements.subband_pmi_re[eNB][6][1], + ue->measurements.subband_pmi_im[eNB][6][1]); len += sprintf(&buffer[len], "[UE PROC] PMI Antenna selection eNB%d : [%d %d %d %d %d %d %d]\n", eNB, - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][0], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][1], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][2], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][3], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][4], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][5], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][6]); + ue->measurements.selected_rx_antennas[eNB][0], + ue->measurements.selected_rx_antennas[eNB][1], + ue->measurements.selected_rx_antennas[eNB][2], + ue->measurements.selected_rx_antennas[eNB][3], + ue->measurements.selected_rx_antennas[eNB][4], + ue->measurements.selected_rx_antennas[eNB][5], + ue->measurements.selected_rx_antennas[eNB][6]); - len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&phy_vars_ue->PHY_measurements,eNB,7))); + len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&ue->measurements,eNB,7))); len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (both): %jx,%jx\n",eNB, - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,0,7)), - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,1,7))); + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,0,7)), + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,1,7))); break; case 50: len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 0): [%d %d %d %d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][5], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][6], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][7], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][8]); + ue->measurements.subband_cqi_dB[eNB][0][0], + ue->measurements.subband_cqi_dB[eNB][0][1], + ue->measurements.subband_cqi_dB[eNB][0][2], + ue->measurements.subband_cqi_dB[eNB][0][3], + ue->measurements.subband_cqi_dB[eNB][0][4], + ue->measurements.subband_cqi_dB[eNB][0][5], + ue->measurements.subband_cqi_dB[eNB][0][6], + ue->measurements.subband_cqi_dB[eNB][0][7], + ue->measurements.subband_cqi_dB[eNB][0][8]); len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 1): [%d %d %d %d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][5], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][6], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][7], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][8]); + ue->measurements.subband_cqi_dB[eNB][1][0], + ue->measurements.subband_cqi_dB[eNB][1][1], + ue->measurements.subband_cqi_dB[eNB][1][2], + ue->measurements.subband_cqi_dB[eNB][1][3], + ue->measurements.subband_cqi_dB[eNB][1][4], + ue->measurements.subband_cqi_dB[eNB][1][5], + ue->measurements.subband_cqi_dB[eNB][1][6], + ue->measurements.subband_cqi_dB[eNB][1][7], + ue->measurements.subband_cqi_dB[eNB][1][8]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 0): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][6][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][6][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][7][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][7][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][8][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][8][0]); + ue->measurements.subband_pmi_re[eNB][0][0], + ue->measurements.subband_pmi_im[eNB][0][0], + ue->measurements.subband_pmi_re[eNB][1][0], + ue->measurements.subband_pmi_im[eNB][1][0], + ue->measurements.subband_pmi_re[eNB][2][0], + ue->measurements.subband_pmi_im[eNB][2][0], + ue->measurements.subband_pmi_re[eNB][3][0], + ue->measurements.subband_pmi_im[eNB][3][0], + ue->measurements.subband_pmi_re[eNB][4][0], + ue->measurements.subband_pmi_im[eNB][4][0], + ue->measurements.subband_pmi_re[eNB][5][0], + ue->measurements.subband_pmi_im[eNB][5][0], + ue->measurements.subband_pmi_re[eNB][6][0], + ue->measurements.subband_pmi_im[eNB][6][0], + ue->measurements.subband_pmi_re[eNB][7][0], + ue->measurements.subband_pmi_im[eNB][7][0], + ue->measurements.subband_pmi_re[eNB][8][0], + ue->measurements.subband_pmi_im[eNB][8][0]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 1): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][6][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][6][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][7][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][7][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][8][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][8][1]); + ue->measurements.subband_pmi_re[eNB][0][1], + ue->measurements.subband_pmi_im[eNB][0][1], + ue->measurements.subband_pmi_re[eNB][1][1], + ue->measurements.subband_pmi_im[eNB][1][1], + ue->measurements.subband_pmi_re[eNB][2][1], + ue->measurements.subband_pmi_im[eNB][2][1], + ue->measurements.subband_pmi_re[eNB][3][1], + ue->measurements.subband_pmi_im[eNB][3][1], + ue->measurements.subband_pmi_re[eNB][4][1], + ue->measurements.subband_pmi_im[eNB][4][1], + ue->measurements.subband_pmi_re[eNB][5][1], + ue->measurements.subband_pmi_im[eNB][5][1], + ue->measurements.subband_pmi_re[eNB][6][1], + ue->measurements.subband_pmi_im[eNB][6][1], + ue->measurements.subband_pmi_re[eNB][7][1], + ue->measurements.subband_pmi_im[eNB][7][1], + ue->measurements.subband_pmi_re[eNB][8][1], + ue->measurements.subband_pmi_im[eNB][8][1]); len += sprintf(&buffer[len], "[UE PROC] PMI Antenna selection eNB%d : [%d %d %d %d %d %d %d %d %d]\n", eNB, - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][0], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][1], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][2], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][3], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][4], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][5], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][6], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][7], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][8]); + ue->measurements.selected_rx_antennas[eNB][0], + ue->measurements.selected_rx_antennas[eNB][1], + ue->measurements.selected_rx_antennas[eNB][2], + ue->measurements.selected_rx_antennas[eNB][3], + ue->measurements.selected_rx_antennas[eNB][4], + ue->measurements.selected_rx_antennas[eNB][5], + ue->measurements.selected_rx_antennas[eNB][6], + ue->measurements.selected_rx_antennas[eNB][7], + ue->measurements.selected_rx_antennas[eNB][8]); - len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&phy_vars_ue->PHY_measurements,eNB,9))); + len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&ue->measurements,eNB,9))); len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (both): %jx,%jx\n",eNB, - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,0,9)), - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,1,9))); + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,0,9)), + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,1,9))); break; case 100: len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 0): [%d %d %d %d %d %d %d %d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][5], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][6], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][7], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][8], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][9], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][10], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][11], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][0][12]); + ue->measurements.subband_cqi_dB[eNB][0][0], + ue->measurements.subband_cqi_dB[eNB][0][1], + ue->measurements.subband_cqi_dB[eNB][0][2], + ue->measurements.subband_cqi_dB[eNB][0][3], + ue->measurements.subband_cqi_dB[eNB][0][4], + ue->measurements.subband_cqi_dB[eNB][0][5], + ue->measurements.subband_cqi_dB[eNB][0][6], + ue->measurements.subband_cqi_dB[eNB][0][7], + ue->measurements.subband_cqi_dB[eNB][0][8], + ue->measurements.subband_cqi_dB[eNB][0][9], + ue->measurements.subband_cqi_dB[eNB][0][10], + ue->measurements.subband_cqi_dB[eNB][0][11], + ue->measurements.subband_cqi_dB[eNB][0][12]); len += sprintf(&buffer[len], "[UE PROC] Subband CQI eNB%d (Ant 1): [%d %d %d %d %d %d %d %d %d %d %d %d %d] dB\n", eNB, - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][2], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][3], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][4], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][5], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][6], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][7], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][8], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][9], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][10], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][11], - phy_vars_ue->PHY_measurements.subband_cqi_dB[eNB][1][12]); + ue->measurements.subband_cqi_dB[eNB][1][0], + ue->measurements.subband_cqi_dB[eNB][1][1], + ue->measurements.subband_cqi_dB[eNB][1][2], + ue->measurements.subband_cqi_dB[eNB][1][3], + ue->measurements.subband_cqi_dB[eNB][1][4], + ue->measurements.subband_cqi_dB[eNB][1][5], + ue->measurements.subband_cqi_dB[eNB][1][6], + ue->measurements.subband_cqi_dB[eNB][1][7], + ue->measurements.subband_cqi_dB[eNB][1][8], + ue->measurements.subband_cqi_dB[eNB][1][9], + ue->measurements.subband_cqi_dB[eNB][1][10], + ue->measurements.subband_cqi_dB[eNB][1][11], + ue->measurements.subband_cqi_dB[eNB][1][12]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 0): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][6][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][6][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][7][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][7][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][8][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][8][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][9][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][9][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][10][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][10][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][11][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][11][0], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][12][0], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][12][0]); + ue->measurements.subband_pmi_re[eNB][0][0], + ue->measurements.subband_pmi_im[eNB][0][0], + ue->measurements.subband_pmi_re[eNB][1][0], + ue->measurements.subband_pmi_im[eNB][1][0], + ue->measurements.subband_pmi_re[eNB][2][0], + ue->measurements.subband_pmi_im[eNB][2][0], + ue->measurements.subband_pmi_re[eNB][3][0], + ue->measurements.subband_pmi_im[eNB][3][0], + ue->measurements.subband_pmi_re[eNB][4][0], + ue->measurements.subband_pmi_im[eNB][4][0], + ue->measurements.subband_pmi_re[eNB][5][0], + ue->measurements.subband_pmi_im[eNB][5][0], + ue->measurements.subband_pmi_re[eNB][6][0], + ue->measurements.subband_pmi_im[eNB][6][0], + ue->measurements.subband_pmi_re[eNB][7][0], + ue->measurements.subband_pmi_im[eNB][7][0], + ue->measurements.subband_pmi_re[eNB][8][0], + ue->measurements.subband_pmi_im[eNB][8][0], + ue->measurements.subband_pmi_re[eNB][9][0], + ue->measurements.subband_pmi_im[eNB][9][0], + ue->measurements.subband_pmi_re[eNB][10][0], + ue->measurements.subband_pmi_im[eNB][10][0], + ue->measurements.subband_pmi_re[eNB][11][0], + ue->measurements.subband_pmi_im[eNB][11][0], + ue->measurements.subband_pmi_re[eNB][12][0], + ue->measurements.subband_pmi_im[eNB][12][0]); len += sprintf(&buffer[len], "[UE PROC] Subband PMI eNB%d (Ant 1): [(%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d) (%d %d)]\n", eNB, - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][0][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][1][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][2][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][3][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][4][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][5][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][5][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][6][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][6][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][7][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][7][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][8][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][8][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][9][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][9][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][10][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][10][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][11][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][11][1], - phy_vars_ue->PHY_measurements.subband_pmi_re[eNB][12][1], - phy_vars_ue->PHY_measurements.subband_pmi_im[eNB][12][1]); + ue->measurements.subband_pmi_re[eNB][0][1], + ue->measurements.subband_pmi_im[eNB][0][1], + ue->measurements.subband_pmi_re[eNB][1][1], + ue->measurements.subband_pmi_im[eNB][1][1], + ue->measurements.subband_pmi_re[eNB][2][1], + ue->measurements.subband_pmi_im[eNB][2][1], + ue->measurements.subband_pmi_re[eNB][3][1], + ue->measurements.subband_pmi_im[eNB][3][1], + ue->measurements.subband_pmi_re[eNB][4][1], + ue->measurements.subband_pmi_im[eNB][4][1], + ue->measurements.subband_pmi_re[eNB][5][1], + ue->measurements.subband_pmi_im[eNB][5][1], + ue->measurements.subband_pmi_re[eNB][6][1], + ue->measurements.subband_pmi_im[eNB][6][1], + ue->measurements.subband_pmi_re[eNB][7][1], + ue->measurements.subband_pmi_im[eNB][7][1], + ue->measurements.subband_pmi_re[eNB][8][1], + ue->measurements.subband_pmi_im[eNB][8][1], + ue->measurements.subband_pmi_re[eNB][9][1], + ue->measurements.subband_pmi_im[eNB][9][1], + ue->measurements.subband_pmi_re[eNB][10][1], + ue->measurements.subband_pmi_im[eNB][10][1], + ue->measurements.subband_pmi_re[eNB][11][1], + ue->measurements.subband_pmi_im[eNB][11][1], + ue->measurements.subband_pmi_re[eNB][12][1], + ue->measurements.subband_pmi_im[eNB][12][1]); len += sprintf(&buffer[len], "[UE PROC] PMI Antenna selection eNB%d : [%d %d %d %d %d %d %d %d %d %d %d %d %d]\n", eNB, - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][0], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][1], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][2], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][3], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][4], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][5], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][6], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][7], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][8], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][9], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][10], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][11], - phy_vars_ue->PHY_measurements.selected_rx_antennas[eNB][12]); + ue->measurements.selected_rx_antennas[eNB][0], + ue->measurements.selected_rx_antennas[eNB][1], + ue->measurements.selected_rx_antennas[eNB][2], + ue->measurements.selected_rx_antennas[eNB][3], + ue->measurements.selected_rx_antennas[eNB][4], + ue->measurements.selected_rx_antennas[eNB][5], + ue->measurements.selected_rx_antennas[eNB][6], + ue->measurements.selected_rx_antennas[eNB][7], + ue->measurements.selected_rx_antennas[eNB][8], + ue->measurements.selected_rx_antennas[eNB][9], + ue->measurements.selected_rx_antennas[eNB][10], + ue->measurements.selected_rx_antennas[eNB][11], + ue->measurements.selected_rx_antennas[eNB][12]); - len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&phy_vars_ue->PHY_measurements,eNB,13))); + len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (max): %jx\n",eNB,pmi2hex_2Ar1(quantize_subband_pmi(&ue->measurements,eNB,13))); len += sprintf(&buffer[len], "[UE PROC] Quantized PMI eNB %d (both): %jx,%jx\n",eNB, - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,0,13)), - pmi2hex_2Ar1(quantize_subband_pmi2(&phy_vars_ue->PHY_measurements,eNB,1,13))); + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,0,13)), + pmi2hex_2Ar1(quantize_subband_pmi2(&ue->measurements,eNB,1,13))); break; } #ifdef OPENAIR2 - RRC_status = mac_UE_get_rrc_status(phy_vars_ue->Mod_id, 0); + RRC_status = mac_UE_get_rrc_status(ue->Mod_id, 0); len += sprintf(&buffer[len],"[UE PROC] RRC status = %d\n",RRC_status); #endif - len += sprintf(&buffer[len], "[UE PROC] Transmission Mode %d (mode1_flag %d)\n",phy_vars_ue->transmission_mode[eNB],phy_vars_ue->lte_frame_parms.mode1_flag); + len += sprintf(&buffer[len], "[UE PROC] Transmission Mode %d (mode1_flag %d)\n",ue->transmission_mode[eNB],ue->frame_parms.mode1_flag); len += sprintf(&buffer[len], "[UE PROC] PBCH err conseq %d, PBCH error total %d, PBCH FER %d\n", - phy_vars_ue->lte_ue_pbch_vars[eNB]->pdu_errors_conseq, - phy_vars_ue->lte_ue_pbch_vars[eNB]->pdu_errors, - phy_vars_ue->lte_ue_pbch_vars[eNB]->pdu_fer); + ue->pbch_vars[eNB]->pdu_errors_conseq, + ue->pbch_vars[eNB]->pdu_errors, + ue->pbch_vars[eNB]->pdu_fer); - if (phy_vars_ue->transmission_mode[eNB] == 6) - len += sprintf(&buffer[len], "[UE PROC] Mode 6 Wideband CQI eNB %d : %d dB\n",eNB,phy_vars_ue->PHY_measurements.precoded_cqi_dB[eNB][0]); + if (ue->transmission_mode[eNB] == 6) + len += sprintf(&buffer[len], "[UE PROC] Mode 6 Wideband CQI eNB %d : %d dB\n",eNB,ue->measurements.precoded_cqi_dB[eNB][0]); for (harq_pid=0;harq_pid<8;harq_pid++) { - len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 0 harq_pid %d, mcs %d:",eNB,harq_pid,phy_vars_ue->dlsch_ue[0][0]->harq_processes[harq_pid]->mcs); + len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 0 harq_pid %d, mcs %d:",eNB,harq_pid,ue->dlsch[0][0]->harq_processes[harq_pid]->mcs); for (round=0;round<8;round++) len+=sprintf(&buffer[len],"%d/%d ", - phy_vars_ue->dlsch_ue[0][0]->harq_processes[harq_pid]->errors[round], - phy_vars_ue->dlsch_ue[0][0]->harq_processes[harq_pid]->trials[round]); + ue->dlsch[0][0]->harq_processes[harq_pid]->errors[round], + ue->dlsch[0][0]->harq_processes[harq_pid]->trials[round]); len+=sprintf(&buffer[len],"\n"); } - if (phy_vars_ue->dlsch_ue[0] && phy_vars_ue->dlsch_ue[0][0] && phy_vars_ue->dlsch_ue[0][1]) { - len += sprintf(&buffer[len], "[UE PROC] Saved PMI for DLSCH eNB %d : %jx (%p)\n",eNB,pmi2hex_2Ar1(phy_vars_ue->dlsch_ue[0][0]->pmi_alloc),phy_vars_ue->dlsch_ue[0][0]); + if (ue->dlsch[0] && ue->dlsch[0][0] && ue->dlsch[0][1]) { + len += sprintf(&buffer[len], "[UE PROC] Saved PMI for DLSCH eNB %d : %jx (%p)\n",eNB,pmi2hex_2Ar1(ue->dlsch[0][0]->pmi_alloc),ue->dlsch[0][0]); - len += sprintf(&buffer[len], "[UE PROC] eNB %d: dl_power_off = %d\n",eNB,phy_vars_ue->dlsch_ue[0][0]->harq_processes[0]->dl_power_off); + len += sprintf(&buffer[len], "[UE PROC] eNB %d: dl_power_off = %d\n",eNB,ue->dlsch[0][0]->harq_processes[0]->dl_power_off); for (harq_pid=0;harq_pid<8;harq_pid++) { - len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 1 harq_pid %d, mcs %d:",eNB,harq_pid,phy_vars_ue->dlsch_ue[0][1]->harq_processes[0]->mcs); + len+=sprintf(&buffer[len],"[UE PROC] eNB %d: CW 1 harq_pid %d, mcs %d:",eNB,harq_pid,ue->dlsch[0][1]->harq_processes[0]->mcs); for (round=0;round<8;round++) len+=sprintf(&buffer[len],"%d/%d ", - phy_vars_ue->dlsch_ue[0][1]->harq_processes[harq_pid]->errors[round], - phy_vars_ue->dlsch_ue[0][1]->harq_processes[harq_pid]->trials[round]); + ue->dlsch[0][1]->harq_processes[harq_pid]->errors[round], + ue->dlsch[0][1]->harq_processes[harq_pid]->trials[round]); len+=sprintf(&buffer[len],"\n"); } } - len += sprintf(&buffer[len], "[UE PROC] DLSCH Total %d, Error %d, FER %d\n",phy_vars_ue->dlsch_received[0],phy_vars_ue->dlsch_errors[0],phy_vars_ue->dlsch_fer[0]); - len += sprintf(&buffer[len], "[UE PROC] DLSCH (SI) Total %d, Error %d\n",phy_vars_ue->dlsch_SI_received[0],phy_vars_ue->dlsch_SI_errors[0]); - len += sprintf(&buffer[len], "[UE PROC] DLSCH (RA) Total %d, Error %d\n",phy_vars_ue->dlsch_ra_received[0],phy_vars_ue->dlsch_ra_errors[0]); + len += sprintf(&buffer[len], "[UE PROC] DLSCH Total %d, Error %d, FER %d\n",ue->dlsch_received[0],ue->dlsch_errors[0],ue->dlsch_fer[0]); + len += sprintf(&buffer[len], "[UE PROC] DLSCH (SI) Total %d, Error %d\n",ue->dlsch_SI_received[0],ue->dlsch_SI_errors[0]); + len += sprintf(&buffer[len], "[UE PROC] DLSCH (RA) Total %d, Error %d\n",ue->dlsch_ra_received[0],ue->dlsch_ra_errors[0]); #ifdef Rel10 int i=0; - //len += sprintf(&buffer[len], "[UE PROC] MCH Total %d\n", phy_vars_ue->dlsch_mch_received[0]); - for(i=0; i lte_frame_parms.num_MBSFN_config; i++ ) { + //len += sprintf(&buffer[len], "[UE PROC] MCH Total %d\n", ue->dlsch_mch_received[0]); + for(i=0; i frame_parms.num_MBSFN_config; i++ ) { len += sprintf(&buffer[len], "[UE PROC] MCH (MCCH MBSFN %d) Total %d, Error %d, Trials %d\n", - i, phy_vars_ue->dlsch_mcch_received[i][0],phy_vars_ue->dlsch_mcch_errors[i][0],phy_vars_ue->dlsch_mcch_trials[i][0]); + i, ue->dlsch_mcch_received[i][0],ue->dlsch_mcch_errors[i][0],ue->dlsch_mcch_trials[i][0]); len += sprintf(&buffer[len], "[UE PROC] MCH (MTCH MBSFN %d) Total %d, Error %d, Trials %d\n", - i, phy_vars_ue->dlsch_mtch_received[i][0],phy_vars_ue->dlsch_mtch_errors[i][0],phy_vars_ue->dlsch_mtch_trials[i][0]); + i, ue->dlsch_mtch_received[i][0],ue->dlsch_mtch_errors[i][0],ue->dlsch_mtch_trials[i][0]); } #endif - len += sprintf(&buffer[len], "[UE PROC] DLSCH Bitrate %dkbps\n",(phy_vars_ue->bitrate[0]/1000)); - len += sprintf(&buffer[len], "[UE PROC] Total Received Bits %dkbits\n",(phy_vars_ue->total_received_bits[0]/1000)); - len += sprintf(&buffer[len], "[UE PROC] IA receiver %d\n",phy_vars_ue->use_ia_receiver); + len += sprintf(&buffer[len], "[UE PROC] DLSCH Bitrate %dkbps\n",(ue->bitrate[0]/1000)); + len += sprintf(&buffer[len], "[UE PROC] Total Received Bits %dkbits\n",(ue->total_received_bits[0]/1000)); + len += sprintf(&buffer[len], "[UE PROC] IA receiver %d\n",ue->use_ia_receiver); } } else { len += sprintf(&buffer[len], "[UE PROC] Frame count: %d, RSSI %3.2f dB (%d dB, %d dB), N0 %3.2f dB (%d dB, %d dB)\n", - phy_vars_ue->frame_rx, - 10*log10(phy_vars_ue->PHY_measurements.rssi), - phy_vars_ue->PHY_measurements.rx_power_dB[0][0], - phy_vars_ue->PHY_measurements.rx_power_dB[0][1], - 10*log10(phy_vars_ue->PHY_measurements.n0_power_tot), - phy_vars_ue->PHY_measurements.n0_power_dB[0], - phy_vars_ue->PHY_measurements.n0_power_dB[1]); + ue->frame_rx, + 10*log10(ue->measurements.rssi), + ue->measurements.rx_power_dB[0][0], + ue->measurements.rx_power_dB[0][1], + 10*log10(ue->measurements.n0_power_tot), + ue->measurements.n0_power_dB[0], + ue->measurements.n0_power_dB[1]); #ifdef EXMIMO - phy_vars_ue->rx_total_gain_dB = ((int)(10*log10(phy_vars_ue->PHY_measurements.rssi)))-input_level_dBm; + ue->rx_total_gain_dB = ((int)(10*log10(ue->measurements.rssi)))-input_level_dBm; len += sprintf(&buffer[len], "[UE PROC] rxg_mode %d, input level (set by user) %d dBm, VGA gain %d dB ==> total gain %3.2f dB, noise figure %3.2f dB\n", openair0_cfg[0].rxg_mode[0], input_level_dBm, (int)openair0_cfg[0].rx_gain[0], - 10*log10(phy_vars_ue->PHY_measurements.rssi)-input_level_dBm, - 10*log10(phy_vars_ue->PHY_measurements.n0_power_tot)-phy_vars_ue->rx_total_gain_dB+105); + 10*log10(ue->measurements.rssi)-input_level_dBm, + 10*log10(ue->measurements.n0_power_tot)-ue->rx_total_gain_dB+105); #endif } @@ -559,137 +559,137 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t } // is_clusterhead -int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) +int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length) { unsigned int success=0; - uint8_t eNB,UE_id,i,j,number_of_cards_l=1; + uint8_t eNB_id,UE_id,i,j,number_of_cards_l=1; uint32_t ulsch_errors=0,dlsch_errors=0; uint32_t ulsch_round_attempts[4]= {0,0,0,0},ulsch_round_errors[4]= {0,0,0,0}; uint32_t dlsch_round_attempts[4]= {0,0,0,0},dlsch_round_errors[4]= {0,0,0,0}; uint32_t UE_id_mac, RRC_status; - if (phy_vars_eNB==NULL) + if (eNB==NULL) return 0; int len = length; - // if(phy_vars_eNB->frame==0){ - phy_vars_eNB->total_dlsch_bitrate = 0;//phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_bitrate + phy_vars_eNB->total_dlsch_bitrate; - phy_vars_eNB->total_transmitted_bits = 0;// phy_vars_eNB->eNB_UE_stats[UE_id].total_transmitted_bits + phy_vars_eNB->total_transmitted_bits; - phy_vars_eNB->total_system_throughput = 0;//phy_vars_eNB->eNB_UE_stats[UE_id].total_transmitted_bits + phy_vars_eNB->total_system_throughput; + // if(eNB->frame==0){ + eNB->total_dlsch_bitrate = 0;//eNB->UE_stats[UE_id].dlsch_bitrate + eNB->total_dlsch_bitrate; + eNB->total_transmitted_bits = 0;// eNB->UE_stats[UE_id].total_transmitted_bits + eNB->total_transmitted_bits; + eNB->total_system_throughput = 0;//eNB->UE_stats[UE_id].total_transmitted_bits + eNB->total_system_throughput; // } - for (eNB=0; eNBproc[0].frame_tx, - phy_vars_eNB->rx_total_gain_eNB_dB, - phy_vars_eNB->PHY_measurements_eNB[eNB].n0_power_tot_dBm, - phy_vars_eNB->PHY_measurements_eNB[eNB].n0_power_dB[0], - phy_vars_eNB->PHY_measurements_eNB[eNB].n0_power_dB[1]); + eNB_id,number_of_cards_l, + eNB->proc[0].frame_tx, + eNB->rx_total_gain_dB, + eNB->measurements[eNB_id].n0_power_tot_dBm, + eNB->measurements[eNB_id].n0_power_dB[0], + eNB->measurements[eNB_id].n0_power_dB[1]); len += sprintf(&buffer[len],"PRB I0 (%X.%X.%X.%X): ", - phy_vars_eNB->rb_mask_ul[0], - phy_vars_eNB->rb_mask_ul[1],phy_vars_eNB->rb_mask_ul[2],phy_vars_eNB->rb_mask_ul[3]); + eNB->rb_mask_ul[0], + eNB->rb_mask_ul[1],eNB->rb_mask_ul[2],eNB->rb_mask_ul[3]); - for (i=0; ilte_frame_parms.N_RB_UL; i++) { + for (i=0; iframe_parms.N_RB_UL; i++) { len += sprintf(&buffer[len],"%4d ", - phy_vars_eNB->PHY_measurements_eNB[eNB].n0_subband_power_tot_dBm[i]); + eNB->measurements[eNB_id].n0_subband_power_tot_dBm[i]); if ((i>0) && ((i%25) == 0)) len += sprintf(&buffer[len],"\n"); } len += sprintf(&buffer[len],"\n"); len += sprintf(&buffer[len],"\nPERFORMANCE PARAMETERS\n"); /* - len += sprintf(&buffer[len],"[eNB PROC] Total DLSCH Bitrate for the System %dkbps\n",((phy_vars_eNB->eNB_UE_stats[0].dlsch_bitrate + phy_vars_eNB->eNB_UE_stats[1].dlsch_bitrate)/1000)); - len += sprintf(&buffer[len],"[eNB PROC] Total Bits successfully transitted %dKbits in %dframe(s)\n",((phy_vars_eNB->eNB_UE_stats[0].total_transmitted_bits + phy_vars_eNB->eNB_UE_stats[1].total_transmitted_bits)/1000),phy_vars_eNB->frame+1); - len += sprintf(&buffer[len],"[eNB PROC] Average System Throughput %dKbps\n",(phy_vars_eNB->eNB_UE_stats[0].total_transmitted_bits + phy_vars_eNB->eNB_UE_stats[1].total_transmitted_bits)/((phy_vars_eNB->frame+1)*10)); + len += sprintf(&buffer[len],"[eNB PROC] Total DLSCH Bitrate for the System %dkbps\n",((eNB->UE_stats[0].dlsch_bitrate + eNB->UE_stats[1].dlsch_bitrate)/1000)); + len += sprintf(&buffer[len],"[eNB PROC] Total Bits successfully transitted %dKbits in %dframe(s)\n",((eNB->UE_stats[0].total_transmitted_bits + eNB->UE_stats[1].total_transmitted_bits)/1000),eNB->frame+1); + len += sprintf(&buffer[len],"[eNB PROC] Average System Throughput %dKbps\n",(eNB->UE_stats[0].total_transmitted_bits + eNB->UE_stats[1].total_transmitted_bits)/((eNB->frame+1)*10)); */ for (UE_id=0; UE_iddlsch_eNB[(uint8_t)UE_id][0]->rnti>0)&& - (phy_vars_eNB->eNB_UE_stats[UE_id].mode == PUSCH)) { + if ((eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&& + (eNB->UE_stats[UE_id].mode == PUSCH)) { - phy_vars_eNB->total_dlsch_bitrate = phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_bitrate + phy_vars_eNB->total_dlsch_bitrate; - phy_vars_eNB->total_transmitted_bits = phy_vars_eNB->eNB_UE_stats[UE_id].total_TBS + phy_vars_eNB->total_transmitted_bits; + eNB->total_dlsch_bitrate = eNB->UE_stats[UE_id].dlsch_bitrate + eNB->total_dlsch_bitrate; + eNB->total_transmitted_bits = eNB->UE_stats[UE_id].total_TBS + eNB->total_transmitted_bits; - //phy_vars_eNB->total_system_throughput = phy_vars_eNB->eNB_UE_stats[UE_id].total_transmitted_bits + phy_vars_eNB->total_system_throughput; + //eNB->total_system_throughput = eNB->UE_stats[UE_id].total_transmitted_bits + eNB->total_system_throughput; for (i=0; i<8; i++) - success = success + (phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_trials[i][0] - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_l2_errors[i]); + success = success + (eNB->UE_stats[UE_id].dlsch_trials[i][0] - eNB->UE_stats[UE_id].dlsch_l2_errors[i]); - len += sprintf(&buffer[len],"Total DLSCH %d kbits / %d frames ",(phy_vars_eNB->total_transmitted_bits/1000),phy_vars_eNB->proc[0].frame_tx+1); - len += sprintf(&buffer[len],"Total DLSCH throughput %d kbps ",(phy_vars_eNB->total_dlsch_bitrate/1000)); - len += sprintf(&buffer[len],"Total DLSCH trans %d / %d frames\n",success,phy_vars_eNB->proc[0].frame_tx+1); - //len += sprintf(&buffer[len],"[eNB PROC] FULL MU-MIMO Transmissions/Total Transmissions = %d/%d\n",phy_vars_eNB->FULL_MUMIMO_transmissions,phy_vars_eNB->check_for_total_transmissions); - //len += sprintf(&buffer[len],"[eNB PROC] MU-MIMO Transmissions/Total Transmissions = %d/%d\n",phy_vars_eNB->check_for_MUMIMO_transmissions,phy_vars_eNB->check_for_total_transmissions); - //len += sprintf(&buffer[len],"[eNB PROC] SU-MIMO Transmissions/Total Transmissions = %d/%d\n",phy_vars_eNB->check_for_SUMIMO_transmissions,phy_vars_eNB->check_for_total_transmissions); + len += sprintf(&buffer[len],"Total DLSCH %d kbits / %d frames ",(eNB->total_transmitted_bits/1000),eNB->proc[0].frame_tx+1); + len += sprintf(&buffer[len],"Total DLSCH throughput %d kbps ",(eNB->total_dlsch_bitrate/1000)); + len += sprintf(&buffer[len],"Total DLSCH trans %d / %d frames\n",success,eNB->proc[0].frame_tx+1); + //len += sprintf(&buffer[len],"[eNB PROC] FULL MU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->FULL_MUMIMO_transmissions,eNB->check_for_total_transmissions); + //len += sprintf(&buffer[len],"[eNB PROC] MU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->check_for_MUMIMO_transmissions,eNB->check_for_total_transmissions); + //len += sprintf(&buffer[len],"[eNB PROC] SU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->check_for_SUMIMO_transmissions,eNB->check_for_total_transmissions); len += sprintf(&buffer[len],"UE %d (%x) Power: (%d,%d) dB, Po_PUSCH: (%d,%d) dBm, Po_PUCCH (%d/%d) dBm, Po_PUCCH1 (%d,%d) dBm, PUCCH1 Thres %d dBm \n", UE_id, - phy_vars_eNB->eNB_UE_stats[UE_id].crnti, - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[UE_id]->ulsch_power[0]), - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[UE_id]->ulsch_power[1]), - phy_vars_eNB->eNB_UE_stats[UE_id].UL_rssi[0], - phy_vars_eNB->eNB_UE_stats[UE_id].UL_rssi[1], - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, - phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, - PUCCH1_THRES+phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm-dB_fixed(phy_vars_eNB->lte_frame_parms.N_RB_UL)); + eNB->UE_stats[UE_id].crnti, + dB_fixed(eNB->pusch_vars[UE_id]->ulsch_power[0]), + dB_fixed(eNB->pusch_vars[UE_id]->ulsch_power[1]), + eNB->UE_stats[UE_id].UL_rssi[0], + eNB->UE_stats[UE_id].UL_rssi[1], + dB_fixed(eNB->UE_stats[UE_id].Po_PUCCH/eNB->frame_parms.N_RB_UL)-eNB->rx_total_gain_dB, + eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, + dB_fixed(eNB->UE_stats[UE_id].Po_PUCCH1_below/eNB->frame_parms.N_RB_UL)-eNB->rx_total_gain_dB, + dB_fixed(eNB->UE_stats[UE_id].Po_PUCCH1_above/eNB->frame_parms.N_RB_UL)-eNB->rx_total_gain_dB, + PUCCH1_THRES+eNB->measurements[0].n0_power_tot_dBm-dB_fixed(eNB->frame_parms.N_RB_UL)); len+= sprintf(&buffer[len],"DL mcs %d, UL mcs %d, UL rb %d, delta_TF %d, ", - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[0]->mcs, - phy_vars_eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[0]->mcs, - phy_vars_eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[0]->nb_rb, - phy_vars_eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[0]->delta_TF); + eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[0]->mcs, + eNB->ulsch[(uint8_t)UE_id]->harq_processes[0]->mcs, + eNB->ulsch[(uint8_t)UE_id]->harq_processes[0]->nb_rb, + eNB->ulsch[(uint8_t)UE_id]->harq_processes[0]->delta_TF); len += sprintf(&buffer[len],"Wideband CQI: (%d,%d) dB\n", - phy_vars_eNB->PHY_measurements_eNB[eNB].wideband_cqi_dB[UE_id][0], - phy_vars_eNB->PHY_measurements_eNB[eNB].wideband_cqi_dB[UE_id][1]); + eNB->measurements[eNB_id].wideband_cqi_dB[UE_id][0], + eNB->measurements[eNB_id].wideband_cqi_dB[UE_id][1]); /* len += sprintf(&buffer[len],"[eNB PROC] Subband CQI: "); - for (i=0; ilte_frame_parms.N_RB_DL; i++) + for (i=0; iframe_parms.N_RB_DL; i++) len += sprintf(&buffer[len],"%2d ", - phy_vars_eNB->PHY_measurements_eNB[eNB].subband_cqi_tot_dB[UE_id][i]); + eNB->measurements[eNB_id].subband_cqi_tot_dB[UE_id][i]); len += sprintf(&buffer[len],"\n"); */ len += sprintf(&buffer[len],"DL TM %d, DL_cqi %d, DL_pmi_single %jx ", - phy_vars_eNB->transmission_mode[UE_id], - phy_vars_eNB->eNB_UE_stats[UE_id].DL_cqi[0], - pmi2hex_2Ar1(phy_vars_eNB->eNB_UE_stats[UE_id].DL_pmi_single)); + eNB->transmission_mode[UE_id], + eNB->UE_stats[UE_id].DL_cqi[0], + pmi2hex_2Ar1(eNB->UE_stats[UE_id].DL_pmi_single)); len += sprintf(&buffer[len],"Timing advance %d samples (%d 16Ts), update %d ", - phy_vars_eNB->eNB_UE_stats[UE_id].UE_timing_offset, - phy_vars_eNB->eNB_UE_stats[UE_id].UE_timing_offset>>2, - phy_vars_eNB->eNB_UE_stats[UE_id].timing_advance_update); + eNB->UE_stats[UE_id].UE_timing_offset, + eNB->UE_stats[UE_id].UE_timing_offset>>2, + eNB->UE_stats[UE_id].timing_advance_update); len += sprintf(&buffer[len],"Mode = %s(%d) ", - mode_string[phy_vars_eNB->eNB_UE_stats[UE_id].mode], - phy_vars_eNB->eNB_UE_stats[UE_id].mode); - UE_id_mac = find_UE_id(phy_vars_eNB->Mod_id,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti); + mode_string[eNB->UE_stats[UE_id].mode], + eNB->UE_stats[UE_id].mode); + UE_id_mac = find_UE_id(eNB->Mod_id,eNB->dlsch[(uint8_t)UE_id][0]->rnti); if (UE_id_mac != -1) { - RRC_status = mac_eNB_get_rrc_status(phy_vars_eNB->Mod_id,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti); + RRC_status = mac_eNB_get_rrc_status(eNB->Mod_id,eNB->dlsch[(uint8_t)UE_id][0]->rnti); len += sprintf(&buffer[len],"UE_id_mac = %d, RRC status = %d\n",UE_id_mac,RRC_status); } else len += sprintf(&buffer[len],"UE_id_mac = -1\n"); len += sprintf(&buffer[len],"SR received/total: %d/%d (diff %d)\n", - phy_vars_eNB->eNB_UE_stats[UE_id].sr_received, - phy_vars_eNB->eNB_UE_stats[UE_id].sr_total, - phy_vars_eNB->eNB_UE_stats[UE_id].sr_total-phy_vars_eNB->eNB_UE_stats[UE_id].sr_received); + eNB->UE_stats[UE_id].sr_received, + eNB->UE_stats[UE_id].sr_total, + eNB->UE_stats[UE_id].sr_total-eNB->UE_stats[UE_id].sr_received); len += sprintf(&buffer[len],"DL Subband CQI: "); int nb_sb; - switch (phy_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: nb_sb=0; break; @@ -713,7 +713,7 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) } for (i=0; ieNB_UE_stats[UE_id].DL_subband_cqi[0][i]); + eNB->UE_stats[UE_id].DL_subband_cqi[0][i]); len += sprintf(&buffer[len],"\n"); @@ -730,25 +730,25 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) for (i=0; i<8; i++) { len += sprintf(&buffer[len]," harq %d: %d/%d (fer %d) (%d/%d, %d/%d, %d/%d, %d/%d) ", i, - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_errors[i], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_decoding_attempts[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_round_fer[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_round_errors[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_decoding_attempts[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_round_errors[i][1], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_decoding_attempts[i][1], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_round_errors[i][2], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_decoding_attempts[i][2], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_round_errors[i][3], - phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_decoding_attempts[i][3]); + eNB->UE_stats[UE_id].ulsch_errors[i], + eNB->UE_stats[UE_id].ulsch_decoding_attempts[i][0], + eNB->UE_stats[UE_id].ulsch_round_fer[i][0], + eNB->UE_stats[UE_id].ulsch_round_errors[i][0], + eNB->UE_stats[UE_id].ulsch_decoding_attempts[i][0], + eNB->UE_stats[UE_id].ulsch_round_errors[i][1], + eNB->UE_stats[UE_id].ulsch_decoding_attempts[i][1], + eNB->UE_stats[UE_id].ulsch_round_errors[i][2], + eNB->UE_stats[UE_id].ulsch_decoding_attempts[i][2], + eNB->UE_stats[UE_id].ulsch_round_errors[i][3], + eNB->UE_stats[UE_id].ulsch_decoding_attempts[i][3]); if ((i&1) == 1) len += sprintf(&buffer[len],"\n"); - ulsch_errors+=phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_errors[i]; + ulsch_errors+=eNB->UE_stats[UE_id].ulsch_errors[i]; for (j=0; j<4; j++) { - ulsch_round_attempts[j]+=phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_decoding_attempts[i][j]; - ulsch_round_errors[j]+=phy_vars_eNB->eNB_UE_stats[UE_id].ulsch_round_errors[i][j]; + ulsch_round_attempts[j]+=eNB->UE_stats[UE_id].ulsch_decoding_attempts[i][j]; + ulsch_round_errors[j]+=eNB->UE_stats[UE_id].ulsch_round_errors[i][j]; } } @@ -772,29 +772,29 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) for (i=0; i<8; i++) { len += sprintf(&buffer[len]," harq %d: %d/%d (%d/%d/%d, %d/%d/%d, %d/%d/%d, %d/%d/%d) ", i, - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_l2_errors[i], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_trials[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_ACK[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_NAK[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_trials[i][0], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_ACK[i][1], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_NAK[i][1], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_trials[i][1], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_ACK[i][2], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_NAK[i][2], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_trials[i][2], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_ACK[i][3], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_NAK[i][3], - phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_trials[i][3]); + eNB->UE_stats[UE_id].dlsch_l2_errors[i], + eNB->UE_stats[UE_id].dlsch_trials[i][0], + eNB->UE_stats[UE_id].dlsch_ACK[i][0], + eNB->UE_stats[UE_id].dlsch_NAK[i][0], + eNB->UE_stats[UE_id].dlsch_trials[i][0], + eNB->UE_stats[UE_id].dlsch_ACK[i][1], + eNB->UE_stats[UE_id].dlsch_NAK[i][1], + eNB->UE_stats[UE_id].dlsch_trials[i][1], + eNB->UE_stats[UE_id].dlsch_ACK[i][2], + eNB->UE_stats[UE_id].dlsch_NAK[i][2], + eNB->UE_stats[UE_id].dlsch_trials[i][2], + eNB->UE_stats[UE_id].dlsch_ACK[i][3], + eNB->UE_stats[UE_id].dlsch_NAK[i][3], + eNB->UE_stats[UE_id].dlsch_trials[i][3]); if ((i&1) == 1) len += sprintf(&buffer[len],"\n"); - dlsch_errors+=phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_l2_errors[i]; + dlsch_errors+=eNB->UE_stats[UE_id].dlsch_l2_errors[i]; for (j=0; j<4; j++) { - dlsch_round_attempts[j]+=phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_trials[i][j]; - dlsch_round_errors[j]+=phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_NAK[i][j]; + dlsch_round_attempts[j]+=eNB->UE_stats[UE_id].dlsch_trials[i][j]; + dlsch_round_errors[j]+=eNB->UE_stats[UE_id].dlsch_NAK[i][j]; } } @@ -806,15 +806,15 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) dlsch_round_errors[3],dlsch_round_attempts[3]); - len += sprintf(&buffer[len],"DLSCH total bits from MAC: %dkbit ",(phy_vars_eNB->eNB_UE_stats[UE_id].total_TBS_MAC)/1000); - len += sprintf(&buffer[len],"DLSCH total bits ack'ed: %dkbit ",(phy_vars_eNB->eNB_UE_stats[UE_id].total_TBS)/1000); - len += sprintf(&buffer[len],"DLSCH Average throughput (100 frames): %dkbps\n",(phy_vars_eNB->eNB_UE_stats[UE_id].dlsch_bitrate/1000)); - // len += sprintf(&buffer[len],"[eNB PROC] Transmission Mode %d\n",phy_vars_eNB->transmission_mode[UE_id]); + len += sprintf(&buffer[len],"DLSCH total bits from MAC: %dkbit ",(eNB->UE_stats[UE_id].total_TBS_MAC)/1000); + len += sprintf(&buffer[len],"DLSCH total bits ack'ed: %dkbit ",(eNB->UE_stats[UE_id].total_TBS)/1000); + len += sprintf(&buffer[len],"DLSCH Average throughput (100 frames): %dkbps\n",(eNB->UE_stats[UE_id].dlsch_bitrate/1000)); + // len += sprintf(&buffer[len],"[eNB PROC] Transmission Mode %d\n",eNB->transmission_mode[UE_id]); /* - if(phy_vars_eNB->transmission_mode[UE_id] == 5) { - if(phy_vars_eNB->mu_mimo_mode[UE_id].dl_pow_off == 0) + if(eNB->transmission_mode[UE_id] == 5) { + if(eNB->mu_mimo_mode[UE_id].dl_pow_off == 0) len += sprintf(&buffer[len],"[eNB PROC] ****UE %d is in MU-MIMO mode****\n",UE_id); - else if(phy_vars_eNB->mu_mimo_mode[UE_id].dl_pow_off == 1) + else if(eNB->mu_mimo_mode[UE_id].dl_pow_off == 1) len += sprintf(&buffer[len],"[eNB PROC] ****UE %d is in SU-MIMO mode****\n",UE_id); else len += sprintf(&buffer[len],"[eNB PROC] ****UE %d is not scheduled****\n",UE_id); @@ -823,13 +823,13 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) /* len += sprintf(&buffer[len],"[eNB PROC] RB Allocation on Sub-bands: "); - // for (j=0;j< mac_xface->lte_frame_parms->N_RBGS;j++) + // for (j=0;j< mac_xface->frame_parms->N_RBGS;j++) for (j=0; j<7; j++) len += sprintf(&buffer[len],"%d ", - phy_vars_eNB->mu_mimo_mode[UE_id].rballoc_sub[j]); + eNB->mu_mimo_mode[UE_id].rballoc_sub[j]); len += sprintf(&buffer[len],"\n"); - len += sprintf(&buffer[len],"[eNB PROC] Total Number of Allocated PRBs = %d\n",phy_vars_eNB->mu_mimo_mode[UE_id].pre_nb_available_rbs); + len += sprintf(&buffer[len],"[eNB PROC] Total Number of Allocated PRBs = %d\n",eNB->mu_mimo_mode[UE_id].pre_nb_available_rbs); */ } } diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index e723eb67a4..75ebcdfbfe 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -400,7 +400,7 @@ void generate_pucch(int32_t **txdataF, } -void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, +void generate_pucch_emul(PHY_VARS_UE *ue, PUCCH_FMT_t format, uint8_t ncs1, uint8_t *pucch_payload, @@ -408,32 +408,32 @@ void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, uint8_t subframe) { - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pucch_flag = format; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pucch_Ncs1 = ncs1; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_flag = format; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_Ncs1 = ncs1; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.sr = sr; - // the value of phy_vars_ue->pucch_sel[subframe] is set by get_n1_pucch - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pucch_sel = phy_vars_ue->pucch_sel[subframe]; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.sr = sr; + // the value of ue->pucch_sel[subframe] is set by get_n1_pucch + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_sel = ue->pucch_sel[subframe]; - // LOG_I(PHY,"subframe %d emu tx pucch_sel is %d sr is %d \n", subframe, UE_transport_info[phy_vars_ue->Mod_id].cntl.pucch_sel, sr); + // LOG_I(PHY,"subframe %d emu tx pucch_sel is %d sr is %d \n", subframe, UE_transport_info[ue->Mod_id].cntl.pucch_sel, sr); if (format == pucch_format1a) { - phy_vars_ue->pucch_payload[0] = pucch_payload[0]; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pucch_payload = pucch_payload[0]; + ue->pucch_payload[0] = pucch_payload[0]; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0]; } else if (format == pucch_format1b) { - phy_vars_ue->pucch_payload[0] = pucch_payload[0] + (pucch_payload[1]<<1); - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pucch_payload = pucch_payload[0] + (pucch_payload[1]<<1); + ue->pucch_payload[0] = pucch_payload[0] + (pucch_payload[1]<<1); + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0] + (pucch_payload[1]<<1); } else if (format == pucch_format1) { - LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_tx,subframe,sr); + LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",ue->Mod_id,ue->frame_tx,subframe,sr); } - phy_vars_ue->sr[subframe] = sr; + ue->sr[subframe] = sr; } -uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, +uint32_t rx_pucch(PHY_VARS_eNB *eNB, PUCCH_FMT_t fmt, uint8_t UE_id, uint16_t n1_pucch, @@ -446,15 +446,15 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, static int first_call=1; - LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; - // PUCCH_CONFIG_DEDICATED *pucch_config_dedicated = &phy_vars_eNB->pucch_config_dedicated[UE_id]; - int8_t sigma2_dB = phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dB[0]-10; - uint32_t *Po_PUCCH = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH); - int32_t *Po_PUCCH_dBm = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH_dBm); - uint32_t *Po_PUCCH1_below = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below); - uint32_t *Po_PUCCH1_above = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above); - int32_t *Po_PUCCH_update = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH_update); + LTE_eNB_COMMON *common_vars = &eNB->common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + // PUCCH_CONFIG_DEDICATED *pucch_config_dedicated = &eNB->pucch_config_dedicated[UE_id]; + int8_t sigma2_dB = eNB->measurements[0].n0_subband_power_tot_dB[0]-10; + uint32_t *Po_PUCCH = &(eNB->UE_stats[UE_id].Po_PUCCH); + int32_t *Po_PUCCH_dBm = &(eNB->UE_stats[UE_id].Po_PUCCH_dBm); + uint32_t *Po_PUCCH1_below = &(eNB->UE_stats[UE_id].Po_PUCCH1_below); + uint32_t *Po_PUCCH1_above = &(eNB->UE_stats[UE_id].Po_PUCCH1_above); + int32_t *Po_PUCCH_update = &(eNB->UE_stats[UE_id].Po_PUCCH_update); uint32_t u,v,n,aa; uint32_t z[12*14]; int16_t *zptr; @@ -486,8 +486,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, if (first_call == 1) { for (i=0;i<10;i++) { for (j=0;jpucch1_stats_cnt[j][i]=0; - phy_vars_eNB->pucch1ab_stats_cnt[j][i]=0; + eNB->pucch1_stats_cnt[j][i]=0; + eNB->pucch1ab_stats_cnt[j][i]=0; } } first_call=0; @@ -585,7 +585,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, //loop over symbols in slot for (l=0; lncs_cell[ns][l]; + n_cs = eNB->ncs_cell[ns][l]; if (frame_parms->Ncp==0) { // normal CP n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc%deltaPUCCH_Shift))%Nprime)%12; @@ -700,7 +700,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, re_offset -= (frame_parms->ofdm_symbol_size); symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*l; - rxptr = (int16_t *)&eNB_common_vars->rxdataF[0][aa][symbol_offset]; + rxptr = (int16_t *)&common_vars->rxdataF[0][aa][symbol_offset]; for (i=0; i<12; i++,j+=2,re_offset++) { rxcomp[aa][j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[j])>>15) - ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[1+j])>>15); @@ -789,17 +789,17 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, #endif #ifdef DEBUG_PUCCH_RX - LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max); + LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max); #endif - phy_vars_eNB->pucch1_stats[UE_id][(subframe<<10)+phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max; - phy_vars_eNB->pucch1_stats_thres[UE_id][(subframe<<10)+phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres; - phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023; + eNB->pucch1_stats[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max; + eNB->pucch1_stats_thres[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres; + eNB->pucch1_stats_cnt[UE_id][subframe] = (eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023; /* - if (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe] == 0) { + if (eNB->pucch1_stats_cnt[UE_id][subframe] == 0) { write_output("pucch_debug.m","pucch_energy", - &phy_vars_eNB->pucch1_stats[UE_id][(subframe<<10)], + &eNB->pucch1_stats[UE_id][(subframe<<10)], 1024,1,2); AssertFatal(0,"Exiting for PUCCH 1 debug\n"); @@ -810,13 +810,13 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) { *payload = 1; *Po_PUCCH1_above = ((*Po_PUCCH1_above<<9) + (stat_max<<9)+1024)>>10; - //LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); + //LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); } else { *payload = 0; *Po_PUCCH1_below = ((*Po_PUCCH1_below<<9) + (stat_max<<9)+1024)>>10; } - LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); + LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); *Po_PUCCH_update = 1; if (UE_id==0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_ENERGY,dB_fixed(stat_max)); @@ -910,7 +910,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, stat_im=0; LOG_D(PHY,"PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH); *Po_PUCCH = ((*Po_PUCCH>>1) + ((stat_max)>>1)); - *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - phy_vars_eNB->rx_total_gain_eNB_dB; + *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - eNB->rx_total_gain_dB; *Po_PUCCH_update = 1; LOG_D(PHY,"PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n", @@ -1030,12 +1030,12 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, #ifdef DEBUG_PUCCH_RX LOG_I(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im, - (subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])); + (subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])); #endif - phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<11) + 2*(phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_re); - phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<11) + 1+2*(phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_im); - phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + eNB->pucch1ab_stats[UE_id][(subframe<<11) + 2*(eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_re); + eNB->pucch1ab_stats[UE_id][(subframe<<11) + 1+2*(eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_im); + eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; @@ -1045,9 +1045,9 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, *(1+payload) = (stat_im<0) ? 1 : 0; } else { // insufficient energy on PUCCH so NAK *payload = 0; - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); - phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + ((int16_t*)&eNB->pucch1ab_stats[UE_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); + ((int16_t*)&eNB->pucch1ab_stats[UE_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); + eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; *payload = (stat_re<0) ? 1 : 0; @@ -1063,22 +1063,22 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } -int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, +int32_t rx_pucch_emul(PHY_VARS_eNB *eNB, uint8_t UE_index, PUCCH_FMT_t fmt, uint8_t n1_pucch_sel, uint8_t *payload, - uint8_t sched_subframe) + uint8_t thread_id) { uint8_t UE_id; uint16_t rnti; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - uint8_t CC_id = phy_vars_eNB->CC_id; + int subframe = eNB->proc[thread_id].subframe_rx; + uint8_t CC_id = eNB->CC_id; - rnti = phy_vars_eNB->ulsch_eNB[UE_index]->rnti; + rnti = eNB->ulsch[UE_index]->rnti; for (UE_id=0; UE_idlte_ue_pdcch_vars[0]->crnti) + if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti) break; } @@ -1095,7 +1095,7 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, payload[0] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[0]; payload[1] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[1]; } else - LOG_E(PHY,"[eNB] Frame %d: Can't handle formats 2/2a/2b\n",phy_vars_eNB->proc[sched_subframe].frame_rx); + LOG_E(PHY,"[eNB] Frame %d: Can't handle formats 2/2a/2b\n",eNB->proc[thread_id].frame_rx); if (PHY_vars_UE_g[UE_id][CC_id]->pucch_sel[subframe] == n1_pucch_sel) return(99); diff --git a/openair1/PHY/LTE_TRANSPORT/rar_tools.c b/openair1/PHY/LTE_TRANSPORT/rar_tools.c index 40dec0ec6f..dbac1e2280 100644 --- a/openair1/PHY/LTE_TRANSPORT/rar_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/rar_tools.c @@ -174,27 +174,28 @@ int generate_eNB_ulsch_params_from_rar(unsigned char *rar_pdu, int8_t delta_PUSCH_msg2[8] = {-6,-4,-2,0,2,4,6,8}; -int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue, +int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, unsigned char eNB_id ) { // RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)rar_pdu; - uint8_t transmission_mode = phy_vars_ue->transmission_mode[eNB_id]; - unsigned char *rar_pdu = phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->b; - unsigned char subframe = phy_vars_ue->ulsch_ue_Msg3_subframe[eNB_id]; - LTE_UE_ULSCH_t *ulsch = phy_vars_ue->ulsch_ue[eNB_id]; - PHY_MEASUREMENTS *meas = &phy_vars_ue->PHY_measurements; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - // int current_dlsch_cqi = phy_vars_ue->current_dlsch_cqi[eNB_id]; + uint8_t transmission_mode = ue->transmission_mode[eNB_id]; + unsigned char *rar_pdu = ue->dlsch_ra[eNB_id]->harq_processes[0]->b; + unsigned char subframe = ue->ulsch_Msg3_subframe[eNB_id]; + LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; + PHY_MEASUREMENTS *meas = &ue->measurements; + + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + // int current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id]; uint8_t *rar = (uint8_t *)(rar_pdu+1); - uint8_t harq_pid = subframe2harq_pid(frame_parms,phy_vars_ue->frame_tx,subframe); + uint8_t harq_pid = subframe2harq_pid(frame_parms,ue->frame_tx,subframe); uint16_t rballoc; uint8_t cqireq; uint16_t *RIV2nb_rb_LUT, *RIV2first_rb_LUT; uint16_t RIV_max = 0; - LOG_D(PHY,"[eNB][RAPROC] Frame %d: generate_ue_ulsch_params_from_rar: subframe %d (harq_pid %d)\n",phy_vars_ue->frame_tx,subframe,harq_pid); + LOG_D(PHY,"[eNB][RAPROC] Frame %d: generate_ue_ulsch_params_from_rar: subframe %d (harq_pid %d)\n",ue->frame_tx,subframe,harq_pid); switch (frame_parms->N_RB_DL) { case 6: @@ -269,10 +270,10 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue, } ulsch->uci_format = HLC_subband_cqi_nopmi; - fill_CQI(ulsch,meas,eNB_id,0,phy_vars_ue->lte_frame_parms.N_RB_DL,0, transmission_mode,phy_vars_ue->sinr_eff); + fill_CQI(ulsch,meas,eNB_id,0,ue->frame_parms.N_RB_DL,0, transmission_mode,ue->sinr_eff); - if (((phy_vars_ue->frame_tx % 100) == 0) || (phy_vars_ue->frame_tx < 10)) - print_CQI(ulsch->o,ulsch->uci_format,eNB_id,phy_vars_ue->lte_frame_parms.N_RB_DL); + if (((ue->frame_tx % 100) == 0) || (ue->frame_tx < 10)) + print_CQI(ulsch->o,ulsch->uci_format,eNB_id,ue->frame_parms.N_RB_DL); } else { ulsch->O_RI = 0; ulsch->O = 0; @@ -304,10 +305,10 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue, // initialize power control based on PRACH power ulsch->f_pusch = delta_PUSCH_msg2[ulsch->harq_processes[harq_pid]->TPC] + - mac_xface->get_deltaP_rampup(phy_vars_ue->Mod_id,phy_vars_ue->CC_id); + mac_xface->get_deltaP_rampup(ue->Mod_id,ue->CC_id); LOG_D(PHY,"[UE %d][PUSCH PC] Initializing f_pusch to %d dB, TPC %d (delta_PUSCH_msg2 %d dB), deltaP_rampup %d dB\n", - phy_vars_ue->Mod_id,ulsch->f_pusch,ulsch->harq_processes[harq_pid]->TPC,delta_PUSCH_msg2[ulsch->harq_processes[harq_pid]->TPC], - mac_xface->get_deltaP_rampup(phy_vars_ue->Mod_id,phy_vars_ue->CC_id)); + ue->Mod_id,ulsch->f_pusch,ulsch->harq_processes[harq_pid]->TPC,delta_PUSCH_msg2[ulsch->harq_processes[harq_pid]->TPC], + mac_xface->get_deltaP_rampup(ue->Mod_id,ue->CC_id)); //#ifdef DEBUG_RAR diff --git a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c index 249fd81ee4..cb5d653909 100644 --- a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c @@ -129,15 +129,15 @@ int compareints (const void * a, const void * b) } -int32_t generate_srs_tx(PHY_VARS_UE *phy_vars_ue, +int32_t generate_srs_tx(PHY_VARS_UE *ue, uint8_t eNB_id, int16_t amp, uint32_t subframe) { - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; - SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated=&phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id]; - int32_t *txdataF = phy_vars_ue->lte_ue_common_vars.txdataF[0]; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; + int32_t *txdataF = ue->common_vars.txdataF[0]; uint16_t msrsb=0,Nb=0,nb,b,msrs0=0,k,Msc_RS,Msc_RS_idx,carrier_pos,symbol_offset; uint16_t *Msc_idx_ptr; int32_t k0; diff --git a/openair1/PHY/LTE_TRANSPORT/sss.c b/openair1/PHY/LTE_TRANSPORT/sss.c index 34d55daaea..97fe212ac5 100644 --- a/openair1/PHY/LTE_TRANSPORT/sss.c +++ b/openair1/PHY/LTE_TRANSPORT/sss.c @@ -90,7 +90,7 @@ int generate_sss(int32_t **txdataF, return(0); } -int pss_ch_est(PHY_VARS_UE *phy_vars_ue, +int pss_ch_est(PHY_VARS_UE *ue, int32_t pss_ext[4][72], int32_t sss_ext[4][72]) { @@ -98,9 +98,9 @@ int pss_ch_est(PHY_VARS_UE *phy_vars_ue, int16_t *pss; int16_t *pss_ext2,*sss_ext2,*sss_ext3,tmp_re,tmp_im,tmp_re2,tmp_im2; uint8_t aarx,i; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - switch (phy_vars_ue->lte_ue_common_vars.eNb_id) { + switch (ue->common_vars.eNb_id) { case 0: pss = &primary_synch0[10]; @@ -154,7 +154,7 @@ int pss_ch_est(PHY_VARS_UE *phy_vars_ue, } -int pss_sss_extract(PHY_VARS_UE *phy_vars_ue, +int pss_sss_extract(PHY_VARS_UE *ue, int32_t pss_ext[4][72], int32_t sss_ext[4][72]) { @@ -165,12 +165,12 @@ int pss_sss_extract(PHY_VARS_UE *phy_vars_ue, uint8_t i,aarx; int32_t *pss_rxF,*pss_rxF_ext; int32_t *sss_rxF,*sss_rxF_ext; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; int rx_offset = frame_parms->ofdm_symbol_size-3*12; uint8_t pss_symb,sss_symb; - int32_t **rxdataF = phy_vars_ue->lte_ue_common_vars.rxdataF; + int32_t **rxdataF = ue->common_vars.rxdataF; if (frame_parms->frame_type == FDD) { pss_symb = 6-frame_parms->Ncp; @@ -219,74 +219,74 @@ int16_t phase_re[7] = {16383, 25101, 30791, 32767, 30791, 25101, 16383}; int16_t phase_im[7] = {-28378, -21063, -11208, 0, 11207, 21062, 28377}; -int rx_sss(PHY_VARS_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uint8_t *phase_max) +int rx_sss(PHY_VARS_UE *ue,int32_t *tot_metric,uint8_t *flip_max,uint8_t *phase_max) { uint8_t i; int32_t pss_ext[4][72]; int32_t sss0_ext[4][72],sss5_ext[4][72]; - uint8_t Nid2 = phy_vars_ue->lte_ue_common_vars.eNb_id; + uint8_t Nid2 = ue->common_vars.eNb_id; uint8_t flip,phase; uint16_t Nid1; int16_t *sss0,*sss5; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int32_t metric; int16_t *d0,*d5; - if (phy_vars_ue->lte_frame_parms.frame_type == FDD) { + if (frame_parms->frame_type == FDD) { #ifdef DEBUG_SSS - if (phy_vars_ue->lte_frame_parms.Ncp == NORMAL) - msg("[PHY][UE%d] Doing SSS for FDD Normal Prefix\n",phy_vars_ue->Mod_id); + if (frame_parms->Ncp == NORMAL) + msg("[PHY][UE%d] Doing SSS for FDD Normal Prefix\n",ue->Mod_id); else - msg("[PHY][UE%d] Doing SSS for FDD Extended Prefix\n",phy_vars_ue->Mod_id); + msg("[PHY][UE%d] Doing SSS for FDD Extended Prefix\n",ue->Mod_id); #endif // Do FFTs for SSS/PSS // SSS - slot_fep(phy_vars_ue, + slot_fep(ue, (frame_parms->symbols_per_tti/2)-2, // second to last symbol of 0, // slot 0 - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); // PSS - slot_fep(phy_vars_ue, + slot_fep(ue, (frame_parms->symbols_per_tti/2)-1, // last symbol of 0, // slot 0 - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); } else { // TDD #ifdef DEBUG_SSS - if (phy_vars_ue->lte_frame_parms.Ncp == NORMAL) - msg("[PHY][UE%d] Doing SSS for TDD Normal Prefix\n",phy_vars_ue->Mod_id); + if (ue->frame_parms->Ncp == NORMAL) + msg("[PHY][UE%d] Doing SSS for TDD Normal Prefix\n",ue->Mod_id); else - msg("[PHY][UE%d] Doing SSS for TDD Extended Prefix\n",phy_vars_ue->Mod_id); + msg("[PHY][UE%d] Doing SSS for TDD Extended Prefix\n",ue->Mod_id); #endif // SSS - slot_fep(phy_vars_ue, + slot_fep(ue, (frame_parms->symbols_per_tti>>1)-1, // last symbol of 1, // slot 1 - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); // PSS - slot_fep(phy_vars_ue, + slot_fep(ue, 2, // symbol 2 of 2, // slot 2 - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); } - pss_sss_extract(phy_vars_ue, + pss_sss_extract(ue, pss_ext, sss0_ext); /* - write_output("rxsig0.m","rxs0",&phy_vars_ue->lte_ue_common_vars.rxdata[0][0],phy_vars_ue->lte_frame_parms.samples_per_tti,1,1); - write_output("rxdataF0.m","rxF0",&phy_vars_ue->lte_ue_common_vars.rxdataF[0][0],2*14*phy_vars_ue->lte_frame_parms.ofdm_symbol_size,2,1); + write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_tti,1,1); + write_output("rxdataF0.m","rxF0",&ue->common_vars.rxdataF[0][0],2*14*ue->frame_parms.ofdm_symbol_size,2,1); write_output("pss_ext0.m","pssext0",pss_ext,72,1,1); write_output("sss0_ext0.m","sss0ext0",sss0_ext,72,1,1); */ @@ -294,44 +294,44 @@ int rx_sss(PHY_VARS_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uint8_ // get conjugated channel estimate from PSS (symbol 6), H* = R* \cdot PSS // and do channel estimation and compensation based on PSS - pss_ch_est(phy_vars_ue, + pss_ch_est(ue, pss_ext, sss0_ext); // write_output("sss0_comp0.m","sss0comp0",sss0_ext,72,1,1); - if (phy_vars_ue->lte_frame_parms.frame_type == FDD) { // FDD + if (ue->frame_parms.frame_type == FDD) { // FDD // SSS - slot_fep(phy_vars_ue, + slot_fep(ue, (frame_parms->symbols_per_tti/2)-2, 10, - phy_vars_ue->rx_offset, + ue->rx_offset, 0,1); // PSS - slot_fep(phy_vars_ue, + slot_fep(ue, (frame_parms->symbols_per_tti/2)-1, 10, - phy_vars_ue->rx_offset, + ue->rx_offset, 0,1); } else { // TDD // SSS - slot_fep(phy_vars_ue, + slot_fep(ue, (frame_parms->symbols_per_tti>>1)-1, 11, - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); // PSS - slot_fep(phy_vars_ue, + slot_fep(ue, 2, 12, - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 1); } - pss_sss_extract(phy_vars_ue, + pss_sss_extract(ue, pss_ext, sss5_ext); @@ -339,7 +339,7 @@ int rx_sss(PHY_VARS_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uint8_ // get conjugated channel estimate from PSS (symbol 6), H* = R* \cdot PSS // and do channel estimation and compensation based on PSS - pss_ch_est(phy_vars_ue, + pss_ch_est(ue, pss_ext, sss5_ext); @@ -375,7 +375,7 @@ int rx_sss(PHY_VARS_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uint8_ // if the current metric is better than the last save it if (metric > *tot_metric) { *tot_metric = metric; - phy_vars_ue->lte_frame_parms.Nid_cell = Nid2+(3*Nid1); + ue->frame_parms.Nid_cell = Nid2+(3*Nid1); *phase_max = phase; *flip_max=flip; #ifdef DEBUG_SSS diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c index 1004cfa192..4e45a856bd 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c @@ -205,7 +205,7 @@ LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) uint32_t ulsch_encoding(uint8_t *a, - PHY_VARS_UE *phy_vars_ue, + PHY_VARS_UE *ue, uint8_t harq_pid, uint8_t eNB_id, uint8_t tmode, @@ -213,11 +213,11 @@ uint32_t ulsch_encoding(uint8_t *a, uint8_t Nbundled) { - time_stats_t *seg_stats=&phy_vars_ue->ulsch_segmentation_stats; - time_stats_t *rm_stats=&phy_vars_ue->ulsch_rate_matching_stats; - time_stats_t *te_stats=&phy_vars_ue->ulsch_turbo_encoding_stats; - time_stats_t *i_stats=&phy_vars_ue->ulsch_interleaving_stats; - time_stats_t *m_stats=&phy_vars_ue->ulsch_multiplexing_stats; + time_stats_t *seg_stats=&ue->ulsch_segmentation_stats; + time_stats_t *rm_stats=&ue->ulsch_rate_matching_stats; + time_stats_t *te_stats=&ue->ulsch_turbo_encoding_stats; + time_stats_t *i_stats=&ue->ulsch_interleaving_stats; + time_stats_t *m_stats=&ue->ulsch_multiplexing_stats; // uint16_t offset; uint32_t crc=1; @@ -236,10 +236,10 @@ uint32_t ulsch_encoding(uint8_t *a, uint16_t o_RCC; uint8_t o_flip[8]; uint32_t wACK_idx; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; - PHY_MEASUREMENTS *meas = &phy_vars_ue->PHY_measurements; - LTE_UE_ULSCH_t *ulsch=phy_vars_ue->ulsch_ue[eNB_id]; - LTE_UE_DLSCH_t **dlsch = phy_vars_ue->dlsch_ue[eNB_id]; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + PHY_MEASUREMENTS *meas = &ue->measurements; + LTE_UE_ULSCH_t *ulsch=ue->ulsch[eNB_id]; + LTE_UE_DLSCH_t **dlsch = ue->dlsch[eNB_id]; uint16_t rnti; if (!ulsch) { @@ -266,11 +266,11 @@ uint32_t ulsch_encoding(uint8_t *a, // fill CQI/PMI information if (ulsch->O>0) { - rnti = phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti; - fill_CQI(ulsch,meas,0,harq_pid,phy_vars_ue->lte_frame_parms.N_RB_DL,rnti, tmode,phy_vars_ue->sinr_eff); + rnti = ue->pdcch_vars[eNB_id]->crnti; + fill_CQI(ulsch,meas,0,harq_pid,ue->frame_parms.N_RB_DL,rnti, tmode,ue->sinr_eff); LOG_D(PHY,"UE CQI\n"); - print_CQI(ulsch->o,ulsch->uci_format,0,phy_vars_ue->lte_frame_parms.N_RB_DL); + print_CQI(ulsch->o,ulsch->uci_format,0,ue->frame_parms.N_RB_DL); // save PUSCH pmi for later (transmission modes 4,5,6) if (dlsch[0]) { @@ -324,9 +324,9 @@ uint32_t ulsch_encoding(uint8_t *a, } if ((tmode != 4)) - print_CQI(ulsch->o,wideband_cqi_rank1_2A,0,phy_vars_ue->lte_frame_parms.N_RB_DL); + print_CQI(ulsch->o,wideband_cqi_rank1_2A,0,ue->frame_parms.N_RB_DL); else - print_CQI(ulsch->o,HLC_subband_cqi_rank1_2A,0,phy_vars_ue->lte_frame_parms.N_RB_DL); + print_CQI(ulsch->o,HLC_subband_cqi_rank1_2A,0,ue->frame_parms.N_RB_DL); #endif @@ -938,29 +938,29 @@ uint32_t ulsch_encoding(uint8_t *a, #include "LAYER2/MAC/defs.h" #endif int ulsch_encoding_emul(uint8_t *ulsch_buffer, - PHY_VARS_UE *phy_vars_ue, + PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t harq_pid, uint8_t control_only_flag) { - LTE_UE_ULSCH_t *ulsch = phy_vars_ue->ulsch_ue[eNB_id]; - LTE_UE_DLSCH_t **dlsch = phy_vars_ue->dlsch_ue[eNB_id]; - PHY_MEASUREMENTS *meas = &phy_vars_ue->PHY_measurements; - uint8_t tmode = phy_vars_ue->transmission_mode[eNB_id]; - uint16_t rnti=phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti; + LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; + LTE_UE_DLSCH_t **dlsch = ue->dlsch[eNB_id]; + PHY_MEASUREMENTS *meas = &ue->measurements; + uint8_t tmode = ue->transmission_mode[eNB_id]; + uint16_t rnti=ue->pdcch_vars[eNB_id]->crnti; LOG_D(PHY,"EMUL UE ulsch_encoding for eNB %d,mod_id %d, harq_pid %d rnti %x, ACK(%d,%d) \n", - eNB_id,phy_vars_ue->Mod_id, harq_pid, rnti,ulsch->o_ACK[0],ulsch->o_ACK[1]); + eNB_id,ue->Mod_id, harq_pid, rnti,ulsch->o_ACK[0],ulsch->o_ACK[1]); if (ulsch->O>0) { /* if(flag_LA==1) - sinr_eff = sinr_eff_cqi_calc(phy_vars_ue, eNB_id); + sinr_eff = sinr_eff_cqi_calc(ue, eNB_id); else sinr_eff = meas->wideband_cqi_avg[eNB_id]; */ - fill_CQI(ulsch,meas,eNB_id,harq_pid,phy_vars_ue->lte_frame_parms.N_RB_DL,rnti,tmode,phy_vars_ue->sinr_eff); + fill_CQI(ulsch,meas,eNB_id,harq_pid,ue->frame_parms.N_RB_DL,rnti,tmode,ue->sinr_eff); //LOG_D(PHY,"UE CQI\n"); // print_CQI(ulsch->o,ulsch->uci_format,eNB_id); @@ -970,36 +970,36 @@ int ulsch_encoding_emul(uint8_t *ulsch_buffer, dlsch[0]->harq_processes[harq_pid]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi; } - memcpy(phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->b, + memcpy(ue->ulsch[eNB_id]->harq_processes[harq_pid]->b, ulsch_buffer, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS>>3); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3); - //memcpy(&UE_transport_info[phy_vars_ue->Mod_id].transport_blocks[UE_transport_info_TB_index[phy_vars_ue->Mod_id]], - memcpy(&UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].transport_blocks, + //memcpy(&UE_transport_info[ue->Mod_id].transport_blocks[UE_transport_info_TB_index[ue->Mod_id]], + memcpy(&UE_transport_info[ue->Mod_id][ue->CC_id].transport_blocks, ulsch_buffer, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS>>3); - //UE_transport_info_TB_index[phy_vars_ue->Mod_id]+=phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS>>3; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3); + //UE_transport_info_TB_index[ue->Mod_id]+=ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3; // navid: currently more than one eNB is not supported in the code - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].num_eNB = 1; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].rnti[0] = phy_vars_ue->lte_ue_pdcch_vars[0]->crnti; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].eNB_id[0] = eNB_id; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].harq_pid[0] = harq_pid; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].tbs[0] = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS>>3 ; - // msg("\nphy_vars_ue->Mod_id%d\n",phy_vars_ue->Mod_id); + UE_transport_info[ue->Mod_id][ue->CC_id].num_eNB = 1; + UE_transport_info[ue->Mod_id][ue->CC_id].rnti[0] = ue->pdcch_vars[0]->crnti; + UE_transport_info[ue->Mod_id][ue->CC_id].eNB_id[0] = eNB_id; + UE_transport_info[ue->Mod_id][ue->CC_id].harq_pid[0] = harq_pid; + UE_transport_info[ue->Mod_id][ue->CC_id].tbs[0] = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3 ; + // msg("\nue->Mod_id%d\n",ue->Mod_id); - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pusch_flag = 1; - //UE_transport_info[phy_vars_ue->Mod_id].cntl.pusch_uci = *(uint32_t *)ulsch->o; - memcpy(UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pusch_uci, + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_flag = 1; + //UE_transport_info[ue->Mod_id].cntl.pusch_uci = *(uint32_t *)ulsch->o; + memcpy(UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_uci, ulsch->o, MAX_CQI_BYTES); // msg("[UE]cqi is %d \n", ((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1); - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.length_uci = ulsch->O; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.uci_format = ulsch->uci_format; - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pusch_ri = (ulsch->o_RI[0]&1)+((ulsch->o_RI[1]&1)<<1); - UE_transport_info[phy_vars_ue->Mod_id][phy_vars_ue->CC_id].cntl.pusch_ack = (ulsch->o_ACK[0]&1) + ((ulsch->o_ACK[1]&1)<<1); - //msg("ack is %d %d %d\n",UE_transport_info[phy_vars_ue->Mod_id].cntl.pusch_ack, (ulsch->o_ACK[1]&1)<<1, ulsch->o_ACK[0]&1); + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.length_uci = ulsch->O; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.uci_format = ulsch->uci_format; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_ri = (ulsch->o_RI[0]&1)+((ulsch->o_RI[1]&1)<<1); + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_ack = (ulsch->o_ACK[0]&1) + ((ulsch->o_ACK[1]&1)<<1); + //msg("ack is %d %d %d\n",UE_transport_info[ue->Mod_id].cntl.pusch_ack, (ulsch->o_ACK[1]&1)<<1, ulsch->o_ACK[0]&1); return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index a0a5602261..4a6bfa5f52 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -218,18 +218,18 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) -unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, +unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, uint8_t UE_id, - uint8_t sched_subframe, + uint8_t thread_id, uint8_t control_only_flag, uint8_t Nbundled, uint8_t llr8_flag) { - int16_t *ulsch_llr = phy_vars_eNB->lte_eNB_pusch_vars[UE_id]->llr; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; - LTE_eNB_ULSCH_t *ulsch = phy_vars_eNB->ulsch_eNB[UE_id]; + int16_t *ulsch_llr = eNB->pusch_vars[UE_id]->llr; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; uint8_t harq_pid; unsigned short nb_rb; unsigned int A,E; @@ -260,7 +260,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, int16_t cseq[6*14*1200]; int off; int status[20]; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; + int subframe = eNB->proc[thread_id].subframe_rx; LTE_UL_eNB_HARQ_t *ulsch_harq; uint8_t (*tc)(int16_t *y, @@ -279,7 +279,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, time_stats_t *, time_stats_t *); - harq_pid = subframe2harq_pid(frame_parms,phy_vars_eNB->proc[sched_subframe].frame_rx,subframe); + harq_pid = subframe2harq_pid(frame_parms,eNB->proc[thread_id].frame_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1); @@ -351,7 +351,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, } if (sumKr==0) { - LOG_N(PHY,"[eNB %d] ulsch_decoding.c: FATAL sumKr is 0!\n",phy_vars_eNB->Mod_id); + LOG_N(PHY,"[eNB %d] ulsch_decoding.c: FATAL sumKr is 0!\n",eNB->Mod_id); LOG_D(PHY,"ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n", frame_parms->Nid_cell,ulsch->rnti,x2, harq_pid, @@ -453,7 +453,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, // Clear "tag" interleaving matrix to allow for CQI/DATA identification memset(ytag,0,Cmux*Rmux_prime); - start_meas(&phy_vars_eNB->ulsch_demultiplexing_stats); + start_meas(&eNB->ulsch_demultiplexing_stats); i=0; memset(y,LTE_NULL,Q_m*Hpp); @@ -603,7 +603,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, } - stop_meas(&phy_vars_eNB->ulsch_demultiplexing_stats); + stop_meas(&eNB->ulsch_demultiplexing_stats); if (i!=(H+Q_RI)) LOG_D(PHY,"ulsch_decoding.c: Error in input buffer length (j %d, H+Q_RI %d)\n",i,H+Q_RI); @@ -979,7 +979,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, // return(0); // Do PUSCH Decoding - // stop_meas(&phy_vars_eNB->ulsch_demultiplexing_stats); + // stop_meas(&eNB->ulsch_demultiplexing_stats); r_offset = 0; @@ -1026,7 +1026,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, ulsch_harq->Nl); #endif - start_meas(&phy_vars_eNB->ulsch_rate_unmatching_stats); + start_meas(&eNB->ulsch_rate_unmatching_stats); if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, @@ -1047,14 +1047,14 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, return(-1); } - stop_meas(&phy_vars_eNB->ulsch_rate_unmatching_stats); + stop_meas(&eNB->ulsch_rate_unmatching_stats); r_offset += E; - start_meas(&phy_vars_eNB->ulsch_deinterleaving_stats); + start_meas(&eNB->ulsch_deinterleaving_stats); sub_block_deinterleaving_turbo(4+Kr, &ulsch_harq->d[r][96], ulsch_harq->w[r]); - stop_meas(&phy_vars_eNB->ulsch_deinterleaving_stats); + stop_meas(&eNB->ulsch_deinterleaving_stats); } for (r=0; rC; r++) { @@ -1068,7 +1068,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, else crc_type = CRC24_B; - start_meas(&phy_vars_eNB->ulsch_turbo_decoding_stats); + start_meas(&eNB->ulsch_turbo_decoding_stats); ret = tc(&ulsch_harq->d[r][96], ulsch_harq->c[r], @@ -1078,15 +1078,15 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, crc_type, (r==0) ? ulsch_harq->F : 0, - &phy_vars_eNB->ulsch_tc_init_stats, - &phy_vars_eNB->ulsch_tc_alpha_stats, - &phy_vars_eNB->ulsch_tc_beta_stats, - &phy_vars_eNB->ulsch_tc_gamma_stats, - &phy_vars_eNB->ulsch_tc_ext_stats, - &phy_vars_eNB->ulsch_tc_intl1_stats, - &phy_vars_eNB->ulsch_tc_intl2_stats); + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); - stop_meas(&phy_vars_eNB->ulsch_turbo_decoding_stats); + stop_meas(&eNB->ulsch_turbo_decoding_stats); status[r] = ret; @@ -1500,23 +1500,23 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb #endif -uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, - uint8_t sched_subframe, +uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, + uint8_t thread_id, uint8_t UE_index, uint16_t *crnti) { uint8_t UE_id; uint16_t rnti; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; + int subframe = eNB->proc[thread_id].subframe_rx; uint8_t harq_pid; - uint8_t CC_id = phy_vars_eNB->CC_id; + uint8_t CC_id = eNB->CC_id; - harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms,phy_vars_eNB->proc[sched_subframe].frame_rx,subframe); + harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc[thread_id].frame_rx,subframe); - rnti = phy_vars_eNB->ulsch_eNB[UE_index]->rnti; + rnti = eNB->ulsch[UE_index]->rnti; #ifdef DEBUG_PHY - LOG_D(PHY,"[eNB %d] ulsch_decoding_emul : subframe %d UE_index %d harq_pid %d rnti %x\n",phy_vars_eNB->Mod_id,subframe,UE_index,harq_pid,rnti); + LOG_D(PHY,"[eNB %d] ulsch_decoding_emul : subframe %d UE_index %d harq_pid %d rnti %x\n",eNB->Mod_id,subframe,UE_index,harq_pid,rnti); #endif for (UE_id=0; UE_idMod_id, + eNB->Mod_id, UE_id, PHY_vars_UE_g[UE_id]->lte_ue_pdcch_vars[0]->crnti, NB_UE_INST); @@ -1534,34 +1534,34 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, if (UE_id==NB_UE_INST) { LOG_W(PHY,"[eNB %d] ulsch_decoding_emul: FATAL, didn't find UE with rnti %x (UE index %d)\n", - phy_vars_eNB->Mod_id, rnti, UE_index); - return(1+phy_vars_eNB->ulsch_eNB[UE_id]->max_turbo_iterations); + eNB->Mod_id, rnti, UE_index); + return(1+eNB->ulsch[UE_id]->max_turbo_iterations); } else { - LOG_D(PHY,"[eNB %d] Found UE with rnti %x => UE_id %d\n",phy_vars_eNB->Mod_id, rnti, UE_id); + LOG_D(PHY,"[eNB %d] Found UE with rnti %x => UE_id %d\n",eNB->Mod_id, rnti, UE_id); } - if (PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->harq_processes[harq_pid]->status == CBA_ACTIVE) { + if (PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->harq_processes[harq_pid]->status == CBA_ACTIVE) { *crnti = rnti; - PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->harq_processes[harq_pid]->status=IDLE; + PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->harq_processes[harq_pid]->status=IDLE; } else *crnti = 0x0; // Do abstraction here to determine if packet it in error - /* if (ulsch_abstraction_MIESM(phy_vars_eNB->sinr_dB_eNB,1, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs,phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb) == 1) + /* if (ulsch_abstraction_MIESM(eNB->sinr_dB_eNB,1, eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, eNB->ulsch[UE_id]->harq_processes[harq_pid]->first_rb) == 1) flag = 1; else flag = 0;*/ /* - //SINRdbPost = phy_vars_eNB->sinr_dB_eNB; - mcsPost = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs, - nrbPost = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb; - frbPost = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb; + //SINRdbPost = eNB->sinr_dB_eNB; + mcsPost = eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs, + nrbPost = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb; + frbPost = eNB->ulsch[UE_id]->harq_processes[harq_pid]->first_rb; if(nrbPost > 0) { - SINRdbPost = phy_vars_eNB->sinr_dB_eNB; + SINRdbPost = eNB->sinr_dB_eNB; ULflag1 = 1; } else @@ -1571,7 +1571,7 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, }*/ // - // write_output("postprocSINR.m","SINReNB",phy_vars_eNB->sinr_dB,301,1,7); + // write_output("postprocSINR.m","SINReNB",eNB->sinr_dB,301,1,7); //Yazdir buraya her frame icin 300 eNb @@ -1580,51 +1580,51 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, // fprintf(csv_fd,"%e+i*(%e),",channelx,channely); - // if (ulsch_abstraction(phy_vars_eNB->sinr_dB,1, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs,phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb) == 1) { + // if (ulsch_abstraction(eNB->sinr_dB,1, eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, eNB->ulsch[UE_id]->harq_processes[harq_pid]->first_rb) == 1) { if (1) { LOG_D(PHY,"ulsch_decoding_emul abstraction successful\n"); - memcpy(phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->b, - PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->harq_processes[harq_pid]->b, - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->TBS>>3); + memcpy(eNB->ulsch[UE_index]->harq_processes[harq_pid]->b, + PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->harq_processes[harq_pid]->b, + eNB->ulsch[UE_index]->harq_processes[harq_pid]->TBS>>3); // get local ue's ack if ((UE_index >= oai_emulation.info.first_ue_local) ||(UE_index <(oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local))) { - get_ack(&phy_vars_eNB->lte_frame_parms, - PHY_vars_UE_g[UE_id][CC_id]->dlsch_ue[0][0]->harq_ack, + get_ack(&eNB->frame_parms, + PHY_vars_UE_g[UE_id][CC_id]->dlsch[0][0]->harq_ack, subframe, - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->o_ACK); + eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK); } else { // get remote UEs' ack - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->o_ACK[0] = PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->o_ACK[0]; - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->o_ACK[1] = PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->o_ACK[1]; + eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[0] = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_ACK[0]; + eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[1] = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_ACK[1]; } // Do abstraction of PUSCH feedback #ifdef DEBUG_PHY LOG_D(PHY,"[eNB %d][EMUL] ue index %d UE_id %d: subframe %d : o_ACK (%d %d), cqi (val %d, len %d)\n", - phy_vars_eNB->Mod_id,UE_index, UE_id, subframe,phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->o_ACK[0], - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->o_ACK[1], - ((HLC_subband_cqi_rank1_2A_5MHz *)PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->o)->cqi1, - PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->O); + eNB->Mod_id,UE_index, UE_id, subframe,eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[1], + ((HLC_subband_cqi_rank1_2A_5MHz *)PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o)->cqi1, + PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->O); #endif - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->Or1 = PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->O; - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->Or2 = PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->O; + eNB->ulsch[UE_index]->harq_processes[harq_pid]->Or1 = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->O; + eNB->ulsch[UE_index]->harq_processes[harq_pid]->Or2 = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->O; - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->uci_format = PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->uci_format; - memcpy(phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->o,PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->o,MAX_CQI_BYTES); - memcpy(phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->o_RI,PHY_vars_UE_g[UE_id][CC_id]->ulsch_ue[0]->o_RI,2); + eNB->ulsch[UE_index]->harq_processes[harq_pid]->uci_format = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->uci_format; + memcpy(eNB->ulsch[UE_index]->harq_processes[harq_pid]->o,PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o,MAX_CQI_BYTES); + memcpy(eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_RI,PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_RI,2); - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->cqi_crc_status = 1; + eNB->ulsch[UE_index]->harq_processes[harq_pid]->cqi_crc_status = 1; return(1); } else { - LOG_W(PHY,"[eNB %d] ulsch_decoding_emul abstraction failed for UE %d\n",phy_vars_eNB->Mod_id,UE_index); + LOG_W(PHY,"[eNB %d] ulsch_decoding_emul abstraction failed for UE %d\n",eNB->Mod_id,UE_index); - phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->cqi_crc_status = 0; + eNB->ulsch[UE_index]->harq_processes[harq_pid]->cqi_crc_status = 0; // retransmission - return(1+phy_vars_eNB->ulsch_eNB[UE_index]->max_turbo_iterations); + return(1+eNB->ulsch[UE_index]->max_turbo_iterations); } } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index e52cdf9567..87c21b6a6b 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1576,8 +1576,8 @@ void ulsch_channel_level(int32_t **drs_ch_estimates_ext, int32_t avgU[2]; int32_t avgU_0[2],avgU_1[2]; // For the Distributed Alamouti Scheme -void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, - uint32_t sched_subframe, +void rx_ulsch(PHY_VARS_eNB *eNB, + uint32_t thread_id, uint8_t eNB_id, // this is the effective sector id uint8_t UE_id, LTE_eNB_ULSCH_t **ulsch, @@ -1585,9 +1585,9 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, { // flagMag = 0; - LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; - LTE_eNB_PUSCH *eNB_pusch_vars = phy_vars_eNB->lte_eNB_pusch_vars[UE_id]; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; + LTE_eNB_COMMON *common_vars = &eNB->common_vars; + LTE_eNB_PUSCH *pusch_vars = eNB->pusch_vars[UE_id]; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; uint32_t l,i; int32_t avgs; @@ -1603,9 +1603,9 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, uint8_t Qm; uint16_t rx_power_correction; int16_t *llrp; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; + int subframe = eNB->proc[thread_id].subframe_rx; - harq_pid = subframe2harq_pid(frame_parms,phy_vars_eNB->proc[sched_subframe].frame_rx,subframe); + harq_pid = subframe2harq_pid(frame_parms,eNB->proc[thread_id].frame_rx,subframe); Qm = get_Qm_ul(ulsch[UE_id]->harq_processes[harq_pid]->mcs); #ifdef DEBUG_ULSCH msg("rx_ulsch: eNB_id %d, harq_pid %d, nb_rb %d first_rb %d, cooperation %d\n",eNB_id,harq_pid,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,ulsch[UE_id]->harq_processes[harq_pid]->first_rb, @@ -1625,22 +1625,22 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, msg("rx_ulsch : symbol %d (first_rb %d,nb_rb %d), rxdataF %p, rxdataF_ext %p\n",l, ulsch[UE_id]->harq_processes[harq_pid]->first_rb, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, - eNB_common_vars->rxdataF[eNB_id], - eNB_pusch_vars->rxdataF_ext[eNB_id]); + common_vars->rxdataF[eNB_id], + pusch_vars->rxdataF_ext[eNB_id]); #endif //DEBUG_ULSCH - ulsch_extract_rbs_single(eNB_common_vars->rxdataF[eNB_id], - eNB_pusch_vars->rxdataF_ext[eNB_id], + ulsch_extract_rbs_single(common_vars->rxdataF[eNB_id], + pusch_vars->rxdataF_ext[eNB_id], ulsch[UE_id]->harq_processes[harq_pid]->first_rb, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, l%(frame_parms->symbols_per_tti/2), l/(frame_parms->symbols_per_tti/2), frame_parms); - lte_ul_channel_estimation(phy_vars_eNB, + lte_ul_channel_estimation(eNB, eNB_id, UE_id, - sched_subframe, + thread_id, l%(frame_parms->symbols_per_tti/2), l/(frame_parms->symbols_per_tti/2), cooperation_flag); @@ -1648,36 +1648,36 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, if(cooperation_flag == 2) { for (i=0; inb_antennas_rx; i++) { - eNB_pusch_vars->ulsch_power_0[i] = signal_energy(eNB_pusch_vars->drs_ch_estimates_0[eNB_id][i], + pusch_vars->ulsch_power_0[i] = signal_energy(pusch_vars->drs_ch_estimates_0[eNB_id][i], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)*rx_power_correction; - eNB_pusch_vars->ulsch_power_1[i] = signal_energy(eNB_pusch_vars->drs_ch_estimates_1[eNB_id][i], + pusch_vars->ulsch_power_1[i] = signal_energy(pusch_vars->drs_ch_estimates_1[eNB_id][i], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)*rx_power_correction; } } else { for (i=0; inb_antennas_rx; i++) { /* - eNB_pusch_vars->ulsch_power[i] = signal_energy_nodc(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], + pusch_vars->ulsch_power[i] = signal_energy_nodc(pusch_vars->drs_ch_estimates[eNB_id][i], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)*rx_power_correction; */ - eNB_pusch_vars->ulsch_power[i] = signal_energy_nodc(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], + pusch_vars->ulsch_power[i] = signal_energy_nodc(pusch_vars->drs_ch_estimates[eNB_id][i], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); #ifdef LOCALIZATION - eNB_pusch_vars->subcarrier_power = (int32_t *)malloc(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12*sizeof(int32_t)); - eNB_pusch_vars->active_subcarrier = subcarrier_energy(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], - ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12, eNB_pusch_vars->subcarrier_power, rx_power_correction); + pusch_vars->subcarrier_power = (int32_t *)malloc(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12*sizeof(int32_t)); + pusch_vars->active_subcarrier = subcarrier_energy(pusch_vars->drs_ch_estimates[eNB_id][i], + ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12, pusch_vars->subcarrier_power, rx_power_correction); #endif } } - //write_output("rxdataF_ext.m","rxF_ext",eNB_pusch_vars->rxdataF_ext[eNB_id][0],300*(frame_parms->symbols_per_tti-ulsch[UE_id]->srs_active),1,1); - //write_output("ulsch_chest.m","drs_est",eNB_pusch_vars->drs_ch_estimates[eNB_id][0],300*(frame_parms->symbols_per_tti-ulsch[UE_id]->srs_active),1,1); + //write_output("rxdataF_ext.m","rxF_ext",pusch_vars->rxdataF_ext[eNB_id][0],300*(frame_parms->symbols_per_tti-ulsch[UE_id]->srs_active),1,1); + //write_output("ulsch_chest.m","drs_est",pusch_vars->drs_ch_estimates[eNB_id][0],300*(frame_parms->symbols_per_tti-ulsch[UE_id]->srs_active),1,1); if(cooperation_flag == 2) { - ulsch_channel_level(eNB_pusch_vars->drs_ch_estimates_0[eNB_id], + ulsch_channel_level(pusch_vars->drs_ch_estimates_0[eNB_id], frame_parms, avgU_0, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); @@ -1695,7 +1695,7 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, msg("[ULSCH] log2_maxh_0 = %d (%d,%d)\n",log2_maxh_0,avgU_0[0],avgs_0); #endif - ulsch_channel_level(eNB_pusch_vars->drs_ch_estimates_1[eNB_id], + ulsch_channel_level(pusch_vars->drs_ch_estimates_1[eNB_id], frame_parms, avgU_1, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); @@ -1714,7 +1714,7 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, #endif log2_maxh = max(log2_maxh_0,log2_maxh_1); } else { - ulsch_channel_level(eNB_pusch_vars->drs_ch_estimates[eNB_id], + ulsch_channel_level(pusch_vars->drs_ch_estimates[eNB_id], frame_parms, avgU, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); @@ -1746,15 +1746,15 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, if(cooperation_flag == 2) { ulsch_channel_compensation_alamouti( - eNB_pusch_vars->rxdataF_ext[eNB_id], - eNB_pusch_vars->drs_ch_estimates_0[eNB_id], - eNB_pusch_vars->drs_ch_estimates_1[eNB_id], - eNB_pusch_vars->ul_ch_mag_0[eNB_id], - eNB_pusch_vars->ul_ch_magb_0[eNB_id], - eNB_pusch_vars->ul_ch_mag_1[eNB_id], - eNB_pusch_vars->ul_ch_magb_1[eNB_id], - eNB_pusch_vars->rxdataF_comp_0[eNB_id], - eNB_pusch_vars->rxdataF_comp_1[eNB_id], + pusch_vars->rxdataF_ext[eNB_id], + pusch_vars->drs_ch_estimates_0[eNB_id], + pusch_vars->drs_ch_estimates_1[eNB_id], + pusch_vars->ul_ch_mag_0[eNB_id], + pusch_vars->ul_ch_magb_0[eNB_id], + pusch_vars->ul_ch_mag_1[eNB_id], + pusch_vars->ul_ch_magb_1[eNB_id], + pusch_vars->rxdataF_comp_0[eNB_id], + pusch_vars->rxdataF_comp_1[eNB_id], frame_parms, l, Qm, @@ -1762,24 +1762,24 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, log2_maxh); ulsch_alamouti(frame_parms, - eNB_pusch_vars->rxdataF_comp[eNB_id], - eNB_pusch_vars->rxdataF_comp_0[eNB_id], - eNB_pusch_vars->rxdataF_comp_1[eNB_id], - eNB_pusch_vars->ul_ch_mag[eNB_id], - eNB_pusch_vars->ul_ch_magb[eNB_id], - eNB_pusch_vars->ul_ch_mag_0[eNB_id], - eNB_pusch_vars->ul_ch_magb_0[eNB_id], - eNB_pusch_vars->ul_ch_mag_1[eNB_id], - eNB_pusch_vars->ul_ch_magb_1[eNB_id], + pusch_vars->rxdataF_comp[eNB_id], + pusch_vars->rxdataF_comp_0[eNB_id], + pusch_vars->rxdataF_comp_1[eNB_id], + pusch_vars->ul_ch_mag[eNB_id], + pusch_vars->ul_ch_magb[eNB_id], + pusch_vars->ul_ch_mag_0[eNB_id], + pusch_vars->ul_ch_magb_0[eNB_id], + pusch_vars->ul_ch_mag_1[eNB_id], + pusch_vars->ul_ch_magb_1[eNB_id], l, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); } else { ulsch_channel_compensation( - eNB_pusch_vars->rxdataF_ext[eNB_id], - eNB_pusch_vars->drs_ch_estimates[eNB_id], - eNB_pusch_vars->ul_ch_mag[eNB_id], - eNB_pusch_vars->ul_ch_magb[eNB_id], - eNB_pusch_vars->rxdataF_comp[eNB_id], + pusch_vars->rxdataF_ext[eNB_id], + pusch_vars->drs_ch_estimates[eNB_id], + pusch_vars->ul_ch_mag[eNB_id], + pusch_vars->ul_ch_magb[eNB_id], + pusch_vars->rxdataF_comp[eNB_id], frame_parms, l, Qm, @@ -1794,7 +1794,7 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, //writing for the first time write_output(namepointer_log2,"xxx",log2_maxh,1,1,12); - write_output(namepointer_chMag,"xxx",eNB_pusch_vars->ul_ch_mag[eNB_id][0],300,1,11); + write_output(namepointer_chMag,"xxx",pusch_vars->ul_ch_mag[eNB_id][0],300,1,11); //namepointer_chMag = NULL; flagMag=1; @@ -1802,20 +1802,20 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, if (frame_parms->nb_antennas_rx > 1) ulsch_detection_mrc(frame_parms, - eNB_pusch_vars->rxdataF_comp[eNB_id], - eNB_pusch_vars->ul_ch_mag[eNB_id], - eNB_pusch_vars->ul_ch_magb[eNB_id], + pusch_vars->rxdataF_comp[eNB_id], + pusch_vars->ul_ch_mag[eNB_id], + pusch_vars->ul_ch_magb[eNB_id], l, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); #ifndef OFDMA_ULSCH - if ((phy_vars_eNB->PHY_measurements_eNB->n0_power_dB[0]+3)ulsch_power[0]) { + if ((eNB->measurements->n0_power_dB[0]+3)ulsch_power[0]) { freq_equalization(frame_parms, - eNB_pusch_vars->rxdataF_comp[eNB_id], - eNB_pusch_vars->ul_ch_mag[eNB_id], - eNB_pusch_vars->ul_ch_magb[eNB_id], + pusch_vars->rxdataF_comp[eNB_id], + pusch_vars->ul_ch_mag[eNB_id], + pusch_vars->ul_ch_magb[eNB_id], l, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12, Qm); @@ -1830,7 +1830,7 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, // Inverse-Transform equalized outputs // msg("Doing IDFTs\n"); lte_idft(frame_parms, - (uint32_t*)eNB_pusch_vars->rxdataF_comp[eNB_id][0], + (uint32_t*)pusch_vars->rxdataF_comp[eNB_id][0], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); // msg("Done\n"); //#endif //DEBUG_ULSCH @@ -1838,7 +1838,7 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, #endif - llrp = (int16_t*)&eNB_pusch_vars->llr[0]; + llrp = (int16_t*)&pusch_vars->llr[0]; for (l=0; lsymbols_per_tti-ulsch[UE_id]->harq_processes[harq_pid]->srs_active; l++) { @@ -1850,8 +1850,8 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, switch (Qm) { case 2 : ulsch_qpsk_llr(frame_parms, - eNB_pusch_vars->rxdataF_comp[eNB_id], - eNB_pusch_vars->llr, + pusch_vars->rxdataF_comp[eNB_id], + pusch_vars->llr, l, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, &llrp); @@ -1859,19 +1859,19 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, case 4 : ulsch_16qam_llr(frame_parms, - eNB_pusch_vars->rxdataF_comp[eNB_id], - eNB_pusch_vars->llr, - eNB_pusch_vars->ul_ch_mag[eNB_id], + pusch_vars->rxdataF_comp[eNB_id], + pusch_vars->llr, + pusch_vars->ul_ch_mag[eNB_id], l,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, &llrp); break; case 6 : ulsch_64qam_llr(frame_parms, - eNB_pusch_vars->rxdataF_comp[eNB_id], - eNB_pusch_vars->llr, - eNB_pusch_vars->ul_ch_mag[eNB_id], - eNB_pusch_vars->ul_ch_magb[eNB_id], + pusch_vars->rxdataF_comp[eNB_id], + pusch_vars->llr, + pusch_vars->ul_ch_mag[eNB_id], + pusch_vars->ul_ch_magb[eNB_id], l,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, &llrp); break; @@ -1886,66 +1886,66 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, } -void rx_ulsch_emul(PHY_VARS_eNB *phy_vars_eNB, +void rx_ulsch_emul(PHY_VARS_eNB *eNB, uint8_t subframe, uint8_t sect_id, uint8_t UE_index) { - msg("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",phy_vars_eNB->Mod_id,subframe,sect_id,UE_index); - phy_vars_eNB->lte_eNB_pusch_vars[UE_index]->ulsch_power[0] = 31622; //=45dB; - phy_vars_eNB->lte_eNB_pusch_vars[UE_index]->ulsch_power[1] = 31622; //=45dB; + msg("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",eNB->Mod_id,subframe,sect_id,UE_index); + eNB->pusch_vars[UE_index]->ulsch_power[0] = 31622; //=45dB; + eNB->pusch_vars[UE_index]->ulsch_power[1] = 31622; //=45dB; } -void dump_ulsch(PHY_VARS_eNB *PHY_vars_eNB,uint8_t sched_subframe, uint8_t UE_id) +void dump_ulsch(PHY_VARS_eNB *eNB,uint8_t thread_id, uint8_t UE_id) { - uint32_t nsymb = (PHY_vars_eNB->lte_frame_parms.Ncp == 0) ? 14 : 12; + uint32_t nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; uint8_t harq_pid; - int subframe = PHY_vars_eNB->proc[sched_subframe].subframe_rx; + int subframe = eNB->proc[thread_id].subframe_rx; - harq_pid = subframe2harq_pid(&PHY_vars_eNB->lte_frame_parms,PHY_vars_eNB->proc[sched_subframe].frame_rx,subframe); + harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc[thread_id].frame_rx,subframe); - printf("Dumping ULSCH in subframe %d with harq_pid %d, for NB_rb %d, mcs %d, Qm %d, N_symb %d\n", subframe,harq_pid,PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb, - PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs,get_Qm_ul(PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs), - PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); + printf("Dumping ULSCH in subframe %d with harq_pid %d, for NB_rb %d, mcs %d, Qm %d, N_symb %d\n", subframe,harq_pid,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, + eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,get_Qm_ul(eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs), + eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); //#ifndef OAI_EMU - write_output("/tmp/ulsch_d.m","ulsch_dseq",&PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->d[0][96], - PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Kplus*3,1,0); - write_output("/tmp/rxsig0.m","rxs0", &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][0],PHY_vars_eNB->lte_frame_parms.samples_per_tti*10,1,1); + write_output("/tmp/ulsch_d.m","ulsch_dseq",&eNB->ulsch[UE_id]->harq_processes[harq_pid]->d[0][96], + eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus*3,1,0); + write_output("/tmp/rxsig0.m","rxs0", &eNB->common_vars.rxdata[0][0][0],eNB->frame_parms.samples_per_tti*10,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_rx>1) - write_output("/tmp/rxsig1.m","rxs1", &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][1][0],PHY_vars_eNB->lte_frame_parms.samples_per_tti*10,1,1); + if (eNB->frame_parms.nb_antennas_rx>1) + write_output("/tmp/rxsig1.m","rxs1", &eNB->common_vars.rxdata[0][1][0],eNB->frame_parms.samples_per_tti*10,1,1); - write_output("/tmp/rxsigF0.m","rxsF0", &PHY_vars_eNB->lte_eNB_common_vars.rxdataF[0][0][0],PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + write_output("/tmp/rxsigF0.m","rxsF0", &eNB->common_vars.rxdataF[0][0][0],eNB->frame_parms.ofdm_symbol_size*nsymb,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_rx>1) - write_output("/tmp/rxsigF1.m","rxsF1", &PHY_vars_eNB->lte_eNB_common_vars.rxdataF[0][1][0],PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + if (eNB->frame_parms.nb_antennas_rx>1) + write_output("/tmp/rxsigF1.m","rxsF1", &eNB->common_vars.rxdataF[0][1][0],eNB->frame_parms.ofdm_symbol_size*nsymb,1,1); - write_output("/tmp/rxsigF0_ext.m","rxsF0_ext", &PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->rxdataF_ext[0][0][0],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); + write_output("/tmp/rxsigF0_ext.m","rxsF0_ext", &eNB->pusch_vars[UE_id]->rxdataF_ext[0][0][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_rx>1) - write_output("/tmp/rxsigF1_ext.m","rxsF1_ext", &PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->rxdataF_ext[1][0][0],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); + if (eNB->frame_parms.nb_antennas_rx>1) + write_output("/tmp/rxsigF1_ext.m","rxsF1_ext", &eNB->pusch_vars[UE_id]->rxdataF_ext[1][0][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); - write_output("/tmp/srs_est0.m","srsest0",PHY_vars_eNB->lte_eNB_srs_vars[UE_id].srs_ch_estimates[0][0],PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size,1,1); + write_output("/tmp/srs_est0.m","srsest0",eNB->srs_vars[UE_id].srs_ch_estimates[0][0],eNB->frame_parms.ofdm_symbol_size,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_rx>1) - write_output("/tmp/srs_est1.m","srsest1",PHY_vars_eNB->lte_eNB_srs_vars[UE_id].srs_ch_estimates[0][1],PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size,1,1); + if (eNB->frame_parms.nb_antennas_rx>1) + write_output("/tmp/srs_est1.m","srsest1",eNB->srs_vars[UE_id].srs_ch_estimates[0][1],eNB->frame_parms.ofdm_symbol_size,1,1); - write_output("/tmp/drs_est0.m","drsest0",PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->drs_ch_estimates[0][0],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); + write_output("/tmp/drs_est0.m","drsest0",eNB->pusch_vars[UE_id]->drs_ch_estimates[0][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_rx>1) - write_output("/tmp/drs_est1.m","drsest1",PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->drs_ch_estimates[0][1],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); + if (eNB->frame_parms.nb_antennas_rx>1) + write_output("/tmp/drs_est1.m","drsest1",eNB->pusch_vars[UE_id]->drs_ch_estimates[0][1],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); - write_output("/tmp/ulsch_rxF_comp0.m","ulsch0_rxF_comp0",&PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->rxdataF_comp[0][0][0],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); - // write_output("ulsch_rxF_comp1.m","ulsch0_rxF_comp1",&PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->rxdataF_comp[0][1][0],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); - write_output("/tmp/ulsch_rxF_llr.m","ulsch_llr",PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->llr, - PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb*12*get_Qm_ul(PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs) - *PHY_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Nsymb_pusch,1,0); - write_output("/tmp/ulsch_ch_mag.m","ulsch_ch_mag",&PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->ul_ch_mag[0][0][0],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); - // write_output("ulsch_ch_mag1.m","ulsch_ch_mag1",&PHY_vars_eNB->lte_eNB_pusch_vars[UE_id]->ul_ch_mag[0][1][0],PHY_vars_eNB->lte_frame_parms.N_RB_UL*12*nsymb,1,1); + write_output("/tmp/ulsch_rxF_comp0.m","ulsch0_rxF_comp0",&eNB->pusch_vars[UE_id]->rxdataF_comp[0][0][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); + // write_output("ulsch_rxF_comp1.m","ulsch0_rxF_comp1",&eNB->pusch_vars[UE_id]->rxdataF_comp[0][1][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); + write_output("/tmp/ulsch_rxF_llr.m","ulsch_llr",eNB->pusch_vars[UE_id]->llr, + eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12*get_Qm_ul(eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs) + *eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch,1,0); + write_output("/tmp/ulsch_ch_mag.m","ulsch_ch_mag",&eNB->pusch_vars[UE_id]->ul_ch_mag[0][0][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); + // write_output("ulsch_ch_mag1.m","ulsch_ch_mag1",&eNB->pusch_vars[UE_id]->ul_ch_mag[0][1][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); //#endif } diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c index 6a63043e9c..eb2296077a 100644 --- a/openair1/PHY/MODULATION/slot_fep.c +++ b/openair1/PHY/MODULATION/slot_fep.c @@ -33,7 +33,7 @@ #define SOFFSET 0 -int slot_fep(PHY_VARS_UE *phy_vars_ue, +int slot_fep(PHY_VARS_UE *ue, unsigned char l, unsigned char Ns, int sample_offset, @@ -41,8 +41,8 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, int reset_freq_est) { - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - LTE_UE_COMMON *ue_common_vars = &phy_vars_ue->lte_ue_common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + LTE_UE_COMMON *common_vars = &ue->common_vars; uint8_t eNB_id = 0;//ue_common_vars->eNb_id; unsigned char aa; unsigned char symbol = l+((7-frame_parms->Ncp)*(Ns&1)); ///symbol within sub-frame @@ -111,37 +111,37 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, for (aa=0; aanb_antennas_rx; aa++) { - memset(&ue_common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); + memset(&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); rx_offset = sample_offset + slot_offset + nb_prefix_samples0 + subframe_offset - SOFFSET; // Align with 256 bit // rx_offset = rx_offset&0xfffffff8; #ifdef DEBUG_FEP - // if (phy_vars_ue->frame <100) - printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", phy_vars_ue->frame_rx,Ns, symbol, + // if (ue->frame <100) + printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", ue->frame_rx,Ns, symbol, nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset); #endif if (l==0) { if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short *)&ue_common_vars->rxdata[aa][frame_length_samples], - (short *)&ue_common_vars->rxdata[aa][0], + memcpy((short *)&common_vars->rxdata[aa][frame_length_samples], + (short *)&common_vars->rxdata[aa][0], frame_parms->ofdm_symbol_size*sizeof(int)); if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs memcpy((void *)tmp_dft_in, - (void *)&ue_common_vars->rxdata[aa][rx_offset % frame_length_samples], + (void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); dft((int16_t *)tmp_dft_in, - (int16_t *)&ue_common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + (int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - start_meas(&phy_vars_ue->rx_dft_stats); + start_meas(&ue->rx_dft_stats); - dft((int16_t *)&ue_common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&ue_common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - stop_meas(&phy_vars_ue->rx_dft_stats); + dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + (int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + stop_meas(&ue->rx_dft_stats); } } else { @@ -149,54 +149,54 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, // (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1); #ifdef DEBUG_FEP - // if (phy_vars_ue->frame <100) - printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", phy_vars_ue->frame_rx,Ns, symbol, + // if (ue->frame <100) + printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", ue->frame_rx,Ns, symbol, nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset); #endif if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *)&ue_common_vars->rxdata[aa][frame_length_samples], - (void *)&ue_common_vars->rxdata[aa][0], + memcpy((void *)&common_vars->rxdata[aa][frame_length_samples], + (void *)&common_vars->rxdata[aa][0], frame_parms->ofdm_symbol_size*sizeof(int)); - start_meas(&phy_vars_ue->rx_dft_stats); + start_meas(&ue->rx_dft_stats); if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs memcpy((void *)tmp_dft_in, - (void *)&ue_common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + (void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); dft((int16_t *)tmp_dft_in, - (int16_t *)&ue_common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + (int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - dft((int16_t *)&ue_common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&ue_common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + (int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } - stop_meas(&phy_vars_ue->rx_dft_stats); + stop_meas(&ue->rx_dft_stats); } } - if (phy_vars_ue->perfect_ce == 0) { + if (ue->perfect_ce == 0) { if ((l==0) || (l==(4-frame_parms->Ncp))) { for (aa=0; aanb_antennas_tx_eNB; aa++) { #ifdef DEBUG_FEP printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l); #endif - start_meas(&phy_vars_ue->dlsch_channel_estimation_stats); - lte_dl_channel_estimation(phy_vars_ue,eNB_id,0, + start_meas(&ue->dlsch_channel_estimation_stats); + lte_dl_channel_estimation(ue,eNB_id,0, Ns, aa, l, symbol); - stop_meas(&phy_vars_ue->dlsch_channel_estimation_stats); + stop_meas(&ue->dlsch_channel_estimation_stats); - for (i=0; iPHY_measurements.n_adj_cells; i++) { - lte_dl_channel_estimation(phy_vars_ue,eNB_id,i+1, + for (i=0; imeasurements.n_adj_cells; i++) { + lte_dl_channel_estimation(ue,eNB_id,i+1, Ns, aa, l, @@ -212,13 +212,13 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, #endif if (l==(4-frame_parms->Ncp)) { - start_meas(&phy_vars_ue->dlsch_freq_offset_estimation_stats); - lte_est_freq_offset(ue_common_vars->dl_ch_estimates[0], + start_meas(&ue->dlsch_freq_offset_estimation_stats); + lte_est_freq_offset(common_vars->dl_ch_estimates[0], frame_parms, l, - &ue_common_vars->freq_offset, + &common_vars->freq_offset, reset_freq_est); - stop_meas(&phy_vars_ue->dlsch_freq_offset_estimation_stats); + stop_meas(&ue->dlsch_freq_offset_estimation_stats); } } diff --git a/openair1/PHY/MODULATION/slot_fep_mbsfn.c b/openair1/PHY/MODULATION/slot_fep_mbsfn.c index f6ca4aa2f4..f2d2421496 100644 --- a/openair1/PHY/MODULATION/slot_fep_mbsfn.c +++ b/openair1/PHY/MODULATION/slot_fep_mbsfn.c @@ -32,15 +32,15 @@ #define SOFFSET 0 -int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, +int slot_fep_mbsfn(PHY_VARS_UE *ue, unsigned char l, int subframe, int sample_offset, int no_prefix) { - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; - LTE_UE_COMMON *ue_common_vars = &phy_vars_ue->lte_ue_common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + LTE_UE_COMMON *common_vars = &ue->common_vars; uint8_t eNB_id = 0;//ue_common_vars->eNb_id; unsigned char aa; @@ -117,34 +117,34 @@ int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, for (aa=0; aanb_antennas_rx; aa++) { - memset(&ue_common_vars->rxdataF[aa][2*frame_parms->ofdm_symbol_size*l],0,2*frame_parms->ofdm_symbol_size*sizeof(int)); + memset(&common_vars->rxdataF[aa][2*frame_parms->ofdm_symbol_size*l],0,2*frame_parms->ofdm_symbol_size*sizeof(int)); if (l==0) { - start_meas(&phy_vars_ue->rx_dft_stats); - dft((int16_t *)&ue_common_vars->rxdata[aa][(sample_offset + + start_meas(&ue->rx_dft_stats); + dft((int16_t *)&common_vars->rxdata[aa][(sample_offset + nb_prefix_samples0 + subframe_offset - SOFFSET) % frame_length_samples], - (int16_t *)&ue_common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*l],1); - stop_meas(&phy_vars_ue->rx_dft_stats); + (int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*l],1); + stop_meas(&ue->rx_dft_stats); } else { if ((sample_offset + (frame_parms->ofdm_symbol_size+nb_prefix_samples0+nb_prefix_samples) + (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1) + subframe_offset- SOFFSET) > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short *)&ue_common_vars->rxdata[aa][frame_length_samples], - (short *)&ue_common_vars->rxdata[aa][0], + memcpy((short *)&common_vars->rxdata[aa][frame_length_samples], + (short *)&common_vars->rxdata[aa][0], frame_parms->ofdm_symbol_size*sizeof(int)); - start_meas(&phy_vars_ue->rx_dft_stats); - dft((int16_t *)&ue_common_vars->rxdata[aa][(sample_offset + + start_meas(&ue->rx_dft_stats); + dft((int16_t *)&common_vars->rxdata[aa][(sample_offset + (frame_parms->ofdm_symbol_size+nb_prefix_samples0+nb_prefix_samples) + (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1) + subframe_offset- SOFFSET) % frame_length_samples], - (int16_t *)&ue_common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*l],1); - stop_meas(&phy_vars_ue->rx_dft_stats); + (int16_t *)&common_vars->rxdataF[aa][frame_parms->ofdm_symbol_size*l],1); + stop_meas(&ue->rx_dft_stats); } } @@ -153,29 +153,29 @@ int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, // changed to invoke MBSFN channel estimation in symbols 2,6,10 if ((l==2)||(l==6)||(l==10)) { for (aa=0; aanb_antennas_tx; aa++) { - if (phy_vars_ue->perfect_ce == 0) { + if (ue->perfect_ce == 0) { #ifdef DEBUG_FEP msg("Channel estimation eNB %d, aatx %d, subframe %d, symbol %d\n",eNB_id,aa,subframe,l); #endif - lte_dl_mbsfn_channel_estimation(phy_vars_ue, + lte_dl_mbsfn_channel_estimation(ue, eNB_id, 0, subframe, l); - /* for (i=0;iPHY_measurements.n_adj_cells;i++) { - lte_dl_mbsfn_channel_estimation(phy_vars_ue, + /* for (i=0;iPHY_measurements.n_adj_cells;i++) { + lte_dl_mbsfn_channel_estimation(ue, eNB_id, i+1, subframe, l); - lte_dl_channel_estimation(phy_vars_ue,eNB_id,0, + lte_dl_channel_estimation(ue,eNB_id,0, Ns, aa, l, symbol); - for (i=0;iPHY_measurements.n_adj_cells;i++) { - lte_dl_channel_estimation(phy_vars_ue,eNB_id,i+1, + for (i=0;iPHY_measurements.n_adj_cells;i++) { + lte_dl_channel_estimation(ue,eNB_id,i+1, Ns, aa, l, @@ -189,10 +189,10 @@ int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, #endif // if ((l == 0) || (l==(4-frame_parms->Ncp))) /* if ((l==2)||(l==6)||(l==10)) - lte_mbsfn_est_freq_offset(ue_common_vars->dl_ch_estimates[0], + lte_mbsfn_est_freq_offset(common_vars->dl_ch_estimates[0], frame_parms, l, - &ue_common_vars->freq_offset); */ + &common_vars->freq_offset); */ } } } diff --git a/openair1/PHY/MODULATION/ul_7_5_kHz.c b/openair1/PHY/MODULATION/ul_7_5_kHz.c index 4a50ad395e..481e0dd2a0 100755 --- a/openair1/PHY/MODULATION/ul_7_5_kHz.c +++ b/openair1/PHY/MODULATION/ul_7_5_kHz.c @@ -42,7 +42,7 @@ short conjugate75[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1} ; short conjugate75_2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1} ; short negate[8]__attribute__((aligned(16))) = {-1,-1,-1,-1,-1,-1,-1,-1}; -void apply_7_5_kHz(PHY_VARS_UE *phy_vars_ue,int32_t*txdata,uint8_t slot) +void apply_7_5_kHz(PHY_VARS_UE *ue,int32_t*txdata,uint8_t slot) { @@ -58,7 +58,7 @@ void apply_7_5_kHz(PHY_VARS_UE *phy_vars_ue,int32_t*txdata,uint8_t slot) uint32_t slot_offset; // uint8_t aa; uint32_t i; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; switch (frame_parms->N_RB_UL) { @@ -91,10 +91,8 @@ void apply_7_5_kHz(PHY_VARS_UE *phy_vars_ue,int32_t*txdata,uint8_t slot) break; } - slot_offset = (uint32_t)slot * phy_vars_ue->lte_frame_parms.samples_per_tti/2; - // if ((slot&1)==1) - // slot_offset += (len/4); - len = phy_vars_ue->lte_frame_parms.samples_per_tti/2; + slot_offset = (uint32_t)slot * frame_parms->samples_per_tti/2; + len = frame_parms->samples_per_tti/2; #if defined(__x86_64__) || defined(__i386__) txptr128 = (__m128i *)&txdata[slot_offset]; @@ -149,12 +147,12 @@ void apply_7_5_kHz(PHY_VARS_UE *phy_vars_ue,int32_t*txdata,uint8_t slot) } -void remove_7_5_kHz(PHY_VARS_eNB *phy_vars_eNB,uint8_t slot) +void remove_7_5_kHz(PHY_VARS_eNB *eNB,uint8_t slot) { - int32_t **rxdata=phy_vars_eNB->lte_eNB_common_vars.rxdata[0]; - int32_t **rxdata_7_5kHz=phy_vars_eNB->lte_eNB_common_vars.rxdata_7_5kHz[0]; + int32_t **rxdata=eNB->common_vars.rxdata[0]; + int32_t **rxdata_7_5kHz=eNB->common_vars.rxdata_7_5kHz[0]; uint16_t len; uint32_t *kHz7_5ptr; #if defined(__x86_64__) || defined(__i386__) @@ -168,9 +166,9 @@ void remove_7_5_kHz(PHY_VARS_eNB *phy_vars_eNB,uint8_t slot) uint32_t slot_offset,slot_offset2; uint8_t aa; uint32_t i; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms; - switch (phy_vars_eNB->lte_frame_parms.N_RB_UL) { + switch (frame_parms->N_RB_UL) { case 6: kHz7_5ptr = (frame_parms->Ncp==0) ? (uint32_t*)s6n_kHz_7_5 : (uint32_t*)s6e_kHz_7_5; @@ -202,12 +200,12 @@ void remove_7_5_kHz(PHY_VARS_eNB *phy_vars_eNB,uint8_t slot) } - slot_offset = (uint32_t)slot * phy_vars_eNB->lte_frame_parms.samples_per_tti/2-phy_vars_eNB->N_TA_offset; - slot_offset2 = (uint32_t)(slot&1) * phy_vars_eNB->lte_frame_parms.samples_per_tti/2; + slot_offset = (uint32_t)slot * frame_parms->samples_per_tti/2-eNB->N_TA_offset; + slot_offset2 = (uint32_t)(slot&1) * frame_parms->samples_per_tti/2; - len = phy_vars_eNB->lte_frame_parms.samples_per_tti/2; + len = frame_parms->samples_per_tti/2; - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aanb_antennas_rx; aa++) { #if defined(__x86_64__) || defined(__i386__) rxptr128 = (__m128i *)&rxdata[aa][slot_offset]; @@ -270,3 +268,4 @@ void remove_7_5_kHz(PHY_VARS_eNB *phy_vars_eNB,uint8_t slot) } } } + diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 468aae8052..601e2fb199 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -161,7 +161,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, { int eNB_id = 0; int i,i2,arx,atx,ind,k; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->frame_parms; int nsymb_ce = 12*frame_parms->N_RB_UL*frame_parms->symbols_per_tti; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_tx = 1; // frame_parms->nb_antennas_tx; // in LTE Rel. 8 and 9 only a single transmit antenna is assumed at the UE @@ -190,9 +190,9 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, int mcs = 0; // choose max MCS to compute coded_bits_per_codeword - if (phy_vars_enb->ulsch_eNB[UE_id]!=NULL) { + if (phy_vars_enb->ulsch[UE_id]!=NULL) { for (harq_pid=0; harq_pid<3; harq_pid++) { - mcs = cmax(phy_vars_enb->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs,mcs); + mcs = cmax(phy_vars_enb->ulsch[UE_id]->harq_processes[harq_pid]->mcs,mcs); } } @@ -202,11 +202,11 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero bit = malloc(coded_bits_per_codeword*sizeof(float)); - rxsig_t = (int16_t**) phy_vars_enb->lte_eNB_common_vars.rxdata[eNB_id]; - chest_t = (int16_t**) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; - chest_f = (int16_t**) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->drs_ch_estimates[eNB_id]; - pusch_llr = (int16_t*) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->llr; - pusch_comp = (int16_t*) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; + rxsig_t = (int16_t**) phy_vars_enb->common_vars.rxdata[eNB_id]; + chest_t = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; + chest_f = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates[eNB_id]; + pusch_llr = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->llr; + pusch_comp = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id]; pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id]; pucch1ab_comp = (int32_t*) phy_vars_enb->pucch1ab_stats[UE_id]; @@ -488,7 +488,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, uint8_t subframe) { int i,arx,atx,ind,k; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; int nsymb_ce = frame_parms->ofdm_symbol_size;//*frame_parms->symbols_per_tti; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx_eNB; @@ -516,32 +516,32 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, unsigned char harq_pid = 0; - if (phy_vars_ue->dlsch_ue[eNB_id][0]!=NULL) { - harq_pid = phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid; + if (phy_vars_ue->dlsch[eNB_id][0]!=NULL) { + harq_pid = phy_vars_ue->dlsch[eNB_id][0]->current_harq_pid; if (harq_pid>=8) return; - mcs = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs; + mcs = phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs; // Button 0 - if(!phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off) { + if(!phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off) { // we are in TM5 fl_show_object(form->button_0); } } - if (phy_vars_ue->lte_ue_pdcch_vars[eNB_id]!=NULL) { - num_pdcch_symbols = phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols; + if (phy_vars_ue->pdcch_vars[eNB_id]!=NULL) { + num_pdcch_symbols = phy_vars_ue->pdcch_vars[eNB_id]->num_pdcch_symbols; } // coded_bits_per_codeword = frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); - if (phy_vars_ue->dlsch_ue[eNB_id][0]!=NULL) { + if (phy_vars_ue->dlsch[eNB_id][0]!=NULL) { coded_bits_per_codeword = get_G(frame_parms, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb, + phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, get_Qm(mcs), - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Nl, + phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, num_pdcch_symbols, frame, subframe); @@ -563,16 +563,16 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, llr_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); // init to zero bit_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); - rxsig_t = (int16_t**) phy_vars_ue->lte_ue_common_vars.rxdata; - chest_t = (int16_t**) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates_time[eNB_id]; - chest_f = (int16_t**) phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id]; - pbch_llr = (int8_t*) phy_vars_ue->lte_ue_pbch_vars[eNB_id]->llr; - pbch_comp = (int16_t*) phy_vars_ue->lte_ue_pbch_vars[eNB_id]->rxdataF_comp[0]; - pdcch_llr = (int8_t*) phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->llr; - pdcch_comp = (int16_t*) phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->rxdataF_comp[0]; - pdsch_llr = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->llr[0]; // stream 0 + rxsig_t = (int16_t**) phy_vars_ue->common_vars.rxdata; + chest_t = (int16_t**) phy_vars_ue->common_vars.dl_ch_estimates_time[eNB_id]; + chest_f = (int16_t**) phy_vars_ue->common_vars.dl_ch_estimates[eNB_id]; + pbch_llr = (int8_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; + pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; + pdcch_llr = (int8_t*) phy_vars_ue->pdcch_vars[eNB_id]->llr; + pdcch_comp = (int16_t*) phy_vars_ue->pdcch_vars[eNB_id]->rxdataF_comp[0]; + pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[eNB_id]->llr[0]; // stream 0 // pdsch_llr = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0]; // stream 0 - pdsch_comp = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0[0]; + pdsch_comp = (int16_t*) phy_vars_ue->pdsch_vars[eNB_id]->rxdataF_comp0[0]; // Received signal in time domain of receive antenna 0 if (rxsig_t != NULL) { diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index b72c5f648a..dd543bbbf8 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -45,6 +45,8 @@ #include #include #include +#include "common_lib.h" + //#include #include "assertions.h" #ifdef MEX @@ -151,9 +153,14 @@ enum transmission_access_mode { CANCELED_ACCESS, UNKNOWN_ACCESS, SCHEDULED_ACCESS, - CBA_ACCESS -}; + CBA_ACCESS}; +typedef enum { + eNodeB_3GPP=0, // classical eNodeB function + NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) + NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) +} eNB_func_t; + typedef struct UE_SCAN_INFO_s { /// 10 best amplitudes (linear) for each pss signals int32_t amp[3][10]; @@ -175,8 +182,12 @@ typedef struct ral_threshold_phy_s { typedef struct { /// Component Carrier index uint8_t CC_id; - /// subframe index - int subframe; + /// thread index + int thread_index; + /// timestamp received from HW + openair0_timestamp timestamp_rx; + /// timestamp transmitted to HW + openair0_timestamp timestamp_tx; /// subframe to act upon for transmission int subframe_tx; /// subframe to act upon for reception @@ -189,25 +200,39 @@ typedef struct { /// \internal This variable is protected by \ref mutex_tx. int instance_cnt_tx; /// \brief Instance count for rx processing thread. - /// \internal This variable is protected by \ref mutex_rx. - int instance_cnt_rx; + /// \internal This variable is protected by \ref mutex_prach. + int instance_cnt_prach; /// pthread structure for tx processing thread pthread_t pthread_tx; /// pthread structure for rx processing thread pthread_t pthread_rx; + /// pthread attributes for tx processing thread + pthread_attr_t attr_tx; + /// pthread attributes for rx processing thread + pthread_attr_t attr_rx; + /// pthread attributes for prach processing thread + pthread_attr_t attr_prach; + /// scheduling parameters for tx thread + struct sched_param sched_param_tx; + /// scheduling parameters for rx thread + struct sched_param sched_param_rx; + /// scheduling parameters for prach thread + struct sched_param sched_param_prach; /// condition variable for tx processing thread + pthread_t pthread_prach; + /// condition variable for prach processing thread pthread_cond_t cond_tx; - /// condition variable for rx processing thread - pthread_cond_t cond_rx; + /// condition variable for rx processing thread; + pthread_cond_t cond_prach; /// mutex for tx processing thread pthread_mutex_t mutex_tx; /// mutex for tx processing thread - pthread_mutex_t mutex_rx; + pthread_mutex_t mutex_prach; } eNB_proc_t; //! \brief Number of eNB TX and RX threads. //! This number must be equal to the number of LTE subframes (10). Each thread is responsible for a single subframe. -#define NUM_ENB_THREADS 10 +#define NUM_ENB_THREADS 1 /// Top-level PHY Data Structure for eNB typedef struct PHY_VARS_eNB_s { @@ -215,25 +240,25 @@ typedef struct PHY_VARS_eNB_s { module_id_t Mod_id; uint8_t CC_id; eNB_proc_t proc[NUM_ENB_THREADS]; + eNB_func_t node_function; uint8_t local_flag; - uint32_t rx_total_gain_eNB_dB; - LTE_DL_FRAME_PARMS lte_frame_parms; - PHY_MEASUREMENTS_eNB PHY_measurements_eNB[NUMBER_OF_eNB_SECTORS_MAX]; /// Measurement variables - LTE_eNB_COMMON lte_eNB_common_vars; - LTE_eNB_SRS lte_eNB_srs_vars[NUMBER_OF_UE_MAX]; - LTE_eNB_PBCH lte_eNB_pbch; + uint32_t rx_total_gain_dB; + LTE_DL_FRAME_PARMS frame_parms; + PHY_MEASUREMENTS_eNB measurements[NUMBER_OF_eNB_SECTORS_MAX]; /// Measurement variables + LTE_eNB_COMMON common_vars; + LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; + LTE_eNB_PBCH pbch; /// \brief ?. /// - first index: UE [0..NUMBER_OF_UE_MAX[ (hard coded) /// - second index: UE [0..NUMBER_OF_UE_MAX[ - LTE_eNB_PUSCH *lte_eNB_pusch_vars[NUMBER_OF_UE_MAX]; - LTE_eNB_PRACH lte_eNB_prach_vars; - LTE_eNB_DLSCH_t *dlsch_eNB[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams - // old: LTE_eNB_DLSCH_t **dlsch_eNB[2]; // Nusers times two spatial streams - LTE_eNB_ULSCH_t *ulsch_eNB[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA - LTE_eNB_DLSCH_t *dlsch_eNB_SI,*dlsch_eNB_ra; - LTE_eNB_DLSCH_t *dlsch_eNB_MCH; - LTE_eNB_UE_stats eNB_UE_stats[NUMBER_OF_UE_MAX]; - LTE_eNB_UE_stats *eNB_UE_stats_ptr[NUMBER_OF_UE_MAX]; + LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX]; + LTE_eNB_PRACH prach_vars; + LTE_eNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams + LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA + LTE_eNB_DLSCH_t *dlsch_SI,*dlsch_ra; + LTE_eNB_DLSCH_t *dlsch_MCH; + LTE_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX]; + LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX]; /// cell-specific reference symbols uint32_t lte_gold_table[20][2][14]; @@ -497,26 +522,24 @@ typedef struct { /// \brief indicator that Handover procedure has been triggered uint8_t ho_triggered; /// \brief Measurement variables. - PHY_MEASUREMENTS PHY_measurements; - LTE_DL_FRAME_PARMS lte_frame_parms; + PHY_MEASUREMENTS measurements; + LTE_DL_FRAME_PARMS frame_parms; /// \brief Frame parame before ho used to recover if ho fails. - LTE_DL_FRAME_PARMS lte_frame_parms_before_ho; - LTE_UE_COMMON lte_ue_common_vars; + LTE_DL_FRAME_PARMS frame_parms_before_ho; + LTE_UE_COMMON common_vars; - LTE_UE_PDSCH *lte_ue_pdsch_vars[NUMBER_OF_CONNECTED_eNB_MAX+1]; - LTE_UE_PDSCH_FLP *lte_ue_pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; - LTE_UE_PDSCH *lte_ue_pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; - LTE_UE_PDSCH *lte_ue_pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; - LTE_UE_PDSCH *lte_ue_pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_PBCH *lte_ue_pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_PDCCH *lte_ue_pdcch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_PRACH *lte_ue_prach_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_DLSCH_t *dlsch_ue[NUMBER_OF_CONNECTED_eNB_MAX][2]; - LTE_UE_ULSCH_t *ulsch_ue[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_DLSCH_t *dlsch_ue_col[NUMBER_OF_CONNECTED_eNB_MAX][2]; - LTE_UE_DLSCH_t *ulsch_ue_col[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_DLSCH_t *dlsch_ue_SI[NUMBER_OF_CONNECTED_eNB_MAX],*dlsch_ue_ra[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_DLSCH_t *dlsch_ue_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_PDSCH *pdsch_vars[NUMBER_OF_CONNECTED_eNB_MAX+1]; + LTE_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; + LTE_UE_PDSCH *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; + LTE_UE_PDSCH *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; + LTE_UE_PDSCH *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_PDCCH *pdcch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_DLSCH_t *dlsch[NUMBER_OF_CONNECTED_eNB_MAX][2]; + LTE_UE_ULSCH_t *ulsch[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX],*dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; // This is for SIC in the UE, to store the reencoded data LTE_eNB_DLSCH_t *dlsch_eNB[NUMBER_OF_CONNECTED_eNB_MAX]; @@ -544,11 +567,9 @@ typedef struct { char ulsch_no_allocation_counter[NUMBER_OF_CONNECTED_eNB_MAX]; - unsigned char ulsch_ue_Msg3_active[NUMBER_OF_CONNECTED_eNB_MAX]; - uint32_t ulsch_ue_Msg3_frame[NUMBER_OF_CONNECTED_eNB_MAX]; - unsigned char ulsch_ue_Msg3_subframe[NUMBER_OF_CONNECTED_eNB_MAX]; - // unsigned char Msg3_timer[NUMBER_OF_CONNECTED_eNB_MAX]; - //unsigned char *Msg3_ptr[NUMBER_OF_CONNECTED_eNB_MAX]; + unsigned char ulsch_Msg3_active[NUMBER_OF_CONNECTED_eNB_MAX]; + uint32_t ulsch_Msg3_frame[NUMBER_OF_CONNECTED_eNB_MAX]; + unsigned char ulsch_Msg3_subframe[NUMBER_OF_CONNECTED_eNB_MAX]; PRACH_RESOURCES_t *prach_resources[NUMBER_OF_CONNECTED_eNB_MAX]; int turbo_iterations, turbo_cntl_iterations; /// \brief ?. diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index 23e44d6692..fa6239d930 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -215,37 +215,52 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac void phy_procedures_UE_S_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for UE RX procedures in TDD S-subframes. - @param last_slot Index of last slot (0-19) + @param thread_index Thread index in proc vector @param phy_vars_ue Pointer to UE variables on which to act @param eNB_id Local id of eNB on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_UE_S_RX(uint8_t last_slot,PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag, relaying_type_t r_type); +void phy_procedures_UE_S_RX(uint8_t thread_index,PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag, relaying_type_t r_type); /*! \brief Scheduling for eNB TX procedures in normal subframes. - @param next_slot Index of next slot (0-19) + @param thread_index Index of thread in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param phy_vars_rn pointer to the RN variables */ -void phy_procedures_eNB_TX(uint8_t next_slot,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); +void phy_procedures_eNB_TX(uint8_t thread_index,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); -/*! \brief Scheduling for eNB RX procedures in normal subframes. - @param last_slot Index of last slot (0-19) +/*! \brief Scheduling for eNB RX UE-specific procedures in normal subframes. + @param thread_index Thread index in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_RX(uint8_t last_slot,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_uespec_RX(uint8_t thread_index,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for eNB TX procedures in TDD S-subframes. - @param next_slot Index of next slot (0-19) + @param thread_index Index of thread in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ + +/*! \brief Scheduling for eNB RX common procedures in normal subframes. + @param thread_index Thread index in proc vector + @param phy_vars_eNB Pointer to eNB variables on which to act + @param abstraction_flag Indicator of PHY abstraction +*/ +void phy_procedures_eNB_common_RX(uint8_t thread_index,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag); + +/*! \brief Scheduling for eNB TX procedures in TDD S-subframes. + @param thread_index Index of thread in proc vector + @param phy_vars_eNB Pointer to eNB variables on which to act + @param abstraction_flag Indicator of PHY abstraction + @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying +*/ + void phy_procedures_eNB_S_TX(uint8_t next_slot,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for eNB RX procedures in TDD S-subframes. @@ -261,6 +276,14 @@ void phy_procedures_eNB_S_RX(uint8_t last_slot,PHY_VARS_eNB *phy_vars_eNB,uint8_ @param subframe Subframe index @returns Subframe type (DL,UL,S) */ + +/*! \brief Scheduling for eNB PRACH RX procedures + @param phy_vars_eNB Pointer to eNB variables on which to act + @param thread_id Index of thread in proc vector + @param abstraction_flag Indicator of PHY abstraction +*/ +void prach_procedures(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t abstraction_flag); + lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); /*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. Same as subframe_select, except that it uses the Mod_id and is provided as a service to the MAC scheduler. @@ -420,14 +443,14 @@ subframe n-4 which is acknowledged in subframe n (for FDD) according to n1_pucch TDD, this routine computes the complex procedure described in Section 10.1 of 36.213 (through tables 10.1-1,10.1-2) @param phy_vars_ue Pointer to UE variables @param eNB_id Index of eNB -@param sched_subframe Index of subframe where procedures were scheduled +@param thread_id Index of thread where procedures are executed @param b Pointer to PUCCH payload (b[0],b[1]) @param SR 1 means there's a positive SR in parallel to ACK/NAK @returns n1_pucch */ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, - uint8_t sched_subframe, + uint8_t thread_id, uint8_t *b, uint8_t SR); @@ -508,7 +531,7 @@ int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index); */ double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE_id, frame_t frameP, sub_frame_t subframeP, int32_t UE_tx_power_dB); #endif -LTE_eNB_UE_stats* get_eNB_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); +LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); LTE_DL_FRAME_PARMS *get_lte_frame_parms(module_id_t Mod_id, uint8_t CC_id); diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c index 78c035de37..0b4fffe3d3 100644 --- a/openair1/SCHED/phy_mac_stub.c +++ b/openair1/SCHED/phy_mac_stub.c @@ -48,18 +48,18 @@ #include "SCHED/phy_procedures_emos.h" #endif -void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_eNB) +void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) { - int i; - //uint8_t cooperation_flag = phy_vars_eNB->cooperation_flag; - uint8_t transmission_mode = phy_vars_eNB->transmission_mode[0]; + + //uint8_t cooperation_flag = eNB->cooperation_flag; + uint8_t transmission_mode = eNB->transmission_mode[0]; uint32_t rballoc = 0x7FFF; //uint32_t rballoc2 = 0x000F; - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_tx; + int subframe = eNB->proc[thread_id].subframe_tx; - LTE_eNB_DLSCH_t *DLSCH_ptr = phy_vars_eNB->dlsch_eNB[0][0]; + LTE_eNB_DLSCH_t *DLSCH_ptr = eNB->dlsch[0][0]; /* uint32_t rand = taus(); @@ -82,14 +82,14 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e DCI_pdu->dci_alloc[0].format = format1A; DCI_pdu->dci_alloc[0].ra_flag = 0; - switch (phy_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { + if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_1_5MHz_FDD_t; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -100,7 +100,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -112,12 +112,12 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e case 25: default: - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { + if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_5MHz_FDD_t; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -128,7 +128,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -139,12 +139,12 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e break; case 50: - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { + if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_10MHz_FDD_t; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -155,7 +155,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; @@ -166,12 +166,12 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e break; case 100: - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { + if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_20MHz_FDD_t; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -182,7 +182,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -226,17 +226,17 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e if (transmission_mode<3) { //user 1 - switch (phy_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 25: - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { + if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_FDD_t; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; - //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; + //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -252,8 +252,8 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; - //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; + //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28); + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -265,9 +265,9 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; - //((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); - ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; + //((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); + ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -283,8 +283,8 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; - //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; + //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28); + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -295,15 +295,15 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e case 50: - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { + if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_10MHz_FDD_t; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; - //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; + //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t)); @@ -319,8 +319,8 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; - //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; + //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28); + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t)); @@ -332,9 +332,9 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; - //((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); - ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; + //((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); + ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t)); @@ -350,8 +350,8 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; - //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; + //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28); + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t)); @@ -361,15 +361,15 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e break; case 100: - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) { + if (eNB->frame_parms.frame_type == FDD) { DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_FDD_t; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; - //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; + //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -385,8 +385,8 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; - //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; + //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28); + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -398,9 +398,9 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; - ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; - //((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); - ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; + //((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); + ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_20MHz_TDD_t)); @@ -416,8 +416,8 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->TPC = 0; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->dai = 0; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->harq_pid = 1; - //((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = phy_vars_eNB->target_ue_dl_mcs; + //((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28); + ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->ndi = 1; ((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_20MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t)); @@ -437,15 +437,15 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tpmi = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv1 = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi1 = phy_vars_eNB->proc[sched_subframe].frame_tx&1; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs1 = phy_vars_eNB->target_ue_dl_mcs; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi1 = eNB->proc[thread_id].frame_tx&1; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs1 = eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv2 = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi2 = phy_vars_eNB->proc[sched_subframe].frame_tx&1; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs2 = phy_vars_eNB->target_ue_dl_mcs; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi2 = eNB->proc[thread_id].frame_tx&1; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs2 = eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tb_swap = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->TPC = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rballoc = phy_vars_eNB->ue_dl_rb_alloc; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rballoc = eNB->ue_dl_rb_alloc; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rah = 0; } else if (transmission_mode==5) { @@ -459,16 +459,16 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback DLSCH_alloc_pdu1E.rv = 0; - DLSCH_alloc_pdu1E.ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; - //DLSCH_alloc_pdu1E.mcs = cqi_to_mcs[phy_vars_eNB->eNB_UE_stats->DL_cqi[0]]; + DLSCH_alloc_pdu1E.ndi = eNB->proc[thread_id].frame_tx&1; + //DLSCH_alloc_pdu1E.mcs = cqi_to_mcs[eNB->eNB_UE_stats->DL_cqi[0]]; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); - DLSCH_alloc_pdu1E.mcs = phy_vars_eNB->target_ue_dl_mcs; - //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((phy_vars_eNB->proc[subframe].frame%1024)%28); - phy_vars_eNB->eNB_UE_stats[0].dlsch_mcs1 = DLSCH_alloc_pdu1E.mcs; + DLSCH_alloc_pdu1E.mcs = eNB->target_ue_dl_mcs; + //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((eNB->proc[subframe].frame%1024)%28); + eNB->UE_stats[0].dlsch_mcs1 = DLSCH_alloc_pdu1E.mcs; DLSCH_alloc_pdu1E.harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; DLSCH_alloc_pdu1E.dai = 0; DLSCH_alloc_pdu1E.TPC = 0; - DLSCH_alloc_pdu1E.rballoc = phy_vars_eNB->ue_dl_rb_alloc; + DLSCH_alloc_pdu1E.rballoc = eNB->ue_dl_rb_alloc; DLSCH_alloc_pdu1E.rah = 0; DLSCH_alloc_pdu1E.dl_power_off = 0; //0=second user present memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); @@ -479,16 +479,16 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e DCI_pdu->dci_alloc[1].rnti = 0x1236; DCI_pdu->dci_alloc[1].format = format1E_2A_M10PRB; DCI_pdu->dci_alloc[1].ra_flag = 0; - //DLSCH_alloc_pdu1E.mcs = phy_vars_eNB->target_ue_dl_mcs; + //DLSCH_alloc_pdu1E.mcs = eNB->target_ue_dl_mcs; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); - //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((phy_vars_eNB->frame%1024)%28); - DLSCH_alloc_pdu1E.mcs = (unsigned char) (((phy_vars_eNB->proc[sched_subframe].frame_tx%1024)/3)%28); - phy_vars_eNB->eNB_UE_stats[1].dlsch_mcs1 = DLSCH_alloc_pdu1E.mcs; + //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((eNB->frame%1024)%28); + DLSCH_alloc_pdu1E.mcs = (unsigned char) (((eNB->proc[thread_id].frame_tx%1024)/3)%28); + eNB->UE_stats[1].dlsch_mcs1 = DLSCH_alloc_pdu1E.mcs; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); // set the precoder of the second UE orthogonal to the first - phy_vars_eNB->eNB_UE_stats[1].DL_pmi_single = (phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single ^ 0x1555); + eNB->UE_stats[1].DL_pmi_single = (eNB->UE_stats[0].DL_pmi_single ^ 0x1555); } break; //subframe switch @@ -519,7 +519,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e DCI_pdu->Num_ue_spec_dci = 1; //user 1 - if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) + if (eNB->frame_parms.frame_type == FDD) DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI0_5MHz_FDD_t ; else DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI0_5MHz_TDD_1_6_t ; @@ -531,9 +531,9 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; - UL_alloc_pdu.rballoc = computeRIV(25,2,phy_vars_eNB->ue_ul_nb_rb); - UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; - UL_alloc_pdu.ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + UL_alloc_pdu.rballoc = computeRIV(25,2,eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; + UL_alloc_pdu.ndi = eNB->proc[thread_id].frame_tx&1; UL_alloc_pdu.TPC = 0; UL_alloc_pdu.cshift = 0; UL_alloc_pdu.dai = 0; @@ -551,11 +551,11 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; if (cooperation_flag==0) - UL_alloc_pdu.rballoc = computeRIV(25,2+phy_vars_eNB->ue_ul_nb_rb,phy_vars_eNB->ue_ul_nb_rb); + UL_alloc_pdu.rballoc = computeRIV(25,2+eNB->ue_ul_nb_rb,eNB->ue_ul_nb_rb); else - UL_alloc_pdu.rballoc = computeRIV(25,0,phy_vars_eNB->ue_ul_nb_rb); - UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; - UL_alloc_pdu.ndi = phy_vars_eNB->proc[sched_subframe].frame_tx&1; + UL_alloc_pdu.rballoc = computeRIV(25,0,eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; + UL_alloc_pdu.ndi = eNB->proc[thread_id].frame_tx&1; UL_alloc_pdu.TPC = 0; if ((cooperation_flag==0) || (cooperation_flag==1)) UL_alloc_pdu.cshift = 0; @@ -580,12 +580,12 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_e */ } -void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eNB) +void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *eNB) { - int i; - //uint8_t cooperation_flag = phy_vars_eNB->cooperation_flag; - uint8_t transmission_mode = phy_vars_eNB->transmission_mode[0]; + + //uint8_t cooperation_flag = eNB->cooperation_flag; + uint8_t transmission_mode = eNB->transmission_mode[0]; //uint32_t rballoc = 0x00F0; //uint32_t rballoc2 = 0x000F; @@ -612,11 +612,11 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN DCI_pdu->dci_alloc[0].format = format1; DCI_pdu->dci_alloc[0].ra_flag = 0; - DLSCH_alloc_pdu.rballoc = phy_vars_eNB->ue_dl_rb_alloc; + DLSCH_alloc_pdu.rballoc = eNB->ue_dl_rb_alloc; DLSCH_alloc_pdu.TPC = 0; DLSCH_alloc_pdu.dai = 0; DLSCH_alloc_pdu.harq_pid = 1; - DLSCH_alloc_pdu.mcs = phy_vars_eNB->target_ue_dl_mcs; + DLSCH_alloc_pdu.mcs = eNB->target_ue_dl_mcs; DLSCH_alloc_pdu.ndi = 1; DLSCH_alloc_pdu.rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -633,7 +633,7 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN DLSCH_alloc_pdu.TPC = 0; DLSCH_alloc_pdu.dai = 0; DLSCH_alloc_pdu.harq_pid = 1; - DLSCH_alloc_pdu.mcs = phy_vars_eNB->target_ue_dl_mcs; + DLSCH_alloc_pdu.mcs = eNB->target_ue_dl_mcs; DLSCH_alloc_pdu.ndi = 1; DLSCH_alloc_pdu.rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -650,11 +650,11 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback DLSCH_alloc_pdu1E.rv = 0; DLSCH_alloc_pdu1E.ndi = 1; - DLSCH_alloc_pdu1E.mcs = phy_vars_eNB->target_ue_dl_mcs; + DLSCH_alloc_pdu1E.mcs = eNB->target_ue_dl_mcs; DLSCH_alloc_pdu1E.harq_pid = 1; DLSCH_alloc_pdu1E.dai = 0; DLSCH_alloc_pdu1E.TPC = 0; - DLSCH_alloc_pdu1E.rballoc = phy_vars_eNB->ue_dl_rb_alloc; + DLSCH_alloc_pdu1E.rballoc = eNB->ue_dl_rb_alloc; DLSCH_alloc_pdu1E.rah = 0; DLSCH_alloc_pdu1E.dl_power_off = 0; //0=second user present memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); @@ -669,7 +669,7 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); // set the precoder of the second UE orthogonal to the first - phy_vars_eNB->eNB_UE_stats[1].DL_pmi_single = (phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single ^ 0x1555); + eNB->UE_stats[1].DL_pmi_single = (eNB->UE_stats[0].DL_pmi_single ^ 0x1555); } break; @@ -706,8 +706,8 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; - UL_alloc_pdu.rballoc = computeRIV(25,0,phy_vars_eNB->ue_ul_nb_rb); - UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; + UL_alloc_pdu.rballoc = computeRIV(25,0,eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; UL_alloc_pdu.ndi = 1; UL_alloc_pdu.TPC = 0; UL_alloc_pdu.cshift = 0; @@ -726,10 +726,10 @@ void fill_dci_emos(DCI_PDU *DCI_pdu, uint8_t subframe, PHY_VARS_eNB *phy_vars_eN UL_alloc_pdu.type = 0; UL_alloc_pdu.hopping = 0; if (cooperation_flag==0) - UL_alloc_pdu.rballoc = computeRIV(25,2+phy_vars_eNB->ue_ul_nb_rb,phy_vars_eNB->ue_ul_nb_rb); + UL_alloc_pdu.rballoc = computeRIV(25,2+eNB->ue_ul_nb_rb,eNB->ue_ul_nb_rb); else - UL_alloc_pdu.rballoc = computeRIV(25,0,phy_vars_eNB->ue_ul_nb_rb); - UL_alloc_pdu.mcs = phy_vars_eNB->target_ue_ul_mcs; + UL_alloc_pdu.rballoc = computeRIV(25,0,eNB->ue_ul_nb_rb); + UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; UL_alloc_pdu.ndi = 1; UL_alloc_pdu.TPC = 0; if ((cooperation_flag==0) || (cooperation_flag==1)) diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c index e56606e262..860cf9d4a0 100755 --- a/openair1/SCHED/phy_procedures_lte_common.c +++ b/openair1/SCHED/phy_procedures_lte_common.c @@ -529,7 +529,7 @@ lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,unsigned char sub lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe) { - return(subframe_select(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe)); + return(subframe_select(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,subframe)); } @@ -595,20 +595,20 @@ double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE struct timeval ts; double sys_bw = 0; uint8_t N_RB_DL; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; - Mod_id = phy_vars_eNB->Mod_id; - CC_id = phy_vars_eNB->CC_id; - ref_timestamp_ms = phy_vars_eNB->ulsch_eNB[UE_id+1]->reference_timestamp_ms; + Mod_id = eNB->Mod_id; + CC_id = eNB->CC_id; + ref_timestamp_ms = eNB->ulsch[UE_id+1]->reference_timestamp_ms; for (i=0; i<13; i++) { - len += sprintf(&cqis[len]," %d ", phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].DL_subband_cqi[0][i]); + len += sprintf(&cqis[len]," %d ", eNB->UE_stats[(uint32_t)UE_id].DL_subband_cqi[0][i]); } len = 0; - for (i=0; ilte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) { - len += sprintf(&sub_powers[len]," %d ", phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]); + for (i=0; ilte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) { + len += sprintf(&sub_powers[len]," %d ", eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]); } gettimeofday(&ts, NULL); @@ -629,23 +629,23 @@ double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE "Wideband CQI (%d,%d), " "DL Subband CQI[13] %s \n", // "timestamp %d, (%d active subcarrier) %s \n" - phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms, + eNB->dlsch[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms, frame,subframe, UE_tx_power_dB, - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[0], - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[1], - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]), - dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]), - phy_vars_eNB->rx_total_gain_eNB_dB, - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset, // raw timing advance 1/sampling rate - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update, - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].DL_cqi[0],phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].DL_cqi[1], - phy_vars_eNB->PHY_measurements_eNB[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][0], - phy_vars_eNB->PHY_measurements_eNB[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][1], + eNB->UE_stats[(uint32_t)UE_id].UL_rssi[0], + eNB->UE_stats[(uint32_t)UE_id].UL_rssi[1], + dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]), + dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]), + eNB->rx_total_gain_eNB_dB, + eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset, // raw timing advance 1/sampling rate + eNB->UE_stats[(uint32_t)UE_id].timing_advance_update, + eNB->UE_stats[(uint32_t)UE_id].DL_cqi[0],eNB->UE_stats[(uint32_t)UE_id].DL_cqi[1], + eNB->measurements[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][0], + eNB->measurements[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][1], cqis); LOG_D(LOCALIZE, " PHY: timestamp %d, (%d active subcarrier) %s \n", current_timestamp_ms, - phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier, + eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier, sub_powers); N_RB_DL = frame_parms->N_RB_DL; @@ -668,75 +668,75 @@ double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE break; } - if ((current_timestamp_ms - ref_timestamp_ms > phy_vars_eNB->ulsch_eNB[UE_id+1]->aggregation_period_ms)) { + if ((current_timestamp_ms - ref_timestamp_ms > eNB->ulsch[UE_id+1]->aggregation_period_ms)) { // check the size of one list to be sure there was a message transmitted during the defined aggregation period // make the reference timestamp == current timestamp - phy_vars_eNB->ulsch_eNB[UE_id+1]->reference_timestamp_ms = current_timestamp_ms; + eNB->ulsch[UE_id+1]->reference_timestamp_ms = current_timestamp_ms; int i; for (i=0; i<10; i++) { - median_power = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[i]); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[i]); - median_rssi = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[i]); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[i]); - median_subcarrier_rss = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[i]); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[i]); - median_TA = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[i]); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[i]); - median_TA_update = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[i]); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[i]); + median_power = calculate_median(&eNB->ulsch[UE_id+1]->loc_rss_list[i]); + del(&eNB->ulsch[UE_id+1]->loc_rss_list[i]); + median_rssi = calculate_median(&eNB->ulsch[UE_id+1]->loc_rssi_list[i]); + del(&eNB->ulsch[UE_id+1]->loc_rssi_list[i]); + median_subcarrier_rss = calculate_median(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[i]); + del(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[i]); + median_TA = calculate_median(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[i]); + del(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[i]); + median_TA_update = calculate_median(&eNB->ulsch[UE_id+1]->loc_timing_update_list[i]); + del(&eNB->ulsch[UE_id+1]->loc_timing_update_list[i]); if (median_power != 0) - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list,median_power); + push_front(&eNB->ulsch[UE_id+1]->tot_loc_rss_list,median_power); if (median_rssi != 0) - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list,median_rssi); + push_front(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list,median_rssi); if (median_subcarrier_rss != 0) - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list,median_subcarrier_rss); + push_front(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list,median_subcarrier_rss); if (median_TA != 0) - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list,median_TA); + push_front(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list,median_TA); if (median_TA_update != 0) - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list,median_TA_update); + push_front(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list,median_TA_update); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[i]); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[i]); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[i]); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[i]); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[i]); + initialize(&eNB->ulsch[UE_id+1]->loc_rss_list[i]); + initialize(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[i]); + initialize(&eNB->ulsch[UE_id+1]->loc_rssi_list[i]); + initialize(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[i]); + initialize(&eNB->ulsch[UE_id+1]->loc_timing_update_list[i]); } - median_power = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list); - median_rssi = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list); - median_subcarrier_rss = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list); - median_TA = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list); - median_TA_update = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list); - del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list); + median_power = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_rss_list); + del(&eNB->ulsch[UE_id+1]->tot_loc_rss_list); + median_rssi = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list); + del(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list); + median_subcarrier_rss = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list); + del(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list); + median_TA = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list); + del(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list); + median_TA_update = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list); + del(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list); - initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list); + initialize(&eNB->ulsch[UE_id+1]->tot_loc_rss_list); + initialize(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list); + initialize(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list); + initialize(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list); + initialize(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list); double alpha = 2, power_distance, time_distance; // distance = 10^((Ptx - Prx - A)/10alpha), A is a constance experimentally evaluated - // A includes the rx gain (phy_vars_eNB->rx_total_gain_eNB_dB) and hardware calibration - power_distance = pow(10, ((UE_tx_power_dB - median_power - phy_vars_eNB->rx_total_gain_eNB_dB + 133)/(10.0*alpha))); + // A includes the rx gain (eNB->rx_total_gain_eNB_dB) and hardware calibration + power_distance = pow(10, ((UE_tx_power_dB - median_power - eNB->rx_total_gain_eNB_dB + 133)/(10.0*alpha))); /* current measurements shows constant UE_timing_offset = 18 and timing_advance_update = 11 at 1m. at 5m, timing_advance_update = 12*/ - //time_distance = (double) 299792458*(phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update)/(sys_bw*1000000); - time_distance = (double) abs(phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update - 11) * 4.89;// (3 x 108 x 1 / (15000 x 2048)) / 2 = 4.89 m + //time_distance = (double) 299792458*(eNB->UE_stats[(uint32_t)UE_id].timing_advance_update)/(sys_bw*1000000); + time_distance = (double) abs(eNB->UE_stats[(uint32_t)UE_id].timing_advance_update - 11) * 4.89;// (3 x 108 x 1 / (15000 x 2048)) / 2 = 4.89 m - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].distance.time_based = time_distance; - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].distance.power_based = power_distance; + eNB->UE_stats[(uint32_t)UE_id].distance.time_based = time_distance; + eNB->UE_stats[(uint32_t)UE_id].distance.power_based = power_distance; LOG_D(LOCALIZE, " PHY agg [UE %x/%d -> eNB %d], timestamp %d, " "frame %d, subframe %d " @@ -747,61 +747,61 @@ double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE "power estimated r = %0.3f, " " TA %d, update %d " "TA estimated r = %0.3f\n" - ,phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms, + ,eNB->dlsch[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms, frame, subframe, UE_tx_power_dB, median_rssi, median_power, - phy_vars_eNB->rx_total_gain_eNB_dB, + eNB->rx_total_gain_eNB_dB, power_distance, - phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset, median_TA_update, + eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset, median_TA_update, time_distance); return 0; } else { - avg_power = (dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]) + dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]))/2; - avg_rssi = (phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[0] + phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[1])/2; + avg_power = (dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]) + dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]))/2; + avg_rssi = (eNB->UE_stats[(uint32_t)UE_id].UL_rssi[0] + eNB->UE_stats[(uint32_t)UE_id].UL_rssi[1])/2; - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[subframe],avg_power); - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[subframe],avg_rssi); + push_front(&eNB->ulsch[UE_id+1]->loc_rss_list[subframe],avg_power); + push_front(&eNB->ulsch[UE_id+1]->loc_rssi_list[subframe],avg_rssi); - for (i=0; ilte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) { - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[subframe], phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]); + for (i=0; ilte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) { + push_front(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[subframe], eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]); } - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[subframe], phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset); - push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[subframe], phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update); + push_front(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[subframe], eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset); + push_front(&eNB->ulsch[UE_id+1]->loc_timing_update_list[subframe], eNB->UE_stats[(uint32_t)UE_id].timing_advance_update); return -1; } } #endif -LTE_eNB_UE_stats* get_eNB_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti) +LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti) { int8_t UE_id; if ((PHY_vars_eNB_g == NULL) || (PHY_vars_eNB_g[Mod_id] == NULL) || (PHY_vars_eNB_g[Mod_id][CC_id]==NULL)) { - LOG_E(PHY,"get_eNB_UE_stats: No phy_vars_eNB found (or not allocated) for Mod_id %d,CC_id %d\n",Mod_id,CC_id); + LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",Mod_id,CC_id); return NULL; } UE_id = find_ue(rnti, PHY_vars_eNB_g[Mod_id][CC_id]); if (UE_id == -1) { - // LOG_E(PHY,"get_eNB_UE_stats: UE with rnti %x not found\n",rnti); + // LOG_E(PHY,"get_UE_stats: UE with rnti %x not found\n",rnti); return NULL; } - return(&PHY_vars_eNB_g[Mod_id][CC_id]->eNB_UE_stats[(uint32_t)UE_id]); + return(&PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[(uint32_t)UE_id]); } -int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB) +int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *eNB) { uint8_t i; for (i=0; idlsch_eNB[i]) && - (phy_vars_eNB->dlsch_eNB[i][0]) && - (phy_vars_eNB->dlsch_eNB[i][0]->rnti==rnti)) { + if ((eNB->dlsch[i]) && + (eNB->dlsch[i][0]) && + (eNB->dlsch[i][0]->rnti==rnti)) { return(i); } } @@ -809,9 +809,9 @@ int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB) #ifdef CBA for (i=0; iulsch_eNB[i]) && // ue J is the representative of group j - (phy_vars_eNB->ulsch_eNB[i]->num_active_cba_groups) && - (phy_vars_eNB->ulsch_eNB[i]->cba_rnti[i]== rnti)) + if ((eNB->ulsch[i]) && // ue J is the representative of group j + (eNB->ulsch[i]->num_active_cba_groups) && + (eNB->ulsch[i]->cba_rnti[i]== rnti)) return(i); } @@ -823,7 +823,7 @@ int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB) LTE_DL_FRAME_PARMS* get_lte_frame_parms(module_id_t Mod_id, uint8_t CC_id) { - return(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms); + return(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms); } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 619ef6578d..d26980b0f8 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -61,9 +61,6 @@ #if defined(ENABLE_ITTI) # include "intertask_interface.h" -# if ENABLE_RAL -# include "timer.h" -# endif #endif //#define DIAG_PHY @@ -72,8 +69,11 @@ #define PUCCH 1 +void exit_fun(const char* s); + extern int exit_openair; +extern openair0_device openair0; unsigned char dlsch_input_buffer[2700] __attribute__ ((aligned(32))); int eNB_sync_buffer0[640*6] __attribute__ ((aligned(32))); @@ -101,30 +101,31 @@ extern uint8_t smbv_frame_cnt; extern int rx_sig_fifo; #endif -uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t sched_subframe) +uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,uint8_t UE_id,uint8_t thread_id) { - const int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; - const int frame = phy_vars_eNB->proc[sched_subframe].frame_rx; + eNB_proc_t *proc = &eNB->proc[thread_id]; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking for SR TXOp(sr_ConfigIndex %d)\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->ulsch_eNB[UE_id]->rnti,frame,subframe, - phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex); + eNB->Mod_id,eNB->ulsch[UE_id]->rnti,frame,subframe, + eNB->scheduling_request_config[UE_id].sr_ConfigIndex); - if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 4) { // 5 ms SR period - if ((subframe%5) == phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex) + if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 4) { // 5 ms SR period + if ((subframe%5) == eNB->scheduling_request_config[UE_id].sr_ConfigIndex) return(1); - } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 14) { // 10 ms SR period - if (subframe==(phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-5)) + } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 14) { // 10 ms SR period + if (subframe==(eNB->scheduling_request_config[UE_id].sr_ConfigIndex-5)) return(1); - } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 34) { // 20 ms SR period - if ((10*(frame&1)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-15)) + } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 34) { // 20 ms SR period + if ((10*(frame&1)+subframe) == (eNB->scheduling_request_config[UE_id].sr_ConfigIndex-15)) return(1); - } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 74) { // 40 ms SR period - if ((10*(frame&3)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-35)) + } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 74) { // 40 ms SR period + if ((10*(frame&3)+subframe) == (eNB->scheduling_request_config[UE_id].sr_ConfigIndex-35)) return(1); - } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 154) { // 80 ms SR period - if ((10*(frame&7)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-75)) + } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 154) { // 80 ms SR period + if ((10*(frame&7)+subframe) == (eNB->scheduling_request_config[UE_id].sr_ConfigIndex-75)) return(1); } @@ -155,37 +156,37 @@ void remove_harq_pid_from_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid) DLSCH_ptr->head_freelist = (DLSCH_ptr->head_freelist + 1) % 10; } -int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB) +int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB) { uint8_t i; #ifdef DEBUG_PHY_PROC LOG_I(PHY,"[eNB %d/%d] Adding UE with rnti %x\n", - phy_vars_eNB->Mod_id, - phy_vars_eNB->CC_id, + eNB->Mod_id, + eNB->CC_id, (uint16_t)rnti); #endif for (i=0; idlsch_eNB[i]==NULL) || (phy_vars_eNB->ulsch_eNB[i]==NULL)) { + if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) { MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed add ue %"PRIx16" (ENOMEM)", rnti); LOG_E(PHY,"Can't add UE, not enough memory allocated\n"); return(-1); } else { - if (phy_vars_eNB->eNB_UE_stats[i].crnti==0) { + if (eNB->UE_stats[i].crnti==0) { MSC_LOG_EVENT(MSC_PHY_ENB, "0 Add ue %"PRIx16" ", rnti); LOG_D(PHY,"UE_id %d associated with rnti %x\n",i, (uint16_t)rnti); - phy_vars_eNB->dlsch_eNB[i][0]->rnti = rnti; - phy_vars_eNB->ulsch_eNB[i]->rnti = rnti; - phy_vars_eNB->eNB_UE_stats[i].crnti = rnti; + eNB->dlsch[i][0]->rnti = rnti; + eNB->ulsch[i]->rnti = rnti; + eNB->UE_stats[i].crnti = rnti; - phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH1_below = 0; - phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH1_above = (int32_t)pow(10.0,.1*(phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH+phy_vars_eNB->rx_total_gain_eNB_dB)); - phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH = (int32_t)pow(10.0,.1*(phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH+phy_vars_eNB->rx_total_gain_eNB_dB)); + eNB->UE_stats[i].Po_PUCCH1_below = 0; + eNB->UE_stats[i].Po_PUCCH1_above = (int32_t)pow(10.0,.1*(eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+eNB->rx_total_gain_dB)); + eNB->UE_stats[i].Po_PUCCH = (int32_t)pow(10.0,.1*(eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+eNB->rx_total_gain_dB)); LOG_D(PHY,"Initializing Po_PUCCH: p0_NominalPUCCH %d, gain %d => %d\n", - phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - phy_vars_eNB->rx_total_gain_eNB_dB, - phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH); + eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, + eNB->rx_total_gain_dB, + eNB->UE_stats[i].Po_PUCCH); return(i); } @@ -197,33 +198,33 @@ int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB) int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) { uint8_t i; int j,CC_id; - PHY_VARS_eNB *phy_vars_eNB; + PHY_VARS_eNB *eNB; for (CC_id=0;CC_iddlsch_eNB[i]==NULL) || (phy_vars_eNB->ulsch_eNB[i]==NULL)) { + if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) { MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (ENOMEM)", rnti); LOG_E(PHY,"Can't remove UE, not enough memory allocated\n"); return(-1); } else { - if (phy_vars_eNB->eNB_UE_stats[i].crnti==rntiP) { + if (eNB->UE_stats[i].crnti==rntiP) { MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP); #ifdef DEBUG_PHY_PROC - LOG_I(PHY,"eNB %d removing UE %d with rnti %x\n",phy_vars_eNB->Mod_id,i,rnti); + LOG_I(PHY,"eNB %d removing UE %d with rnti %x\n",eNB->Mod_id,i,rnti); #endif //LOG_D(PHY,("[PHY] UE_id %d\n",i); - clean_eNb_dlsch(phy_vars_eNB->dlsch_eNB[i][0]); - clean_eNb_ulsch(phy_vars_eNB->ulsch_eNB[i]); - //phy_vars_eNB->eNB_UE_stats[i].crnti = 0; - memset(&phy_vars_eNB->eNB_UE_stats[i],0,sizeof(LTE_eNB_UE_stats)); + clean_eNb_dlsch(eNB->dlsch[i][0]); + clean_eNb_ulsch(eNB->ulsch[i]); + //eNB->UE_stats[i].crnti = 0; + memset(&eNB->UE_stats[i],0,sizeof(LTE_eNB_UE_stats)); // mac_exit_wrapper("Removing UE"); /* clear the harq pid freelist */ - phy_vars_eNB->dlsch_eNB[i][0]->head_freelist = 0; - phy_vars_eNB->dlsch_eNB[i][0]->tail_freelist = 0; + eNB->dlsch[i][0]->head_freelist = 0; + eNB->dlsch[i][0]->tail_freelist = 0; for (j = 0; j < 8; j++) - put_harq_pid_in_freelist(phy_vars_eNB->dlsch_eNB[i][0], j); + put_harq_pid_in_freelist(eNB->dlsch[i][0], j); return(i); } @@ -234,15 +235,15 @@ int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) { return(-1); } -int8_t find_next_ue_index(PHY_VARS_eNB *phy_vars_eNB) +int8_t find_next_ue_index(PHY_VARS_eNB *eNB) { uint8_t i; for (i=0; ieNB_UE_stats[i].crnti==0) { - /*if ((phy_vars_eNB->dlsch_eNB[i]) && - (phy_vars_eNB->dlsch_eNB[i][0]) && - (phy_vars_eNB->dlsch_eNB[i][0]->rnti==0))*/ + if (eNB->UE_stats[i].crnti==0) { + /*if ((eNB->dlsch[i]) && + (eNB->dlsch[i][0]) && + (eNB->dlsch[i][0]->rnti==0))*/ LOG_D(PHY,"Next free UE id is %d\n",i); return(i); } @@ -267,7 +268,7 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16 } if (ul_flag == 0) {// this is a DL request - DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch_eNB[(uint32_t)UE_id][0]; + DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0]; // set to no available process first *harq_pid = -1; @@ -305,11 +306,11 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16 frame,subframe,*harq_pid); } else { // This is a UL request - ULSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->ulsch_eNB[(uint32_t)UE_id]; - ulsch_subframe = pdcch_alloc2ul_subframe(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe); - ulsch_frame = pdcch_alloc2ul_frame(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,frame,subframe); + ULSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[(uint32_t)UE_id]; + ulsch_subframe = pdcch_alloc2ul_subframe(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,subframe); + ulsch_frame = pdcch_alloc2ul_frame(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,frame,subframe); // Note this is for TDD configuration 3,4,5 only - *harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms, + *harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms, ulsch_frame, ulsch_subframe); *round = ULSCH_ptr->harq_processes[*harq_pid]->round; @@ -321,18 +322,16 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16 int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id) { - //return PHY_vars_eNB_g[module_idP][CC_id]->PHY_measurements_eNB[0].n0_power_tot_dBm; - return PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.ul_power_control_config_common.p0_NominalPUSCH; + return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH; } int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id) { - //return PHY_vars_eNB_g[module_idP][CC_id]->PHY_measurements_eNB[0].n0_power_tot_dBm; - return PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH; + return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH; } #ifdef EMOS -void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *phy_vars_eNB) +void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB) { } @@ -340,27 +339,27 @@ void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *phy_vars_e -void phy_procedures_eNB_S_RX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type) +void phy_procedures_eNB_S_RX(unsigned char thread_id,PHY_VARS_eNB *eNB,uint8_t abstraction_flag,relaying_type_t r_type) { UNUSED(r_type); - - int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx; + eNB_proc_t *proc = &eNB->proc[thread_id]; + int subframe = proc->subframe_rx; #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_rx, subframe); + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", eNB->Mod_id,proc->frame_rx, subframe); #endif if (abstraction_flag == 0) { - lte_eNB_I0_measurements(phy_vars_eNB, + lte_eNB_I0_measurements(eNB, subframe, 0, - phy_vars_eNB->first_run_I0_measurements); + eNB->first_run_I0_measurements); } #ifdef PHY_ABSTRACTION else { - lte_eNB_I0_measurements_emul(phy_vars_eNB, + lte_eNB_I0_measurements_emul(eNB, 0); } @@ -372,12 +371,12 @@ void phy_procedures_eNB_S_RX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars #ifdef EMOS -void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *phy_vars_eNB) +void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *eNB) { uint8_t aa; uint16_t last_subframe_emos; - uint16_t pilot_pos1 = 3 - phy_vars_eNB->lte_frame_parms.Ncp, pilot_pos2 = 10 - 2*phy_vars_eNB->lte_frame_parms.Ncp; + uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp; uint32_t bytes; last_subframe_emos=0; @@ -389,37 +388,37 @@ void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *phy_vars_eN //if (last_slot%2==1) // this is for all UL subframes if (subframe==3) - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { - memcpy(&emos_dump_eNB.channel[aa][last_subframe_emos*2*phy_vars_eNB->lte_frame_parms.N_RB_UL*12], - &phy_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][aa][phy_vars_eNB->lte_frame_parms.N_RB_UL*12*pilot_pos1], - phy_vars_eNB->lte_frame_parms.N_RB_UL*12*sizeof(int)); - memcpy(&emos_dump_eNB.channel[aa][(last_subframe_emos*2+1)*phy_vars_eNB->lte_frame_parms.N_RB_UL*12], - &phy_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][aa][phy_vars_eNB->lte_frame_parms.N_RB_UL*12*pilot_pos2], - phy_vars_eNB->lte_frame_parms.N_RB_UL*12*sizeof(int)); + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { + memcpy(&emos_dump_eNB.channel[aa][last_subframe_emos*2*eNB->frame_parms.N_RB_UL*12], + &eNB->pusch_vars[0]->drs_ch_estimates[0][aa][eNB->frame_parms.N_RB_UL*12*pilot_pos1], + eNB->frame_parms.N_RB_UL*12*sizeof(int)); + memcpy(&emos_dump_eNB.channel[aa][(last_subframe_emos*2+1)*eNB->frame_parms.N_RB_UL*12], + &eNB->pusch_vars[0]->drs_ch_estimates[0][aa][eNB->frame_parms.N_RB_UL*12*pilot_pos2], + eNB->frame_parms.N_RB_UL*12*sizeof(int)); } #endif if (subframe==4) { emos_dump_eNB.timestamp = rt_get_time_ns(); - emos_dump_eNB.frame_tx = phy_vars_eNB->proc[subframe].frame_rx; - emos_dump_eNB.rx_total_gain_dB = phy_vars_eNB->rx_total_gain_eNB_dB; - emos_dump_eNB.mimo_mode = phy_vars_eNB->transmission_mode[0]; - memcpy(&emos_dump_eNB.PHY_measurements_eNB, - &phy_vars_eNB->PHY_measurements_eNB[0], + emos_dump_eNB.frame_tx = eNB->proc[subframe].frame_rx; + emos_dump_eNB.rx_total_gain_dB = eNB->rx_total_gain_dB; + emos_dump_eNB.mimo_mode = eNB->transmission_mode[0]; + memcpy(&emos_dump_eNB.measurements, + &eNB->measurements[0], sizeof(PHY_MEASUREMENTS_eNB)); - memcpy(&emos_dump_eNB.eNB_UE_stats[0],&phy_vars_eNB->eNB_UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats)); + memcpy(&emos_dump_eNB.UE_stats[0],&eNB->UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats)); bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_eNB, sizeof(fifo_dump_emos_eNB)); //bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, "test", sizeof("test")); if (bytes!=sizeof(fifo_dump_emos_eNB)) { LOG_W(PHY,"[eNB %d] Frame %d, subframe %d, Problem writing EMOS data to FIFO (bytes=%d, size=%d)\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[(subframe+1)%10].frame_rx, subframe,bytes,sizeof(fifo_dump_emos_eNB)); + eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, subframe,bytes,sizeof(fifo_dump_emos_eNB)); } else { - if (phy_vars_eNB->proc[(subframe+1)%10].frame_tx%100==0) { + if (eNB->proc[(subframe+1)%10].frame_tx%100==0) { LOG_I(PHY,"[eNB %d] Frame %d (%d), subframe %d, Writing %d bytes EMOS data to FIFO\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[(subframe+1)%10].frame_rx, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, subframe, bytes); + eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, subframe, bytes); } } } @@ -433,148 +432,22 @@ int QPSK[4]= {AMP_OVER_SQRT2|(AMP_OVER_SQRT2<<16),AMP_OVER_SQRT2|((65536-AMP_OVE int QPSK2[4]= {AMP_OVER_2|(AMP_OVER_2<<16),AMP_OVER_2|((65536-AMP_OVER_2)<<16),((65536-AMP_OVER_2)<<16)|AMP_OVER_2,((65536-AMP_OVER_2)<<16)|(65536-AMP_OVER_2)}; -#if defined(ENABLE_ITTI) -# if ENABLE_RAL -extern PHY_MEASUREMENTS PHY_measurements; - -void phy_eNB_lte_measurement_thresholds_test_and_report(instance_t instanceP, ral_threshold_phy_t* threshold_phy_pP, uint16_t valP) -{ - MessageDef *message_p = NULL; - - if ( - ( - ((threshold_phy_pP->threshold.threshold_val < valP) && (threshold_phy_pP->threshold.threshold_xdir == RAL_ABOVE_THRESHOLD)) || - ((threshold_phy_pP->threshold.threshold_val > valP) && (threshold_phy_pP->threshold.threshold_xdir == RAL_BELOW_THRESHOLD)) - ) || - (threshold_phy_pP->threshold.threshold_xdir == RAL_NO_THRESHOLD) - ) { - message_p = itti_alloc_new_message(TASK_PHY_ENB , PHY_MEAS_REPORT_IND); - memset(&PHY_MEAS_REPORT_IND(message_p), 0, sizeof(PHY_MEAS_REPORT_IND(message_p))); - - memcpy(&PHY_MEAS_REPORT_IND (message_p).threshold, - &threshold_phy_pP->threshold, - sizeof(PHY_MEAS_REPORT_IND (message_p).threshold)); - - memcpy(&PHY_MEAS_REPORT_IND (message_p).link_param, - &threshold_phy_pP->link_param, - sizeof(PHY_MEAS_REPORT_IND (message_p).link_param)); - \ - - switch (threshold_phy_pP->link_param.choice) { - case RAL_LINK_PARAM_CHOICE_LINK_PARAM_VAL: - PHY_MEAS_REPORT_IND (message_p).link_param._union.link_param_val = valP; - break; - - case RAL_LINK_PARAM_CHOICE_QOS_PARAM_VAL: - //PHY_MEAS_REPORT_IND (message_p).link_param._union.qos_param_val. - AssertFatal (1 == 0, "TO DO RAL_LINK_PARAM_CHOICE_QOS_PARAM_VAL\n"); - break; - } - - itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p); - } -} - -void phy_eNB_lte_check_measurement_thresholds(instance_t instanceP, ral_threshold_phy_t* threshold_phy_pP) -{ - unsigned int mod_id; - - mod_id = instanceP; - - switch (threshold_phy_pP->link_param.link_param_type.choice) { - - case RAL_LINK_PARAM_TYPE_CHOICE_GEN: - switch (threshold_phy_pP->link_param.link_param_type._union.link_param_gen) { - case RAL_LINK_PARAM_GEN_DATA_RATE: - phy_eNB_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0); - break; - - case RAL_LINK_PARAM_GEN_SIGNAL_STRENGTH: - phy_eNB_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0); - break; - - case RAL_LINK_PARAM_GEN_SINR: - phy_eNB_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0); - break; - - case RAL_LINK_PARAM_GEN_THROUGHPUT: - break; - - case RAL_LINK_PARAM_GEN_PACKET_ERROR_RATE: - break; - - default: - ; - } - - break; - - case RAL_LINK_PARAM_TYPE_CHOICE_LTE: - switch (threshold_phy_pP->link_param.link_param_type._union.link_param_gen) { - case RAL_LINK_PARAM_LTE_UE_RSRP: - break; - - case RAL_LINK_PARAM_LTE_UE_RSRQ: - break; - - case RAL_LINK_PARAM_LTE_UE_CQI: - break; - - case RAL_LINK_PARAM_LTE_AVAILABLE_BW: - break; - - case RAL_LINK_PARAM_LTE_PACKET_DELAY: - break; - - case RAL_LINK_PARAM_LTE_PACKET_LOSS_RATE: - break; - - case RAL_LINK_PARAM_LTE_L2_BUFFER_STATUS: - break; - - case RAL_LINK_PARAM_LTE_MOBILE_NODE_CAPABILITIES: - break; - - case RAL_LINK_PARAM_LTE_EMBMS_CAPABILITY: - break; - - case RAL_LINK_PARAM_LTE_JUMBO_FEASIBILITY: - break; - - case RAL_LINK_PARAM_LTE_JUMBO_SETUP_STATUS: - break; - - case RAL_LINK_PARAM_LTE_NUM_ACTIVE_EMBMS_RECEIVERS_PER_FLOW: - break; - - default: - ; - } - - break; - - default: - ; - } -} -# endif -#endif - unsigned int taus(void); -void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int sched_subframe,int abstraction_flag,relaying_type_t r_type) { +void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int thread_id,int abstraction_flag,relaying_type_t r_type) { #ifdef Rel10 MCH_PDU *mch_pduP; MCH_PDU mch_pdu; // uint8_t sync_area=255; #endif + eNB_proc_t *proc = &eNB->proc[thread_id]; if (abstraction_flag==0) { // This is DL-Cell spec pilots in Control region generate_pilots_slot(eNB, - eNB->lte_eNB_common_vars.txdataF[0], + eNB->common_vars.txdataF[0], AMP, subframe<<1,1); } @@ -584,18 +457,18 @@ void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int sched_s // when mcch is active, MAC sched does not allow MCCH and MTCH multiplexing mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id, eNB->CC_id, - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, subframe); switch (r_type) { case no_relay: if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0 LOG_I(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n", - eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->mcs, - eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3); + eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs, + eNB->dlsch_MCH->harq_processes[0]->TBS>>3); else { LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n", - eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->sync_area, + eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->sync_area, (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment"); mch_pduP = NULL; } @@ -626,7 +499,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int sched_s default: LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n", - eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,r_type); + eNB->Mod_id,proc->frame_tx,subframe,r_type); mch_pduP=NULL; break; }// switch @@ -634,19 +507,20 @@ void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int sched_s if (mch_pduP) { fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0, abstraction_flag); // Generate PMCH - generate_mch(eNB,sched_subframe,(uint8_t*)mch_pduP->payload,abstraction_flag); + generate_mch(eNB,thread_id,(uint8_t*)mch_pduP->payload,abstraction_flag); } else { - LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",eNB->proc[sched_subframe].frame_tx,subframe); + LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe); } #endif } -void common_signal_procedures (int subframe,int sched_subframe,PHY_VARS_eNB *eNB,int abstraction_flag) { +void common_signal_procedures (int subframe,int thread_id,PHY_VARS_eNB *eNB,int abstraction_flag) { - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; - int **txdataF = eNB->lte_eNB_common_vars.txdataF[0]; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int **txdataF = eNB->common_vars.txdataF[0]; uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; + eNB_proc_t *proc = &eNB->proc[thread_id]; // generate Cell-Specific Reference Signals for both slots if (abstraction_flag==0) { @@ -683,7 +557,7 @@ void common_signal_procedures (int subframe,int sched_subframe,PHY_VARS_eNB *eNB } // generate PBCH (Physical Broadcast CHannel) info - if ((eNB->proc[sched_subframe].frame_tx&3) == 0) { + if ((proc->frame_tx&3) == 0) { pbch_pdu[2] = 0; // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators @@ -743,8 +617,8 @@ void common_signal_procedures (int subframe,int sched_subframe,PHY_VARS_eNB *eNB break; } - pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((eNB->proc[sched_subframe].frame_tx>>8)&0x3); - pbch_pdu[1] = eNB->proc[sched_subframe].frame_tx&0xfc; + pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((proc->frame_tx>>8)&0x3); + pbch_pdu[1] = proc->frame_tx&0xfc; pbch_pdu[0] = 0; } @@ -761,12 +635,12 @@ void common_signal_procedures (int subframe,int sched_subframe,PHY_VARS_eNB *eNB /// generate PBCH if (abstraction_flag==0) { - generate_pbch(&eNB->lte_eNB_pbch, + generate_pbch(&eNB->pbch, txdataF, AMP, fp, pbch_pdu, - eNB->proc[sched_subframe].frame_tx&3); + proc->frame_tx&3); } #ifdef PHY_ABSTRACTION else { @@ -791,12 +665,12 @@ void common_signal_procedures (int subframe,int sched_subframe,PHY_VARS_eNB *eNB (abstraction_flag==0)) { generate_pss(txdataF, AMP, - &eNB->lte_frame_parms, + &eNB->frame_parms, (fp->Ncp==NORMAL) ? 6 : 5, 10); generate_sss(txdataF, AMP, - &eNB->lte_frame_parms, + &eNB->frame_parms, (fp->Ncp==NORMAL) ? 5 : 4, 10); @@ -826,9 +700,10 @@ void common_signal_procedures (int subframe,int sched_subframe,PHY_VARS_eNB *eNB } -void generate_eNB_dlsch_params(const int frame,const int subframe,int sched_subframe,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { +void generate_eNB_dlsch_params(const int frame,const int subframe,int thread_id,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc[thread_id]; // if we have SI_RNTI, configure dlsch parameters and CCE index if (dci_alloc->rnti == SI_RNTI) { @@ -838,25 +713,25 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int sched_subf &dci_alloc->dci_pdu[0], dci_alloc->rnti, dci_alloc->format, - &eNB->dlsch_eNB_SI, + &eNB->dlsch_SI, fp, eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); - eNB->dlsch_eNB_SI->nCCE[subframe] = dci_alloc->firstCCE; + eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE; - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe, - eNB->dlsch_eNB_SI->nCCE[subframe]); + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"\n",eNB->Mod_id,proc->frame_tx,subframe, + eNB->dlsch_SI->nCCE[subframe]); #if defined(SMBV) // configure SI DCI - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",proc->frame_tx,subframe,i); smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", dci_alloc, i); } @@ -871,24 +746,24 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int sched_subf &dci_alloc->dci_pdu[0], dci_alloc->rnti, dci_alloc->format, - &eNB->dlsch_eNB_ra, + &eNB->dlsch_ra, fp, eNB->pdsch_config_dedicated, SI_RNTI, dci_alloc->rnti, P_RNTI, - eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); - eNB->dlsch_eNB_ra->nCCE[subframe] = dci_alloc->firstCCE; + eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE; - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe, - eNB->dlsch_eNB_ra->nCCE[subframe]); + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"\n",eNB->Mod_id,proc->frame_tx,subframe, + eNB->dlsch_ra->nCCE[subframe]); #if defined(SMBV) // configure RA DCI - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",proc->frame_tx,subframe,i); smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", dci_alloc, i); } @@ -906,8 +781,8 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int sched_subf if (UE_id>=0) { #if defined(SMBV) // Configure this user - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %"PRIu16" in TM%"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,subframe,(smbv_frame_cnt*10) + (subframe),UE_id+1, + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %"PRIu16" in TM%"PRIu8"\n",proc->frame_tx,subframe,(smbv_frame_cnt*10) + (subframe),UE_id+1, dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]); smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti); } @@ -920,27 +795,27 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int sched_subf &dci_alloc->dci_pdu[0], dci_alloc->rnti, dci_alloc->format, - eNB->dlsch_eNB[(uint8_t)UE_id], + eNB->dlsch[(uint8_t)UE_id], fp, eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - eNB->eNB_UE_stats[(uint8_t)UE_id].DL_pmi_single); + eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single); LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n", - eNB->Mod_id,dci_alloc->rnti,eNB->dlsch_eNB[(uint8_t)UE_id][0]->current_harq_pid,eNB->proc[sched_subframe].frame_tx,subframe); + eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,proc->frame_tx,subframe); - eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE; + eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE; - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe, - dci_alloc->rnti,eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]); + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",eNB->Mod_id,proc->frame_tx,subframe, + dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]); #if defined(SMBV) // configure UE-spec DCI - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",proc->frame_tx,subframe,i); smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1,dci_alloc, i); } @@ -948,31 +823,32 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int sched_subf LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n", eNB->Mod_id, dci_alloc->rnti, - eNB->proc[sched_subframe].frame_tx, subframe,UE_id, + proc->frame_tx, subframe,UE_id, dci_alloc->format, 1<L); } else { LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n", - eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,dci_alloc->rnti); + eNB->Mod_id,proc->frame_tx,dci_alloc->rnti); } } } -void generate_eNB_ulsch_params(const int frame,const int subframe,int sched_subframe,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { +void generate_eNB_ulsch_params(const int frame,const int subframe,int thread_id,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { int harq_pid; - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc[thread_id]; LOG_D(PHY, "[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8"), aggregation %d\n", eNB->Mod_id, subframe2harq_pid(fp, - pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe), + pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe), pdcch_alloc2ul_subframe(fp,subframe)), - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, subframe, - pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe), + pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe), pdcch_alloc2ul_subframe(fp,subframe), dci_alloc->rnti, dci_alloc->dci_pdu[0], @@ -980,7 +856,7 @@ void generate_eNB_ulsch_params(const int frame,const int subframe,int sched_subf generate_eNB_ulsch_params_from_dci(&dci_alloc->dci_pdu[0], dci_alloc->rnti, - sched_subframe, + thread_id, format0, UE_id, eNB, @@ -991,14 +867,14 @@ void generate_eNB_ulsch_params(const int frame,const int subframe,int sched_subf 0); // do_srs LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d\n", - eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,dci_alloc->rnti, + eNB->Mod_id,proc->frame_tx,subframe,dci_alloc->rnti, dci_alloc->firstCCE); #if defined(SMBV) // configure UE-spec DCI for UL Grant - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",eNB->proc[sched_subframe].frame_tx,subframe,i); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",proc->frame_tx,subframe,i); smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); } @@ -1007,27 +883,28 @@ void generate_eNB_ulsch_params(const int frame,const int subframe,int sched_subf // get the hard_pid for this subframe harq_pid = subframe2harq_pid(fp, - pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe), + pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe), pdcch_alloc2ul_subframe(fp,subframe)); if (harq_pid==255) { // should not happen, log an error and exit, this is a fatal error - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx); + LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,proc->frame_tx); mac_xface->macphy_exit("FATAL\n"); } if ((dci_alloc->rnti >= CBA_RNTI) && (dci_alloc->rnti < P_RNTI)) - eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1; + eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1; else - eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; } -void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int subframe,int sched_subframe,int num_pdcch_symbols,int abstraction_flag) { +void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int subframe,int thread_id,int num_pdcch_symbols,int abstraction_flag) { + eNB_proc_t *proc = &eNB->proc[thread_id]; int harq_pid = dlsch->current_harq_pid; LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid]; int input_buffer_length = dlsch_harq->TBS/8; - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t *DLSCH_pdu=NULL; uint8_t DLSCH_pdu_tmp[768*8]; uint8_t DLSCH_pdu_rar[256]; @@ -1036,13 +913,13 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t LOG_D(PHY, "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n", eNB->Mod_id, dlsch->rnti,harq_pid, - eNB->proc[sched_subframe].frame_tx, subframe, input_buffer_length, + proc->frame_tx, subframe, input_buffer_length, get_G(fp, dlsch_harq->nb_rb, dlsch_harq->rb_alloc, get_Qm(dlsch_harq->mcs), dlsch_harq->Nl, - num_pdcch_symbols,eNB->proc[sched_subframe].frame_tx,subframe), + num_pdcch_symbols,proc->frame_tx,subframe), dlsch_harq->nb_rb, dlsch_harq->mcs, pmi2hex_2Ar1(dlsch_harq->pmi_alloc), @@ -1054,14 +931,14 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t MSC_PHY_ENB,MSC_PHY_UE, NULL,0, "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")", - eNB->proc[sched_subframe].frame_tx, subframe, + proc->frame_tx, subframe, input_buffer_length, get_G(fp, dlsch_harq->nb_rb, dlsch_harq->rb_alloc, get_Qm(dlsch_harq->mcs), dlsch_harq->Nl, - num_pdcch_symbols,eNB->proc[sched_subframe].frame_tx,subframe), + num_pdcch_symbols,proc->frame_tx,subframe), dlsch_harq->nb_rb, dlsch_harq->mcs, pmi2hex_2Ar1(dlsch_harq->pmi_alloc), @@ -1080,14 +957,14 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t if (ra_flag == 0) { DLSCH_pdu = mac_xface->get_dlsch_sdu(eNB->Mod_id, eNB->CC_id, - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, dlsch->rnti, 0); } else { int16_t crnti = mac_xface->fill_rar(eNB->Mod_id, eNB->CC_id, - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, DLSCH_pdu_rar, fp->N_RB_UL, input_buffer_length); @@ -1104,32 +981,32 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t LOG_W(PHY,"[eNB] Max user count reached.\n"); mac_xface->cancel_ra_proc(eNB->Mod_id, eNB->CC_id, - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, crnti); } else { - eNB->eNB_UE_stats[(uint32_t)UE_id].mode = RA_RESPONSE; + eNB->UE_stats[(uint32_t)UE_id].mode = RA_RESPONSE; // Initialize indicator for first SR (to be cleared after ConnectionSetup is acknowledged) eNB->first_sr[(uint32_t)UE_id] = 1; generate_eNB_ulsch_params_from_rar(DLSCH_pdu, - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, (subframe), - eNB->ulsch_eNB[(uint32_t)UE_id], + eNB->ulsch[(uint32_t)UE_id], fp); - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active = 1; + eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1; get_Msg3_alloc(fp, subframe, - eNB->proc[sched_subframe].frame_tx, - &eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, - &eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); + proc->frame_tx, + &eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, + &eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n", - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, subframe, UE_id, - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); + eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, + eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); } if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS; } @@ -1144,9 +1021,9 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t #if defined(SMBV) // Configures the data source of allocation (allocation is configured by DCI) - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); - smbv_configure_datalist_for_user(smbv_fname, find_ue(dlsch->rnti,eNB)+1, DLSCH_pdu, input_buffer_length); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %"PRIu8"\n",proc->frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + // smbv_configure_datalist_for_user(smbv_fname, find_ue(dlsch->rnti,eNB)+1, DLSCH_pdu, input_buffer_length); } #endif @@ -1180,7 +1057,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t fp, num_pdcch_symbols, dlsch, - eNB->proc[sched_subframe].frame_tx,subframe, + proc->frame_tx,subframe, &eNB->dlsch_rate_matching_stats, &eNB->dlsch_turbo_encoding_stats, &eNB->dlsch_interleaving_stats); @@ -1195,14 +1072,14 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t dlsch_harq->rb_alloc, get_Qm(dlsch_harq->mcs), dlsch_harq->Nl, - num_pdcch_symbols,eNB->proc[sched_subframe].frame_tx,subframe), + num_pdcch_symbols,proc->frame_tx,subframe), 0, subframe<<1); stop_meas(&eNB->dlsch_scrambling_stats); start_meas(&eNB->dlsch_modulation_stats); - dlsch_modulation(eNB->lte_eNB_common_vars.txdataF[0], + dlsch_modulation(eNB->common_vars.txdataF[0], AMP, subframe, fp, @@ -1226,23 +1103,24 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t dlsch->active = 0; } -void phy_procedures_eNB_TX(unsigned char sched_subframe, +void phy_procedures_eNB_TX(unsigned char thread_id, PHY_VARS_eNB *eNB, uint8_t abstraction_flag, relaying_type_t r_type, PHY_VARS_RN *rn) { UNUSED(rn); - uint16_t input_buffer_length; + eNB_proc_t *proc = &eNB->proc[thread_id]; + // uint16_t input_buffer_length; uint32_t i,aa; uint8_t harq_pid; DCI_PDU *DCI_pdu; DCI_PDU DCI_pdu_tmp; - int8_t UE_id; + int8_t UE_id=0; uint8_t num_pdcch_symbols=0; uint8_t ul_subframe; uint32_t ul_frame; - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL; #if defined(SMBV) @@ -1250,8 +1128,8 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, // there is at least one allocation for PDCCH uint8_t smbv_alloc_cnt = 1; #endif - int frame = eNB->proc[sched_subframe].frame_tx; - int subframe = eNB->proc[sched_subframe].subframe_tx; + int frame = proc->frame_tx; + int subframe = proc->subframe_tx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,1); start_meas(&eNB->phy_proc_tx); @@ -1259,14 +1137,14 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, for (i=0; ieNB_UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) { + if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) { LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n", - eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->eNB_UE_stats[i].ulsch_consecutive_errors); - eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0; + eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors); + eNB->UE_stats[i].ulsch_consecutive_errors=0; mac_xface->UL_failure_indication(eNB->Mod_id, eNB->CC_id, frame, - eNB->eNB_UE_stats[i].crnti, + eNB->UE_stats[i].crnti, subframe); } @@ -1279,30 +1157,30 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, // This is called only for the CC_id = 0 and triggers scheduling for all CC_id's if (eNB->mac_enabled==1) { if (eNB->CC_id == 0) { - mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,eNB->proc[sched_subframe].frame_tx,subframe);//,1); + mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,proc->frame_tx,subframe);//,1); } } // clear the transmit data array for the current subframe if (abstraction_flag==0) { for (aa=0; aanb_antennas_tx_eNB; aa++) { - memset(&eNB->lte_eNB_common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], + memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], 0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t)); } } - if (is_pmch_subframe(eNB->proc[sched_subframe].frame_tx,subframe,fp)) { - pmch_procedures(eNB,rn,subframe,sched_subframe,abstraction_flag,r_type); + if (is_pmch_subframe(proc->frame_tx,subframe,fp)) { + pmch_procedures(eNB,rn,subframe,thread_id,abstraction_flag,r_type); } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH - common_signal_procedures(subframe,sched_subframe,eNB,abstraction_flag); + common_signal_procedures(subframe,thread_id,eNB,abstraction_flag); } #if defined(SMBV) // PBCH takes one allocation - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { if (subframe==0) smbv_alloc_cnt++; } @@ -1314,21 +1192,21 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1); DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id, eNB->CC_id, - eNB->proc[sched_subframe].frame_tx, + proc->frame_tx, subframe); } else { DCI_pdu = &DCI_pdu_tmp; #ifdef EMOS_CHANNEL - fill_dci_emos(DCI_pdu,sched_subframe,eNB); + fill_dci_emos(DCI_pdu,thread_id,eNB); #else - fill_dci(DCI_pdu,sched_subframe,eNB); + fill_dci(DCI_pdu,thread_id,eNB); #endif } // clear existing ulsch dci allocations before applying info from MAC (this is table ul_subframe = pdcch_alloc2ul_subframe(fp,subframe); - ul_frame = pdcch_alloc2ul_frame(fp,eNB->proc[sched_subframe].frame_tx,subframe); + ul_frame = pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe); if ((subframe_select(fp,ul_subframe)==SF_UL) || (fp->frame_type == FDD)) { @@ -1336,15 +1214,15 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, // clear DCI allocation maps for new subframe for (i=0; iulsch_eNB[i]) { - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc=0; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc=0; + if (eNB->ulsch[i]) { + eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc=0; + eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc=0; } } // clear previous allocation information for all UEs for (i=0; idlsch_eNB[i][0]->subframe_tx[subframe] = 0; + eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } @@ -1354,8 +1232,8 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, #if defined(SMBV) // Sets up PDCCH and DCI table - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) { - LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",proc->frame_tx,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); dump_dci(fp,&DCI_pdu->dci_alloc[0]); smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); } @@ -1380,7 +1258,7 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, } else UE_id=0; - generate_eNB_dlsch_params(frame,subframe,sched_subframe,eNB,dci_alloc,UE_id); + generate_eNB_dlsch_params(frame,subframe,thread_id,eNB,dci_alloc,UE_id); } @@ -1399,10 +1277,10 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, UE_id = i; if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,dci_alloc->rnti); + LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,proc->frame_tx,dci_alloc->rnti); mac_xface->macphy_exit("FATAL\n"); } - generate_eNB_ulsch_params(frame,subframe,sched_subframe,eNB,dci_alloc,UE_id); + generate_eNB_ulsch_params(frame,subframe,thread_id,eNB,dci_alloc,UE_id); } } @@ -1422,7 +1300,7 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, if (abstraction_flag == 0) { if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx, subframe, + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,proc->frame_tx, subframe, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci, @@ -1431,14 +1309,14 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, 0, AMP, fp, - eNB->lte_eNB_common_vars.txdataF[0], + eNB->common_vars.txdataF[0], subframe); } #ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious else { - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx, subframe); + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,proc->frame_tx, subframe); num_pdcch_symbols = generate_dci_top_emul(eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,subframe); } @@ -1448,15 +1326,15 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, // Check for SI activity - if (eNB->dlsch_eNB_SI->active == 1) { + if (eNB->dlsch_SI->active == 1) { - pdsch_procedures(eNB,eNB->dlsch_eNB_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,subframe,sched_subframe,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,subframe,thread_id,num_pdcch_symbols,abstraction_flag); #if defined(SMBV) // Configures the data source of allocation (allocation is configured by DCI) - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",proc->frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length); } @@ -1464,49 +1342,49 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, } // Check for RA activity - if (eNB->dlsch_eNB_ra->active == 1) { + if (eNB->dlsch_ra->active == 1) { #if defined(SMBV) // Configures the data source of allocation (allocation is configured by DCI) - if (smbv_is_config_frame(eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",eNB->proc[sched_subframe].frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",proc->frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length); } #endif - LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA) with input size = %"PRIu16",Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n", + LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n", eNB->Mod_id, - eNB->proc[sched_subframe].frame_tx, subframe,input_buffer_length, - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame, - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe); + proc->frame_tx, subframe, + eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, + eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); - pdsch_procedures(eNB,eNB->dlsch_eNB_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,subframe,sched_subframe,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,subframe,thread_id,num_pdcch_symbols,abstraction_flag); - eNB->dlsch_eNB_ra->active = 0; + eNB->dlsch_ra->active = 0; } // Now scan UE specific DLSCH for (UE_id=0; UE_iddlsch_eNB[(uint8_t)UE_id][0])&& - (eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti>0)&& - (eNB->dlsch_eNB[(uint8_t)UE_id][0]->active == 1)) { + if ((eNB->dlsch[(uint8_t)UE_id][0])&& + (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&& + (eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) { - pdsch_procedures(eNB,eNB->dlsch_eNB[(uint8_t)UE_id][0],eNB->dlsch_eNB[(uint8_t)UE_id][1],&eNB->eNB_UE_stats[(uint32_t)UE_id],0,subframe,sched_subframe,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,subframe,thread_id,num_pdcch_symbols,abstraction_flag); } - else if ((eNB->dlsch_eNB[(uint8_t)UE_id][0])&& - (eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti>0)&& - (eNB->dlsch_eNB[(uint8_t)UE_id][0]->active == 0)) { + else if ((eNB->dlsch[(uint8_t)UE_id][0])&& + (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&& + (eNB->dlsch[(uint8_t)UE_id][0]->active == 0)) { // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) - eNB->dlsch_eNB[(uint8_t)UE_id][0]->subframe_tx[subframe]=0; + eNB->dlsch[(uint8_t)UE_id][0]->subframe_tx[subframe]=0; } } @@ -1517,7 +1395,7 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, if (is_phich_subframe(fp,subframe)) { generate_phich_top(eNB, - sched_subframe, + thread_id, AMP, 0, abstraction_flag); @@ -1534,13 +1412,13 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, if (abstraction_flag==0) { start_meas(&eNB->ofdm_mod_stats); - do_OFDM_mod(eNB->lte_eNB_common_vars.txdataF[0], - eNB->lte_eNB_common_vars.txdata[0], - eNB->proc[sched_subframe].frame_tx,subframe<<1, + do_OFDM_mod(eNB->common_vars.txdataF[0], + eNB->common_vars.txdata[0], + proc->frame_tx,subframe<<1, fp); - do_OFDM_mod(eNB->lte_eNB_common_vars.txdataF[0], - eNB->lte_eNB_common_vars.txdata[0], - eNB->proc[sched_subframe].frame_tx,1+(subframe<<1), + do_OFDM_mod(eNB->common_vars.txdataF[0], + eNB->common_vars.txdata[0], + proc->frame_tx,1+(subframe<<1), fp); stop_meas(&eNB->ofdm_mod_stats); } @@ -1553,30 +1431,30 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe, } -void process_Msg3(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t UE_id, uint8_t harq_pid) +void process_Msg3(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t UE_id, uint8_t harq_pid) { // this prepares the demodulation of the first PUSCH of a new user, containing Msg3 - - int subframe = eNB->proc[sched_subframe].subframe_rx; - int frame = eNB->proc[sched_subframe].frame_rx; + eNB_proc_t *proc = &eNB->proc[thread_id]; + int subframe = proc->subframe_rx; + int frame = proc->frame_rx; LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n", eNB->Mod_id, frame,subframe, - UE_id,eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active, - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe, - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame); - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_flag = 0; + UE_id,eNB->ulsch[(uint32_t)UE_id]->Msg3_active, + eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe, + eNB->ulsch[(uint32_t)UE_id]->Msg3_frame); + eNB->ulsch[(uint32_t)UE_id]->Msg3_flag = 0; - if ((eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active == 1) && - (eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_subframe == subframe) && - (eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_frame == (uint32_t)frame)) { + if ((eNB->ulsch[(uint32_t)UE_id]->Msg3_active == 1) && + (eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe == subframe) && + (eNB->ulsch[(uint32_t)UE_id]->Msg3_frame == (uint32_t)frame)) { // harq_pid = 0; - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_active = 0; - eNB->ulsch_eNB[(uint32_t)UE_id]->Msg3_flag = 1; - eNB->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag=1; + eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 0; + eNB->ulsch[(uint32_t)UE_id]->Msg3_flag = 1; + eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag=1; LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n", eNB->Mod_id, frame,subframe,UE_id); @@ -1590,7 +1468,7 @@ void process_Msg3(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t UE_id, uint8_ // rate-adaptation based on the error statistics derived from the ACK/NAK process void process_HARQ_feedback(uint8_t UE_id, - uint8_t sched_subframe, + uint8_t thread_id, PHY_VARS_eNB *eNB, uint8_t pusch_flag, uint8_t *pucch_payload, @@ -1598,16 +1476,17 @@ void process_HARQ_feedback(uint8_t UE_id, uint8_t SR_payload) { - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + eNB_proc_t *proc = &eNB->proc[thread_id]; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe; - LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_eNB[(uint32_t)UE_id][0]; - LTE_eNB_UE_stats *ue_stats = &eNB->eNB_UE_stats[(uint32_t)UE_id]; + LTE_eNB_DLSCH_t *dlsch = eNB->dlsch[(uint32_t)UE_id][0]; + LTE_eNB_UE_stats *ue_stats = &eNB->UE_stats[(uint32_t)UE_id]; LTE_DL_eNB_HARQ_t *dlsch_harq_proc; uint8_t subframe_m4,M,m; int mp; int all_ACKed=1,nb_alloc=0,nb_ACK=0; - int frame = eNB->proc[sched_subframe].frame_rx; - int subframe = eNB->proc[sched_subframe].subframe_rx; + int frame = proc->frame_rx; + int subframe = proc->subframe_rx; int harq_pid = subframe2harq_pid( fp,frame,subframe); @@ -1618,7 +1497,7 @@ void process_HARQ_feedback(uint8_t UE_id, M=1; if (pusch_flag == 1) { - dlsch_ACK[0] = eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; + dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; if (dlsch->subframe_tx[subframe_m4]==1) LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUSCH for subframe %d\n",eNB->Mod_id, frame,dlsch_ACK[0],subframe_m4); @@ -1660,9 +1539,9 @@ void process_HARQ_feedback(uint8_t UE_id, // otherwise, it depends on how many of the PDSCH in the set are scheduled, we can leave it like this, // but we have to adapt the code below. For example, if only one out of 2 are scheduled, only 1 bit o_ACK is used - dlsch_ACK[0] = eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; + dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]; dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling) - ?eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]:eNB->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[1]; + ?eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]:eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[1]; } else { // PUCCH ACK/NAK @@ -1814,10 +1693,10 @@ void process_HARQ_feedback(uint8_t UE_id, dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq; ue_stats->total_TBS = ue_stats->total_TBS + - eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; + eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; /* ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits + - eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; + eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS; */ } @@ -1862,24 +1741,25 @@ void process_HARQ_feedback(uint8_t UE_id, void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, uint8_t UE_id, - uint8_t sched_subframe, + uint8_t thread_id, int16_t *n1_pucch0, int16_t *n1_pucch1, int16_t *n1_pucch2, int16_t *n1_pucch3) { - LTE_DL_FRAME_PARMS *frame_parms=&eNB->lte_frame_parms; + eNB_proc_t *proc = &eNB->proc[thread_id]; + LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms; uint8_t nCCE0,nCCE1; int sf; - int frame = eNB->proc[sched_subframe].frame_rx; - int subframe = eNB->proc[sched_subframe].subframe_rx; + int frame = proc->frame_rx; + int subframe = proc->subframe_rx; if (frame_parms->frame_type == FDD ) { sf = (subframe<4) ? (subframe+6) : (subframe-4); - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[sf]>0) { - *n1_pucch0 = frame_parms->pucch_config_common.n1PUCCH_AN + eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[sf]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[sf]>0) { + *n1_pucch0 = frame_parms->pucch_config_common.n1PUCCH_AN + eNB->dlsch[(uint32_t)UE_id][0]->nCCE[sf]; *n1_pucch1 = -1; } else { *n1_pucch0 = -1; @@ -1890,15 +1770,15 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, switch (frame_parms->tdd_config) { case 1: // DL:S:UL:UL:DL:DL:S:UL:UL:DL if (subframe == 2) { // ACK subframes 5 and 6 - /* if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[6]>0) { - nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[6]; + /* if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) { + nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch1 = -1;*/ - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[5]>0) { - nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[5]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) { + nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -1906,8 +1786,8 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, *n1_pucch1 = -1; } else if (subframe == 3) { // ACK subframe 9 - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[9]>0) { - nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[9]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) { + nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -1917,8 +1797,8 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, } else if (subframe == 7) { // ACK subframes 0 and 1 //harq_ack[0].nCCE; //harq_ack[1].nCCE; - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[0]>0) { - nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[0]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) { + nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -1926,8 +1806,8 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, *n1_pucch1 = -1; } else if (subframe == 8) { // ACK subframes 4 //harq_ack[4].nCCE; - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[4]>0) { - nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[4]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) { + nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -1945,43 +1825,43 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, case 3: // DL:S:UL:UL:UL:DL:DL:DL:DL:DL if (subframe == 2) { // ACK subframes 5,6 and 1 (S in frame-2), forget about n-11 for the moment (S-subframe) - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[6]>0) { - nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[6]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) { + nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch1 = -1; - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[5]>0) { - nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[5]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) { + nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; } else if (subframe == 3) { // ACK subframes 7 and 8 LOG_D(PHY,"get_n1_pucch_eNB : subframe 3, subframe_tx[7] %d, subframe_tx[8] %d\n", - eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[8]); + eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]); - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[8]>0) { - nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[8]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) { + nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; LOG_D(PHY,"nCCE1 %d, n1_pucch1 %d\n",nCCE1,*n1_pucch1); } else *n1_pucch1 = -1; - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[7]>0) { - nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[7]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) { + nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN; LOG_D(PHY,"nCCE0 %d, n1_pucch0 %d\n",nCCE0,*n1_pucch0); } else *n1_pucch0 = -1; } else if (subframe == 4) { // ACK subframes 9 and 0 - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[0]>0) { - nCCE1 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[0]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) { + nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0]; *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch1 = -1; - if (eNB->dlsch_eNB[(uint32_t)UE_id][0]->subframe_tx[9]>0) { - nCCE0 = eNB->dlsch_eNB[(uint32_t)UE_id][0]->nCCE[9]; + if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) { + nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9]; *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN; } else *n1_pucch0 = -1; @@ -2000,16 +1880,17 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, } } -void prach_procedures(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t abstraction_flag) +void prach_procedures(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t abstraction_flag) { - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint16_t preamble_energy_list[64],preamble_delay_list[64]; uint16_t preamble_max,preamble_energy_max; uint16_t i; int8_t UE_id; - int subframe = eNB->proc[sched_subframe].subframe_rx; - int frame = eNB->proc[sched_subframe].frame_rx; + eNB_proc_t *proc = &eNB->proc[thread_id]; + int subframe = proc->subframe_rx; + int frame = proc->frame_rx; uint8_t CC_id = eNB->CC_id; memset(&preamble_energy_list[0],0,64*sizeof(uint16_t)); @@ -2017,7 +1898,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t abstracti if (abstraction_flag == 0) { LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id, - frame,subframe,dB_fixed(signal_energy(&eNB->lte_eNB_common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_eNB_dB); + frame,subframe,dB_fixed(signal_energy(&eNB->common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_dB); rx_prach(eNB, @@ -2031,12 +1912,12 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t abstracti LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n", UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach, - PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.prach_config_common.rootSequenceIndex, + PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex, fp->prach_config_common.rootSequenceIndex, PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex); if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) && - (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.prach_config_common.rootSequenceIndex == + (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex == fp->prach_config_common.rootSequenceIndex) ) { preamble_energy_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 800; preamble_delay_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 5; @@ -2067,9 +1948,9 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t sched_subframe,uint8_t abstracti UE_id = find_next_ue_index(eNB); if (UE_id>=0) { - eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits + eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits - eNB->eNB_UE_stats[(uint32_t)UE_id].sector = 0; + eNB->UE_stats[(uint32_t)UE_id].sector = 0; LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, @@ -2128,9 +2009,9 @@ void ulsch_decoding_procedures(unsigned char subframe, unsigned int i, PHY_VARS_ } -void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0}; int16_t n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3; uint8_t do_SR = 0; @@ -2138,30 +2019,30 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U int32_t metric0=0,metric1=0,metric0_SR=0; ANFBmode_t bundling_flag; PUCCH_FMT_t format; + eNB_proc_t *proc = &eNB->proc[thread_id]; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; - const int subframe = eNB->proc[sched_subframe].subframe_rx; - const int frame = eNB->proc[sched_subframe].frame_rx; - - if ((eNB->dlsch_eNB[UE_id][0]) && - (eNB->dlsch_eNB[UE_id][0]->rnti>0) && - (eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { + if ((eNB->dlsch[UE_id][0]) && + (eNB->dlsch[UE_id][0]->rnti>0) && + (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { // check SR availability - do_SR = is_SR_subframe(eNB,UE_id,sched_subframe); + do_SR = is_SR_subframe(eNB,UE_id,thread_id); // do_SR = 0; // Now ACK/NAK // First check subframe_tx flag for earlier subframes get_n1_pucch_eNB(eNB, UE_id, - sched_subframe, + thread_id, &n1_pucch0, &n1_pucch1, &n1_pucch2, &n1_pucch3); LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n", - eNB->Mod_id,eNB->dlsch_eNB[UE_id][0]->rnti, + eNB->Mod_id,eNB->dlsch[UE_id][0]->rnti, frame,subframe, n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR); @@ -2198,7 +2079,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U } if (do_SR == 1) { - eNB->eNB_UE_stats[UE_id].sr_total++; + eNB->UE_stats[UE_id].sr_total++; if (abstraction_flag == 0) metric0_SR = rx_pucch(eNB, @@ -2218,35 +2099,35 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U pucch_format1, 0, &SR_payload, - sched_subframe); + thread_id); LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",eNB->Mod_id, - eNB->ulsch_eNB[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); + eNB->ulsch[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); } #endif if (SR_payload == 1) { LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id, - eNB->ulsch_eNB[UE_id]->rnti,frame,subframe); - eNB->eNB_UE_stats[UE_id].sr_received++; + eNB->ulsch[UE_id]->rnti,frame,subframe); + eNB->UE_stats[UE_id].sr_received++; if (eNB->first_sr[UE_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4 /* is this test necessary? */ - if (eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->status != SCH_IDLE) - put_harq_pid_in_freelist(eNB->dlsch_eNB[UE_id][0], 0); + if (eNB->dlsch[UE_id][0]->harq_processes[0]->status != SCH_IDLE) + put_harq_pid_in_freelist(eNB->dlsch[UE_id][0], 0); eNB->first_sr[UE_id] = 0; - eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->round=0; - eNB->dlsch_eNB[UE_id][0]->harq_processes[0]->status=SCH_IDLE; + eNB->dlsch[UE_id][0]->harq_processes[0]->round=0; + eNB->dlsch[UE_id][0]->harq_processes[0]->status=SCH_IDLE; LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n", eNB->Mod_id, - eNB->ulsch_eNB[UE_id]->rnti,frame,subframe); + eNB->ulsch[UE_id]->rnti,frame,subframe); } if (eNB->mac_enabled==1) { mac_xface->SR_indication(eNB->Mod_id, eNB->CC_id, frame, - eNB->dlsch_eNB[UE_id][0]->rnti,subframe); + eNB->dlsch[UE_id][0]->rnti,subframe); } } }// do_SR==1 @@ -2296,12 +2177,12 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n", eNB->Mod_id, - eNB->dlsch_eNB[UE_id][0]->rnti, + eNB->dlsch[UE_id][0]->rnti, frame,subframe, pucch_payload0[0],metric0); #endif - process_HARQ_feedback(UE_id,sched_subframe,eNB, + process_HARQ_feedback(UE_id,thread_id,eNB, 0,// pusch_flag pucch_payload0, 2, @@ -2326,7 +2207,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U if (SR_payload==1) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",eNB->Mod_id, - eNB->dlsch_eNB[UE_id][0]->rnti, + eNB->dlsch[UE_id][0]->rnti, frame,subframe, n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format); #endif @@ -2353,7 +2234,7 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U } else { //using n1_pucch0/n1_pucch1 resources #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",eNB->Mod_id, - eNB->dlsch_eNB[UE_id][0]->rnti, + eNB->dlsch[UE_id][0]->rnti, frame,subframe, n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format); #endif @@ -2428,11 +2309,11 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",eNB->Mod_id, - eNB->dlsch_eNB[UE_id][0]->rnti, + eNB->dlsch[UE_id][0]->rnti, frame,subframe, metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]); #endif - process_HARQ_feedback(UE_id,sched_subframe,eNB, + process_HARQ_feedback(UE_id,thread_id,eNB, 0,// pusch_flag pucch_payload, pucch_sel, @@ -2443,37 +2324,38 @@ void pucch_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int U } } -void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void cba_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { + eNB_proc_t *proc = &eNB->proc[thread_id]; uint8_t access_mode; int num_active_cba_groups; - const int subframe = eNB->proc[sched_subframe].subframe_rx; - const int frame = eNB->proc[sched_subframe].frame_rx; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; uint16_t rnti=0; int ret=0; - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - num_active_cba_groups = eNB->ulsch_eNB[UE_id]->num_active_cba_groups; + num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups; - if ((eNB->ulsch_eNB[UE_id]) && + if ((eNB->ulsch[UE_id]) && (num_active_cba_groups > 0) && - (eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups]>0) && - (eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1)) { + (eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]>0) && + (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1)) { rnti=0; #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Checking PUSCH/ULSCH CBA Reception for UE %d with cba rnti %x mode %s\n", eNB->Mod_id,harq_pid, frame,subframe, - UE_id, (uint16_t)eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->eNB_UE_stats[UE_id].mode]); + UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]); #endif if (abstraction_flag==0) { rx_ulsch(eNB, - sched_subframe, - eNB->eNB_UE_stats[UE_id].sector, // this is the effective sector id + thread_id, + eNB->UE_stats[UE_id].sector, // this is the effective sector id UE_id, - eNB->ulsch_eNB, + eNB->ulsch, 0); } @@ -2481,7 +2363,7 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_ else { rx_ulsch_emul(eNB, subframe, - eNB->eNB_UE_stats[UE_id].sector, // this is the effective sector id + eNB->UE_stats[UE_id].sector, // this is the effective sector id UE_id); } @@ -2490,76 +2372,76 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_ if (abstraction_flag == 0) { ret = ulsch_decoding(eNB, UE_id, - sched_subframe, + thread_id, 0, // control_only_flag - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->V_UL_DAI, - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); + eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI, + eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); } #ifdef PHY_ABSTRACTION else { ret = ulsch_decoding_emul(eNB, - sched_subframe, + thread_id, UE_id, &rnti); } #endif - if (eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) { + if (eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) { #ifdef DEBUG_PHY_PROC - print_CQI(eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o,eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL); + print_CQI(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o,eNB->ulsch[UE_id]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL); #endif access_mode = UNKNOWN_ACCESS; - extract_CQI(eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o, - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->uci_format, - &eNB->eNB_UE_stats[UE_id], + extract_CQI(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o, + eNB->ulsch[UE_id]->harq_processes[harq_pid]->uci_format, + &eNB->UE_stats[UE_id], fp->N_RB_DL, &rnti, &access_mode); - eNB->eNB_UE_stats[UE_id].rank = eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->o_RI[0]; + eNB->UE_stats[UE_id].rank = eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_RI[0]; } - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0; - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE; if ((num_active_cba_groups > 0) && (UE_id + num_active_cba_groups < NUMBER_OF_UE_MAX) && - (eNB->ulsch_eNB[UE_id+num_active_cba_groups]->cba_rnti[UE_id%num_active_cba_groups] > 0 ) && - (eNB->ulsch_eNB[UE_id+num_active_cba_groups]->num_active_cba_groups> 0)) { + (eNB->ulsch[UE_id+num_active_cba_groups]->cba_rnti[UE_id%num_active_cba_groups] > 0 ) && + (eNB->ulsch[UE_id+num_active_cba_groups]->num_active_cba_groups> 0)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d resetting the subframe_scheduling_flag for Ue %d cba groups %d members\n", eNB->Mod_id,harq_pid,frame,subframe,UE_id,harq_pid, - UE_id+num_active_cba_groups, UE_id%eNB->ulsch_eNB[UE_id]->num_active_cba_groups); + UE_id+num_active_cba_groups, UE_id%eNB->ulsch[UE_id]->num_active_cba_groups); #endif - eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=1; - eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->status= CBA_ACTIVE; - eNB->ulsch_eNB[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->TBS=eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS; + eNB->ulsch[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=1; + eNB->ulsch[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->status= CBA_ACTIVE; + eNB->ulsch[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->TBS=eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS; } if (ret == (1+MAX_TURBO_ITERATIONS)) { - eNB->eNB_UE_stats[UE_id].ulsch_round_errors[harq_pid][eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round]++; - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active = 1; - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK = 0; - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round++; + eNB->UE_stats[UE_id].ulsch_round_errors[harq_pid][eNB->ulsch[UE_id]->harq_processes[harq_pid]->round]++; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK = 0; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->round++; } // ulsch in error else { LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n", eNB->Mod_id,harq_pid, frame,subframe); - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_active = 1; - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->phich_ACK = 1; - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round = 0; - eNB->eNB_UE_stats[UE_id].ulsch_consecutive_errors = 0; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK = 1; + eNB->ulsch[UE_id]->harq_processes[harq_pid]->round = 0; + eNB->UE_stats[UE_id].ulsch_consecutive_errors = 0; #ifdef DEBUG_PHY_PROC #ifdef DEBUG_ULSCH LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:", frame,subframe, - harq_pid,eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3); + harq_pid,eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3); - for (j=0; julsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->b[j]); + for (j=0; julsch[UE_id]->harq_processes[harq_pid]->TBS>>3; j++) + LOG_T(PHY,"%x.",eNB->ulsch[UE_id]->harq_processes[harq_pid]->b[j]); LOG_T(PHY,"\n"); #endif @@ -2568,17 +2450,17 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_ if (access_mode > UNKNOWN_ACCESS) { LOG_D(PHY,"[eNB %d] Frame %d, Subframe %d : received ULSCH SDU from CBA transmission, UE (%d,%x), CBA (group %d, rnti %x)\n", eNB->Mod_id, frame,subframe, - UE_id, eNB->ulsch_eNB[UE_id]->rnti, - UE_id % eNB->ulsch_eNB[UE_id]->num_active_cba_groups, eNB->ulsch_eNB[UE_id]->cba_rnti[UE_id%num_active_cba_groups]); + UE_id, eNB->ulsch[UE_id]->rnti, + UE_id % eNB->ulsch[UE_id]->num_active_cba_groups, eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]); // detect if there is a CBA collision if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) { mac_xface->rx_sdu(eNB->Mod_id, eNB->CC_id, frame,subframe, - eNB->ulsch_eNB[UE_id]->rnti, - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->b, - eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->TBS>>3, + eNB->ulsch[UE_id]->rnti, + eNB->ulsch[UE_id]->harq_processes[harq_pid]->b, + eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3, harq_pid, NULL); @@ -2597,7 +2479,7 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_ mac_xface->SR_indication(eNB->Mod_id, eNB->CC_id, frame, - eNB->dlsch_eNB[UE_id][0]->rnti,subframe); + eNB->dlsch[UE_id][0]->rnti,subframe); } } // UNKNOWN_ACCESS } // ULSCH CBA not in error @@ -2605,22 +2487,173 @@ void cba_procedures(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,int UE_ } -void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB,const uint8_t abstraction_flag,const relaying_type_t r_type) + + +void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { + + eNB_proc_t *proc = &eNB->proc[thread_id]; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + int i,l; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + void *rxp[fp->nb_antennas_rx]; + unsigned int rxs; + + AssertFatal(thread_id < NUM_ENB_THREADS, "Bad thread_id %d", thread_id); + + // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_COMMON_RX,1); + start_meas(&eNB->phy_proc_rx); +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); +#endif + + if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) + + for (i=0; inb_antennas_rx; i++) + if ((eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF and front-end processing + rxp[i] = (void*)&eNB->common_vars.rxdata[i][subframe*fp->samples_per_tti]; + rxs = openair0.trx_read_func(&openair0, + &proc->timestamp_rx, + rxp, + fp->samples_per_tti>>1, + fp->nb_antennas_rx); + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + + if (frame > 20){ + if (rxs != fp->samples_per_tti>>1) + exit_fun( "problem receiving samples" ); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + + remove_7_5_kHz(eNB,subframe<<1); + for (l=0; lsymbols_per_tti/2; l++) + slot_fep_ul(fp, + &eNB->common_vars, + l, + subframe<<1, + 0, + 0 + ); + + if (eNB->node_function == NGFI_RRU_IF4) { + //send_IF4(eNB,subframe<<1); + } + + remove_7_5_kHz(eNB,(subframe<<1)+1); + for (l=0; lsymbols_per_tti/2; l++) + slot_fep_ul(fp, + &eNB->common_vars, + l, + (subframe<<1)+1, + 0, + 0 + ); + if (eNB->node_function == NGFI_RRU_IF4) { + //send_IF4(eNB,(subframe<<1)+1); + } + + } + else if (eNB->node_function == NGFI_RCC_IF4) { // => acquisition from RRU (IF4) + // get frame/subframe information from IF4 interface + + //recv_IF4(eNB,subframe<<1); + //recv_IF4(eNB,1+(subframe<<1)); + + } + else { // should not get here + AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); + } + + + // check if we have to detect PRACH first + if (is_prach_subframe(fp,frame,subframe)>0) { + // wake up thread for PRACH RX + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", thread_id, proc->instance_cnt_prach ); + exit_fun( "error locking mutex_prach" ); + return; + } + + int cnt_prach = ++proc->instance_cnt_prach; + + pthread_mutex_unlock( &proc->mutex_prach ); + + if (cnt_prach == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", proc->frame_tx); + exit_fun( "PRACH thread busy" ); + return; + } + + + } + + // wake up TX thread + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", thread_id, proc->instance_cnt_tx ); + exit_fun( "error locking mutex_tx" ); + return; + } + + int cnt_tx = ++proc->instance_cnt_tx; + // We have just received and processed the common part of an entire subframe, say n. + // TX_rx is the last received timestamp (start of 2nd slot), TX_tx is the desired + // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_per_frame) was (n+.5)*samples_per_tti, + // we want to generate subframe (n+3), so TS_tx = TX_rx+2.5*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+3 + proc->timestamp_tx = proc->timestamp_rx + (fp->samples_per_tti<<1) + (fp->samples_per_tti>>1); + proc->frame_tx = (proc->subframe_rx > 6) ? (proc->frame_rx+1) : proc->frame_rx; + proc->subframe_rx = (proc->subframe_rx + 3)%10; + + pthread_mutex_unlock( &proc->mutex_tx ); + + if (cnt_tx == 0){ + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n", thread_id); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (cnt_tx %i)\n", proc->frame_tx, thread_id, cnt_tx ); + exit_fun( "TX thread busy" ); + return; + } + + } + + else { // grab transport channel information from network interface + + } +} + +void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eNB,const uint8_t abstraction_flag,const relaying_type_t r_type) { - //RX processing + //RX processing for ue-specific resources (i UNUSED(r_type); + eNB_proc_t *proc = &eNB->proc[thread_id]; uint32_t l, ret=0,i,j,k; uint32_t harq_pid, harq_idx, round; uint8_t nPRS; int sync_pos; uint16_t rnti=0; uint8_t access_mode; - LTE_DL_FRAME_PARMS *fp=&eNB->lte_frame_parms; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - const int subframe = eNB->proc[sched_subframe].subframe_rx; - const int frame = eNB->proc[sched_subframe].frame_rx; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; - AssertFatal(sched_subframe < NUM_ENB_THREADS, "Bad sched_subframe %d", sched_subframe); + AssertFatal(thread_id < NUM_ENB_THREADS, "Bad thread_id %d", thread_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1); start_meas(&eNB->phy_proc_rx); @@ -2634,17 +2667,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, eNB->rb_mask_ul[2]=0; eNB->rb_mask_ul[3]=0; - if (abstraction_flag == 0) { - remove_7_5_kHz(eNB,subframe<<1); - remove_7_5_kHz(eNB,(subframe<<1)+1); - } - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); - prach_procedures(eNB,sched_subframe,abstraction_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); - } if (abstraction_flag == 0) { start_meas(&eNB->ofdm_demod_stats); @@ -2652,14 +2675,14 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, for (l=0; lsymbols_per_tti/2; l++) { slot_fep_ul(fp, - &eNB->lte_eNB_common_vars, + &eNB->common_vars, l, subframe<<1, 0, 0 ); slot_fep_ul(fp, - &eNB->lte_eNB_common_vars, + &eNB->common_vars, l, (subframe<<1)+1, 0, @@ -2682,15 +2705,15 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, // Do PUCCH processing first for (i=0; imac_enabled==1) { - if (eNB->eNB_UE_stats[i].mode == RA_RESPONSE) { - process_Msg3(eNB,sched_subframe,i,harq_pid); + if (eNB->UE_stats[i].mode == RA_RESPONSE) { + process_Msg3(eNB,thread_id,i,harq_pid); } } @@ -2699,30 +2722,30 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, eNB->pusch_stats_round[i][(frame*10)+subframe] = 0; eNB->pusch_stats_mcs[i][(frame*10)+subframe] = -63; - if ((eNB->ulsch_eNB[i]) && - (eNB->ulsch_eNB[i]->rnti>0) && - (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) { + if ((eNB->ulsch[i]) && + (eNB->ulsch[i]->rnti>0) && + (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) { // UE is has ULSCH scheduling - round = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; + round = eNB->ulsch[i]->harq_processes[harq_pid]->round; for (int rb=0; - rb<=eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; + rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb; rb++) { - int rb2 = rb+eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb; + int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb; eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Scheduling PUSCH/ULSCH Reception for rnti %x (UE_id %d)\n", eNB->Mod_id,harq_pid, - frame,subframe,eNB->ulsch_eNB[i]->rnti,i); + frame,subframe,eNB->ulsch[i]->rnti,i); #endif - if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->ulsch[i]->Msg3_flag == 1) { LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n", eNB->Mod_id, frame, subframe, - eNB->eNB_UE_stats[i].sector); + eNB->UE_stats[i].sector); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1); } else { LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n", @@ -2730,52 +2753,52 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, frame, subframe, i, - mode_string[eNB->eNB_UE_stats[i].mode]); + mode_string[eNB->UE_stats[i].mode]); } nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]; - eNB->ulsch_eNB[i]->cyclicShift = (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + + eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + nPRS)%12; if (fp->frame_type == FDD ) { int sf = (subframe<4) ? (subframe+6) : (subframe-4); - if (eNB->dlsch_eNB[i][0]->subframe_tx[sf]>0) { // we have downlink transmission - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK = 1; + if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission + eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1; } else { - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK = 0; + eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0; } } LOG_D(PHY, "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, nprs %d), O_ACK %d \n", eNB->Mod_id,harq_pid,frame,subframe, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->dci_alloc, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rar_alloc, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->mcs, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->rvidx, - eNB->ulsch_eNB[i]->cyclicShift, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->n_DMRS2, + eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc, + eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc, + eNB->ulsch[i]->harq_processes[harq_pid]->round, + eNB->ulsch[i]->harq_processes[harq_pid]->first_rb, + eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb, + eNB->ulsch[i]->harq_processes[harq_pid]->mcs, + eNB->ulsch[i]->harq_processes[harq_pid]->TBS, + eNB->ulsch[i]->harq_processes[harq_pid]->rvidx, + eNB->ulsch[i]->cyclicShift, + eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2, fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, nPRS, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK); - eNB->pusch_stats_rb[i][(frame*10)+subframe] = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; - eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; - eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->mcs; + eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK); + eNB->pusch_stats_rb[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb; + eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->round; + eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->mcs; start_meas(&eNB->ulsch_demodulation_stats); if (abstraction_flag==0) { rx_ulsch(eNB, - sched_subframe, - eNB->eNB_UE_stats[i].sector, // this is the effective sector id + thread_id, + eNB->UE_stats[i].sector, // this is the effective sector id i, - eNB->ulsch_eNB, + eNB->ulsch, 0); } @@ -2783,7 +2806,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, else { rx_ulsch_emul(eNB, subframe, - eNB->eNB_UE_stats[i].sector, // this is the effective sector id + eNB->UE_stats[i].sector, // this is the effective sector id i); } @@ -2796,16 +2819,16 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, if (abstraction_flag == 0) { ret = ulsch_decoding(eNB, i, - sched_subframe, + thread_id, 0, // control_only_flag - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->V_UL_DAI, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); + eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI, + eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); } #ifdef PHY_ABSTRACTION else { ret = ulsch_decoding_emul(eNB, - sched_subframe, + thread_id, i, &rnti); } @@ -2816,104 +2839,104 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", eNB->Mod_id,harq_pid, frame,subframe, - eNB->ulsch_eNB[i]->rnti, - dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), - dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), - eNB->eNB_UE_stats[i].UL_rssi[0], - eNB->eNB_UE_stats[i].UL_rssi[1], - eNB->PHY_measurements_eNB->n0_power_dB[0], - eNB->PHY_measurements_eNB->n0_power_dB[1], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->ulsch[i]->rnti, + dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), + dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), + eNB->UE_stats[i].UL_rssi[0], + eNB->UE_stats[i].UL_rssi[1], + eNB->measurements->n0_power_dB[0], + eNB->measurements->n0_power_dB[1], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1], ret); //compute the expected ULSCH RX power (for the stats) - eNB->ulsch_eNB[(uint32_t)i]->harq_processes[harq_pid]->delta_TF = + eNB->ulsch[(uint32_t)i]->harq_processes[harq_pid]->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered - //dump_ulsch(eNB, sched_subframe, i); + //dump_ulsch(eNB, thread_id, i); - eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++; + eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++; #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d Clearing subframe_scheduling_flag\n", eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid); #endif - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0; + eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0; - if (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->cqi_crc_status == 1) { + if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) { #ifdef DEBUG_PHY_PROC - //if (((eNB->proc[sched_subframe].frame_tx%10) == 0) || (eNB->proc[sched_subframe].frame_tx < 50)) - print_CQI(eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o,eNB->ulsch_eNB[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL); + //if (((proc->frame_tx%10) == 0) || (proc->frame_tx < 50)) + print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL); #endif - extract_CQI(eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->uci_format, - &eNB->eNB_UE_stats[i], + extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o, + eNB->ulsch[i]->harq_processes[harq_pid]->uci_format, + &eNB->UE_stats[i], fp->N_RB_DL, &rnti, &access_mode); - eNB->eNB_UE_stats[i].rank = eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_RI[0]; + eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0]; } - if (eNB->ulsch_eNB[i]->Msg3_flag == 1) + if (eNB->ulsch[i]->Msg3_flag == 1) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0); if (ret == (1+MAX_TURBO_ITERATIONS)) { - eNB->eNB_UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round]++; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 0; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round++; + eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++; + eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 0; + eNB->ulsch[i]->harq_processes[harq_pid]->round++; - LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round); + LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->round); - if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->ulsch[i]->Msg3_flag == 1) { LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n", eNB->Mod_id, eNB->CC_id, frame,subframe, i, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1, + eNB->ulsch[i]->harq_processes[harq_pid]->round-1, fp->maxHARQ_Msg3Tx-1); LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", eNB->Mod_id,harq_pid, frame,subframe, - eNB->ulsch_eNB[i]->rnti, - dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), - dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), - eNB->eNB_UE_stats[i].UL_rssi[0], - eNB->eNB_UE_stats[i].UL_rssi[1], - eNB->PHY_measurements_eNB->n0_power_dB[0], - eNB->PHY_measurements_eNB->n0_power_dB[1], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->ulsch[i]->rnti, + dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), + dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), + eNB->UE_stats[i].UL_rssi[0], + eNB->UE_stats[i].UL_rssi[1], + eNB->measurements->n0_power_dB[0], + eNB->measurements->n0_power_dB[1], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1], ret); - if (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round == + if (eNB->ulsch[i]->harq_processes[harq_pid]->round == fp->maxHARQ_Msg3Tx) { LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n", eNB->Mod_id, i); - eNB->eNB_UE_stats[i].mode = PRACH; + eNB->UE_stats[i].mode = PRACH; if (eNB->mac_enabled==1) { mac_xface->cancel_ra_proc(eNB->Mod_id, eNB->CC_id, frame, - eNB->eNB_UE_stats[i].crnti); + eNB->UE_stats[i].crnti); } - mac_phy_remove_ue(eNB->Mod_id,eNB->eNB_UE_stats[i].crnti); + mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti); - eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 0; - //eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 0; + eNB->ulsch[(uint32_t)i]->Msg3_active = 0; + //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0; } else { // activate retransmission for Msg3 (signalled to UE PHY by PHICH (not MAC/DCI) - eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 1; + eNB->ulsch[(uint32_t)i]->Msg3_active = 1; get_Msg3_alloc_ret(fp, subframe, frame, - &eNB->ulsch_eNB[i]->Msg3_frame, - &eNB->ulsch_eNB[i]->Msg3_subframe); + &eNB->ulsch[i]->Msg3_frame, + &eNB->ulsch[i]->Msg3_subframe); } LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i); } // This is Msg3 error @@ -2922,10 +2945,10 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", eNB->Mod_id,harq_pid, frame,subframe, i, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1, - eNB->ulsch_eNB[i]->Mlimit, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1]); + eNB->ulsch[i]->harq_processes[harq_pid]->round-1, + eNB->ulsch[i]->Mlimit, + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1]); #if defined(MESSAGE_CHART_GENERATOR_PHY) MSC_LOG_RX_DISCARDED_MESSAGE( @@ -2933,51 +2956,51 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, NULL,0, "%05u:%02u ULSCH received rnti %x harq id %u round %d", frame,subframe, - eNB->ulsch_eNB[i]->rnti,harq_pid, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round-1 + eNB->ulsch[i]->rnti,harq_pid, + eNB->ulsch[i]->harq_processes[harq_pid]->round-1 ); #endif - if (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round== eNB->ulsch_eNB[i]->Mlimit) { + if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n", eNB->Mod_id,harq_pid, frame,subframe, i, - eNB->ulsch_eNB[i]->Mlimit); + eNB->ulsch[i]->Mlimit); - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round=0; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active=0; - eNB->eNB_UE_stats[i].ulsch_errors[harq_pid]++; - eNB->eNB_UE_stats[i].ulsch_consecutive_errors++; + eNB->ulsch[i]->harq_processes[harq_pid]->round=0; + eNB->ulsch[i]->harq_processes[harq_pid]->phich_active=0; + eNB->UE_stats[i].ulsch_errors[harq_pid]++; + eNB->UE_stats[i].ulsch_consecutive_errors++; // indicate error to MAC mac_xface->rx_sdu(eNB->Mod_id, eNB->CC_id, frame,subframe, - eNB->ulsch_eNB[i]->rnti, + eNB->ulsch[i]->rnti, NULL, 0, harq_pid, - &eNB->ulsch_eNB[i]->Msg3_flag); + &eNB->ulsch[i]->Msg3_flag); } } } // ulsch in error else { - if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->ulsch[i]->Msg3_flag == 1) { LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n", eNB->Mod_id,harq_pid, frame,subframe); LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", eNB->Mod_id,harq_pid, frame,subframe, - eNB->ulsch_eNB[i]->rnti, - dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[0]), - dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[1]), - eNB->eNB_UE_stats[i].UL_rssi[0], - eNB->eNB_UE_stats[i].UL_rssi[1], - eNB->PHY_measurements_eNB->n0_power_dB[0], - eNB->PHY_measurements_eNB->n0_power_dB[1], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->ulsch[i]->rnti, + dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), + dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), + eNB->UE_stats[i].UL_rssi[0], + eNB->UE_stats[i].UL_rssi[1], + eNB->measurements->n0_power_dB[0], + eNB->measurements->n0_power_dB[1], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1], ret); } #if defined(MESSAGE_CHART_GENERATOR_PHY) @@ -2986,26 +3009,26 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, NULL,0, "%05u:%02u ULSCH received rnti %x harq id %u", frame,subframe, - eNB->ulsch_eNB[i]->rnti,harq_pid + eNB->ulsch[i]->rnti,harq_pid ); #endif for (j=0; jnb_antennas_rx; j++) //this is the RSSI per RB - eNB->eNB_UE_stats[i].UL_rssi[j] = + eNB->UE_stats[i].UL_rssi[j] = - dB_fixed(eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]* - (eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb*12)/ + dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]* + (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/ fp->ofdm_symbol_size) - - eNB->rx_total_gain_eNB_dB - - hundred_times_log10_NPRB[eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb-1]/100 - + eNB->rx_total_gain_dB - + hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 - get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1; - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0; - eNB->eNB_UE_stats[i].ulsch_consecutive_errors = 0; + eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1; + eNB->ulsch[i]->harq_processes[harq_pid]->round = 0; + eNB->UE_stats[i].ulsch_consecutive_errors = 0; - if (eNB->ulsch_eNB[i]->Msg3_flag == 1) { + if (eNB->ulsch[i]->Msg3_flag == 1) { if (eNB->mac_enabled==1) { LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n", @@ -3015,62 +3038,62 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, mac_xface->rx_sdu(eNB->Mod_id, eNB->CC_id, frame,subframe, - eNB->ulsch_eNB[i]->rnti, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3, + eNB->ulsch[i]->rnti, + eNB->ulsch[i]->harq_processes[harq_pid]->b, + eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3, harq_pid, - &eNB->ulsch_eNB[i]->Msg3_flag); + &eNB->ulsch[i]->Msg3_flag); // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI) - if (eNB->ulsch_eNB[i]->Msg3_flag == 0 ) { - eNB->eNB_UE_stats[i].mode = PRACH; + if (eNB->ulsch[i]->Msg3_flag == 0 ) { + eNB->UE_stats[i].mode = PRACH; mac_xface->cancel_ra_proc(eNB->Mod_id, eNB->CC_id, frame, - eNB->eNB_UE_stats[i].crnti); - mac_phy_remove_ue(eNB->Mod_id,eNB->eNB_UE_stats[i].crnti); - eNB->ulsch_eNB[(uint32_t)i]->Msg3_active = 0; + eNB->UE_stats[i].crnti); + mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti); + eNB->ulsch[(uint32_t)i]->Msg3_active = 0; } // Msg3_flag == 0 } // mac_enabled==1 - eNB->eNB_UE_stats[i].mode = PUSCH; - eNB->ulsch_eNB[i]->Msg3_flag = 0; + eNB->UE_stats[i].mode = PUSCH; + eNB->ulsch[i]->Msg3_flag = 0; LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",eNB->Mod_id,frame,subframe,i); for (k=0; k<8; k++) { //harq_processes - for (j=0; jdlsch_eNB[i][0]->Mlimit; j++) { - eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0; - eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0; - eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0; + for (j=0; jdlsch[i][0]->Mlimit; j++) { + eNB->UE_stats[i].dlsch_NAK[k][j]=0; + eNB->UE_stats[i].dlsch_ACK[k][j]=0; + eNB->UE_stats[i].dlsch_trials[k][j]=0; } - eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0; - eNB->eNB_UE_stats[i].ulsch_errors[k]=0; - eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0; + eNB->UE_stats[i].dlsch_l2_errors[k]=0; + eNB->UE_stats[i].ulsch_errors[k]=0; + eNB->UE_stats[i].ulsch_consecutive_errors=0; - for (j=0; julsch_eNB[i]->Mlimit; j++) { - eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0; - eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; - eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0; - eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0; + for (j=0; julsch[i]->Mlimit; j++) { + eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; + eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; + eNB->UE_stats[i].ulsch_round_errors[k][j]=0; + eNB->UE_stats[i].ulsch_round_fer[k][j]=0; } } - eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0; - eNB->eNB_UE_stats[i].dlsch_NAK_round0=0; - eNB->eNB_UE_stats[i].dlsch_mcs_offset=0; + eNB->UE_stats[i].dlsch_sliding_cnt=0; + eNB->UE_stats[i].dlsch_NAK_round0=0; + eNB->UE_stats[i].dlsch_mcs_offset=0; } // Msg3_flag==1 else { // Msg3_flag == 0 #ifdef DEBUG_PHY_PROC #ifdef DEBUG_ULSCH LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe, - harq_pid,eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3); + harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3); - for (j=0; julsch_eNB[i]->harq_processes[harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b[j]); + for (j=0; julsch[i]->harq_processes[harq_pid]->TBS>>3; j++) + LOG_T(PHY,"%x.",eNB->ulsch[i]->harq_processes[harq_pid]->b[j]); LOG_T(PHY,"\n"); #endif @@ -3081,9 +3104,9 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, mac_xface->rx_sdu(eNB->Mod_id, eNB->CC_id, frame,subframe, - eNB->ulsch_eNB[i]->rnti, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->b, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->TBS>>3, + eNB->ulsch[i]->rnti, + eNB->ulsch[i]->harq_processes[harq_pid]->b, + eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3, harq_pid, NULL); @@ -3102,8 +3125,8 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, // estimate timing advance for MAC if (abstraction_flag == 0) { - sync_pos = lte_est_timing_advance_pusch(eNB,i,sched_subframe); - eNB->eNB_UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check + sync_pos = lte_est_timing_advance_pusch(eNB,i,thread_id); + eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check } #ifdef DEBUG_PHY_PROC @@ -3111,7 +3134,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, eNB->Mod_id, frame, subframe, i, - eNB->eNB_UE_stats[i].timing_advance_update); + eNB->UE_stats[i].timing_advance_update); #endif @@ -3120,12 +3143,12 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, // process HARQ feedback #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id, - eNB->dlsch_eNB[i][0]->rnti, + eNB->dlsch[i][0]->rnti, frame,subframe, i); #endif process_HARQ_feedback(i, - sched_subframe, + thread_id, eNB, 1, // pusch_flag 0, @@ -3135,15 +3158,15 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d subframe %d, sect %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n", eNB->Mod_id,frame,subframe, - eNB->eNB_UE_stats[i].sector, + eNB->UE_stats[i].sector, harq_pid, i, ret, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->cqi_crc_status, - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], - eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], - eNB->eNB_UE_stats[i].ulsch_errors[harq_pid], - eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); + eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status, + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0], + eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1], + eNB->UE_stats[i].ulsch_errors[harq_pid], + eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); #endif // dump stats to VCD @@ -3151,45 +3174,45 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *eNB, VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS0+harq_pid,eNB->pusch_stats_mcs[0][(frame*10)+subframe]); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB0+harq_pid,eNB->pusch_stats_rb[0][(frame*10)+subframe]); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND0+harq_pid,eNB->pusch_stats_round[0][(frame*10)+subframe]); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->lte_eNB_pusch_vars[0]->ulsch_power[0])); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0])); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES0+harq_pid,ret); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN0+harq_pid,(frame*10)+subframe); } - } // ulsch_eNB[0] && ulsch_eNB[0]->rnti>0 && ulsch_eNB[0]->subframe_scheduling_flag == 1 + } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1 // update ULSCH statistics for tracing if ((frame % 100 == 0) && (subframe == 4)) { for (harq_idx=0; harq_idx<8; harq_idx++) { - for (round=0; roundulsch_eNB[i]->Mlimit; round++) { - if ((eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - - eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]) != 0) { - eNB->eNB_UE_stats[i].ulsch_round_fer[harq_idx][round] = - (100*(eNB->eNB_UE_stats[i].ulsch_round_errors[harq_idx][round] - - eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_idx][round]))/ - (eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - - eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]); + for (round=0; roundulsch[i]->Mlimit; round++) { + if ((eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - + eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]) != 0) { + eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = + (100*(eNB->UE_stats[i].ulsch_round_errors[harq_idx][round] - + eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round]))/ + (eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] - + eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]); } else { - eNB->eNB_UE_stats[i].ulsch_round_fer[harq_idx][round] = 0; + eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0; } - eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round] = - eNB->eNB_UE_stats[i].ulsch_decoding_attempts[harq_idx][round]; - eNB->eNB_UE_stats[i].ulsch_round_errors_last[harq_idx][round] = - eNB->eNB_UE_stats[i].ulsch_round_errors[harq_idx][round]; + eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round] = + eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round]; + eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round] = + eNB->UE_stats[i].ulsch_round_errors[harq_idx][round]; } } } if ((frame % 100 == 0) && (subframe==4)) { - eNB->eNB_UE_stats[i].dlsch_bitrate = (eNB->eNB_UE_stats[i].total_TBS - - eNB->eNB_UE_stats[i].total_TBS_last); + eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS - + eNB->UE_stats[i].total_TBS_last); - eNB->eNB_UE_stats[i].total_TBS_last = eNB->eNB_UE_stats[i].total_TBS; + eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS; } // CBA (non-LTE) - cba_procedures(sched_subframe,eNB,i,harq_pid,abstraction_flag); + cba_procedures(thread_id,eNB,i,harq_pid,abstraction_flag); } // loop i=0 ... NUMBER_OF_UE_MAX-1 if (abstraction_flag == 0) { @@ -3250,6 +3273,7 @@ int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, r return do_proc; } #endif +/* void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t abstraction_flag, relaying_type_t r_type, PHY_VARS_RN *rn) { @@ -3264,10 +3288,7 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t ab int CC_id=0; - /* - if (eNB->proc[sched_subframe].frame_tx >= 1000) - mac_xface->macphy_exit("Exiting after 1000 Frames\n"); - */ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, eNB[0]->proc[subframe].frame_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,1); start_meas(&eNB[0]->phy_proc); @@ -3284,122 +3305,11 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t ab Mod_id = instance; switch (ITTI_MSG_ID(msg_p)) { -# if ENABLE_RAL - case TIMER_HAS_EXPIRED: - // check if it is a measurement timer - { - hashtable_rc_t hashtable_rc; - - hashtable_rc = hashtable_is_key_exists(PHY_vars_eNB_g[Mod_id][0]->ral_thresholds_timed, (uint64_t)(TIMER_HAS_EXPIRED(msg_p).timer_id)); - - if (hashtable_rc == HASH_TABLE_OK) { - phy_eNB_lte_check_measurement_thresholds(instance, (ral_threshold_phy_t*)TIMER_HAS_EXPIRED(msg_p).arg); - } - } - break; - - - case PHY_MEAS_THRESHOLD_REQ: -#warning "TO DO LIST OF THRESHOLDS" - LOG_D(PHY, "[ENB %d] Received %s\n", Mod_id, msg_name); - { - ral_threshold_phy_t* threshold_phy_p = NULL; - int index, res; - long timer_id; - hashtable_rc_t hashtable_rc; - - switch (PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.th_action) { - - case RAL_TH_ACTION_CANCEL_THRESHOLD: - break; - - case RAL_TH_ACTION_SET_NORMAL_THRESHOLD: - case RAL_TH_ACTION_SET_ONE_SHOT_THRESHOLD: - for (index = 0; index < PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.num_thresholds; index++) { - threshold_phy_p = calloc(1, sizeof(ral_threshold_phy_t)); - threshold_phy_p->th_action = PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.th_action; - memcpy(&threshold_phy_p->link_param.link_param_type, - &PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type, - sizeof(ral_link_param_type_t)); - - memcpy(&threshold_phy_p->threshold, - &PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.thresholds[index], - sizeof(ral_threshold_t)); - - switch (PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.union_choice) { - - case RAL_LINK_CFG_PARAM_CHOICE_TIMER_NULL: - switch (PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type.choice) { - case RAL_LINK_PARAM_TYPE_CHOICE_GEN: - SLIST_INSERT_HEAD( - &PHY_vars_eNB_g[Mod_id][0]->ral_thresholds_gen_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_gen], - threshold_phy_p, - ral_thresholds); - break; - - case RAL_LINK_PARAM_TYPE_CHOICE_LTE: - SLIST_INSERT_HEAD( - &PHY_vars_eNB_g[Mod_id][0]->ral_thresholds_lte_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_lte], - threshold_phy_p, - ral_thresholds); - break; - - default: - LOG_E(PHY, "[ENB %d] BAD PARAMETER cfg_param.link_param_type.choice %d in %s\n", - Mod_id, PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type.choice, msg_name); - } - - break; - - case RAL_LINK_CFG_PARAM_CHOICE_TIMER: - res = timer_setup( - (uint32_t)(PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param._union.timer_interval/1000),//uint32_t interval_sec, - (uint32_t)(PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param._union.timer_interval%1000),//uint32_t interval_us, - TASK_PHY_ENB, - instance, - TIMER_PERIODIC, - threshold_phy_p, - &timer_id); - - if (res == 0) { - hashtable_rc = hashtable_insert(PHY_vars_eNB_g[Mod_id][0]->ral_thresholds_timed, (uint64_t )timer_id, (void*)threshold_phy_p); - - if (hashtable_rc == HASH_TABLE_OK) { - threshold_phy_p->timer_id = timer_id; - } else { - LOG_E(PHY, "[ENB %d] %s: Error in hashtable. Could not configure threshold index %d \n", - Mod_id, msg_name, index); - } - - } else { - LOG_E(PHY, "[ENB %d] %s: Could not configure threshold index %d because of timer initialization failure\n", - Mod_id, msg_name, index); - } - - break; - - default: // already checked in RRC, should not happen here - LOG_E(PHY, "[ENB %d] BAD PARAMETER cfg_param.union_choice %d in %s\n", - Mod_id, PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.union_choice, msg_name); - } - } - - break; - - default: - LOG_E(PHY, "[ENB %d] BAD PARAMETER th_action value %d in %s\n", - Mod_id, PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.th_action, msg_name); - } - - } - break; -# endif - - /* Messages from eNB app */ + // Messages from eNB app case PHY_CONFIGURATION_REQ: LOG_I(PHY, "[eNB %d] Received %s\n", instance, msg_name); - /* TODO */ + // TODO break; @@ -3417,23 +3327,23 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t ab for (CC_id=0; CC_idlte_frame_parms.frame_type == TDD)&& - (subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_tx)==SF_DL))|| - (eNB[CC_id]->lte_frame_parms.frame_type == FDD))) { + if ((((eNB[CC_id]->frame_parms.frame_type == TDD)&& + (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_tx)==SF_DL))|| + (eNB[CC_id]->frame_parms.frame_type == FDD))) { #ifdef Rel10 - if (phy_procedures_RN_eNB_TX(eNB[CC_id]->proc[subframe].subframe_rx, eNB[CC_id]->proc[subframe].subframe_tx, r_type) != 0 ) + if (phy_procedures_RN_eNB_TX(eNB[CC_id]->proc[0].subframe_rx, eNB[CC_id]->proc[0].subframe_tx, r_type) != 0 ) #endif phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn); } - if ((((eNB[CC_id]->lte_frame_parms.frame_type == TDD )&& - (subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_rx)==SF_UL)) || - (eNB[CC_id]->lte_frame_parms.frame_type == FDD))) { + if ((((eNB[CC_id]->frame_parms.frame_type == TDD )&& + (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_rx)==SF_UL)) || + (eNB[CC_id]->frame_parms.frame_type == FDD))) { phy_procedures_eNB_RX(subframe,eNB[CC_id],abstraction_flag,r_type); } - if (subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_tx)==SF_S) { + if (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_tx)==SF_S) { #ifdef Rel10 if (phy_procedures_RN_eNB_TX(subframe, subframe, r_type) != 0 ) @@ -3441,21 +3351,21 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t ab phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn); } - if ((subframe_select(&eNB[CC_id]->lte_frame_parms,eNB[CC_id]->proc[subframe].subframe_rx)==SF_S)) { + if ((subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_rx)==SF_S)) { phy_procedures_eNB_S_RX(subframe,eNB[CC_id],abstraction_flag,r_type); } - eNB[CC_id]->proc[subframe].frame_tx++; - eNB[CC_id]->proc[subframe].frame_rx++; + eNB[CC_id]->proc[0].frame_tx++; + eNB[CC_id]->proc[0].frame_rx++; - if (eNB[CC_id]->proc[subframe].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h - eNB[CC_id]->proc[subframe].frame_tx-=MAX_FRAME_NUMBER; + if (eNB[CC_id]->proc[0].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h + eNB[CC_id]->proc[0].frame_tx-=MAX_FRAME_NUMBER; - if (eNB[CC_id]->proc[subframe].frame_rx>=MAX_FRAME_NUMBER) - eNB[CC_id]->proc[subframe].frame_rx-=MAX_FRAME_NUMBER; + if (eNB[CC_id]->proc[0].frame_rx>=MAX_FRAME_NUMBER) + eNB[CC_id]->proc[0].frame_rx-=MAX_FRAME_NUMBER; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,0); stop_meas(&eNB[0]->phy_proc); } - +*/ diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 084173248f..c80fdd0e40 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -117,73 +117,73 @@ extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; -void dump_dlsch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid) +void dump_dlsch(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid) { unsigned int coded_bits_per_codeword; - uint8_t nsymb = (phy_vars_ue->lte_frame_parms.Ncp == 0) ? 14 : 12; + uint8_t nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; - coded_bits_per_codeword = get_G(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Nl, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, - phy_vars_ue->frame_rx,subframe); + coded_bits_per_codeword = get_G(&ue->frame_parms, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->frame_rx,subframe); - write_output("rxsigF0.m","rxsF0", phy_vars_ue->lte_ue_common_vars.rxdataF[0],2*nsymb*phy_vars_ue->lte_frame_parms.ofdm_symbol_size,2,1); - write_output("rxsigF0_ext.m","rxsF0_ext", phy_vars_ue->lte_ue_pdsch_vars[0]->rxdataF_ext[0],2*nsymb*phy_vars_ue->lte_frame_parms.ofdm_symbol_size,1,1); - write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", phy_vars_ue->lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[0],300*nsymb,1,1); + write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1); + write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars[0]->dl_ch_estimates_ext[0],300*nsymb,1,1); /* - write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); - write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); - write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); - write_output("dlsch_rho.m","dl_rho",lte_ue_pdsch_vars[0]->rho[0],300*12,1,1); + write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); + write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); + write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); + write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); */ - write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", phy_vars_ue->lte_ue_pdsch_vars[0]->rxdataF_comp0[0],300*12,1,1); - write_output("dlsch_rxF_llr.m","dlsch_llr", phy_vars_ue->lte_ue_pdsch_vars[0]->llr[0],coded_bits_per_codeword,1,0); + write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars[0]->rxdataF_comp0[0],300*12,1,1); + write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars[0]->llr[0],coded_bits_per_codeword,1,0); - write_output("dlsch_mag1.m","dlschmag1",phy_vars_ue->lte_ue_pdsch_vars[0]->dl_ch_mag0,300*12,1,1); - write_output("dlsch_mag2.m","dlschmag2",phy_vars_ue->lte_ue_pdsch_vars[0]->dl_ch_magb0,300*12,1,1); + write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars[0]->dl_ch_mag0,300*12,1,1); + write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars[0]->dl_ch_magb0,300*12,1,1); } -void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe) +void dump_dlsch_SI(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) { unsigned int coded_bits_per_codeword; - uint8_t nsymb = ((phy_vars_ue->lte_frame_parms.Ncp == 0) ? 14 : 12); + uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); - coded_bits_per_codeword = get_G(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even, + coded_bits_per_codeword = get_G(&ue->frame_parms, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even, 2, 1, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, - phy_vars_ue->frame_rx,subframe); + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->frame_rx,subframe); LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", - phy_vars_ue->Mod_id, - phy_vars_ue->lte_frame_parms.ofdm_symbol_size, + ue->Mod_id, + ue->frame_parms.ofdm_symbol_size, nsymb, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->mcs, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, coded_bits_per_codeword); - write_output("rxsig0.m","rxs0", &phy_vars_ue->lte_ue_common_vars.rxdata[0][subframe*phy_vars_ue->lte_frame_parms.samples_per_tti],phy_vars_ue->lte_frame_parms.samples_per_tti,1,1); + write_output("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_tti],ue->frame_parms.samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", phy_vars_ue->lte_ue_common_vars.rxdataF[0],nsymb*phy_vars_ue->lte_frame_parms.ofdm_symbol_size,1,1); - write_output("rxsigF0_ext.m","rxsF0_ext", phy_vars_ue->lte_ue_pdsch_vars_SI[0]->rxdataF_ext[0],2*nsymb*phy_vars_ue->lte_frame_parms.ofdm_symbol_size,1,1); - write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", phy_vars_ue->lte_ue_pdsch_vars_SI[0]->dl_ch_estimates_ext[0],phy_vars_ue->lte_frame_parms.N_RB_DL*12*nsymb,1,1); + write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],nsymb*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_SI[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_SI[0]->dl_ch_estimates_ext[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1); /* - write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); - write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); - write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); - write_output("dlsch_rho.m","dl_rho",lte_ue_pdsch_vars[0]->rho[0],300*12,1,1); + write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); + write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); + write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); + write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); */ - write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", phy_vars_ue->lte_ue_pdsch_vars_SI[0]->rxdataF_comp0[0],phy_vars_ue->lte_frame_parms.N_RB_DL*12*nsymb,1,1); - write_output("dlsch_rxF_llr.m","dlsch_llr", phy_vars_ue->lte_ue_pdsch_vars_SI[0]->llr[0],coded_bits_per_codeword,1,0); + write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_SI[0]->rxdataF_comp0[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1); + write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_SI[0]->llr[0],coded_bits_per_codeword,1,0); - write_output("dlsch_mag1.m","dlschmag1",phy_vars_ue->lte_ue_pdsch_vars_SI[0]->dl_ch_mag0,300*nsymb,1,1); - write_output("dlsch_mag2.m","dlschmag2",phy_vars_ue->lte_ue_pdsch_vars_SI[0]->dl_ch_magb0,300*nsymb,1,1); + write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_SI[0]->dl_ch_mag0,300*nsymb,1,1); + write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_SI[0]->dl_ch_magb0,300*nsymb,1,1); exit(-1); } @@ -251,40 +251,40 @@ unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb #endif -void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe) +void dump_dlsch_ra(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) { unsigned int coded_bits_per_codeword; - uint8_t nsymb = ((phy_vars_ue->lte_frame_parms.Ncp == 0) ? 14 : 12); + uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); - coded_bits_per_codeword = get_G(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->rb_alloc_even, + coded_bits_per_codeword = get_G(&ue->frame_parms, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even, 2, 1, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, - phy_vars_ue->frame_rx,subframe); + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->frame_rx,subframe); LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", - phy_vars_ue->Mod_id, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->mcs, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->Mod_id, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_ra[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, coded_bits_per_codeword); - write_output("rxsigF0.m","rxsF0", phy_vars_ue->lte_ue_common_vars.rxdataF[0],2*12*phy_vars_ue->lte_frame_parms.ofdm_symbol_size,2,1); - write_output("rxsigF0_ext.m","rxsF0_ext", phy_vars_ue->lte_ue_pdsch_vars_ra[0]->rxdataF_ext[0],2*12*phy_vars_ue->lte_frame_parms.ofdm_symbol_size,1,1); - write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", phy_vars_ue->lte_ue_pdsch_vars_ra[0]->dl_ch_estimates_ext[0],300*nsymb,1,1); + write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],2*12*ue->frame_parms.ofdm_symbol_size,2,1); + write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_ra[0]->rxdataF_ext[0],2*12*ue->frame_parms.ofdm_symbol_size,1,1); + write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_ra[0]->dl_ch_estimates_ext[0],300*nsymb,1,1); /* - write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); - write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); - write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",lte_ue_pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); - write_output("dlsch_rho.m","dl_rho",lte_ue_pdsch_vars[0]->rho[0],300*12,1,1); + write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); + write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); + write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); + write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); */ - write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", phy_vars_ue->lte_ue_pdsch_vars_ra[0]->rxdataF_comp0[0],300*nsymb,1,1); - write_output("dlsch_rxF_llr.m","dlsch_llr", phy_vars_ue->lte_ue_pdsch_vars_ra[0]->llr[0],coded_bits_per_codeword,1,0); + write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_ra[0]->rxdataF_comp0[0],300*nsymb,1,1); + write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_ra[0]->llr[0],coded_bits_per_codeword,1,0); - write_output("dlsch_mag1.m","dlschmag1",phy_vars_ue->lte_ue_pdsch_vars_ra[0]->dl_ch_mag0,300*nsymb,1,1); - write_output("dlsch_mag2.m","dlschmag2",phy_vars_ue->lte_ue_pdsch_vars_ra[0]->dl_ch_magb0,300*nsymb,1,1); + write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_ra[0]->dl_ch_mag0,300*nsymb,1,1); + write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_ra[0]->dl_ch_magb0,300*nsymb,1,1); } @@ -295,31 +295,31 @@ void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) // for more flexibility uint8_t i,j,k; - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; //[NUMBER_OF_CONNECTED_eNB_MAX][2]; for(i=0; idlsch_ue[i][j]) { - for(k=0; kdlsch_ue[i][j]->harq_processes[k]; k++) { - phy_vars_ue->dlsch_ue[i][j]->harq_processes[k]->status = SCH_IDLE; + if(ue->dlsch[i][j]) { + for(k=0; kdlsch[i][j]->harq_processes[k]; k++) { + ue->dlsch[i][j]->harq_processes[k]->status = SCH_IDLE; } } } //UL HARQ - if(phy_vars_ue->ulsch_ue[i]) { - for(k=0; kulsch_ue[i]->harq_processes[k]; k++) { - phy_vars_ue->ulsch_ue[i]->harq_processes[k]->status = SCH_IDLE; + if(ue->ulsch[i]) { + for(k=0; kulsch[i]->harq_processes[k]; k++) { + ue->ulsch[i]->harq_processes[k]->status = SCH_IDLE; //Set NDIs for all UL HARQs to 0 - // phy_vars_ue->ulsch_ue[i]->harq_processes[k]->Ndi = 0; + // ue->ulsch[i]->harq_processes[k]->Ndi = 0; } } // flush Msg3 buffer - phy_vars_ue->ulsch_ue_Msg3_active[i] = 0; + ue->ulsch_Msg3_active[i] = 0; } } @@ -340,13 +340,13 @@ void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) LOG_I(PHY,"[UE %d][RAPROC] Frame %d Random-access procedure succeeded\n",Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx); - PHY_vars_UE_g[Mod_id][CC_id]->ulsch_ue_Msg3_active[eNB_index] = 0; + PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0; PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH; for (i=0; i<8; i++) { - if (PHY_vars_UE_g[Mod_id][CC_id]->ulsch_ue[eNB_index]->harq_processes[i]) { - PHY_vars_UE_g[Mod_id][CC_id]->ulsch_ue[eNB_index]->harq_processes[i]->status=IDLE; - PHY_vars_UE_g[Mod_id][CC_id]->dlsch_ue[eNB_index][0]->harq_processes[i]->round=0; + if (PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]) { + PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->status=IDLE; + PHY_vars_UE_g[Mod_id][CC_id]->dlsch[eNB_index][0]->harq_processes[i]->round=0; } } @@ -359,7 +359,7 @@ UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index]); } -void process_timing_advance_rar(PHY_VARS_UE *phy_vars_ue,uint16_t timing_advance) +void process_timing_advance_rar(PHY_VARS_UE *ue,uint16_t timing_advance) { /* @@ -367,11 +367,11 @@ void process_timing_advance_rar(PHY_VARS_UE *phy_vars_ue,uint16_t timing_advance timing_advance = timing_advance - (1<<11); */ - phy_vars_ue->timing_advance = timing_advance*4; + ue->timing_advance = timing_advance*4; #ifdef DEBUG_PHY_PROC - LOG_I(PHY,"[UE %d] Frame %d, received (rar) timing_advance %d, HW timing advance %d\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_rx, phy_vars_ue->timing_advance); + LOG_I(PHY,"[UE %d] Frame %d, received (rar) timing_advance %d, HW timing advance %d\n",ue->Mod_id,ue->frame_rx, ue->timing_advance); #endif } @@ -392,41 +392,41 @@ void process_timing_advance(uint8_t Mod_id,uint8_t CC_id,int16_t timing_advance) } -uint8_t is_SR_TXOp(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe) +uint8_t is_SR_TXOp(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) { LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Checking for SR TXOp (sr_ConfigIndex %d)\n", - phy_vars_ue->Mod_id,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,phy_vars_ue->frame_tx,subframe, - phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex); + ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,ue->frame_tx,subframe, + ue->scheduling_request_config[eNB_id].sr_ConfigIndex); - if (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 4) { // 5 ms SR period - if ((subframe%5) == phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex) + if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 4) { // 5 ms SR period + if ((subframe%5) == ue->scheduling_request_config[eNB_id].sr_ConfigIndex) return(1); - } else if (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 14) { // 10 ms SR period - if (subframe==(phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex-5)) + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 14) { // 10 ms SR period + if (subframe==(ue->scheduling_request_config[eNB_id].sr_ConfigIndex-5)) return(1); - } else if (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period - if ((10*(phy_vars_ue->frame_tx&1)+subframe) == (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15)) + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period + if ((10*(ue->frame_tx&1)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15)) return(1); - } else if (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period - if ((10*(phy_vars_ue->frame_tx&3)+subframe) == (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35)) + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period + if ((10*(ue->frame_tx&3)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35)) return(1); - } else if (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period - if ((10*(phy_vars_ue->frame_tx&7)+subframe) == (phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75)) + } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period + if ((10*(ue->frame_tx&7)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75)) return(1); } return(0); } -uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, +uint16_t get_n1_pucch(PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint8_t *b, uint8_t SR) { - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; uint8_t nCCE0,nCCE1,harq_ack1,harq_ack0; ANFBmode_t bundling_flag; uint16_t n1_pucch0=0,n1_pucch1=0; @@ -435,27 +435,27 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, int M; // clear this, important for case where n1_pucch selection is not used - phy_vars_ue->pucch_sel[subframe] = 0; + ue->pucch_sel[subframe] = 0; if (frame_parms->frame_type == FDD ) { // FDD sf = (subframe<4)? subframe+6 : subframe-4; - LOG_D(PHY,"n1_pucch_UE: subframe %d, nCCE %d\n",sf,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->nCCE[sf]); + LOG_D(PHY,"n1_pucch_UE: subframe %d, nCCE %d\n",sf,ue->pdcch_vars[eNB_id]->nCCE[sf]); if (SR == 0) - return(frame_parms->pucch_config_common.n1PUCCH_AN + phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->nCCE[sf]); + return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[eNB_id]->nCCE[sf]); else - return(phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } else { - bundling_flag = phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; + bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; #ifdef DEBUG_PHY_PROC if (bundling_flag==bundling) { - LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_tx,subframe,SR, - phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,ue->frame_tx,subframe,SR, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } else { - LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_tx,subframe,SR, - phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,ue->frame_tx,subframe,SR, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } #endif @@ -479,29 +479,29 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, subframe_offset = 4; } else { LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", - phy_vars_ue->Mod_id,phy_vars_ue->frame_tx,subframe,frame_parms->tdd_config); + ue->Mod_id,ue->frame_tx,subframe,frame_parms->tdd_config); return(0); } // i=0 - nCCE0 = phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->nCCE[subframe_offset]; + nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[subframe_offset]; n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; // set ACK/NAK to values if not DTX - if (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[subframe_offset].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed - harq_ack0 = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[subframe_offset].ack; + if (ue->dlsch[eNB_id][0]->harq_ack[subframe_offset].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed + harq_ack0 = ue->dlsch[eNB_id][0]->harq_ack[subframe_offset].ack; if (harq_ack0!=2) { // DTX if (SR == 0) { // last paragraph pg 68 from 36.213 (v8.6), m=0 b[0]=(M==2) ? 1-harq_ack0 : harq_ack0; b[1]=harq_ack0; // in case we use pucch format 1b (subframes 2,7) - phy_vars_ue->pucch_sel[subframe] = 0; + ue->pucch_sel[subframe] = 0; return(n1_pucch0); } else { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213) b[0]=harq_ack0; - return(phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } } @@ -517,18 +517,18 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, // This is the offset for a particular subframe (2,3,4) => (0,2,4) subframe_offset = (subframe-2)<<1; // i=0 - nCCE0 = phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->nCCE[5+subframe_offset]; + nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[5+subframe_offset]; n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; // i=1 - nCCE1 = phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->nCCE[(6+subframe_offset)%10]; + nCCE1 = ue->pdcch_vars[eNB_id]->nCCE[(6+subframe_offset)%10]; n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; // set ACK/NAK to values if not DTX - if (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[(6+subframe_offset)%10].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed - harq_ack1 = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[(6+subframe_offset)%10].ack; + if (ue->dlsch[eNB_id][0]->harq_ack[(6+subframe_offset)%10].send_harq_status>0) // n-6 // subframe 6 is to be ACK/NAKed + harq_ack1 = ue->dlsch[eNB_id][0]->harq_ack[(6+subframe_offset)%10].ack; - if (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[5+subframe_offset].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed - harq_ack0 = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[5+subframe_offset].ack; + if (ue->dlsch[eNB_id][0]->harq_ack[5+subframe_offset].send_harq_status>0) // n-6 // subframe 5 is to be ACK/NAKed + harq_ack0 = ue->dlsch[eNB_id][0]->harq_ack[5+subframe_offset].ack; if (harq_ack1!=2) { // n-6 // subframe 6,8,0 and maybe 5,7,9 is to be ACK/NAKed @@ -541,7 +541,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, if (harq_ack0!=2) b[0]=b[0]&harq_ack0; - phy_vars_ue->pucch_sel[subframe] = 1; + ue->pucch_sel[subframe] = 1; return(n1_pucch1); } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 @@ -552,10 +552,10 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, b[0] = (harq_ack0!=harq_ack1)?0:1; if ((harq_ack0 == 1) && (harq_ack1 == 0)) { - phy_vars_ue->pucch_sel[subframe] = 0; + ue->pucch_sel[subframe] = 0; return(n1_pucch0); } else { - phy_vars_ue->pucch_sel[subframe] = 1; + ue->pucch_sel[subframe] = 1; return(n1_pucch1); } } else if (SR==1) { // SR and 0,1,or 2 ACKS, (first 3 entries in Table 7.3-1 of 36.213) @@ -565,22 +565,22 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, b[0]= harq_ack1 | harq_ack0; b[1]= harq_ack1 ^ harq_ack0; - return(phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } } else if (harq_ack0!=2) { // n-7 // subframe 5,7,9 only is to be ACK/NAKed if ((bundling_flag==bundling)&&(SR == 0)) { // last paragraph pg 68 from 36.213 (v8.6), m=0 b[0]=harq_ack0; - phy_vars_ue->pucch_sel[subframe] = 0; + ue->pucch_sel[subframe] = 0; return(n1_pucch0); } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 with i=1 set to DTX b[0] = harq_ack0; b[1] = 1-b[0]; - phy_vars_ue->pucch_sel[subframe] = 0; + ue->pucch_sel[subframe] = 0; return(n1_pucch0); } else if (SR==1) { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213) b[0]=harq_ack0; b[1]=b[0]; - return(phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); + return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } } @@ -589,7 +589,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, } // switch tdd_config } - LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n",phy_vars_ue->frame_tx); + LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n",ue->frame_tx); return(-1); } @@ -602,21 +602,21 @@ void phy_procedures_emos_UE_TX(uint8_t next_slot,uint8_t eNB_id) { if (next_slot%2==0) { // get harq_pid from subframe relationship - harq_pid = subframe2harq_pid(&phy_vars_ue->lte_frame_parms,phy_vars_ue->frame,(next_slot>>1)); + harq_pid = subframe2harq_pid(&ue->frame_parms,ue->frame,(next_slot>>1)); if (harq_pid==255) { LOG_E(PHY,"[UE%d] Frame %d : FATAL ERROR: illegal harq_pid, returning\n", - 0,phy_vars_ue->frame); + 0,ue->frame); return; } - if (ulsch_ue[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { + if (ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { emos_dump_UE.uci_cnt[next_slot>>1] = 1; - memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o,ulsch_ue[eNB_id]->o,MAX_CQI_BITS*sizeof(char)); - emos_dump_UE.UCI_data[0][next_slot>>1].O = ulsch_ue[eNB_id]->O; - memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_RI,ulsch_ue[eNB_id]->o_RI,2*sizeof(char)); - emos_dump_UE.UCI_data[0][next_slot>>1].O_RI = ulsch_ue[eNB_id]->O_RI; - memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_ACK,ulsch_ue[eNB_id]->o_ACK,4*sizeof(char)); - emos_dump_UE.UCI_data[0][next_slot>>1].O_ACK = ulsch_ue[eNB_id]->harq_processes[harq_pid]->O_ACK; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o,ulsch[eNB_id]->o,MAX_CQI_BITS*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O = ulsch[eNB_id]->O; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_RI,ulsch[eNB_id]->o_RI,2*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O_RI = ulsch[eNB_id]->O_RI; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_ACK,ulsch[eNB_id]->o_ACK,4*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O_ACK = ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK; } else { emos_dump_UE.uci_cnt[next_slot>>1] = 0; @@ -629,7 +629,7 @@ void phy_procedures_emos_UE_TX(uint8_t next_slot,uint8_t eNB_id) { int dummy_tx_buffer[3840*4] __attribute__((aligned(16))); PRACH_RESOURCES_t prach_resources_local; -void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) +void phy_procedures_UE_TX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) { int i; @@ -645,7 +645,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra uint8_t SR_payload; int32_t prach_power; uint8_t nsymb; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; uint8_t generate_ul_signal = 0; uint8_t ack_status=0; int8_t Po_PUCCH; @@ -654,69 +654,69 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra int overflow=0; int k,l; #endif - int slot_tx = phy_vars_ue->slot_tx; - int subframe_tx = phy_vars_ue->slot_tx>>1; - int frame_tx = phy_vars_ue->frame_tx; - int Mod_id = phy_vars_ue->Mod_id; - int CC_id = phy_vars_ue->CC_id; + int slot_tx = ue->slot_tx; + int subframe_tx = ue->slot_tx>>1; + int frame_tx = ue->frame_tx; + int Mod_id = ue->Mod_id; + int CC_id = ue->CC_id; int tx_amp; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); - start_meas(&phy_vars_ue->phy_proc_tx); + start_meas(&ue->phy_proc_tx); #ifdef EMOS //phy_procedures_emos_UE_TX(next_slot); #endif if ((slot_tx%2)==0) { - phy_vars_ue->tx_power_dBm=-127; + ue->tx_power_dBm=-127; if (abstraction_flag==0) { for (aa=0; aanb_antennas_tx; aa++) { - memset(&phy_vars_ue->lte_ue_common_vars.txdataF[aa][subframe_tx*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti], + memset(&ue->common_vars.txdataF[aa][subframe_tx*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti], 0, frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*sizeof(int32_t)); } } - if (phy_vars_ue->UE_mode[eNB_id] != PRACH) { + if (ue->UE_mode[eNB_id] != PRACH) { /* #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d: Generating SRS\n",Mod_id,phy_vars_ue->frame,slot_tx); + LOG_D(PHY,"[UE %d] Frame %d, slot %d: Generating SRS\n",Mod_id,ue->frame,slot_tx); #endif if (abstraction_flag == 0) { #ifdef OFDMA_ULSCH - generate_srs_tx(phy_vars_ue,eNB_id,AMP,subframe_tx); + generate_srs_tx(ue,eNB_id,AMP,subframe_tx); #else - generate_srs_tx(phy_vars_ue,eNB_id,AMP,subframe_tx); + generate_srs_tx(ue,eNB_id,AMP,subframe_tx); #endif } #ifdef PHY_ABSTRACTION else { - generate_srs_tx_emul(phy_vars_ue,subframe_tx); + generate_srs_tx_emul(ue,subframe_tx); } #endif */ // get harq_pid from subframe relationship - harq_pid = subframe2harq_pid(&phy_vars_ue->lte_frame_parms, + harq_pid = subframe2harq_pid(&ue->frame_parms, frame_tx, subframe_tx); - if (phy_vars_ue->mac_enabled == 1) { - if ((phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] == 1) && - (phy_vars_ue->ulsch_ue_Msg3_frame[eNB_id] == frame_tx) && - (phy_vars_ue->ulsch_ue_Msg3_subframe[eNB_id] == subframe_tx)) { // Initial Transmission of Msg3 + if (ue->mac_enabled == 1) { + if ((ue->ulsch_Msg3_active[eNB_id] == 1) && + (ue->ulsch_Msg3_frame[eNB_id] == frame_tx) && + (ue->ulsch_Msg3_subframe[eNB_id] == subframe_tx)) { // Initial Transmission of Msg3 - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; - if (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->round==0) - generate_ue_ulsch_params_from_rar(phy_vars_ue, + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) + generate_ue_ulsch_params_from_rar(ue, eNB_id); - phy_vars_ue->ulsch_ue[eNB_id]->power_offset = 14; + ue->ulsch[eNB_id]->power_offset = 14; LOG_D(PHY,"[UE %d][RAPROC] Frame %d: Setting Msg3_flag in subframe %d, for harq_pid %d\n", Mod_id, frame_tx, @@ -730,7 +730,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra Mod_id,frame_tx); mac_xface->macphy_exit("Error in ulsch_decoding"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_tx); + stop_meas(&ue->phy_proc_tx); return; } @@ -738,20 +738,20 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra } } - if (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { generate_ul_signal = 1; // deactivate service request - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; - ack_status = get_ack(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack, + ack_status = get_ack(&ue->frame_parms, + ue->dlsch[eNB_id][0]->harq_ack, subframe_tx, - phy_vars_ue->ulsch_ue[eNB_id]->o_ACK); + ue->ulsch[eNB_id]->o_ACK); - first_rb = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->first_rb; - nb_rb = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->nb_rb; + first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; + nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; //frame_parms->pusch_config_c ommon.ul_ReferenceSignalsPUSCH.cyclicShift = 0; @@ -765,26 +765,26 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra "[UE %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d\n", Mod_id,harq_pid,frame_tx,subframe_tx, first_rb,nb_rb, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->round, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->mcs, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->rvidx, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift+ - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->n_DMRS2+ + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2+ frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[slot_tx])%12, frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->n_DMRS2, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2, frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[slot_tx], - phy_vars_ue->ulsch_ue[eNB_id]->o_ACK[0],phy_vars_ue->ulsch_ue[eNB_id]->o_ACK[1], - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->O_ACK); + ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); #endif if (ack_status > 0) { LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n", Mod_id, - phy_vars_ue->ulsch_ue[eNB_id]->rnti, + ue->ulsch[eNB_id]->rnti, frame_tx,subframe_tx, - phy_vars_ue->ulsch_ue[eNB_id]->o_ACK[0],phy_vars_ue->ulsch_ue[eNB_id]->o_ACK[1], - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->O_ACK); + ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); } @@ -792,50 +792,50 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra //#ifdef DEBUG_PHY_PROC - // debug_LOG_D(PHY,"[UE %d] Frame %d, Subframe %d ulsch harq_pid %d : O %d, O_ACK %d, O_RI %d, TBS %d\n",Mod_id,phy_vars_ue->frame,subframe_tx,harq_pid,phy_vars_ue->ulsch_ue[eNB_id]->O,phy_vars_ue->ulsch_ue[eNB_id]->O_ACK,phy_vars_ue->ulsch_ue[eNB_id]->O_RI,phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS); + // debug_LOG_D(PHY,"[UE %d] Frame %d, Subframe %d ulsch harq_pid %d : O %d, O_ACK %d, O_RI %d, TBS %d\n",Mod_id,ue->frame,subframe_tx,harq_pid,ue->ulsch[eNB_id]->O,ue->ulsch[eNB_id]->O_ACK,ue->ulsch[eNB_id]->O_RI,ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS); //#endif if (Msg3_flag == 1) { LOG_I(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d next slot %d Generating (RRCConnectionRequest) Msg3 (nb_rb %d, first_rb %d, round %d, rvidx %d) Msg3: %x.%x.%x|%x.%x.%x.%x.%x.%x\n",Mod_id,frame_tx, subframe_tx, slot_tx, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->nb_rb, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->first_rb, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->round, - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->prach_resources[eNB_id]->Msg3[0], - phy_vars_ue->prach_resources[eNB_id]->Msg3[1], - phy_vars_ue->prach_resources[eNB_id]->Msg3[2], - phy_vars_ue->prach_resources[eNB_id]->Msg3[3], - phy_vars_ue->prach_resources[eNB_id]->Msg3[4], - phy_vars_ue->prach_resources[eNB_id]->Msg3[5], - phy_vars_ue->prach_resources[eNB_id]->Msg3[6], - phy_vars_ue->prach_resources[eNB_id]->Msg3[7], - phy_vars_ue->prach_resources[eNB_id]->Msg3[8]); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, + ue->prach_resources[eNB_id]->Msg3[0], + ue->prach_resources[eNB_id]->Msg3[1], + ue->prach_resources[eNB_id]->Msg3[2], + ue->prach_resources[eNB_id]->Msg3[3], + ue->prach_resources[eNB_id]->Msg3[4], + ue->prach_resources[eNB_id]->Msg3[5], + ue->prach_resources[eNB_id]->Msg3[6], + ue->prach_resources[eNB_id]->Msg3[7], + ue->prach_resources[eNB_id]->Msg3[8]); - start_meas(&phy_vars_ue->ulsch_encoding_stats); + start_meas(&ue->ulsch_encoding_stats); if (abstraction_flag==0) { - if (ulsch_encoding(phy_vars_ue->prach_resources[eNB_id]->Msg3, - phy_vars_ue, + if (ulsch_encoding(ue->prach_resources[eNB_id]->Msg3, + ue, harq_pid, eNB_id, - phy_vars_ue->transmission_mode[eNB_id],0,0)!=0) { + ue->transmission_mode[eNB_id],0,0)!=0) { LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); mac_xface->macphy_exit("Error in ulsch_coding"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_tx); + stop_meas(&ue->phy_proc_tx); return; } } #ifdef PHY_ABSTRACTION else { - ulsch_encoding_emul(phy_vars_ue->prach_resources[eNB_id]->Msg3,phy_vars_ue,eNB_id,harq_pid,0); + ulsch_encoding_emul(ue->prach_resources[eNB_id]->Msg3,ue,eNB_id,harq_pid,0); } #endif - stop_meas(&phy_vars_ue->ulsch_encoding_stats); + stop_meas(&ue->ulsch_encoding_stats); - if (phy_vars_ue->mac_enabled == 1) { + if (ue->mac_enabled == 1) { // signal MAC that Msg3 was sent mac_xface->Msg3_transmitted(Mod_id, CC_id, @@ -843,12 +843,12 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra eNB_id); } } else { - input_buffer_length = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS/8; + input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; - if (phy_vars_ue->mac_enabled==1) { + if (ue->mac_enabled==1) { // LOG_D(PHY,"[UE %d] ULSCH : Searching for MAC SDUs\n",Mod_id); - if (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->round==0) { - //if (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) { + //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { access_mode=SCHEDULED_ACCESS; mac_xface->ue_get_sdu(Mod_id, CC_id, @@ -864,7 +864,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra else { // Get calibration information from TDD procedures LOG_D(PHY,"[UE %d] Frame %d, subframe %d : ULSCH: Getting TDD Auto-Calibration information\n", - Mod_id,phy_vars_ue->frame,subframe_tx); + Mod_id,ue->frame,subframe_tx); for (i=0;iulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS>>3); + LOG_D(PHY,"[UE] Frame %d, subframe %d : ULSCH SDU (TX harq_pid %d) (%d bytes) : \n",frame_tx,subframe_tx,harq_pid, ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3); - for (i=0; iulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS>>3; i++) + for (i=0; iulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3; i++) LOG_T(PHY,"%x.",ulsch_input_buffer[i]); LOG_T(PHY,"\n"); @@ -886,7 +886,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra else { // the following lines were necessary for the calibration in CROWN /* - if (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { for (i=0;iulsch_ue[eNB_id]->o ,0,MAX_CQI_BYTES*sizeof(uint8_t)); - memset(phy_vars_ue->ulsch_ue[eNB_id]->o_RI ,0,2*sizeof(uint8_t)); - memset(phy_vars_ue->ulsch_ue[eNB_id]->o_ACK,0,4*sizeof(uint8_t)); + memset(ue->ulsch[eNB_id]->o ,0,MAX_CQI_BYTES*sizeof(uint8_t)); + memset(ue->ulsch[eNB_id]->o_RI ,0,2*sizeof(uint8_t)); + memset(ue->ulsch[eNB_id]->o_ACK,0,4*sizeof(uint8_t)); for (i=0;iulsch_encoding_stats); + start_meas(&ue->ulsch_encoding_stats); if (abstraction_flag==0) { /* - if (phy_vars_ue->frame%100==0) { + if (ue->frame%100==0) { LOG_I(PHY,"Encoding ulsch\n"); } */ if (ulsch_encoding(ulsch_input_buffer, - phy_vars_ue, + ue, harq_pid, eNB_id, - phy_vars_ue->transmission_mode[eNB_id],0, + ue->transmission_mode[eNB_id],0, 0)!=0) { // Nbundled, to be updated!!!! LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_tx); + stop_meas(&ue->phy_proc_tx); return; } } #ifdef PHY_ABSTRACTION else { - ulsch_encoding_emul(ulsch_input_buffer,phy_vars_ue,eNB_id,harq_pid,0); + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); } #endif - stop_meas(&phy_vars_ue->ulsch_encoding_stats); + stop_meas(&ue->ulsch_encoding_stats); } if (abstraction_flag == 0) { - if (phy_vars_ue->mac_enabled==1) { - pusch_power_cntl(phy_vars_ue,subframe_tx,eNB_id,1, abstraction_flag); - phy_vars_ue->tx_power_dBm = phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH; + if (ue->mac_enabled==1) { + pusch_power_cntl(ue,subframe_tx,eNB_id,1, abstraction_flag); + ue->tx_power_dBm = ue->ulsch[eNB_id]->Po_PUSCH; } else { - phy_vars_ue->tx_power_dBm = phy_vars_ue->tx_power_max_dBm; + ue->tx_power_dBm = ue->tx_power_max_dBm; } - phy_vars_ue->tx_total_RE = nb_rb*12; + ue->tx_total_RE = nb_rb*12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - tx_amp = get_tx_amp(phy_vars_ue->tx_power_dBm, - phy_vars_ue->tx_power_max_dBm, - phy_vars_ue->lte_frame_parms.N_RB_UL, + tx_amp = get_tx_amp(ue->tx_power_dBm, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, nb_rb); #else tx_amp = AMP; #endif LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", - Mod_id,harq_pid,frame_tx,subframe_tx,phy_vars_ue->tx_power_dBm,phy_vars_ue->tx_power_max_dBm, tx_amp); - start_meas(&phy_vars_ue->ulsch_modulation_stats); - ulsch_modulation(phy_vars_ue->lte_ue_common_vars.txdataF, + Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm,ue->tx_power_max_dBm, tx_amp); + start_meas(&ue->ulsch_modulation_stats); + ulsch_modulation(ue->common_vars.txdataF, tx_amp, frame_tx, subframe_tx, - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->ulsch_ue[eNB_id]); + &ue->frame_parms, + ue->ulsch[eNB_id]); for (aa=0; aa<1/*frame_parms->nb_antennas_tx*/; aa++) - generate_drs_pusch(phy_vars_ue, + generate_drs_pusch(ue, eNB_id, tx_amp, subframe_tx, @@ -976,19 +976,19 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra nb_rb, aa); - stop_meas(&phy_vars_ue->ulsch_modulation_stats); + stop_meas(&ue->ulsch_modulation_stats); } if (abstraction_flag==1) { // clear SR - phy_vars_ue->sr[subframe_tx]=0; + ue->sr[subframe_tx]=0; } } // ULSCH is active #ifdef PUCCH - else if (phy_vars_ue->UE_mode[eNB_id] == PUSCH) { // check if we need to use PUCCH 1a/1b + else if (ue->UE_mode[eNB_id] == PUSCH) { // check if we need to use PUCCH 1a/1b // debug_LOG_D(PHY,"[UE%d] Frame %d, subframe %d: Checking for PUCCH 1a/1b\n",Mod_id,frame_tx,subframe_tx); - bundling_flag = phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; + bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; if ((frame_parms->frame_type==FDD) || (bundling_flag==bundling) || @@ -1001,16 +1001,16 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra } // Check for SR and do ACK/NACK accordingly - if (is_SR_TXOp(phy_vars_ue,eNB_id,subframe_tx)==1) { + if (is_SR_TXOp(ue,eNB_id,subframe_tx)==1) { LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d: got SR_TXOp, Checking for SR for PUSCH from MAC\n", - Mod_id,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx); + Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx); - if (phy_vars_ue->mac_enabled==1) { + if (ue->mac_enabled==1) { SR_payload = mac_xface->ue_get_SR(Mod_id, CC_id, frame_tx, eNB_id, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[eNB_id]->crnti, subframe_tx); // subframe used for meas gap } else { @@ -1020,40 +1020,40 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra if (SR_payload>0) { generate_ul_signal = 1; LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d got the SR for PUSCH is %d\n", - Mod_id,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx,SR_payload); + Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx,SR_payload); } else { - phy_vars_ue->sr[subframe_tx]=0; + ue->sr[subframe_tx]=0; } } else { SR_payload=0; } - if (get_ack(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack, + if (get_ack(&ue->frame_parms, + ue->dlsch[eNB_id][0]->harq_ack, subframe_tx,pucch_ack_payload) > 0) { // we need to transmit ACK/NAK in this subframe generate_ul_signal = 1; - n1_pucch = get_n1_pucch(phy_vars_ue, + n1_pucch = get_n1_pucch(ue, eNB_id, subframe_tx, pucch_ack_payload, SR_payload); - if (phy_vars_ue->mac_enabled == 1) { - Po_PUCCH = pucch_power_cntl(phy_vars_ue,subframe_tx,eNB_id,format); + if (ue->mac_enabled == 1) { + Po_PUCCH = pucch_power_cntl(ue,subframe_tx,eNB_id,format); } else { - Po_PUCCH = phy_vars_ue->tx_power_max_dBm; + Po_PUCCH = ue->tx_power_max_dBm; } - phy_vars_ue->tx_power_dBm = Po_PUCCH; - phy_vars_ue->tx_total_RE = 12; + ue->tx_power_dBm = Po_PUCCH; + ue->tx_total_RE = 12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(Po_PUCCH, - phy_vars_ue->tx_power_max_dBm, - phy_vars_ue->lte_frame_parms.N_RB_UL, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, 1); #else tx_amp = AMP; @@ -1062,16 +1062,16 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra if (SR_payload>0) { LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), n1_pucch %d, Po_PUCCH, amp %d\n", Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, + ue->dlsch[eNB_id][0]->rnti, frame_tx, subframe_tx, pucch_ack_payload[0],pucch_ack_payload[1], - phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, Po_PUCCH, tx_amp); } else { LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n", Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, + ue->dlsch[eNB_id][0]->rnti, frame_tx, subframe_tx, n1_pucch,pucch_ack_payload[0],pucch_ack_payload[1],SR_payload, Po_PUCCH, @@ -1080,11 +1080,11 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra if (abstraction_flag == 0) { - generate_pucch(phy_vars_ue->lte_ue_common_vars.txdataF, - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->ncs_cell, + generate_pucch(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, format, - &phy_vars_ue->pucch_config_dedicated[eNB_id], + &ue->pucch_config_dedicated[eNB_id], n1_pucch, 0, // n2_pucch 1, // shortened format @@ -1095,9 +1095,9 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra } else { #ifdef PHY_ABSTRACTION LOG_D(PHY,"Calling generate_pucch_emul ... (ACK %d %d, SR %d)\n",pucch_ack_payload[0],pucch_ack_payload[1],SR_payload); - generate_pucch_emul(phy_vars_ue, + generate_pucch_emul(ue, format, - phy_vars_ue->lte_frame_parms.pucch_config_common.nCS_AN, + ue->frame_parms.pucch_config_common.nCS_AN, pucch_ack_payload, SR_payload, subframe_tx); @@ -1105,38 +1105,38 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra } } else if (SR_payload==1) { // no ACK/NAK but SR is triggered by MAC - if (phy_vars_ue->mac_enabled == 1) { - Po_PUCCH = pucch_power_cntl(phy_vars_ue,subframe_tx,eNB_id,pucch_format1); + if (ue->mac_enabled == 1) { + Po_PUCCH = pucch_power_cntl(ue,subframe_tx,eNB_id,pucch_format1); } else { - Po_PUCCH = phy_vars_ue->tx_power_max_dBm; + Po_PUCCH = ue->tx_power_max_dBm; } - phy_vars_ue->tx_power_dBm = Po_PUCCH; - phy_vars_ue->tx_total_RE = 12; + ue->tx_power_dBm = Po_PUCCH; + ue->tx_total_RE = 12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(Po_PUCCH, - phy_vars_ue->tx_power_max_dBm, - phy_vars_ue->lte_frame_parms.N_RB_UL, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, 1); #else tx_amp = AMP; #endif LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1 (SR for PUSCH), n1_pucch %d, Po_PUCCH %d\n", Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, + ue->dlsch[eNB_id][0]->rnti, frame_tx, subframe_tx, - phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, Po_PUCCH); if (abstraction_flag == 0) { - generate_pucch(phy_vars_ue->lte_ue_common_vars.txdataF, - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->ncs_cell, + generate_pucch(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, pucch_format1, - &phy_vars_ue->pucch_config_dedicated[eNB_id], - phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + &ue->pucch_config_dedicated[eNB_id], + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, 0, // n2_pucch 1, // shortened format pucch_ack_payload, // this is ignored anyway, we just need a pointer @@ -1144,9 +1144,9 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra subframe_tx); } else { LOG_D(PHY,"Calling generate_pucch_emul ...\n"); - generate_pucch_emul(phy_vars_ue, + generate_pucch_emul(ue, pucch_format1, - phy_vars_ue->lte_frame_parms.pucch_config_common.nCS_AN, + ue->frame_parms.pucch_config_common.nCS_AN, pucch_ack_payload, SR_payload, subframe_tx); @@ -1158,19 +1158,19 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra #ifdef CBA - if ((phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag >= 1) && - (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->status == CBA_ACTIVE)) { - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag=0; //-=1 - // phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->status= IDLE; - first_rb = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->first_rb; - nb_rb = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->nb_rb; - //cba_mcs=phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->mcs; - input_buffer_length = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->TBS/8; + if ((ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag >= 1) && + (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == CBA_ACTIVE)) { + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag=0; //-=1 + // ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; + first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; + nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; + //cba_mcs=ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs; + input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; access_mode=CBA_ACCESS; LOG_D(PHY,"[UE %d] Frame %d, subframe %d: CBA num dci %d\n", Mod_id,frame_tx,subframe_tx, - phy_vars_ue->ulsch_ue[eNB_id]->num_cba_dci[subframe_tx]); + ue->ulsch[eNB_id]->num_cba_dci[subframe_tx]); mac_xface->ue_get_sdu(Mod_id, CC_id, @@ -1181,16 +1181,16 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra input_buffer_length, &access_mode); - phy_vars_ue->ulsch_ue[eNB_id]->num_cba_dci[subframe_tx]=0; + ue->ulsch[eNB_id]->num_cba_dci[subframe_tx]=0; if (access_mode > UNKNOWN_ACCESS) { if (abstraction_flag==0) { if (ulsch_encoding(ulsch_input_buffer, - phy_vars_ue, + ue, harq_pid, eNB_id, - phy_vars_ue->transmission_mode[eNB_id],0, + ue->transmission_mode[eNB_id],0, 0)!=0) { // Nbundled, to be updated!!!! LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); return; @@ -1199,13 +1199,13 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra #ifdef PHY_ABSTRACTION else { - ulsch_encoding_emul(ulsch_input_buffer,phy_vars_ue,eNB_id,harq_pid,0); + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); } #endif } else { - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->status= IDLE; - //reset_cba_uci(phy_vars_ue->ulsch_ue[eNB_id]->o); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; + //reset_cba_uci(ue->ulsch[eNB_id]->o); LOG_N(PHY,"[UE %d] Frame %d, subframe %d: CBA transmission cancelled or postponed\n", Mod_id, frame_tx,subframe_tx); } @@ -1217,75 +1217,75 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra nsymb = (frame_parms->Ncp == 0) ? 14 : 12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case - ulsch_start = (phy_vars_ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- - phy_vars_ue->hw_timing_advance- - phy_vars_ue->timing_advance- - phy_vars_ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); + ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- + ue->hw_timing_advance- + ue->timing_advance- + ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); #else //this is the normal case - ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-phy_vars_ue->N_TA_offset; //-phy_vars_ue->timing_advance; + ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance; #endif //else EXMIMO if ((frame_tx%100) == 0) LOG_D(PHY,"[UE %d] Frame %d, subframe %d: ulsch_start = %d (rxoff %d, HW TA %d, timing advance %d, TA_offset %d\n", Mod_id,frame_tx,subframe_tx, ulsch_start, - phy_vars_ue->rx_offset, - phy_vars_ue->hw_timing_advance, - phy_vars_ue->timing_advance, - phy_vars_ue->N_TA_offset); + ue->rx_offset, + ue->hw_timing_advance, + ue->timing_advance, + ue->N_TA_offset); if (generate_ul_signal == 1 ) { - start_meas(&phy_vars_ue->ofdm_mod_stats); + start_meas(&ue->ofdm_mod_stats); for (aa=0; aanb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(&phy_vars_ue->lte_ue_common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], + PHY_ofdm_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) dummy_tx_buffer, #else - &phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start], + &ue->common_vars.txdata[aa][ulsch_start], #endif frame_parms->ofdm_symbol_size, nsymb, frame_parms->nb_prefix_samples, CYCLIC_PREFIX); else - normal_prefix_mod(&phy_vars_ue->lte_ue_common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], + normal_prefix_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) dummy_tx_buffer, #else - &phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start], + &ue->common_vars.txdata[aa][ulsch_start], #endif nsymb, - &phy_vars_ue->lte_frame_parms); + &ue->frame_parms); /* if (subframe_tx == 8) { printf("Symbol 0 %p (offset %d) base %p\n", - &phy_vars_ue->lte_ue_common_vars.txdataF[0][nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe], + &ue->common_vars.txdataF[0][nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe], nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe, - phy_vars_ue->lte_ue_common_vars.txdataF[0]); - write_output("txsigF8.m","txsF8", &phy_vars_ue->lte_ue_common_vars.txdataF[0][nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe], - phy_vars_ue->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); - write_output("txsig8.m","txs8", &phy_vars_ue->lte_ue_common_vars.txdata[0][phy_vars_ue->lte_frame_parms.samples_per_tti*subframe], - phy_vars_ue->lte_frame_parms.samples_per_tti,1,1); + ue->common_vars.txdataF[0]); + write_output("txsigF8.m","txsF8", &ue->common_vars.txdataF[0][nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe], + ue->frame_parms.ofdm_symbol_size*nsymb,1,1); + write_output("txsig8.m","txs8", &ue->common_vars.txdata[0][ue->frame_parms.samples_per_tti*subframe], + ue->frame_parms.samples_per_tti,1,1); } */ #ifndef OFDMA_ULSCH #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - apply_7_5_kHz(phy_vars_ue,dummy_tx_buffer,0); - apply_7_5_kHz(phy_vars_ue,dummy_tx_buffer,1); + apply_7_5_kHz(ue,dummy_tx_buffer,0); + apply_7_5_kHz(ue,dummy_tx_buffer,1); #else - apply_7_5_kHz(phy_vars_ue,&phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start],0); - apply_7_5_kHz(phy_vars_ue,&phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start],1); + apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0); + apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1); #endif /* if (subframe_tx == 8) { - write_output("txsig8_mod.m","txs8_mod", &phy_vars_ue->lte_ue_common_vars.txdata[0][phy_vars_ue->lte_frame_parms.samples_per_tti*subframe], - phy_vars_ue->lte_frame_parms.samples_per_tti,1,1); + write_output("txsig8_mod.m","txs8_mod", &ue->common_vars.txdata[0][ue->frame_parms.samples_per_tti*subframe], + ue->frame_parms.samples_per_tti,1,1); } */ #endif @@ -1295,34 +1295,34 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra //if ((slot_tx==4) && (aa==0)) printf("ulsch_start %d, overflow %d\n",ulsch_start,overflow); for (k=ulsch_start,l=0; ksamples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti); k++,l++) { - ((short*)phy_vars_ue->lte_ue_common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)phy_vars_ue->lte_ue_common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; } for (k=0; klte_ue_common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)phy_vars_ue->lte_ue_common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; } #if defined(EXMIMO) // handle switch before 1st TX subframe, guarantee that the slot prior to transmission is switch on for (k=ulsch_start - (frame_parms->samples_per_tti>>1) ; klte_ue_common_vars.txdata[aa][k+frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + ue->common_vars.txdata[aa][k+frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; else if (k>(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) - phy_vars_ue->lte_ue_common_vars.txdata[aa][k-frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + ue->common_vars.txdata[aa][k-frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; else - phy_vars_ue->lte_ue_common_vars.txdata[aa][k] &= 0xFFFEFFFE; + ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE; } #endif #endif } //nb_antennas_tx - stop_meas(&phy_vars_ue->ofdm_mod_stats); + stop_meas(&ue->ofdm_mod_stats); } // generate_ul_signal == 1 else { // no uplink so clear signal buffer instead for (aa=0; aanb_antennas_tx; aa++) { - memset(&phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start],0,frame_parms->samples_per_tti<<2); + memset(&ue->common_vars.txdata[aa][ulsch_start],0,frame_parms->samples_per_tti<<2); } } } @@ -1331,33 +1331,33 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra // }// slot_tx is even // else { // slot_tx is odd, do the PRACH here - if ((phy_vars_ue->UE_mode[eNB_id] == PRACH) && (phy_vars_ue->lte_frame_parms.prach_config_common.prach_Config_enabled==1)) { + if ((ue->UE_mode[eNB_id] == PRACH) && (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) { // check if we have PRACH opportunity - if (is_prach_subframe(&phy_vars_ue->lte_frame_parms,frame_tx,subframe_tx)) { - phy_vars_ue->generate_prach=0; + if (is_prach_subframe(&ue->frame_parms,frame_tx,subframe_tx)) { + ue->generate_prach=0; - if (phy_vars_ue->mac_enabled==1){ + if (ue->mac_enabled==1){ // ask L2 for RACH transport if ((mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) && (mode != no_L2_connect) ) { - phy_vars_ue->prach_resources[eNB_id] = mac_xface->ue_get_rach(Mod_id, + ue->prach_resources[eNB_id] = mac_xface->ue_get_rach(Mod_id, CC_id, frame_tx, eNB_id, subframe_tx); - // LOG_I(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,phy_vars_ue->prach_resources[eNB_id],UE_mac_inst[Mod_id].radioResourceConfigCommon); + // LOG_I(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[Mod_id].radioResourceConfigCommon); } } - if (phy_vars_ue->prach_resources[eNB_id]!=NULL) { + if (ue->prach_resources[eNB_id]!=NULL) { - phy_vars_ue->generate_prach=1; - phy_vars_ue->prach_cnt=0; + ue->generate_prach=1; + ue->prach_cnt=0; #ifdef SMBV - phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; + ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; #endif #ifdef OAI_EMU - phy_vars_ue->prach_PreambleIndex=phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex; + ue->prach_PreambleIndex=ue->prach_resources[eNB_id]->ra_PreambleIndex; #endif if (abstraction_flag == 0) { @@ -1365,49 +1365,49 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra Mod_id, frame_tx, subframe_tx, - phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex, - phy_vars_ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER, - phy_vars_ue->prach_resources[eNB_id]->ra_TDD_map_index, - phy_vars_ue->prach_resources[eNB_id]->ra_RNTI); + ue->prach_resources[eNB_id]->ra_PreambleIndex, + ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER, + ue->prach_resources[eNB_id]->ra_TDD_map_index, + ue->prach_resources[eNB_id]->ra_RNTI); - if ((phy_vars_ue->mac_enabled==1) && (mode != calib_prach_tx)) { - phy_vars_ue->tx_power_dBm = phy_vars_ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(Mod_id,CC_id,eNB_id); + if ((ue->mac_enabled==1) && (mode != calib_prach_tx)) { + ue->tx_power_dBm = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(Mod_id,CC_id,eNB_id); } else { - phy_vars_ue->tx_power_dBm = phy_vars_ue->tx_power_max_dBm; - phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; + ue->tx_power_dBm = ue->tx_power_max_dBm; + ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; } - phy_vars_ue->tx_total_RE = 96; + ue->tx_total_RE = 96; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - phy_vars_ue->lte_ue_prach_vars[eNB_id]->amp = get_tx_amp(phy_vars_ue->tx_power_dBm, - phy_vars_ue->tx_power_max_dBm, - phy_vars_ue->lte_frame_parms.N_RB_UL, + ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, 6); #else - phy_vars_ue->lte_ue_prach_vars[eNB_id]->amp = AMP; + ue->prach_vars[eNB_id]->amp = AMP; #endif - if ((mode == calib_prach_tx) && (((phy_vars_ue->frame_tx&0xfffe)%100)==0)) - LOG_D(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d : PRACH TX power %d dBm, amp %d\n",Mod_id,phy_vars_ue->frame_rx,phy_vars_ue->slot_tx>>1,phy_vars_ue->tx_power_dBm, - phy_vars_ue->lte_ue_prach_vars[eNB_id]->amp); + if ((mode == calib_prach_tx) && (((ue->frame_tx&0xfffe)%100)==0)) + LOG_D(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d : PRACH TX power %d dBm, amp %d\n",Mod_id,ue->frame_rx,ue->slot_tx>>1,ue->tx_power_dBm, + ue->prach_vars[eNB_id]->amp); - // start_meas(&phy_vars_ue->tx_prach); + // start_meas(&ue->tx_prach); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN); - prach_power = generate_prach(phy_vars_ue,eNB_id,subframe_tx,frame_tx); + prach_power = generate_prach(ue,eNB_id,subframe_tx,frame_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_OUT); - // stop_meas(&phy_vars_ue->tx_prach); + // stop_meas(&ue->tx_prach); LOG_D(PHY,"[UE %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n", Mod_id, get_PL(Mod_id,CC_id,eNB_id), - phy_vars_ue->tx_power_dBm, + ue->tx_power_dBm, dB_fixed(prach_power), - phy_vars_ue->lte_ue_prach_vars[eNB_id]->amp); + ue->prach_vars[eNB_id]->amp); } else { UE_transport_info[Mod_id][CC_id].cntl.prach_flag=1; - UE_transport_info[Mod_id][CC_id].cntl.prach_id=phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex; - if (phy_vars_ue->mac_enabled==1){ + UE_transport_info[Mod_id][CC_id].cntl.prach_id=ue->prach_resources[eNB_id]->ra_PreambleIndex; + if (ue->mac_enabled==1){ mac_xface->Msg1_transmitted(Mod_id, CC_id, frame_tx, @@ -1417,8 +1417,8 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Generating PRACH (eNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB), l3msg \n", Mod_id,frame_tx,subframe_tx,eNB_id, - phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex, - phy_vars_ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(Mod_id,CC_id,eNB_id), + ue->prach_resources[eNB_id]->ra_PreambleIndex, + ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(Mod_id,CC_id,eNB_id), get_PL(Mod_id,CC_id,eNB_id)); } @@ -1426,29 +1426,29 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra } // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue if (mode == calib_prach_tx) - phy_vars_ue->prach_resources[eNB_id]=NULL; + ue->prach_resources[eNB_id]=NULL; LOG_D(PHY,"[UE %d] frame %d subframe %d : generate_prach %d, prach_cnt %d\n", - Mod_id,frame_tx,subframe_tx,phy_vars_ue->generate_prach,phy_vars_ue->prach_cnt); + Mod_id,frame_tx,subframe_tx,ue->generate_prach,ue->prach_cnt); - phy_vars_ue->prach_cnt++; + ue->prach_cnt++; - if (phy_vars_ue->prach_cnt==3) - phy_vars_ue->generate_prach=0; + if (ue->prach_cnt==3) + ue->generate_prach=0; } // mode is PRACH else { - phy_vars_ue->generate_prach=0; + ue->generate_prach=0; } } // slot_tx is even VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_tx); + stop_meas(&ue->phy_proc_tx); } -void phy_procedures_UE_S_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type) +void phy_procedures_UE_S_TX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type) { int aa;//i,aa; - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; if (abstraction_flag==0) { @@ -1457,10 +1457,10 @@ void phy_procedures_UE_S_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abst int i; // set the whole tx buffer to RX for (i=0; isamples_per_tti; i++) - phy_vars_ue->lte_ue_common_vars.txdata[aa][i] = 0x00010001; + ue->common_vars.txdata[aa][i] = 0x00010001; #else //this is the normal case - memset(&phy_vars_ue->lte_ue_common_vars.txdata[aa][0],0, + memset(&ue->common_vars.txdata[aa][0],0, (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti)*sizeof(int32_t)); #endif //else EXMIMO @@ -1468,17 +1468,17 @@ void phy_procedures_UE_S_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abst } } -void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode) +void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode) { - LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; // int aa; #if defined(EXMIMO) && defined(DRIVER2013) // exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[0].exmimo_config_ptr; // int aa; #endif - int slot_rx = phy_vars_ue->slot_rx; + int slot_rx = ue->slot_rx; int subframe_rx = slot_rx>>1; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN); @@ -1486,32 +1486,32 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t if (l==0) { // UE measurements on symbol 0 if (abstraction_flag==0) { - LOG_D(PHY,"Calling measurements subframe %d, rxdata %p\n",subframe_rx,phy_vars_ue->lte_ue_common_vars.rxdata); + LOG_D(PHY,"Calling measurements subframe %d, rxdata %p\n",subframe_rx,ue->common_vars.rxdata); - lte_ue_measurements(phy_vars_ue, - (subframe_rx*frame_parms->samples_per_tti+phy_vars_ue->rx_offset)%(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME), + lte_ue_measurements(ue, + (subframe_rx*frame_parms->samples_per_tti+ue->rx_offset)%(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME), (slot_rx == 2) ? 1 : 0, 0); } else { - lte_ue_measurements(phy_vars_ue, + lte_ue_measurements(ue, 0, 0, 1); } } - if (l==(6-phy_vars_ue->lte_frame_parms.Ncp)) { + if (l==(6-ue->frame_parms.Ncp)) { // make sure we have signal from PSS/SSS for N0 measurement VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_IN); - ue_rrc_measurements(phy_vars_ue, + ue_rrc_measurements(ue, slot_rx, abstraction_flag); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_OUT); if (abstraction_flag==1) - phy_vars_ue->sinr_eff = sinr_eff_cqi_calc(phy_vars_ue, 0); + ue->sinr_eff = sinr_eff_cqi_calc(ue, 0); } @@ -1524,7 +1524,7 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t #ifndef OAI_USRP #ifndef OAI_BLADERF #ifndef OAI_LMSSDR - phy_adjust_gain (phy_vars_ue,dB_fixed(phy_vars_ue->PHY_measurements.rssi),0); + phy_adjust_gain (ue,dB_fixed(ue->measurements.rssi),0); #endif #endif #endif @@ -1534,8 +1534,8 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id = 0; if (abstraction_flag == 0) - lte_adjust_synch(&phy_vars_ue->lte_frame_parms, - phy_vars_ue, + lte_adjust_synch(&ue->frame_parms, + ue, eNB_id, 0, 16384); @@ -1548,13 +1548,13 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t } #ifdef EMOS -void phy_procedures_emos_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t last_slot,uint8_t eNB_id) +void phy_procedures_emos_UE_RX(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) { uint8_t i,j; //uint16_t last_slot_emos; uint32_t bytes; - int Mod_id = phy_vars_ue->Mod_id; + int Mod_id = ue->Mod_id; /* if (last_slot<2) @@ -1570,16 +1570,16 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t last_slot,uint8_ #ifdef EMOS_CHANNEL if ((last_slot==10) || (last_slot==11)) { - for (i=0; ilte_frame_parms.nb_antennas_rx; i++) - for (j=0; jlte_frame_parms.nb_antennas_tx; j++) { + for (i=0; iframe_parms.nb_antennas_rx; i++) + for (j=0; jframe_parms.nb_antennas_tx; j++) { // first OFDM symbol with pilots - memcpy(&emos_dump_UE.channel[i][j][(last_slot%2)*2*phy_vars_ue->lte_frame_parms.ofdm_symbol_size], - &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][0], - phy_vars_ue->lte_frame_parms.ofdm_symbol_size*sizeof(int)); + memcpy(&emos_dump_UE.channel[i][j][(last_slot%2)*2*ue->frame_parms.ofdm_symbol_size], + &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][0], + ue->frame_parms.ofdm_symbol_size*sizeof(int)); // second OFDM symbol with pilots - memcpy(&emos_dump_UE.channel[i][j][((last_slot%2)*2+1)*phy_vars_ue->lte_frame_parms.ofdm_symbol_size], - &phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][(phy_vars_ue->lte_frame_parms.Ncp == 0 ? 4 : 3)*phy_vars_ue->lte_frame_parms.ofdm_symbol_size], - phy_vars_ue->lte_frame_parms.ofdm_symbol_size*sizeof(int)); + memcpy(&emos_dump_UE.channel[i][j][((last_slot%2)*2+1)*ue->frame_parms.ofdm_symbol_size], + &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][(ue->frame_parms.Ncp == 0 ? 4 : 3)*ue->frame_parms.ofdm_symbol_size], + ue->frame_parms.ofdm_symbol_size*sizeof(int)); } } @@ -1587,47 +1587,47 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t last_slot,uint8_ if (last_slot==0) { emos_dump_UE.timestamp = rt_get_time_ns(); - emos_dump_UE.frame_rx = phy_vars_ue->frame_rx; - emos_dump_UE.UE_mode = phy_vars_ue->UE_mode[eNB_id]; - emos_dump_UE.mimo_mode = phy_vars_ue->transmission_mode[eNB_id]; - emos_dump_UE.freq_offset = phy_vars_ue->lte_ue_common_vars.freq_offset; - emos_dump_UE.timing_advance = phy_vars_ue->timing_advance; - emos_dump_UE.timing_offset = phy_vars_ue->rx_offset; - emos_dump_UE.rx_total_gain_dB = phy_vars_ue->rx_total_gain_dB; + emos_dump_UE.frame_rx = ue->frame_rx; + emos_dump_UE.UE_mode = ue->UE_mode[eNB_id]; + emos_dump_UE.mimo_mode = ue->transmission_mode[eNB_id]; + emos_dump_UE.freq_offset = ue->common_vars.freq_offset; + emos_dump_UE.timing_advance = ue->timing_advance; + emos_dump_UE.timing_offset = ue->rx_offset; + emos_dump_UE.rx_total_gain_dB = ue->rx_total_gain_dB; emos_dump_UE.eNb_id = eNB_id; - memcpy(&emos_dump_UE.PHY_measurements,&phy_vars_ue->PHY_measurements,sizeof(PHY_MEASUREMENTS)); + memcpy(&emos_dump_UE.PHY_measurements,&measurements,sizeof(PHY_MEASUREMENTS)); } if (last_slot==1) { - emos_dump_UE.pbch_errors = phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors; - emos_dump_UE.pbch_errors_last = phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_last; - emos_dump_UE.pbch_errors_conseq = phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq; - emos_dump_UE.pbch_fer = phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_fer; + emos_dump_UE.pbch_errors = ue->pbch_vars[eNB_id]->pdu_errors; + emos_dump_UE.pbch_errors_last = ue->pbch_vars[eNB_id]->pdu_errors_last; + emos_dump_UE.pbch_errors_conseq = ue->pbch_vars[eNB_id]->pdu_errors_conseq; + emos_dump_UE.pbch_fer = ue->pbch_vars[eNB_id]->pdu_fer; } if (last_slot==19) { - emos_dump_UE.dlsch_errors = phy_vars_ue->dlsch_errors[eNB_id]; - emos_dump_UE.dlsch_errors_last = phy_vars_ue->dlsch_errors_last[eNB_id]; - emos_dump_UE.dlsch_received = phy_vars_ue->dlsch_received[eNB_id]; - emos_dump_UE.dlsch_received_last = phy_vars_ue->dlsch_received_last[eNB_id]; - emos_dump_UE.dlsch_fer = phy_vars_ue->dlsch_fer[eNB_id]; - emos_dump_UE.dlsch_cntl_errors = phy_vars_ue->dlsch_SI_errors[eNB_id]; - emos_dump_UE.dlsch_ra_errors = phy_vars_ue->dlsch_ra_errors[eNB_id]; - emos_dump_UE.total_TBS = phy_vars_ue->total_TBS[eNB_id]; - emos_dump_UE.total_TBS_last = phy_vars_ue->total_TBS_last[eNB_id]; - emos_dump_UE.bitrate = phy_vars_ue->bitrate[eNB_id]; - emos_dump_UE.total_received_bits = phy_vars_ue->total_received_bits[eNB_id]; - emos_dump_UE.pmi_saved = phy_vars_ue->dlsch_ue[eNB_id][0]->pmi_alloc; - emos_dump_UE.mcs = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->mcs; + emos_dump_UE.dlsch_errors = ue->dlsch_errors[eNB_id]; + emos_dump_UE.dlsch_errors_last = ue->dlsch_errors_last[eNB_id]; + emos_dump_UE.dlsch_received = ue->dlsch_received[eNB_id]; + emos_dump_UE.dlsch_received_last = ue->dlsch_received_last[eNB_id]; + emos_dump_UE.dlsch_fer = ue->dlsch_fer[eNB_id]; + emos_dump_UE.dlsch_cntl_errors = ue->dlsch_SI_errors[eNB_id]; + emos_dump_UE.dlsch_ra_errors = ue->dlsch_ra_errors[eNB_id]; + emos_dump_UE.total_TBS = ue->total_TBS[eNB_id]; + emos_dump_UE.total_TBS_last = ue->total_TBS_last[eNB_id]; + emos_dump_UE.bitrate = ue->bitrate[eNB_id]; + emos_dump_UE.total_received_bits = ue->total_received_bits[eNB_id]; + emos_dump_UE.pmi_saved = ue->dlsch[eNB_id][0]->pmi_alloc; + emos_dump_UE.mcs = ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs; emos_dump_UE.use_ia_receiver = openair_daq_vars.use_ia_receiver; bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_UE, sizeof(fifo_dump_emos_UE)); if (bytes!=sizeof(fifo_dump_emos_UE)) { - LOG_W(PHY,"[UE %d] frame %d, slot %d, Problem writing EMOS data to FIFO\n",Mod_id,phy_vars_ue->frame_rx, last_slot); + LOG_W(PHY,"[UE %d] frame %d, slot %d, Problem writing EMOS data to FIFO\n",Mod_id,ue->frame_rx, last_slot); } else { - if (phy_vars_ue->frame_rx%100==0) { - LOG_I(PHY,"[UE %d] frame %d, slot %d, Writing %d bytes EMOS data to FIFO\n",Mod_id,phy_vars_ue->frame_rx, last_slot, bytes); + if (ue->frame_rx%100==0) { + LOG_I(PHY,"[UE %d] frame %d, slot %d, Writing %d bytes EMOS data to FIFO\n",Mod_id,ue->frame_rx, last_slot, bytes); } } } @@ -1636,65 +1636,65 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t last_slot,uint8_ #endif -void restart_phy(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag) +void restart_phy(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag) { // uint8_t last_slot; uint8_t i; - LOG_I(PHY,"[UE %d] frame %d, slot %d, restarting PHY!\n",phy_vars_ue->Mod_id,phy_vars_ue->frame_rx,phy_vars_ue->slot_rx); + LOG_I(PHY,"[UE %d] frame %d, slot %d, restarting PHY!\n",ue->Mod_id,ue->frame_rx,ue->slot_rx); mac_xface->macphy_exit("restart_phy called"); // first_run = 1; if (abstraction_flag ==0 ) { - phy_vars_ue->UE_mode[eNB_id] = NOT_SYNCHED; + ue->UE_mode[eNB_id] = NOT_SYNCHED; } else { - phy_vars_ue->UE_mode[eNB_id] = PRACH; - phy_vars_ue->prach_resources[eNB_id]=NULL; + ue->UE_mode[eNB_id] = PRACH; + ue->prach_resources[eNB_id]=NULL; } - phy_vars_ue->frame_rx = -1; - phy_vars_ue->frame_tx = -1; - // phy_vars_ue->synch_wait_cnt=0; - // phy_vars_ue->sched_cnt=-1; + ue->frame_rx = -1; + ue->frame_tx = -1; + // ue->synch_wait_cnt=0; + // ue->sched_cnt=-1; - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq=0; - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors=0; + ue->pbch_vars[eNB_id]->pdu_errors_conseq=0; + ue->pbch_vars[eNB_id]->pdu_errors=0; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors = 0; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_missed = 0; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false = 0; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_received = 0; + ue->pdcch_vars[eNB_id]->dci_errors = 0; + ue->pdcch_vars[eNB_id]->dci_missed = 0; + ue->pdcch_vars[eNB_id]->dci_false = 0; + ue->pdcch_vars[eNB_id]->dci_received = 0; - phy_vars_ue->dlsch_errors[eNB_id] = 0; - phy_vars_ue->dlsch_errors_last[eNB_id] = 0; - phy_vars_ue->dlsch_received[eNB_id] = 0; - phy_vars_ue->dlsch_received_last[eNB_id] = 0; - phy_vars_ue->dlsch_fer[eNB_id] = 0; - phy_vars_ue->dlsch_SI_received[eNB_id] = 0; - phy_vars_ue->dlsch_ra_received[eNB_id] = 0; - phy_vars_ue->dlsch_SI_errors[eNB_id] = 0; - phy_vars_ue->dlsch_ra_errors[eNB_id] = 0; + ue->dlsch_errors[eNB_id] = 0; + ue->dlsch_errors_last[eNB_id] = 0; + ue->dlsch_received[eNB_id] = 0; + ue->dlsch_received_last[eNB_id] = 0; + ue->dlsch_fer[eNB_id] = 0; + ue->dlsch_SI_received[eNB_id] = 0; + ue->dlsch_ra_received[eNB_id] = 0; + ue->dlsch_SI_errors[eNB_id] = 0; + ue->dlsch_ra_errors[eNB_id] = 0; - phy_vars_ue->dlsch_mch_received[eNB_id] = 0; + ue->dlsch_mch_received[eNB_id] = 0; for (i=0; i < MAX_MBSFN_AREA ; i ++) { - phy_vars_ue->dlsch_mch_received_sf[i][eNB_id] = 0; - phy_vars_ue->dlsch_mcch_received[i][eNB_id] = 0; - phy_vars_ue->dlsch_mtch_received[i][eNB_id] = 0; - phy_vars_ue->dlsch_mcch_errors[i][eNB_id] = 0; - phy_vars_ue->dlsch_mtch_errors[i][eNB_id] = 0; - phy_vars_ue->dlsch_mcch_trials[i][eNB_id] = 0; - phy_vars_ue->dlsch_mtch_trials[i][eNB_id] = 0; + ue->dlsch_mch_received_sf[i][eNB_id] = 0; + ue->dlsch_mcch_received[i][eNB_id] = 0; + ue->dlsch_mtch_received[i][eNB_id] = 0; + ue->dlsch_mcch_errors[i][eNB_id] = 0; + ue->dlsch_mtch_errors[i][eNB_id] = 0; + ue->dlsch_mcch_trials[i][eNB_id] = 0; + ue->dlsch_mtch_trials[i][eNB_id] = 0; } - //phy_vars_ue->total_TBS[eNB_id] = 0; - //phy_vars_ue->total_TBS_last[eNB_id] = 0; - //phy_vars_ue->bitrate[eNB_id] = 0; - //phy_vars_ue->total_received_bits[eNB_id] = 0; + //ue->total_TBS[eNB_id] = 0; + //ue->total_TBS_last[eNB_id] = 0; + //ue->bitrate[eNB_id] = 0; + //ue->total_received_bits[eNB_id] = 0; } -void lte_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abstraction_flag) +void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) { // int i; @@ -1704,9 +1704,9 @@ void lte_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst static uint8_t first_run = 1; uint8_t pbch_trials = 0; - DevAssert(phy_vars_ue); - int slot_rx = phy_vars_ue->slot_rx; - int frame_rx = phy_vars_ue->frame_rx; + DevAssert(ue); + int slot_rx = ue->slot_rx; + int frame_rx = ue->frame_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN); @@ -1717,14 +1717,14 @@ void lte_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst for (pbch_trials=0; pbch_trials<4; pbch_trials++) { //for (pbch_phase=0;pbch_phase<4;pbch_phase++) { - //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, eNB_id %d)\n",phy_vars_ue->Mod_id,frame_rx,pbch_phase,phy_vars_ue->lte_frame_parms.Nid_cell,eNB_id); + //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, eNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,eNB_id); if (abstraction_flag == 0) { - pbch_tx_ant = rx_pbch(&phy_vars_ue->lte_ue_common_vars, - phy_vars_ue->lte_ue_pbch_vars[eNB_id], - &phy_vars_ue->lte_frame_parms, + pbch_tx_ant = rx_pbch(&ue->common_vars, + ue->pbch_vars[eNB_id], + &ue->frame_parms, eNB_id, - phy_vars_ue->lte_frame_parms.mode1_flag==1?SISO:ALAMOUTI, - phy_vars_ue->high_speed_flag, + ue->frame_parms.mode1_flag==1?SISO:ALAMOUTI, + ue->high_speed_flag, pbch_phase); @@ -1733,7 +1733,7 @@ void lte_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #ifdef PHY_ABSTRACTION else { - pbch_tx_ant = rx_pbch_emul(phy_vars_ue, + pbch_tx_ant = rx_pbch_emul(ue, eNB_id, pbch_phase); } @@ -1761,85 +1761,85 @@ void lte_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst } - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq = 0; - frame_tx = (((int)(phy_vars_ue->lte_ue_pbch_vars[eNB_id]->decoded_output[2]&0x03))<<8); - frame_tx += ((int)(phy_vars_ue->lte_ue_pbch_vars[eNB_id]->decoded_output[1]&0xfc)); + ue->pbch_vars[eNB_id]->pdu_errors_conseq = 0; + frame_tx = (((int)(ue->pbch_vars[eNB_id]->decoded_output[2]&0x03))<<8); + frame_tx += ((int)(ue->pbch_vars[eNB_id]->decoded_output[1]&0xfc)); frame_tx += pbch_phase; - if (phy_vars_ue->mac_enabled==1) { - mac_xface->dl_phy_sync_success(phy_vars_ue->Mod_id,frame_rx,eNB_id, - phy_vars_ue->UE_mode[eNB_id]==NOT_SYNCHED ? 1 : 0); + if (ue->mac_enabled==1) { + mac_xface->dl_phy_sync_success(ue->Mod_id,frame_rx,eNB_id, + ue->UE_mode[eNB_id]==NOT_SYNCHED ? 1 : 0); } #ifdef EMOS //emos_dump_UE.frame_tx = frame_tx; - //emos_dump_UE.mimo_mode = phy_vars_ue->lte_ue_pbch_vars[eNB_id]->decoded_output[1]; + //emos_dump_UE.mimo_mode = ue->pbch_vars[eNB_id]->decoded_output[1]; #endif if (first_run) { first_run = 0; LOG_I(PHY,"[UE %d] frame %d, slot %d: Adjusting frame counter (PBCH ant_tx=%d, frame_tx=%d, phase %d).\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx, slot_rx, pbch_tx_ant, frame_tx, pbch_phase); - phy_vars_ue->frame_rx = (phy_vars_ue->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); - phy_vars_ue->frame_tx = phy_vars_ue->frame_rx; - frame_rx = phy_vars_ue->frame_rx; - } else if (((frame_tx & 0x03FF) != (phy_vars_ue->frame_rx & 0x03FF))) { - //(pbch_tx_ant != phy_vars_ue->lte_frame_parms.nb_antennas_tx)) { + ue->frame_rx = (ue->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); + ue->frame_tx = ue->frame_rx; + frame_rx = ue->frame_rx; + } else if (((frame_tx & 0x03FF) != (ue->frame_rx & 0x03FF))) { + //(pbch_tx_ant != ue->frame_parms.nb_antennas_tx)) { LOG_D(PHY,"[UE %d] frame %d, slot %d: Re-adjusting frame counter (PBCH ant_tx=%d, frame_rx=%d, frame%1024=%d, phase %d).\n", - phy_vars_ue->Mod_id, - phy_vars_ue->frame_rx, + ue->Mod_id, + ue->frame_rx, slot_rx, pbch_tx_ant, frame_tx, frame_rx & 0x03FF, pbch_phase); - phy_vars_ue->frame_rx = (phy_vars_ue->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); - phy_vars_ue->frame_tx = phy_vars_ue->frame_rx; - frame_rx = phy_vars_ue->frame_rx; + ue->frame_rx = (ue->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); + ue->frame_tx = ue->frame_rx; + frame_rx = ue->frame_rx; /* LOG_D(PHY,"[UE %d] frame %d, slot %d: PBCH PDU does not match, ignoring it (PBCH ant_tx=%d, frame_tx=%d).\n", - phy_vars_ue->Mod_id, - phy_vars_ue->frame, + ue->Mod_id, + ue->frame, slot_rx, pbch_tx_ant, frame_tx); */ - //phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq = 21; // this will make it go out of sync - //phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq += 1; // this will make it go out of sync + //ue->pbch_vars[eNB_id]->pdu_errors_conseq = 21; // this will make it go out of sync + //ue->pbch_vars[eNB_id]->pdu_errors_conseq += 1; // this will make it go out of sync } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] frame %d, slot %d, Received PBCH (MIB): mode1_flag %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx, slot_rx, - phy_vars_ue->lte_frame_parms.mode1_flag, + ue->frame_parms.mode1_flag, pbch_tx_ant, frame_tx, - phy_vars_ue->lte_frame_parms.N_RB_DL, - phy_vars_ue->lte_frame_parms.phich_config_common.phich_duration, - phy_vars_ue->lte_frame_parms.phich_config_common.phich_resource); + ue->frame_parms.N_RB_DL, + ue->frame_parms.phich_config_common.phich_duration, + ue->frame_parms.phich_config_common.phich_resource); /* if (frame_rx%100 == 0) { LOG_I(PHY,"[UE %d] frame %d, slot %d, PBCH: mode1_flag %d, tx_ant %d, frame_tx %d, phase %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6,Frequency offset %d Hz (%d)\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx, slot_rx, - phy_vars_ue->lte_frame_parms.mode1_flag, + ue->frame_parms.mode1_flag, pbch_tx_ant, frame_tx, pbch_phase, - phy_vars_ue->lte_frame_parms.N_RB_DL, - phy_vars_ue->lte_frame_parms.phich_config_common.phich_duration, - phy_vars_ue->lte_frame_parms.phich_config_common.phich_resource, - phy_vars_ue->lte_ue_common_vars.freq_offset,openair_daq_vars.freq_offset); - //dump_frame_parms(&phy_vars_ue->lte_frame_parms); + ue->frame_parms.N_RB_DL, + ue->frame_parms.phich_config_common.phich_duration, + ue->frame_parms.phich_config_common.phich_resource, + ue->common_vars.freq_offset,openair_daq_vars.freq_offset); + //dump_frame_parms(&ue->frame_parms); } */ @@ -1847,14 +1847,14 @@ void lte_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst } else { LOG_E(PHY,"[UE %d] frame %d, slot %d, Error decoding PBCH!\n", - phy_vars_ue->Mod_id,frame_rx, slot_rx); - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq++; - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors++; - if (phy_vars_ue->mac_enabled == 1) { - mac_xface->out_of_sync_ind(phy_vars_ue->Mod_id,frame_rx,eNB_id); + ue->Mod_id,frame_rx, slot_rx); + ue->pbch_vars[eNB_id]->pdu_errors_conseq++; + ue->pbch_vars[eNB_id]->pdu_errors++; + if (ue->mac_enabled == 1) { + mac_xface->out_of_sync_ind(ue->Mod_id,frame_rx,eNB_id); } else{ - if (phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq>=100) { + if (ue->pbch_vars[eNB_id]->pdu_errors_conseq>=100) { LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n"); mac_xface->macphy_exit("More that 100 consecutive PBCH errors!"); } @@ -1862,20 +1862,20 @@ void lte_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst } if (frame_rx % 100 == 0) { - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_fer = phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_last; - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_last = phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors; + ue->pbch_vars[eNB_id]->pdu_fer = ue->pbch_vars[eNB_id]->pdu_errors - ue->pbch_vars[eNB_id]->pdu_errors_last; + ue->pbch_vars[eNB_id]->pdu_errors_last = ue->pbch_vars[eNB_id]->pdu_errors; } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n", - phy_vars_ue->Mod_id,frame_rx, slot_rx, - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors, - phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq); + ue->Mod_id,frame_rx, slot_rx, + ue->pbch_vars[eNB_id]->pdu_errors, + ue->pbch_vars[eNB_id]->pdu_errors_conseq); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); } -int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abstraction_flag) +int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) { unsigned int dci_cnt=0, i; @@ -1883,8 +1883,8 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst //uint16_t ra_RNTI; - int frame_rx = phy_vars_ue->frame_rx; - int slot_rx = phy_vars_ue->slot_rx; + int frame_rx = ue->frame_rx; + int slot_rx = ue->slot_rx; int subframe_rx = slot_rx>>1; @@ -1901,29 +1901,29 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst if (abstraction_flag == 0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); - rx_pdcch(&phy_vars_ue->lte_ue_common_vars, - phy_vars_ue->lte_ue_pdcch_vars, - &phy_vars_ue->lte_frame_parms, + rx_pdcch(&ue->common_vars, + ue->pdcch_vars, + &ue->frame_parms, subframe_rx, eNB_id, - (phy_vars_ue->lte_frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, - phy_vars_ue->high_speed_flag, - phy_vars_ue->is_secondary_ue); + (ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, + ue->high_speed_flag, + ue->is_secondary_ue); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_IN); - dci_cnt = dci_decoding_procedure(phy_vars_ue, + dci_cnt = dci_decoding_procedure(ue, dci_alloc_rx, - (phy_vars_ue->UE_mode[eNB_id] < PUSCH)? 1 : 0, // if we're in PUSCH don't listen to common search space, + (ue->UE_mode[eNB_id] < PUSCH)? 1 : 0, // if we're in PUSCH don't listen to common search space, // later when we need paging or RA during connection, update this ... eNB_id,subframe_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT); - //LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d PHICH RX\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx); + //LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d PHICH RX\n",ue->Mod_id,frame_rx,subframe_rx); - if (is_phich_subframe(&phy_vars_ue->lte_frame_parms,subframe_rx)) { + if (is_phich_subframe(&ue->frame_parms,subframe_rx)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_IN); - rx_phich(phy_vars_ue, + rx_phich(ue, subframe_rx,eNB_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_OUT); } @@ -1933,7 +1933,7 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst else { for (i=0; ilte_frame_parms.Nid_cell == phy_vars_ue->lte_frame_parms.Nid_cell) + if (PHY_vars_eNB_g[i][CC_id]->frame_parms.Nid_cell == ue->frame_parms.Nid_cell) break; if (CC_id < MAX_NUM_CCs) @@ -1941,48 +1941,48 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst } if (i==NB_eNB_INST) { - LOG_E(PHY,"[UE %d] phy_procedures_lte_ue.c: FATAL : Could not find attached eNB for DCI emulation (Nid_cell %d)!!!!\n",phy_vars_ue->Mod_id,phy_vars_ue->lte_frame_parms.Nid_cell); + LOG_E(PHY,"[UE %d] phy_procedures_lte_ue.c: FATAL : Could not find attached eNB for DCI emulation (Nid_cell %d)!!!!\n",ue->Mod_id,ue->frame_parms.Nid_cell); mac_xface->macphy_exit("Could not find attached eNB for DCI emulation"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(-1); } LOG_D(PHY,"Calling dci_decoding_proc_emul ...\n"); - dci_cnt = dci_decoding_procedure_emul(phy_vars_ue->lte_ue_pdcch_vars, + dci_cnt = dci_decoding_procedure_emul(ue->pdcch_vars, PHY_vars_eNB_g[i][CC_id]->num_ue_spec_dci[subframe_rx&1], PHY_vars_eNB_g[i][CC_id]->num_common_dci[subframe_rx&1], PHY_vars_eNB_g[i][CC_id]->dci_alloc[subframe_rx&1], dci_alloc_rx, eNB_id); // printf("DCI: dci_cnt %d\n",dci_cnt); - UE_id = (uint32_t)find_ue((int16_t)phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,PHY_vars_eNB_g[i][CC_id]); + UE_id = (uint32_t)find_ue((int16_t)ue->pdcch_vars[eNB_id]->crnti,PHY_vars_eNB_g[i][CC_id]); if (UE_id>=0) { // msg("Checking PHICH for UE %d (eNB %d)\n",UE_id,i); - if (is_phich_subframe(&phy_vars_ue->lte_frame_parms,subframe_rx)) { - harq_pid = phich_subframe_to_harq_pid(&phy_vars_ue->lte_frame_parms,frame_rx,subframe_rx); + if (is_phich_subframe(&ue->frame_parms,subframe_rx)) { + harq_pid = phich_subframe_to_harq_pid(&ue->frame_parms,frame_rx,subframe_rx); - if (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->status == ACTIVE) { - // phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->phich_ACK=1; - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->status = IDLE; - phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] = 0; - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->round = 0; + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == ACTIVE) { + // ue->ulsch[eNB_id]->harq_processes[harq_pid]->phich_ACK=1; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->status = IDLE; + ue->ulsch_Msg3_active[eNB_id] = 0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; LOG_D(PHY,"Msg3 inactive\n"); /* Phich is not abstracted for the moment if (PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->phich_ACK==0) { // NAK - if (phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] == 1) { + if (ue->ulsch_Msg3_active[eNB_id] == 1) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Msg3 PHICH, received NAK\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx, subframe_rx); #endif - get_Msg3_alloc_ret(&phy_vars_ue->lte_frame_parms, + get_Msg3_alloc_ret(&ue->frame_parms, subframe_rx, frame_rx, - &phy_vars_ue->ulsch_ue_Msg3_frame[eNB_id], - &phy_vars_ue->ulsch_ue_Msg3_subframe[eNB_id]); + &ue->ulsch_Msg3_frame[eNB_id], + &ue->ulsch_Msg3_subframe[eNB_id]); } // PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; // PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Ndi = 0; @@ -1990,16 +1990,16 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst } else { #ifdef DEBUG_PHY_PROC - if (phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] == 1) + if (ue->ulsch_Msg3_active[eNB_id] == 1) LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Msg3 PHICH, received ACK\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx, subframe_rx); #endif PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->status = IDLE; // inform MAC? - phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] = 0; + ue->ulsch_Msg3_active[eNB_id] = 0; } //phich_ACK */ } // harq_pid is ACTIVE } // This is a PHICH subframe @@ -2009,19 +2009,19 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #endif //#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,mode_string[phy_vars_ue->UE_mode[eNB_id]],dci_cnt); + LOG_D(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",ue->Mod_id,frame_rx,slot_rx,mode_string[ue->UE_mode[eNB_id]],dci_cnt); //#endif - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_received += dci_cnt; + ue->pdcch_vars[eNB_id]->dci_received += dci_cnt; /* #ifdef DEBUG_PHY_PROC if (slot_rx==18) debug_LOG_D(PHY,"[UE %d] Frame %d, slot %d: PDCCH: DCI errors %d, DCI received %d, DCI missed %d, DCI False Detection %d \n", - phy_vars_ue->Mod_id,frame_rx,slot_rx, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_received, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_missed, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false); + ue->Mod_id,frame_rx,slot_rx, + ue->pdcch_vars[eNB_id]->dci_errors, + ue->pdcch_vars[eNB_id]->dci_received, + ue->pdcch_vars[eNB_id]->dci_missed, + ue->pdcch_vars[eNB_id]->dci_false); #endif */ #ifdef EMOS @@ -2030,46 +2030,46 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst /* #ifdef DIAG_PHY - //if (phy_vars_ue->UE_mode[eNB_id] == PUSCH) + //if (ue->UE_mode[eNB_id] == PUSCH) if (dci_cnt > 1) { - LOG_D(PHY,"[UE %d][DIAG] frame %d, subframe %d: received %d>1 DCI!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx,dci_cnt); - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false++; + LOG_D(PHY,"[UE %d][DIAG] frame %d, subframe %d: received %d>1 DCI!\n",ue->Mod_id,frame_rx,subframe_rx,dci_cnt); + ue->pdcch_vars[eNB_id]->dci_false++; } else if (dci_cnt==0) { - LOG_D(PHY,"[UE %d][DIAG] frame %d, subframe %d: received %d DCI!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx,dci_cnt); - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_missed++; + LOG_D(PHY,"[UE %d][DIAG] frame %d, subframe %d: received %d DCI!\n",ue->Mod_id,frame_rx,subframe_rx,dci_cnt); + ue->pdcch_vars[eNB_id]->dci_missed++; } #endif */ // dci_cnt = 0; - // ra_RNTI = (phy_vars_ue->prach_resources[eNB_id]) ? phy_vars_ue->prach_resources[eNB_id]->ra_RNTI : 0; + // ra_RNTI = (ue->prach_resources[eNB_id]) ? ue->prach_resources[eNB_id]->ra_RNTI : 0; for (i=0; ilte_ue_pdcch_vars[eNB_id]->crnti,i,dci_cnt); - dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + LOG_D(PHY,"frame %d, subframe %d, rnti %x: dci %d/%d\n",frame_rx,subframe_rx,ue->pdcch_vars[eNB_id]->crnti,i,dci_cnt); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); } #endif - //if ((phy_vars_ue->UE_mode[eNB_id] != PRACH) && + //if ((ue->UE_mode[eNB_id] != PRACH) && // (dci_alloc_rx[i].rnti != 0x1234) && - if ((phy_vars_ue->UE_mode[eNB_id]>PRACH) && - (dci_alloc_rx[i].rnti == phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti) && + if ((ue->UE_mode[eNB_id]>PRACH) && + (dci_alloc_rx[i].rnti == ue->pdcch_vars[eNB_id]->crnti) && (dci_alloc_rx[i].format != format0)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][DCI][PDSCH %x] frame %d, subframe %d: format %d, num_pdcch_symbols %d, nCCE %d, total CCEs %d\n", - phy_vars_ue->Mod_id,dci_alloc_rx[i].rnti, + ue->Mod_id,dci_alloc_rx[i].rnti, frame_rx,subframe_rx, dci_alloc_rx[i].format, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->nCCE[subframe_rx], - get_nCCE(3,&phy_vars_ue->lte_frame_parms,get_mi(&phy_vars_ue->lte_frame_parms,0))); + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[eNB_id]->nCCE[subframe_rx], + get_nCCE(3,&ue->frame_parms,get_mi(&ue->frame_parms,0))); #endif @@ -2077,60 +2077,60 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst if (!(((subframe_rx == 7) && (dci_alloc_rx[i].format == format1E_2A_M10PRB)) || ((subframe_rx == 7) && (dci_alloc_rx[i].format == format1)))) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received C_RNTI Format %d!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format); - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors++; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false++; + LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received C_RNTI Format %d!\n",ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format); + ue->pdcch_vars[eNB_id]->dci_errors++; + ue->pdcch_vars[eNB_id]->dci_false++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(-1); } #endif - // dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); - if ((phy_vars_ue->UE_mode[eNB_id] > PRACH) && + // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + if ((ue->UE_mode[eNB_id] > PRACH) && (generate_ue_dlsch_params_from_dci(frame_rx, subframe_rx, (void *)&dci_alloc_rx[i].dci_pdu, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[eNB_id]->crnti, dci_alloc_rx[i].format, - phy_vars_ue->dlsch_ue[eNB_id], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->pdsch_config_dedicated, + ue->dlsch[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI)==0)) { #ifdef DIAG_PHY - if (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->mcs != (((frame_rx%1024)%28))) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: wrong mcs!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->mcs); - dump_dci(&phy_vars_ue->lte_frame_parms,(void *)&dci_alloc_rx[i]); + if (ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs != (((frame_rx%1024)%28))) { + LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: wrong mcs!\n",ue->Mod_id,frame_rx,subframe_rx, + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs); + dump_dci(&ue->frame_parms,(void *)&dci_alloc_rx[i]); } #endif - phy_vars_ue->dlsch_received[eNB_id]++; + ue->dlsch_received[eNB_id]++; #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generated UE DLSCH C_RNTI format %d\n",phy_vars_ue->Mod_id,dci_alloc_rx[i].format); - dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); - LOG_D(PHY,"[UE %d] *********** dlsch->active in subframe %d (%d)=> %d\n",phy_vars_ue->Mod_id,subframe_rx,slot_rx,phy_vars_ue->dlsch_ue[eNB_id][0]->active); + LOG_D(PHY,"[UE %d] Generated UE DLSCH C_RNTI format %d\n",ue->Mod_id,dci_alloc_rx[i].format); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + LOG_D(PHY,"[UE %d] *********** dlsch->active in subframe %d (%d)=> %d\n",ue->Mod_id,subframe_rx,slot_rx,ue->dlsch[eNB_id][0]->active); #endif // we received a CRNTI, so we're in PUSCH - if (phy_vars_ue->UE_mode[eNB_id] != PUSCH) { + if (ue->UE_mode[eNB_id] != PUSCH) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Received DCI with CRNTI %x => Mode PUSCH\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti); + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Received DCI with CRNTI %x => Mode PUSCH\n",ue->Mod_id,frame_rx,subframe_rx,ue->pdcch_vars[eNB_id]->crnti); #endif - //dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); - phy_vars_ue->UE_mode[eNB_id] = PUSCH; + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + ue->UE_mode[eNB_id] = PUSCH; //mac_xface->macphy_exit("Connected. Exiting\n"); } } else { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Problem in DCI!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx); - dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Problem in DCI!\n",ue->Mod_id,frame_rx,subframe_rx); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); } } @@ -2138,18 +2138,18 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] subframe %d: Found rnti %x, format 1%s, dci_cnt %d\n",phy_vars_ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); + LOG_D(PHY,"[UE %d] subframe %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); /* if (((frame_rx%100) == 0) || (frame_rx < 20)) - dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); */ #endif #ifdef DIAG_PHY if ((subframe_rx != 5)) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received SI_RNTI!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx); - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors++; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false++; + LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received SI_RNTI!\n",ue->Mod_id,frame_rx,subframe_rx); + ue->pdcch_vars[eNB_id]->dci_errors++; + ue->pdcch_vars[eNB_id]->dci_false++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(-1); } @@ -2161,39 +2161,39 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst (void *)&dci_alloc_rx[i].dci_pdu, SI_RNTI, dci_alloc_rx[i].format, - &phy_vars_ue->dlsch_ue_SI[eNB_id], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->pdsch_config_dedicated, + &ue->dlsch_SI[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI)==0) { - phy_vars_ue->dlsch_SI_received[eNB_id]++; + ue->dlsch_SI_received[eNB_id]++; - LOG_D(PHY,"[UE %d] Frame %d, subframe %d : Generate UE DLSCH SI_RNTI format 1%s\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format==format1A?"A":"C"); - //dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + LOG_D(PHY,"[UE %d] Frame %d, subframe %d : Generate UE DLSCH SI_RNTI format 1%s\n",ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format==format1A?"A":"C"); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); } } - else if ((phy_vars_ue->prach_resources[eNB_id]) && - (dci_alloc_rx[i].rnti == phy_vars_ue->prach_resources[eNB_id]->ra_RNTI) && + else if ((ue->prach_resources[eNB_id]) && + (dci_alloc_rx[i].rnti == ue->prach_resources[eNB_id]->ra_RNTI) && (dci_alloc_rx[i].format == format1A)) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][RAPROC] subframe %d: Found RA rnti %x, format 1A, dci_cnt %d\n",phy_vars_ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,i); + LOG_D(PHY,"[UE %d][RAPROC] subframe %d: Found RA rnti %x, format 1A, dci_cnt %d\n",ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,i); //if (((frame_rx%100) == 0) || (frame_rx < 20)) - //dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); //mac_xface->macphy_exit("so far so good...\n"); #endif #ifdef DIAG_PHY if (subframe_rx != 9) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received RA_RNTI!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx); - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors++; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false++; + LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received RA_RNTI!\n",ue->Mod_id,frame_rx,subframe_rx); + ue->pdcch_vars[eNB_id]->dci_errors++; + ue->pdcch_vars[eNB_id]->dci_false++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(-1); } @@ -2203,53 +2203,53 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst if (generate_ue_dlsch_params_from_dci(frame_rx, subframe_rx, (DCI1A_5MHz_TDD_1_6_t *)&dci_alloc_rx[i].dci_pdu, - phy_vars_ue->prach_resources[eNB_id]->ra_RNTI, + ue->prach_resources[eNB_id]->ra_RNTI, format1A, - &phy_vars_ue->dlsch_ue_ra[eNB_id], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->pdsch_config_dedicated, + &ue->dlsch_ra[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, SI_RNTI, - phy_vars_ue->prach_resources[eNB_id]->ra_RNTI, + ue->prach_resources[eNB_id]->ra_RNTI, P_RNTI)==0) { - phy_vars_ue->dlsch_ra_received[eNB_id]++; + ue->dlsch_ra_received[eNB_id]++; #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE DLSCH RA_RNTI format 1A, rb_alloc %x, dlsch_ue_ra[eNB_id] %p\n", - phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->rb_alloc_even[0],phy_vars_ue->dlsch_ue_ra[eNB_id]); + LOG_D(PHY,"[UE %d] Generate UE DLSCH RA_RNTI format 1A, rb_alloc %x, dlsch_ra[eNB_id] %p\n", + ue->Mod_id,ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even[0],ue->dlsch_ra[eNB_id]); #endif } - } else if( (dci_alloc_rx[i].rnti == phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti) && + } else if( (dci_alloc_rx[i].rnti == ue->pdcch_vars[eNB_id]->crnti) && (dci_alloc_rx[i].format == format0)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d: Found rnti %x, format 0, dci_cnt %d\n", - phy_vars_ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); + ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); /* if (((frame_rx%100) == 0) || (frame_rx < 20)) - dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); */ #endif #ifdef DIAG_PHY if (subframe_rx != 9) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received C_RNTI Format 0!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx); - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors++; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false++; + LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received C_RNTI Format 0!\n",ue->Mod_id,frame_rx,subframe_rx); + ue->pdcch_vars[eNB_id]->dci_errors++; + ue->pdcch_vars[eNB_id]->dci_false++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(-1); } #endif - phy_vars_ue->ulsch_no_allocation_counter[eNB_id] = 0; - //dump_dci(&phy_vars_ue->lte_frame_parms,&dci_alloc_rx[i]); + ue->ulsch_no_allocation_counter[eNB_id] = 0; + //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); - if ((phy_vars_ue->UE_mode[eNB_id] > PRACH) && + if ((ue->UE_mode[eNB_id] > PRACH) && (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[eNB_id]->crnti, subframe_rx, format0, - phy_vars_ue, + ue, SI_RNTI, 0, P_RNTI, @@ -2258,44 +2258,44 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst 0)==0)) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (subframe %d)\n",phy_vars_ue->Mod_id,subframe_rx); + LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx); #endif } - } else if( (dci_alloc_rx[i].rnti == phy_vars_ue->ulsch_ue[eNB_id]->cba_rnti[0]) && + } else if( (dci_alloc_rx[i].rnti == ue->ulsch[eNB_id]->cba_rnti[0]) && (dci_alloc_rx[i].format == format0)) { // UE could belong to more than one CBA group - // phy_vars_ue->Mod_id%phy_vars_ue->ulsch_ue[eNB_id]->num_active_cba_groups] + // ue->Mod_id%ue->ulsch[eNB_id]->num_active_cba_groups] #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d: Found cba rnti %x, format 0, dci_cnt %d\n", - phy_vars_ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); + ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); /* if (((frame_rx%100) == 0) || (frame_rx < 20)) - dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); */ #endif /* #ifdef DIAG_PHY if (subframe_rx != 8) { LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received CBA RNTI Format 0!\n", - phy_vars_ue->Mod_id,frame_rx,subframe_rx); - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors++; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false++; + ue->Mod_id,frame_rx,subframe_rx); + ue->pdcch_vars[eNB_id]->dci_errors++; + ue->pdcch_vars[eNB_id]->dci_false++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(-1); } #endif */ - phy_vars_ue->ulsch_no_allocation_counter[eNB_id] = 0; - //dump_dci(&phy_vars_ue->lte_frame_parms,&dci_alloc_rx[i]); + ue->ulsch_no_allocation_counter[eNB_id] = 0; + //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); - if ((phy_vars_ue->UE_mode[eNB_id] > PRACH) && + if ((ue->UE_mode[eNB_id] > PRACH) && (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, - phy_vars_ue->ulsch_ue[eNB_id]->cba_rnti[0], + ue->ulsch[eNB_id]->cba_rnti[0], subframe_rx, format0, - phy_vars_ue, + ue, SI_RNTI, 0, P_RNTI, @@ -2304,23 +2304,23 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst 0)==0)) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (subframe %d)\n",phy_vars_ue->Mod_id,subframe_rx); + LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx); #endif - phy_vars_ue->ulsch_ue[eNB_id]->num_cba_dci[(subframe_rx+4)%10]++; + ue->ulsch[eNB_id]->num_cba_dci[(subframe_rx+4)%10]++; } } else { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] frame %d, subframe %d: received DCI %d with RNTI=%x (C-RNTI:%x, CBA_RNTI %x) and format %d!\n",phy_vars_ue->Mod_id,frame_rx,subframe_rx,i,dci_alloc_rx[i].rnti, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, - phy_vars_ue->ulsch_ue[eNB_id]->cba_rnti[0], + LOG_D(PHY,"[UE %d] frame %d, subframe %d: received DCI %d with RNTI=%x (C-RNTI:%x, CBA_RNTI %x) and format %d!\n",ue->Mod_id,frame_rx,subframe_rx,i,dci_alloc_rx[i].rnti, + ue->pdcch_vars[eNB_id]->crnti, + ue->ulsch[eNB_id]->cba_rnti[0], dci_alloc_rx[i].format); - // dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); + // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); #endif #ifdef DIAG_PHY - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_errors++; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_false++; + ue->pdcch_vars[eNB_id]->dci_errors++; + ue->pdcch_vars[eNB_id]->dci_false++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(-1); #endif @@ -2329,13 +2329,13 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst } /* if ((frame_rx > 1000) && ((frame_rx&1)==0) && (subframe_rx == 5)) { - write_output("rxsig0.m","rxs0", phy_vars_ue->lte_ue_common_vars.rxdata[0],10*phy_vars_ue->lte_frame_parms.samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", phy_vars_ue->lte_ue_common_vars.rxdataF[0],phy_vars_ue->lte_frame_parms.ofdm_symbol_size*2*((phy_vars_ue->lte_frame_parms.Ncp==0)?14:12),2,1); - write_output("H00.m","h00",&(phy_vars_ue->lte_ue_common_vars.dl_ch_estimates[0][0][0]),((phy_vars_ue->lte_frame_parms.Ncp==0)?7:6)*(phy_vars_ue->lte_frame_parms.ofdm_symbol_size),1,1); + write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],10*ue->frame_parms.samples_per_tti,1,1); + write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],ue->frame_parms.ofdm_symbol_size*2*((ue->frame_parms.Ncp==0)?14:12),2,1); + write_output("H00.m","h00",&(ue->common_vars.dl_ch_estimates[0][0][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1); - write_output("pdcch_rxF_ext0.m","pdcch_rxF_ext0",phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->rxdataF_ext[0],3*12*phy_vars_ue->lte_frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->rxdataF_comp[0],4*12*phy_vars_ue->lte_frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->llr,2400,1,4); + write_output("pdcch_rxF_ext0.m","pdcch_rxF_ext0",ue->pdcch_vars[eNB_id]->rxdataF_ext[0],3*12*ue->frame_parms.N_RB_DL,1,1); + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",ue->pdcch_vars[eNB_id]->rxdataF_comp[0],4*12*ue->frame_parms.N_RB_DL,1,1); + write_output("pdcch_rxF_llr.m","pdcch_llr",ue->pdcch_vars[eNB_id]->llr,2400,1,4); mac_xface->macphy_exit("debug exit"); } */ @@ -2344,7 +2344,7 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst } -int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, +int phy_procedures_UE_RX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn) { @@ -2364,20 +2364,20 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac uint8_t sync_area=255; int pmch_mcs=-1; uint8_t mcch_active=0; - int frame_rx = phy_vars_ue->frame_rx; - int slot_rx = phy_vars_ue->slot_rx; + int frame_rx = ue->frame_rx; + int slot_rx = ue->slot_rx; int subframe_rx = slot_rx>>1; int subframe_prev = (subframe_rx+9)%10; - int CC_id = phy_vars_ue->CC_id; + int CC_id = ue->CC_id; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); - start_meas(&phy_vars_ue->phy_proc_rx); + start_meas(&ue->phy_proc_rx); #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[%s %d] Frame %d subframe %d: Doing phy_procedures_UE_RX(%d)\n", (r_type == multicast_relay) ? "RN/UE" : "UE", - phy_vars_ue->Mod_id,frame_rx, subframe_rx, slot_rx); + ue->Mod_id,frame_rx, subframe_rx, slot_rx); #endif #ifdef EMOS @@ -2390,13 +2390,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac LOG_D(PHY,"[MYEMOS] frame %d, IA receiver %d, MCS %d, bitrate %d\n", frame_rx, openair_daq_vars.use_ia_receiver, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->mcs, - phy_vars_ue->bitrate[eNB_id]); + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs, + ue->bitrate[eNB_id]); } #endif - if (phy_vars_ue->lte_frame_parms.Ncp == 0) { // normal prefix + if (ue->frame_parms.Ncp == 0) { // normal prefix pilot1 = 4; pilot2 = 7; pilot3 = 11; @@ -2407,14 +2407,14 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - if (subframe_select(&phy_vars_ue->lte_frame_parms,subframe_rx) == SF_S) { + if (subframe_select(&ue->frame_parms,subframe_rx) == SF_S) { if ((slot_rx%2)==0) n_symb = 5;//3; else n_symb = 0; } else { /* - if (is_pmch_subframe(frame_rx,subframe_rx,&phy_vars_ue->lte_frame_parms)) { + if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { if ((slot_rx%2)==0) { n_symb=2; pmch_flag=1; @@ -2423,7 +2423,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac n_symb=0; } else*/ - n_symb = phy_vars_ue->lte_frame_parms.symbols_per_tti/2; + n_symb = ue->frame_parms.symbols_per_tti/2; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -2434,62 +2434,62 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac for (l=0; lofdm_demod_stats); + start_meas(&ue->ofdm_demod_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - slot_fep(phy_vars_ue, + slot_fep(ue, l, slot_rx, - phy_vars_ue->rx_offset, + ue->rx_offset, 0, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->ofdm_demod_stats); + stop_meas(&ue->ofdm_demod_stats); } - //if (subframe_select(&phy_vars_ue->lte_frame_parms,subframe_rx) == SF_DL) - lte_ue_measurement_procedures(l,phy_vars_ue,eNB_id,abstraction_flag,mode); + //if (subframe_select(&ue->frame_parms,subframe_rx) == SF_DL) + ue_measurement_procedures(l,ue,eNB_id,abstraction_flag,mode); - if ((slot_rx==1) && (l==4-phy_vars_ue->lte_frame_parms.Ncp)) { + if ((slot_rx==1) && (l==4-ue->frame_parms.Ncp)) { /* - phy_vars_ue->ulsch_no_allocation_counter[eNB_id]++; + ue->ulsch_no_allocation_counter[eNB_id]++; - if (phy_vars_ue->ulsch_no_allocation_counter[eNB_id] == 10) { + if (ue->ulsch_no_allocation_counter[eNB_id] == 10) { #ifdef DEBUG_PHY_PROC - msg("[UE %d] no_allocation : setting mode to PRACH\n",phy_vars_ue->Mod_id); + msg("[UE %d] no_allocation : setting mode to PRACH\n",ue->Mod_id); #endif - phy_vars_ue->UE_mode[eNB_id] = PRACH; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti = 0x1234; + ue->UE_mode[eNB_id] = PRACH; + ue->pdcch_vars[eNB_id]->crnti = 0x1234; } */ - lte_ue_pbch_procedures(eNB_id,phy_vars_ue,abstraction_flag); + ue_pbch_procedures(eNB_id,ue,abstraction_flag); /* - if (phy_vars_ue->UE_mode[eNB_id] == RA_RESPONSE) { - phy_vars_ue->Msg3_timer[eNB_id]--; - msg("[UE RAR] frame %d: Msg3_timer %d\n",frame_rx,phy_vars_ue->Msg3_timer); + if (ue->UE_mode[eNB_id] == RA_RESPONSE) { + ue->Msg3_timer[eNB_id]--; + msg("[UE RAR] frame %d: Msg3_timer %d\n",frame_rx,ue->Msg3_timer); - if (phy_vars_ue->Msg3_timer[eNB_id] == 0) { - LOG_D(PHY,"[UE %d] Frame %d: Msg3_timer = 0 : setting mode to PRACH\n",phy_vars_ue->Mod_id,frame_rx); + if (ue->Msg3_timer[eNB_id] == 0) { + LOG_D(PHY,"[UE %d] Frame %d: Msg3_timer = 0 : setting mode to PRACH\n",ue->Mod_id,frame_rx); // I guess here we also need to tell the RRC - phy_vars_ue->UE_mode[eNB_id] = PRACH; - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti = 0x1234; + ue->UE_mode[eNB_id] = PRACH; + ue->pdcch_vars[eNB_id]->crnti = 0x1234; } } */ } #ifdef DLSCH_THREAD - if (phy_vars_ue->dlsch_ue[eNB_id][0]->active == 1) { + if (ue->dlsch[eNB_id][0]->active == 1) { // activate thread since Chest is now done for slot before slot_rx if (l==0) { - LOG_I(PHY,"frame %d, slot_rx %d: Calling rx_pdsch_thread for harq_pid %d\n",frame_rx,slot_rx, phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid); + LOG_I(PHY,"frame %d, slot_rx %d: Calling rx_pdsch_thread for harq_pid %d\n",frame_rx,slot_rx, ue->dlsch[eNB_id][0]->current_harq_pid); if (pthread_mutex_lock (&rx_pdsch_mutex) != 0) { // Signal MAC_PHY Scheduler - LOG_E(PHY,"[UE %d] ERROR pthread_mutex_lock\n",phy_vars_ue->Mod_id); // lock before accessing shared resource + LOG_E(PHY,"[UE %d] ERROR pthread_mutex_lock\n",ue->Mod_id); // lock before accessing shared resource VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); } else { rx_pdsch_instance_cnt++; @@ -2498,18 +2498,18 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if (rx_pdsch_instance_cnt == 0) { if (pthread_cond_signal(&rx_pdsch_cond) != 0) { - LOG_E(PHY,"[UE %d] ERROR pthread_cond_signal for rx_pdsch_cond\n",phy_vars_ue->Mod_id); + LOG_E(PHY,"[UE %d] ERROR pthread_cond_signal for rx_pdsch_cond\n",ue->Mod_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); } } else { - LOG_W(PHY,"[UE %d] Frame=%d, Slot=%d, RX_PDSCH thread for rx_pdsch_thread busy!!!\n",phy_vars_ue->Mod_id,frame_rx,slot_rx); + LOG_W(PHY,"[UE %d] Frame=%d, Slot=%d, RX_PDSCH thread for rx_pdsch_thread busy!!!\n",ue->Mod_id,frame_rx,slot_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); } } // trigger DLSCH decoding thread if ((slot_rx%2)==1) // odd slots - phy_vars_ue->dlsch_ue[eNB_id][0]->active = 0; + ue->dlsch[eNB_id][0]->active = 0; } } @@ -2518,19 +2518,19 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac // process last DLSCH symbols + invoke decoding if (((slot_rx%2)==0) && (l==0)) { // Regular PDSCH - LOG_D(PHY,"[UE %d] dlsch->active in subframe %d => %d\n",phy_vars_ue->Mod_id,subframe_prev,phy_vars_ue->dlsch_ue[eNB_id][0]->active); + LOG_D(PHY,"[UE %d] dlsch->active in subframe %d => %d\n",ue->Mod_id,subframe_prev,ue->dlsch[eNB_id][0]->active); - if (phy_vars_ue->dlsch_ue[eNB_id][0]->active == 1) { + if (ue->dlsch[eNB_id][0]->active == 1) { #ifndef DLSCH_THREAD //USER_MODE - harq_pid = phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid; - LOG_D(PHY,"[UE %d] PDSCH active in subframe %d, harq_pid %d\n",phy_vars_ue->Mod_id,subframe_prev,harq_pid); + harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; + LOG_D(PHY,"[UE %d] PDSCH active in subframe %d, harq_pid %d\n",ue->Mod_id,subframe_prev,harq_pid); - if ((phy_vars_ue->transmission_mode[eNB_id] == 5) && - (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (phy_vars_ue->use_ia_receiver ==1)) { + if ((ue->transmission_mode[eNB_id] == 5) && + (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && + (ue->use_ia_receiver ==1)) { dual_stream_UE = 1; - eNB_id_i = phy_vars_ue->n_connected_eNB; - i_mod = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm; + eNB_id_i = ue->n_connected_eNB; + i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; if (frame_rx%100==0) { LOG_I(PHY,"using IA receiver\n"); @@ -2544,11 +2544,11 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac // process symbols 10,11,12 and trigger DLSCH decoding if (abstraction_flag == 0) { - start_meas(&phy_vars_ue->dlsch_llr_stats); + start_meas(&ue->dlsch_llr_stats); - for (m=pilot3; mlte_frame_parms.symbols_per_tti; m++) { + for (m=pilot3; mframe_parms.symbols_per_tti; m++) { - rx_pdsch(phy_vars_ue, + rx_pdsch(ue, PDSCH, eNB_id, eNB_id_i, @@ -2557,157 +2557,157 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac 0, // first_symbol_flag dual_stream_UE, i_mod, - phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid); + ue->dlsch[eNB_id][0]->current_harq_pid); } - stop_meas(&phy_vars_ue->dlsch_llr_stats); + stop_meas(&ue->dlsch_llr_stats); } - phy_vars_ue->dlsch_ue[eNB_id][0]->active = 0; + ue->dlsch[eNB_id][0]->active = 0; //#ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d Scheduling DLSCH decoding\n", - phy_vars_ue->Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, + ue->Mod_id, + ue->dlsch[eNB_id][0]->rnti, harq_pid, (subframe_prev == 9) ? (frame_rx-1) : frame_rx,subframe_prev); //#endif - if (phy_vars_ue->dlsch_ue[eNB_id][0]) { + if (ue->dlsch[eNB_id][0]) { if (abstraction_flag == 0) { - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->G = get_G(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Nl, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->G = get_G(&ue->frame_parms, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, frame_rx,subframe_prev); - start_meas(&phy_vars_ue->dlsch_unscrambling_stats); - dlsch_unscrambling(&phy_vars_ue->lte_frame_parms, + start_meas(&ue->dlsch_unscrambling_stats); + dlsch_unscrambling(&ue->frame_parms, 0, - phy_vars_ue->dlsch_ue[0][0], - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->G, - phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->llr[0], + ue->dlsch[0][0], + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->G, + ue->pdsch_vars[eNB_id]->llr[0], 0, subframe_prev<<1); - stop_meas(&phy_vars_ue->dlsch_unscrambling_stats); + stop_meas(&ue->dlsch_unscrambling_stats); - start_meas(&phy_vars_ue->dlsch_decoding_stats); - ret = dlsch_decoding(phy_vars_ue, - phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->llr[0], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue[eNB_id][0], - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid], + start_meas(&ue->dlsch_decoding_stats); + ret = dlsch_decoding(ue, + ue->pdsch_vars[eNB_id]->llr[0], + &ue->frame_parms, + ue->dlsch[eNB_id][0], + ue->dlsch[eNB_id][0]->harq_processes[harq_pid], subframe_prev, harq_pid, - 1,phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->nb_rb>10 ? 1 : 0); - stop_meas(&phy_vars_ue->dlsch_decoding_stats); + 1,ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb>10 ? 1 : 0); + stop_meas(&ue->dlsch_decoding_stats); } else { LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); #ifdef PHY_ABSTRACTION - ret = dlsch_decoding_emul(phy_vars_ue, + ret = dlsch_decoding_emul(ue, subframe_prev, 2, eNB_id); #endif } - if (ret == (1+phy_vars_ue->dlsch_ue[eNB_id][0]->max_turbo_iterations)) { - phy_vars_ue->dlsch_errors[eNB_id]++; + if (ret == (1+ue->dlsch[eNB_id][0]->max_turbo_iterations)) { + ue->dlsch_errors[eNB_id]++; #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n", - phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, + ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, harq_pid,frame_rx,subframe_prev, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); /* if (abstraction_flag ==0 ) - dump_dlsch(phy_vars_ue,eNB_id,subframe_prev,harq_pid); + dump_dlsch(ue,eNB_id,subframe_prev,harq_pid); mac_xface->macphy_exit(""); */ #endif } else { LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d (slot_rx %d): Received DLSCH (rv %d,mcs %d,TBS %d)\n", - phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, + ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, harq_pid,frame_rx,subframe_prev,slot_rx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); #ifdef DEBUG_PHY_PROC #ifdef DEBUG_DLSCH int j; - LOG_D(PHY,"dlsch harq_pid %d (rx): \n",phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid); + LOG_D(PHY,"dlsch harq_pid %d (rx): \n",ue->dlsch[eNB_id][0]->current_harq_pid); - for (j=0; jdlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->b[j]); + for (j=0; jdlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS>>3; j++) + LOG_T(PHY,"%x.",ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->b[j]); LOG_T(PHY,"\n"); #endif #endif - if (phy_vars_ue->mac_enabled == 1) { - mac_xface->ue_send_sdu(phy_vars_ue->Mod_id, + if (ue->mac_enabled == 1) { + mac_xface->ue_send_sdu(ue->Mod_id, CC_id, frame_rx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->b, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->TBS>>3, + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->b, + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS>>3, eNB_id); } - phy_vars_ue->total_TBS[eNB_id] = phy_vars_ue->total_TBS[eNB_id] + - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->TBS; - phy_vars_ue->total_received_bits[eNB_id] = phy_vars_ue->total_TBS[eNB_id] + - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->TBS; + ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS; + ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS; } } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)\n", - phy_vars_ue->Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti,harq_pid, + ue->Mod_id, + ue->dlsch[eNB_id][0]->rnti,harq_pid, frame_rx,subframe_prev,ret, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); if (frame_rx%100==0) { LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d dlsch_errors %d, dlsch_received %d, dlsch_fer %d, current_dlsch_cqi %d\n", - phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, + ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, frame_rx,subframe_prev, - phy_vars_ue->dlsch_errors[eNB_id], - phy_vars_ue->dlsch_received[eNB_id], - phy_vars_ue->dlsch_fer[eNB_id], - phy_vars_ue->PHY_measurements.wideband_cqi_tot[eNB_id]); + ue->dlsch_errors[eNB_id], + ue->dlsch_received[eNB_id], + ue->dlsch_fer[eNB_id], + ue->measurements.wideband_cqi_tot[eNB_id]); } #endif #endif //DLSCH_THREAD } else { // printf("PDSCH inactive in subframe %d\n",subframe_rx-1); - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[subframe_prev].send_harq_status = 0; + ue->dlsch[eNB_id][0]->harq_ack[subframe_prev].send_harq_status = 0; } // SI_DLSCH - if (phy_vars_ue->dlsch_ue_SI[eNB_id]->active == 1) { + if (ue->dlsch_SI[eNB_id]->active == 1) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"SI is active in subframe %d\n",subframe_prev); #endif // process symbols 10,11,12 (13) of last SF and trigger DLSCH decoding if (abstraction_flag==0) { - start_meas(&phy_vars_ue->dlsch_llr_stats); + start_meas(&ue->dlsch_llr_stats); - for (m=pilot3; mlte_frame_parms.symbols_per_tti; m++) { + for (m=pilot3; mframe_parms.symbols_per_tti; m++) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] Frame %d, slot %d: DLSCH (SI) demod between pilot 3 and 4 (2nd slot), m %d\n", - phy_vars_ue->Mod_id,frame_rx,slot_rx,m); + ue->Mod_id,frame_rx,slot_rx,m); #endif - rx_pdsch(phy_vars_ue, + rx_pdsch(ue, SI_PDSCH, eNB_id, eNB_id+1, @@ -2715,64 +2715,64 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac m, 0, 0, - phy_vars_ue->is_secondary_ue, - phy_vars_ue->dlsch_ue_SI[eNB_id]->current_harq_pid); + ue->is_secondary_ue, + ue->dlsch_SI[eNB_id]->current_harq_pid); } - stop_meas(&phy_vars_ue->dlsch_llr_stats); + stop_meas(&ue->dlsch_llr_stats); } - // write_output("dlsch_ra_llr.m","llr",lte_ue_pdsch_vars_ra[eNB_id]->llr[0],40,1,0); + // write_output("dlsch_ra_llr.m","llr",pdsch_vars_ra[eNB_id]->llr[0],40,1,0); - phy_vars_ue->dlsch_ue_SI[eNB_id]->active = 0; + ue->dlsch_SI[eNB_id]->active = 0; - if (frame_rx < phy_vars_ue->dlsch_SI_errors[eNB_id]) - phy_vars_ue->dlsch_SI_errors[eNB_id]=0; + if (frame_rx < ue->dlsch_SI_errors[eNB_id]) + ue->dlsch_SI_errors[eNB_id]=0; - if (phy_vars_ue->dlsch_ue_SI[eNB_id]) { + if (ue->dlsch_SI[eNB_id]) { if (abstraction_flag==0) { - // dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->G = - get_G(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even, + // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + ue->dlsch_SI[eNB_id]->harq_processes[0]->G = + get_G(&ue->frame_parms, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even, 2, 1, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, frame_rx,subframe_prev); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"Decoding DLSCH_SI : rb_alloc %x : nb_rb %d G %d TBS %d, num_pdcch_sym %d\n",phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->G, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->TBS, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols); + LOG_D(PHY,"Decoding DLSCH_SI : rb_alloc %x : nb_rb %d G %d TBS %d, num_pdcch_sym %d\n",ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->G, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols); #endif - dlsch_unscrambling(&phy_vars_ue->lte_frame_parms, + dlsch_unscrambling(&ue->frame_parms, 0, - phy_vars_ue->dlsch_ue_SI[eNB_id], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->G, - phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0], + ue->dlsch_SI[eNB_id], + ue->dlsch_SI[eNB_id]->harq_processes[0]->G, + ue->pdsch_vars_SI[eNB_id]->llr[0], 0, subframe_prev<<1); - ret = dlsch_decoding(phy_vars_ue, - phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_SI[eNB_id], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0], + ret = dlsch_decoding(ue, + ue->pdsch_vars_SI[eNB_id]->llr[0], + &ue->frame_parms, + ue->dlsch_SI[eNB_id], + ue->dlsch_SI[eNB_id]->harq_processes[0], subframe_prev, - phy_vars_ue->dlsch_ue_SI[eNB_id]->current_harq_pid, + ue->dlsch_SI[eNB_id]->current_harq_pid, 0,0); #ifdef DEBUG_PHY_PROC for (int i=0; i<11; i++) - LOG_D(PHY,"dlsch_output_buffer[%d]=%x\n",i,phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->c[0][i]); + LOG_D(PHY,"dlsch_output_buffer[%d]=%x\n",i,ue->dlsch_SI[eNB_id]->harq_processes[0]->c[0][i]); #endif @@ -2781,7 +2781,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac #ifdef PHY_ABSTRACTION else { LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); - ret = dlsch_decoding_emul(phy_vars_ue, + ret = dlsch_decoding_emul(ue, subframe_prev, 0, eNB_id); @@ -2789,25 +2789,25 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac #endif - if (ret == (1+phy_vars_ue->dlsch_ue_SI[eNB_id]->max_turbo_iterations)) { - phy_vars_ue->dlsch_SI_errors[eNB_id]++; + if (ret == (1+ue->dlsch_SI[eNB_id]->max_turbo_iterations)) { + ue->dlsch_SI_errors[eNB_id]++; #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received SI in error (TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx, subframe_prev, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->TBS, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->mcs, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rvidx, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, + ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rvidx, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); #endif - // dump_dlsch_SI(phy_vars_ue,eNB_id,subframe_prev); + // dump_dlsch_SI(ue,eNB_id,subframe_prev); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_rx); + stop_meas(&ue->phy_proc_rx); return(-1); } else { @@ -2815,29 +2815,29 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac #ifdef DEBUG_PHY_PROC //if ((frame_rx % 100) == 0) LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received SI for TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", - phy_vars_ue->Mod_id,frame_rx,subframe_prev, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->TBS, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->mcs, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rvidx, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); + ue->Mod_id,frame_rx,subframe_prev, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, + ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rvidx, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); #endif - if (phy_vars_ue->mac_enabled == 1) { + if (ue->mac_enabled == 1) { /* printf("\n\n"); - for (i=0;idlsch_ue_SI[eNB_id]->harq_processes[0]->TBS>>3;i++) - printf("%02x ",phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->b[i]); + for (i=0;idlsch_SI[eNB_id]->harq_processes[0]->TBS>>3;i++) + printf("%02x ",ue->dlsch_SI[eNB_id]->harq_processes[0]->b[i]); printf("\n"); */ - mac_xface->ue_decode_si(phy_vars_ue->Mod_id, + mac_xface->ue_decode_si(ue->Mod_id, CC_id, frame_rx, eNB_id, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->b, - phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->TBS>>3); + ue->dlsch_SI[eNB_id]->harq_processes[0]->b, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); } } } @@ -2845,23 +2845,23 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac /* #ifdef DEBUG_PHY_PROC debug_LOG_D(PHY,"[UE %d] Frame %d, slot %d: dlsch_decoding (SI) ret %d (%d errors)\n", - phy_vars_ue->Mod_id,frame_rx,slot_rx,ret,phy_vars_ue->dlsch_SI_errors[eNB_id]); + ue->Mod_id,frame_rx,slot_rx,ret,ue->dlsch_SI_errors[eNB_id]); #endif */ } - if (phy_vars_ue->dlsch_ue_ra[eNB_id]->active == 1) { + if (ue->dlsch_ra[eNB_id]->active == 1) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d: DLSCH (RA) demod symbols 10,11,12\n",phy_vars_ue->Mod_id,frame_rx,slot_rx); + LOG_D(PHY,"[UE %d] Frame %d, slot %d: DLSCH (RA) demod symbols 10,11,12\n",ue->Mod_id,frame_rx,slot_rx); #endif // process symbols 10,11,12 and trigger DLSCH decoding if (abstraction_flag==0) { - start_meas(&phy_vars_ue->dlsch_llr_stats); + start_meas(&ue->dlsch_llr_stats); - for (m=pilot3; mlte_frame_parms.symbols_per_tti; m++) - rx_pdsch(phy_vars_ue, + for (m=pilot3; mframe_parms.symbols_per_tti; m++) + rx_pdsch(ue, RA_PDSCH, eNB_id, eNB_id+1, @@ -2869,65 +2869,65 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac m, // symbol 0, // first_symbol_flag 0, - phy_vars_ue->is_secondary_ue, - phy_vars_ue->dlsch_ue_ra[eNB_id]->current_harq_pid); + ue->is_secondary_ue, + ue->dlsch_ra[eNB_id]->current_harq_pid); } - stop_meas(&phy_vars_ue->dlsch_llr_stats); + stop_meas(&ue->dlsch_llr_stats); - phy_vars_ue->dlsch_ue_ra[eNB_id]->active = 0; + ue->dlsch_ra[eNB_id]->active = 0; - if (frame_rx < phy_vars_ue->dlsch_ra_errors[eNB_id]) - phy_vars_ue->dlsch_ra_errors[eNB_id]=0; + if (frame_rx < ue->dlsch_ra_errors[eNB_id]) + ue->dlsch_ra_errors[eNB_id]=0; - if (phy_vars_ue->prach_resources[eNB_id]!=NULL) - phy_vars_ue->dlsch_ue_ra[eNB_id]->rnti = phy_vars_ue->prach_resources[eNB_id]->ra_RNTI; + if (ue->prach_resources[eNB_id]!=NULL) + ue->dlsch_ra[eNB_id]->rnti = ue->prach_resources[eNB_id]->ra_RNTI; else { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d: FATAL, prach_resources is NULL\n",phy_vars_ue->Mod_id,frame_rx,subframe_prev); + LOG_E(PHY,"[UE %d] Frame %d, subframe %d: FATAL, prach_resources is NULL\n",ue->Mod_id,frame_rx,subframe_prev); mac_xface->macphy_exit("prach_resources is NULL"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_rx); + stop_meas(&ue->phy_proc_rx); return 0; } if (abstraction_flag==0) { - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->G = get_G(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->rb_alloc_even, + ue->dlsch_ra[eNB_id]->harq_processes[0]->G = get_G(&ue->frame_parms, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even, 2, 1, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, frame_rx, subframe_prev); #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE] decoding RA (subframe %d): G %d,rnti %x\n" ,subframe_prev, - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->G, - phy_vars_ue->dlsch_ue_ra[eNB_id]->rnti); + ue->dlsch_ra[eNB_id]->harq_processes[0]->G, + ue->dlsch_ra[eNB_id]->rnti); #endif - dlsch_unscrambling(&phy_vars_ue->lte_frame_parms, + dlsch_unscrambling(&ue->frame_parms, 0, - phy_vars_ue->dlsch_ue_ra[eNB_id], - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->G, - phy_vars_ue->lte_ue_pdsch_vars_ra[eNB_id]->llr[0], + ue->dlsch_ra[eNB_id], + ue->dlsch_ra[eNB_id]->harq_processes[0]->G, + ue->pdsch_vars_ra[eNB_id]->llr[0], 0, subframe_prev<<1); - ret = dlsch_decoding(phy_vars_ue, - phy_vars_ue->lte_ue_pdsch_vars_ra[eNB_id]->llr[0], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_ra[eNB_id], - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0], + ret = dlsch_decoding(ue, + ue->pdsch_vars_ra[eNB_id]->llr[0], + &ue->frame_parms, + ue->dlsch_ra[eNB_id], + ue->dlsch_ra[eNB_id]->harq_processes[0], subframe_prev, // subframe - phy_vars_ue->dlsch_ue_ra[eNB_id]->current_harq_pid, + ue->dlsch_ra[eNB_id]->current_harq_pid, 0,0); } #ifdef PHY_ABSTRACTION else { LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); - ret = dlsch_decoding_emul(phy_vars_ue, + ret = dlsch_decoding_emul(ue, subframe_prev, 1, eNB_id); @@ -2935,98 +2935,98 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac #endif - if (ret == (1+phy_vars_ue->dlsch_ue_ra[eNB_id]->max_turbo_iterations)) { - phy_vars_ue->dlsch_ra_errors[eNB_id]++; - LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received RA in error\n",phy_vars_ue->Mod_id,frame_rx,subframe_prev); + if (ret == (1+ue->dlsch_ra[eNB_id]->max_turbo_iterations)) { + ue->dlsch_ra_errors[eNB_id]++; + LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received RA in error\n",ue->Mod_id,frame_rx,subframe_prev); - // dump_dlsch_ra(phy_vars_ue,eNB_id,subframe_prev); exit(-1); + // dump_dlsch_ra(ue,eNB_id,subframe_prev); exit(-1); // oai_exit=1; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_rx); + stop_meas(&ue->phy_proc_rx); return(-1); } else { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Received RAR mode %d\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx, - subframe_prev, phy_vars_ue->UE_mode[eNB_id]); + subframe_prev, ue->UE_mode[eNB_id]); #endif - if (phy_vars_ue->mac_enabled == 1) { - if ((phy_vars_ue->UE_mode[eNB_id] != PUSCH) && (phy_vars_ue->prach_resources[eNB_id]->Msg3!=NULL)) { + if (ue->mac_enabled == 1) { + if ((ue->UE_mode[eNB_id] != PUSCH) && (ue->prach_resources[eNB_id]->Msg3!=NULL)) { LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Invoking MAC for RAR (current preamble %d)\n", - phy_vars_ue->Mod_id,frame_rx-((subframe_prev==9) ? 1 : 0), + ue->Mod_id,frame_rx-((subframe_prev==9) ? 1 : 0), subframe_prev, - phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex); + ue->prach_resources[eNB_id]->ra_PreambleIndex); - timing_advance = mac_xface->ue_process_rar(phy_vars_ue->Mod_id, + timing_advance = mac_xface->ue_process_rar(ue->Mod_id, CC_id, frame_rx-((subframe_prev==0) ? 1 : 0), - phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->b, - &phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, - phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex); + ue->dlsch_ra[eNB_id]->harq_processes[0]->b, + &ue->pdcch_vars[eNB_id]->crnti, + ue->prach_resources[eNB_id]->ra_PreambleIndex); if (timing_advance!=0xffff) { LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Got rnti %x and timing advance %d from RAR\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx-((subframe_prev==9) ? 1 : 0), subframe_prev, - phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, + ue->pdcch_vars[eNB_id]->crnti, timing_advance); //timing_advance = 0; - process_timing_advance_rar(phy_vars_ue,timing_advance); + process_timing_advance_rar(ue,timing_advance); if (mode!=debug_prach) { - phy_vars_ue->ulsch_ue_Msg3_active[eNB_id]=1; - get_Msg3_alloc(&phy_vars_ue->lte_frame_parms, + ue->ulsch_Msg3_active[eNB_id]=1; + get_Msg3_alloc(&ue->frame_parms, subframe_prev, frame_rx-((subframe_prev==9) ? 1 : 0), - &phy_vars_ue->ulsch_ue_Msg3_frame[eNB_id], - &phy_vars_ue->ulsch_ue_Msg3_subframe[eNB_id]); + &ue->ulsch_Msg3_frame[eNB_id], + &ue->ulsch_Msg3_subframe[eNB_id]); LOG_D(PHY,"[UE %d][RAPROC] Got Msg3_alloc Frame %d subframe %d: Msg3_frame %d, Msg3_subframe %d\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx-((subframe_prev==9) ? 1 : 0), subframe_prev, - phy_vars_ue->ulsch_ue_Msg3_frame[eNB_id], - phy_vars_ue->ulsch_ue_Msg3_subframe[eNB_id]); - harq_pid = subframe2harq_pid(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->ulsch_ue_Msg3_frame[eNB_id], - phy_vars_ue->ulsch_ue_Msg3_subframe[eNB_id]); - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->round = 0; + ue->ulsch_Msg3_frame[eNB_id], + ue->ulsch_Msg3_subframe[eNB_id]); + harq_pid = subframe2harq_pid(&ue->frame_parms, + ue->ulsch_Msg3_frame[eNB_id], + ue->ulsch_Msg3_subframe[eNB_id]); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; - phy_vars_ue->UE_mode[eNB_id] = RA_RESPONSE; - // phy_vars_ue->Msg3_timer[eNB_id] = 10; - phy_vars_ue->ulsch_ue[eNB_id]->power_offset = 6; - phy_vars_ue->ulsch_no_allocation_counter[eNB_id] = 0; + ue->UE_mode[eNB_id] = RA_RESPONSE; + // ue->Msg3_timer[eNB_id] = 10; + ue->ulsch[eNB_id]->power_offset = 6; + ue->ulsch_no_allocation_counter[eNB_id] = 0; } } else { // PRACH preamble doesn't match RAR LOG_W(PHY,"[UE %d][RAPROC] Received RAR preamble (%d) doesn't match !!!\n", - phy_vars_ue->Mod_id, - phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex); + ue->Mod_id, + ue->prach_resources[eNB_id]->ra_PreambleIndex); } } // mode != PUSCH } else { - rar = phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->b+1; + rar = ue->dlsch_ra[eNB_id]->harq_processes[0]->b+1; timing_advance = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); - //timing_advance = phy_vars_ue->dlsch_ue_ra[eNB_id]->harq_processes[0]->b[0]; - process_timing_advance_rar(phy_vars_ue,timing_advance); + //timing_advance = ue->dlsch_ra[eNB_id]->harq_processes[0]->b[0]; + process_timing_advance_rar(ue,timing_advance); } } //ret <= MAX_ITERATIONS /* #ifdef DEBUG_PHY_PROC debug_LOG_D(PHY,"[UE %d] Frame %d, slot %d: dlsch_decoding (RA) ret %d (%d errors)\n", - phy_vars_ue->Mod_id,frame_rx,slot_rx,ret,phy_vars_ue->dlsch_ra_errors[eNB_id]); + ue->Mod_id,frame_rx,slot_rx,ret,ue->dlsch_ra_errors[eNB_id]); #endif */ - } // dlsch_ue_ra[eNB_id]->active == 1 + } // dlsch_ra[eNB_id]->active == 1 } @@ -3035,13 +3035,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac ((pmch_flag==1)&&(l==1))) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d: Calling pdcch procedures (eNB %d)\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,eNB_id); + LOG_D(PHY,"[UE %d] Frame %d, slot %d: Calling pdcch procedures (eNB %d)\n",ue->Mod_id,frame_rx,slot_rx,eNB_id); #endif // rt_printk("[PDCCH] Frame %d, slot %d, start %llu\n",frame_rx,slot_rx,rt_get_time_ns()); - if (lte_ue_pdcch_procedures(eNB_id,phy_vars_ue,abstraction_flag) == -1) { + if (ue_pdcch_procedures(eNB_id,ue,abstraction_flag) == -1) { #ifdef DEBUG_PHY_PROC - LOG_E(PHY,"[UE %d] Frame %d, slot %d: Error in pdcch procedures\n",phy_vars_ue->Mod_id,frame_rx,slot_rx); + LOG_E(PHY,"[UE %d] Frame %d, slot %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,slot_rx); #endif return(-1); } @@ -3049,31 +3049,31 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac // rt_printk("[PDCCH] Frame %d, slot %d, stop %llu\n",frame_rx,slot_rx,rt_get_time_ns()); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"num_pdcch_symbols %d\n",phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols); + LOG_D(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[eNB_id]->num_pdcch_symbols); #endif } if (abstraction_flag==0) { if (((slot_rx%2)==1) && (l==0)) { - start_meas(&phy_vars_ue->dlsch_llr_stats); + start_meas(&ue->dlsch_llr_stats); - for (m=phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols; + for (m=ue->pdcch_vars[eNB_id]->num_pdcch_symbols; mdlsch_ue[eNB_id][0]->active == 1) { - harq_pid = phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid; - LOG_D(PHY,"[UE %d] PDSCH active in subframe %d (%d), harq_pid %d\n",phy_vars_ue->Mod_id,subframe_rx,slot_rx,harq_pid); + if (ue->dlsch[eNB_id][0]->active == 1) { + harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; + LOG_D(PHY,"[UE %d] PDSCH active in subframe %d (%d), harq_pid %d\n",ue->Mod_id,subframe_rx,slot_rx,harq_pid); - if ((phy_vars_ue->transmission_mode[eNB_id] == 5) && - (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (phy_vars_ue->use_ia_receiver ==1)) { + if ((ue->transmission_mode[eNB_id] == 5) && + (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && + (ue->use_ia_receiver ==1)) { dual_stream_UE = 1; - eNB_id_i = phy_vars_ue->n_connected_eNB; - i_mod = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm; + eNB_id_i = ue->n_connected_eNB; + i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; } else { dual_stream_UE = 0; eNB_id_i = eNB_id+1; @@ -3082,74 +3082,74 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac // process DLSCH received in first slot - rx_pdsch(phy_vars_ue, + rx_pdsch(ue, PDSCH, eNB_id, eNB_id_i, subframe_rx, // subframe, m, - (m==phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag + (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag dual_stream_UE, i_mod, - phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid); + ue->dlsch[eNB_id][0]->current_harq_pid); } // CRNTI active #endif - if (phy_vars_ue->dlsch_ue_SI[eNB_id]->active == 1) { + if (ue->dlsch_SI[eNB_id]->active == 1) { // process SI DLSCH in first slot - rx_pdsch(phy_vars_ue, + rx_pdsch(ue, SI_PDSCH, eNB_id, eNB_id+1, subframe_rx, // subframe, m, - (m==phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag + (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag 0, - phy_vars_ue->is_secondary_ue, - phy_vars_ue->dlsch_ue_SI[eNB_id]->current_harq_pid); + ue->is_secondary_ue, + ue->dlsch_SI[eNB_id]->current_harq_pid); } // SI active - if (phy_vars_ue->dlsch_ue_ra[eNB_id]->active == 1) { - rx_pdsch(phy_vars_ue, + if (ue->dlsch_ra[eNB_id]->active == 1) { + rx_pdsch(ue, RA_PDSCH, eNB_id, eNB_id+1, subframe_rx, // subframe, m, - (m==phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, + (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, 0, - phy_vars_ue->is_secondary_ue, - phy_vars_ue->dlsch_ue_ra[eNB_id]->current_harq_pid); + ue->is_secondary_ue, + ue->dlsch_ra[eNB_id]->current_harq_pid); } // RA active } // loop from first dlsch symbol to end of slot - stop_meas(&phy_vars_ue->dlsch_llr_stats); + stop_meas(&ue->dlsch_llr_stats); } // 2nd quarter if (((slot_rx%2)==1) && (l==pilot1)) { - start_meas(&phy_vars_ue->dlsch_llr_stats); + start_meas(&ue->dlsch_llr_stats); for (m=pilot2; mdlsch_ue[eNB_id][0]->active == 1) { - harq_pid = phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid; + if (ue->dlsch[eNB_id][0]->active == 1) { + harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; - if ((phy_vars_ue->transmission_mode[eNB_id] == 5) && - (phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (phy_vars_ue->use_ia_receiver ==1)) { + if ((ue->transmission_mode[eNB_id] == 5) && + (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && + (ue->use_ia_receiver ==1)) { dual_stream_UE = 1; - eNB_id_i = phy_vars_ue->n_connected_eNB; - i_mod = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Qm; + eNB_id_i = ue->n_connected_eNB; + i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; } else { dual_stream_UE = 0; eNB_id_i = eNB_id+1; i_mod = 0; } - rx_pdsch(phy_vars_ue, + rx_pdsch(ue, PDSCH, eNB_id, eNB_id_i, @@ -3158,13 +3158,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac 0, dual_stream_UE, i_mod, - phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid); + ue->dlsch[eNB_id][0]->current_harq_pid); } // CRNTI active #endif - if(phy_vars_ue->dlsch_ue_SI[eNB_id]->active == 1) { - rx_pdsch(phy_vars_ue, + if(ue->dlsch_SI[eNB_id]->active == 1) { + rx_pdsch(ue, SI_PDSCH, eNB_id, eNB_id+1, @@ -3172,12 +3172,12 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac m, 0, // first_symbol_flag 0, - phy_vars_ue->is_secondary_ue, - phy_vars_ue->dlsch_ue_SI[eNB_id]->current_harq_pid); + ue->is_secondary_ue, + ue->dlsch_SI[eNB_id]->current_harq_pid); } // SI active - if (phy_vars_ue->dlsch_ue_ra[eNB_id]->active == 1) { - rx_pdsch(phy_vars_ue, + if (ue->dlsch_ra[eNB_id]->active == 1) { + rx_pdsch(ue, RA_PDSCH, eNB_id, eNB_id+1, @@ -3185,13 +3185,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac m, 0, // first_symbol_flag 0, - phy_vars_ue->is_secondary_ue, - phy_vars_ue->dlsch_ue_ra[eNB_id]->current_harq_pid); + ue->is_secondary_ue, + ue->dlsch_ra[eNB_id]->current_harq_pid); } // RA active } // loop over 3rd quarter - stop_meas(&phy_vars_ue->dlsch_llr_stats); + stop_meas(&ue->dlsch_llr_stats); } // 3rd quarter of subframe } // abstraction_flag==0 }// l loop @@ -3199,33 +3199,33 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac // calculate some statistics if (slot_rx==19) { if (frame_rx % 10 == 0) { - if ((phy_vars_ue->dlsch_received[eNB_id] - phy_vars_ue->dlsch_received_last[eNB_id]) != 0) - phy_vars_ue->dlsch_fer[eNB_id] = (100*(phy_vars_ue->dlsch_errors[eNB_id] - phy_vars_ue->dlsch_errors_last[eNB_id]))/(phy_vars_ue->dlsch_received[eNB_id] - phy_vars_ue->dlsch_received_last[eNB_id]); + if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) + ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); - phy_vars_ue->dlsch_errors_last[eNB_id] = phy_vars_ue->dlsch_errors[eNB_id]; - phy_vars_ue->dlsch_received_last[eNB_id] = phy_vars_ue->dlsch_received[eNB_id]; + ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; + ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; } - phy_vars_ue->bitrate[eNB_id] = (phy_vars_ue->total_TBS[eNB_id] - phy_vars_ue->total_TBS_last[eNB_id])*100; - phy_vars_ue->total_TBS_last[eNB_id] = phy_vars_ue->total_TBS[eNB_id]; + ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; + ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", - phy_vars_ue->Mod_id,frame_rx,phy_vars_ue->total_TBS[eNB_id], - phy_vars_ue->total_TBS_last[eNB_id],(float) phy_vars_ue->bitrate[eNB_id]/1000.0); + ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], + ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); /* if ((frame_rx % 100 == 0)) { - LOG_I(PHY,"Throughput %5.1f kbps\n",(float) phy_vars_ue->bitrate[eNB_id]/1000.0); + LOG_I(PHY,"Throughput %5.1f kbps\n",(float) ue->bitrate[eNB_id]/1000.0); } */ } - if (is_pmch_subframe((subframe_rx==9?-1:0)+frame_rx,subframe_rx,&phy_vars_ue->lte_frame_parms)) { + if (is_pmch_subframe((subframe_rx==9?-1:0)+frame_rx,subframe_rx,&ue->frame_parms)) { LOG_D(PHY,"ue calling pmch subframe ..\n "); if ((slot_rx%2)==1) { LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation(%d)\n", - phy_vars_ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,slot_rx); + ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,slot_rx); #ifdef Rel10 - pmch_mcs = mac_xface->ue_query_mch(phy_vars_ue->Mod_id, + pmch_mcs = mac_xface->ue_query_mch(ue->Mod_id, CC_id, (subframe_rx==9?-1:0)+frame_rx, subframe_rx, @@ -3241,20 +3241,20 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac #endif if (pmch_mcs>=0) { - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Programming PMCH demodulation for mcs %d\n",phy_vars_ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,pmch_mcs); - fill_UE_dlsch_MCH(phy_vars_ue,pmch_mcs,1,0,0); + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Programming PMCH demodulation for mcs %d\n",ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,pmch_mcs); + fill_UE_dlsch_MCH(ue,pmch_mcs,1,0,0); if (abstraction_flag == 0 ) { for (l=2; l<12; l++) { - slot_fep_mbsfn(phy_vars_ue, + slot_fep_mbsfn(ue, l, subframe_rx, - 0,0);//phy_vars_ue->rx_offset,0); + 0,0);//ue->rx_offset,0); } for (l=2; l<12; l++) { - rx_pmch(phy_vars_ue, + rx_pmch(ue, 0, subframe_rx, l); @@ -3265,31 +3265,31 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac /* printf("PMCH decoding, Frame %d, subframe %d, G %d\n", (subframe_rx==9?-1:0)+frame_rx, subframe_rx, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->G); + ue->dlsch_MCH[0]->harq_processes[0]->G); */ - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->G = get_G(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->nb_rb, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->rb_alloc_even, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->Qm, + ue->dlsch_MCH[0]->harq_processes[0]->G = get_G(&ue->frame_parms, + ue->dlsch_MCH[0]->harq_processes[0]->nb_rb, + ue->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even, + ue->dlsch_MCH[0]->harq_processes[0]->Qm, 1, 2, (subframe_rx==9?-1:0)+frame_rx,subframe_rx); - dlsch_unscrambling(&phy_vars_ue->lte_frame_parms,1,phy_vars_ue->dlsch_ue_MCH[0], - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->G, - phy_vars_ue->lte_ue_pdsch_vars_MCH[0]->llr[0],0,subframe_prev<<1); + dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0], + ue->dlsch_MCH[0]->harq_processes[0]->G, + ue->pdsch_vars_MCH[0]->llr[0],0,subframe_prev<<1); - ret = dlsch_decoding(phy_vars_ue, - phy_vars_ue->lte_ue_pdsch_vars_MCH[0]->llr[0], - &phy_vars_ue->lte_frame_parms, - phy_vars_ue->dlsch_ue_MCH[0], - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0], + ret = dlsch_decoding(ue, + ue->pdsch_vars_MCH[0]->llr[0], + &ue->frame_parms, + ue->dlsch_MCH[0], + ue->dlsch_MCH[0]->harq_processes[0], subframe_prev, 0, 0,1); } else { // abstraction #ifdef PHY_ABSTRACTION - ret = dlsch_decoding_emul(phy_vars_ue, + ret = dlsch_decoding_emul(ue, subframe_rx, 5, // PMCH eNB_id); @@ -3297,29 +3297,29 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac } if (mcch_active == 1) - phy_vars_ue->dlsch_mcch_trials[sync_area][0]++; + ue->dlsch_mcch_trials[sync_area][0]++; else - phy_vars_ue->dlsch_mtch_trials[sync_area][0]++; + ue->dlsch_mtch_trials[sync_area][0]++; - if (ret == (1+phy_vars_ue->dlsch_ue_MCH[0]->max_turbo_iterations)) { + if (ret == (1+ue->dlsch_MCH[0]->max_turbo_iterations)) { if (mcch_active == 1) - phy_vars_ue->dlsch_mcch_errors[sync_area][0]++; + ue->dlsch_mcch_errors[sync_area][0]++; else - phy_vars_ue->dlsch_mtch_errors[sync_area][0]++; + ue->dlsch_mtch_errors[sync_area][0]++; LOG_D(PHY,"[%s %d] Frame %d, subframe %d: PMCH in error (%d,%d), not passing to L2 (TBS %d, iter %d,G %d)\n", - (r_type == no_relay)? "UE": "RN/UE", phy_vars_ue->Mod_id, + (r_type == no_relay)? "UE": "RN/UE", ue->Mod_id, (subframe_rx==9?-1:0)+frame_rx,subframe_rx, - phy_vars_ue->dlsch_mcch_errors[sync_area][0], - phy_vars_ue->dlsch_mtch_errors[sync_area][0], - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->TBS>>3, - phy_vars_ue->dlsch_ue_MCH[0]->max_turbo_iterations, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->G); - dump_mch(phy_vars_ue,0,phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->G,subframe_rx); + ue->dlsch_mcch_errors[sync_area][0], + ue->dlsch_mtch_errors[sync_area][0], + ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, + ue->dlsch_MCH[0]->max_turbo_iterations, + ue->dlsch_MCH[0]->harq_processes[0]->G); + dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,subframe_rx); #ifdef DEBUG_DLSCH - for (int i=0; idlsch_ue_MCH[0]->harq_processes[0]->TBS>>3; i++) { - LOG_T(PHY,"%02x.",phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->c[0][i]); + for (int i=0; idlsch_MCH[0]->harq_processes[0]->TBS>>3; i++) { + LOG_T(PHY,"%02x.",ue->dlsch_MCH[0]->harq_processes[0]->c[0][i]); } LOG_T(PHY,"\n"); @@ -3331,44 +3331,44 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac #ifdef Rel10 if ((r_type == no_relay) || (mcch_active == 1)) { - mac_xface->ue_send_mch_sdu(phy_vars_ue->Mod_id, + mac_xface->ue_send_mch_sdu(ue->Mod_id, CC_id, frame_rx, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->b, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->TBS>>3, + ue->dlsch_MCH[0]->harq_processes[0]->b, + ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, eNB_id,// not relevant in eMBMS context sync_area); - /* for (i=0;idlsch_ue_MCH[0]->harq_processes[0]->TBS>>3;i++) - msg("%2x.",phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->b[i]); + /* for (i=0;idlsch_MCH[0]->harq_processes[0]->TBS>>3;i++) + msg("%2x.",ue->dlsch_MCH[0]->harq_processes[0]->b[i]); msg("\n"); */ if (mcch_active == 1) - phy_vars_ue->dlsch_mcch_received[sync_area][0]++; + ue->dlsch_mcch_received[sync_area][0]++; else - phy_vars_ue->dlsch_mtch_received[sync_area][0]++; + ue->dlsch_mtch_received[sync_area][0]++; - if (phy_vars_ue->dlsch_mch_received_sf[subframe_rx%5][0] == 1 ) { - phy_vars_ue->dlsch_mch_received_sf[subframe_rx%5][0]=0; + if (ue->dlsch_mch_received_sf[subframe_rx%5][0] == 1 ) { + ue->dlsch_mch_received_sf[subframe_rx%5][0]=0; } else { - phy_vars_ue->dlsch_mch_received[0]+=1; - phy_vars_ue->dlsch_mch_received_sf[subframe_rx][0]=1; + ue->dlsch_mch_received[0]+=1; + ue->dlsch_mch_received_sf[subframe_rx][0]=1; } } else if (r_type == multicast_relay) { // mcch is not active here // only 1 harq process exists // Fix me: this could be a pointer copy memcpy (phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->b, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->b, - phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->TBS>>3); + ue->dlsch_MCH[0]->harq_processes[0]->b, + ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3); // keep the tbs phy_vars_rn->mch_avtive[subframe_rx] = 1; phy_vars_rn->sync_area[subframe_rx] = sync_area; // this could also go the harq data struct - phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS = phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->TBS; - phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs = phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->mcs; + phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS = ue->dlsch_MCH[0]->harq_processes[0]->TBS; + phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs = ue->dlsch_MCH[0]->harq_processes[0]->mcs; LOG_D(PHY,"[RN/UE %d] Frame %d subframe %d: store the MCH PDU for MBSFN sync area %d (MCS %d, TBS %d)\n", - phy_vars_ue->Mod_id, frame_rx,subframe_rx,sync_area, + ue->Mod_id, frame_rx,subframe_rx,sync_area, phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs, phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS>>3); #ifdef DEBUG_PHY @@ -3379,7 +3379,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac msg("\n"); #endif } else - LOG_W(PHY,"[UE %d] Frame %d: not supported option\n",phy_vars_ue->Mod_id, frame_rx); + LOG_W(PHY,"[UE %d] Frame %d: not supported option\n",ue->Mod_id, frame_rx); #endif } @@ -3388,11 +3388,11 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac } #ifdef EMOS - phy_procedures_emos_UE_RX(phy_vars_ue,slot_rx,eNB_id); + phy_procedures_emos_UE_RX(ue,slot_rx,eNB_id); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&phy_vars_ue->phy_proc_rx); + stop_meas(&ue->phy_proc_rx); return (0); } @@ -3426,136 +3426,7 @@ int phy_procedures_RN_UE_RX(uint8_t slot_rx, uint8_t next_slot, relaying_type_t #endif -#if defined(ENABLE_ITTI) -# if ENABLE_RAL -extern PHY_MEASUREMENTS PHY_measurements; - -void phy_UE_lte_measurement_thresholds_test_and_report(instance_t instanceP, ral_threshold_phy_t* threshold_phy_pP, uint16_t valP) -{ - MessageDef *message_p = NULL; - - if ( - ( - (((short) threshold_phy_pP->threshold.threshold_val < (short) valP) && (threshold_phy_pP->threshold.threshold_xdir == RAL_ABOVE_THRESHOLD)) || - (((short)threshold_phy_pP->threshold.threshold_val > (short)valP) && (threshold_phy_pP->threshold.threshold_xdir == RAL_BELOW_THRESHOLD)) - ) || - (threshold_phy_pP->threshold.threshold_xdir == RAL_NO_THRESHOLD) - ) { - message_p = itti_alloc_new_message(TASK_PHY_UE , PHY_MEAS_REPORT_IND); - memset(&PHY_MEAS_REPORT_IND(message_p), 0, sizeof(PHY_MEAS_REPORT_IND(message_p))); - - memcpy(&PHY_MEAS_REPORT_IND (message_p).threshold, - &threshold_phy_pP->threshold, - sizeof(PHY_MEAS_REPORT_IND (message_p).threshold)); - - memcpy(&PHY_MEAS_REPORT_IND (message_p).link_param, - &threshold_phy_pP->link_param, - sizeof(PHY_MEAS_REPORT_IND (message_p).link_param)); - - switch (threshold_phy_pP->link_param.choice) { - case RAL_LINK_PARAM_CHOICE_LINK_PARAM_VAL: - PHY_MEAS_REPORT_IND (message_p).link_param._union.link_param_val = valP; - break; - - case RAL_LINK_PARAM_CHOICE_QOS_PARAM_VAL: - //PHY_MEAS_REPORT_IND (message_p).link_param._union.qos_param_val. - AssertFatal (1 == 0, "TO DO RAL_LINK_PARAM_CHOICE_QOS_PARAM_VAL\n"); - break; - } - - //LOG_I(PHY,"[XXX] Sending link parameters report msg message to RRC\n"); - itti_send_msg_to_task(TASK_RRC_UE, instanceP, message_p); - } -} - -void phy_UE_lte_check_measurement_thresholds(instance_t instanceP, ral_threshold_phy_t* threshold_phy_pP) -{ - unsigned int mod_id; - int CC_id = 0; // this should become the function argument, requested by the upper layers. - - mod_id = instanceP - NB_eNB_INST; - - switch (threshold_phy_pP->link_param.link_param_type.choice) { - - case RAL_LINK_PARAM_TYPE_CHOICE_GEN: - switch (threshold_phy_pP->link_param.link_param_type._union.link_param_gen) { - case RAL_LINK_PARAM_GEN_DATA_RATE: - phy_UE_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0); - break; - - case RAL_LINK_PARAM_GEN_SIGNAL_STRENGTH: - phy_UE_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0); - break; - - case RAL_LINK_PARAM_GEN_SINR: - phy_UE_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0); - break; - - case RAL_LINK_PARAM_GEN_THROUGHPUT: - break; - - default: - ; - } - - break; - - case RAL_LINK_PARAM_TYPE_CHOICE_LTE: - switch (threshold_phy_pP->link_param.link_param_type._union.link_param_gen) { - case RAL_LINK_PARAM_LTE_UE_RSRP: - // phy_UE_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, PHY_vars_UE_g[mod_id]->PHY_measurements.rx_rssi_dBm[0]); - phy_UE_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, PHY_vars_UE_g[mod_id][CC_id]->PHY_measurements.rsrp[0]); - break; - - case RAL_LINK_PARAM_LTE_UE_RSRQ: - phy_UE_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, PHY_vars_UE_g[mod_id][CC_id]->PHY_measurements.rsrq[0]); - break; - - case RAL_LINK_PARAM_LTE_UE_CQI: - phy_UE_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, PHY_vars_UE_g[mod_id][CC_id]->PHY_measurements.wideband_cqi_avg[0]); - break; - - case RAL_LINK_PARAM_LTE_AVAILABLE_BW: - break; - - case RAL_LINK_PARAM_LTE_PACKET_DELAY: - break; - - case RAL_LINK_PARAM_LTE_PACKET_LOSS_RATE: - break; - - case RAL_LINK_PARAM_LTE_L2_BUFFER_STATUS: - break; - - case RAL_LINK_PARAM_LTE_MOBILE_NODE_CAPABILITIES: - break; - - case RAL_LINK_PARAM_LTE_EMBMS_CAPABILITY: - break; - - case RAL_LINK_PARAM_LTE_JUMBO_FEASIBILITY: - break; - - case RAL_LINK_PARAM_LTE_JUMBO_SETUP_STATUS: - break; - - case RAL_LINK_PARAM_LTE_NUM_ACTIVE_EMBMS_RECEIVERS_PER_FLOW: - break; - - default: - LOG_W(PHY,"unknown message %d\n", threshold_phy_pP->link_param.link_param_type._union.link_param_gen); - } - - break; - - default: - LOG_W(PHY,"unknown message %d\n", threshold_phy_pP->link_param.link_param_type.choice); - } -} -# endif -#endif - -void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, +void phy_procedures_UE_lte(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, relaying_type_t r_type, PHY_VARS_RN *phy_vars_rn) { #if defined(ENABLE_ITTI) @@ -3568,19 +3439,19 @@ void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstr # if ENABLE_RAL int CC_id =0; #endif - int frame_rx = phy_vars_ue->frame_rx; - int frame_tx = phy_vars_ue->frame_tx; - int slot_rx = phy_vars_ue->slot_rx; - int slot_tx = phy_vars_ue->slot_tx; + int frame_rx = ue->frame_rx; + int frame_tx = ue->frame_tx; + int slot_rx = ue->slot_rx; + int slot_tx = ue->slot_tx; int subframe_tx = slot_tx>>1; int subframe_rx = slot_rx>>1; #undef DEBUG_PHY_PROC UE_L2_STATE_t ret; - if (phy_vars_ue->mac_enabled == 0) { - phy_vars_ue->UE_mode[eNB_id]=PUSCH; - phy_vars_ue->prach_resources[eNB_id] = &prach_resources_local; + if (ue->mac_enabled == 0) { + ue->UE_mode[eNB_id]=PUSCH; + ue->prach_resources[eNB_id] = &prach_resources_local; prach_resources_local.ra_RNTI = 0xbeef; prach_resources_local.ra_PreambleIndex = 0; } @@ -3592,7 +3463,7 @@ void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstr VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[0].rxcnt_ptr[0])); #endif #endif - start_meas(&phy_vars_ue->phy_proc); + start_meas(&ue->phy_proc); #if defined(ENABLE_ITTI) do { @@ -3634,7 +3505,7 @@ void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstr // check if it is a measurement timer { hashtable_rc_t hashtable_rc; - hashtable_rc = hashtable_is_key_exists(PHY_vars_UE_g[Mod_id][CC_id]->ral_thresholds_timed, (uint64_t)(TIMER_HAS_EXPIRED(msg_p).timer_id)); + hashtable_rc = hashtable_is_key_exists(ue_g[Mod_id][CC_id]->ral_thresholds_timed, (uint64_t)(TIMER_HAS_EXPIRED(msg_p).timer_id)); LOG_I(PHY, "[UE %d] Received TIMER HAS EXPIRED: (hash_rc %d, HASH_TABLE_OK %d)\n", Mod_id, hashtable_rc, HASH_TABLE_OK); if (hashtable_rc == HASH_TABLE_OK) { @@ -3677,14 +3548,14 @@ void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstr switch (PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type.choice) { case RAL_LINK_PARAM_TYPE_CHOICE_GEN: SLIST_INSERT_HEAD( - &PHY_vars_UE_g[Mod_id][CC_id]->ral_thresholds_gen_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_gen], + &ue_g[Mod_id][CC_id]->ral_thresholds_gen_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_gen], threshold_phy_p, ral_thresholds); break; case RAL_LINK_PARAM_TYPE_CHOICE_LTE: SLIST_INSERT_HEAD( - &PHY_vars_UE_g[Mod_id][CC_id]->ral_thresholds_lte_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_lte], + &ue_g[Mod_id][CC_id]->ral_thresholds_lte_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_lte], threshold_phy_p, ral_thresholds); //LOG_E(PHY, "[UE %d] NORMAL/ONE SHOT - TIMER NULL - type LTE in %s\n", Mod_id, msg_name); @@ -3708,7 +3579,7 @@ void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstr &timer_id); if (res == 0) { - hashtable_rc = hashtable_insert(PHY_vars_UE_g[Mod_id][CC_id]->ral_thresholds_timed, (uint64_t )timer_id, (void*)threshold_phy_p); + hashtable_rc = hashtable_insert(ue_g[Mod_id][CC_id]->ral_thresholds_timed, (uint64_t )timer_id, (void*)threshold_phy_p); if (hashtable_rc == HASH_TABLE_OK) { threshold_phy_p->timer_id = timer_id; @@ -3754,62 +3625,62 @@ void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstr #endif - if ((subframe_select(&phy_vars_ue->lte_frame_parms,subframe_tx)==SF_UL)|| - (phy_vars_ue->lte_frame_parms.frame_type == FDD)) { - phy_procedures_UE_TX(phy_vars_ue,eNB_id,abstraction_flag,mode,r_type); + if ((subframe_select(&ue->frame_parms,subframe_tx)==SF_UL)|| + (ue->frame_parms.frame_type == FDD)) { + phy_procedures_UE_TX(ue,eNB_id,abstraction_flag,mode,r_type); } - if ((subframe_select(&phy_vars_ue->lte_frame_parms,subframe_rx)==SF_DL) || - (phy_vars_ue->lte_frame_parms.frame_type == FDD)) { + if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_DL) || + (ue->frame_parms.frame_type == FDD)) { #ifdef Rel10 if (phy_procedures_RN_UE_RX(slot_rx, slot_tx, r_type) != 0 ) #endif - phy_procedures_UE_RX(phy_vars_ue,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); + phy_procedures_UE_RX(ue,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); } - if ((subframe_select(&phy_vars_ue->lte_frame_parms,subframe_tx)==SF_S) && + if ((subframe_select(&ue->frame_parms,subframe_tx)==SF_S) && ((slot_tx&1)==1)) { - phy_procedures_UE_S_TX(phy_vars_ue,eNB_id,abstraction_flag,r_type); + phy_procedures_UE_S_TX(ue,eNB_id,abstraction_flag,r_type); } - if ((subframe_select(&phy_vars_ue->lte_frame_parms,subframe_rx)==SF_S) && + if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_S) && ((slot_rx&1)==0)) { #ifdef Rel10 if (phy_procedures_RN_UE_RX(slot_rx, slot_tx, r_type) != 0 ) #endif - phy_procedures_UE_RX(phy_vars_ue,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); + phy_procedures_UE_RX(ue,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); } - if (phy_vars_ue->mac_enabled==1) { + if (ue->mac_enabled==1) { if (slot_rx%2==0) { - ret = mac_xface->ue_scheduler(phy_vars_ue->Mod_id, + ret = mac_xface->ue_scheduler(ue->Mod_id, frame_tx, subframe_rx, - subframe_select(&phy_vars_ue->lte_frame_parms,subframe_tx), + subframe_select(&ue->frame_parms,subframe_tx), eNB_id, 0/*FIXME CC_id*/); if (ret == CONNECTION_LOST) { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",phy_vars_ue->Mod_id, + LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",ue->Mod_id, frame_rx,subframe_tx); - phy_vars_ue->UE_mode[eNB_id] = PRACH; + ue->UE_mode[eNB_id] = PRACH; // mac_xface->macphy_exit("Connection lost"); } else if (ret == PHY_RESYNCH) { LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n", - phy_vars_ue->Mod_id, + ue->Mod_id, frame_rx,subframe_tx); - phy_vars_ue->UE_mode[eNB_id] = RESYNCH; + ue->UE_mode[eNB_id] = RESYNCH; // mac_xface->macphy_exit("Connection lost"); } else if (ret == PHY_HO_PRACH) { LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n", - phy_vars_ue->Mod_id,frame_rx,subframe_tx); - phy_vars_ue->UE_mode[eNB_id] = PRACH; + ue->Mod_id,frame_rx,subframe_tx); + ue->UE_mode[eNB_id] = PRACH; } } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,0); - stop_meas(&phy_vars_ue->phy_proc); + stop_meas(&ue->phy_proc); } diff --git a/openair1/SCHED/pucch_pc.c b/openair1/SCHED/pucch_pc.c index afcf4bd5b3..229ae3f1a3 100644 --- a/openair1/SCHED/pucch_pc.c +++ b/openair1/SCHED/pucch_pc.c @@ -42,7 +42,7 @@ #include "PHY/LTE_TRANSPORT/proto.h" #include "PHY/extern.h" -int8_t pucch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id,PUCCH_FMT_t pucch_fmt) +int8_t pucch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,PUCCH_FMT_t pucch_fmt) { int8_t Po_PUCCH; @@ -52,29 +52,29 @@ int8_t pucch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id // //if ((pucch_fmt == pucch_format1a) || // (pucch_fmt == pucch_format1b)) { // Update g_pucch based on TPC/delta_PUCCH received in PDCCH for this process - //harq_pid = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_ack[subframe].harq_id; + //harq_pid = ue->dlsch[eNB_id][0]->harq_ack[subframe].harq_id; //this is now done in dci_tools - //phy_vars_ue->g_pucch[eNB_id] += phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->delta_PUCCH; + //ue->g_pucch[eNB_id] += ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->delta_PUCCH; //} - Po_PUCCH = get_PL(phy_vars_ue->Mod_id,phy_vars_ue->CC_id,eNB_id)+ - phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH+ - phy_vars_ue->dlsch_ue[eNB_id][0]->g_pucch; + Po_PUCCH = get_PL(ue->Mod_id,ue->CC_id,eNB_id)+ + ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+ + ue->dlsch[eNB_id][0]->g_pucch; switch (pucch_fmt) { case pucch_format1: case pucch_format2a: case pucch_format2b: - Po_PUCCH += (-2+(phy_vars_ue->lte_frame_parms.ul_power_control_config_common.deltaF_PUCCH_Format1<<1)); + Po_PUCCH += (-2+(ue->frame_parms.ul_power_control_config_common.deltaF_PUCCH_Format1<<1)); break; case pucch_format1a: case pucch_format1b: - Po_PUCCH += (1+(phy_vars_ue->lte_frame_parms.ul_power_control_config_common.deltaF_PUCCH_Format1b<<1)); + Po_PUCCH += (1+(ue->frame_parms.ul_power_control_config_common.deltaF_PUCCH_Format1b<<1)); break; case pucch_format2: - switch (phy_vars_ue->lte_frame_parms.ul_power_control_config_common.deltaF_PUCCH_Format2a) { + switch (ue->frame_parms.ul_power_control_config_common.deltaF_PUCCH_Format2a) { case 0: Po_PUCCH -= 2; break; @@ -97,20 +97,20 @@ int8_t pucch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id if (pucch_fmt!=pucch_format1) { LOG_I(PHY,"[UE %d][PDSCH %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n", - phy_vars_ue->Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti,phy_vars_ue->frame_tx,subframe, + ue->Mod_id, + ue->dlsch[eNB_id][0]->rnti,ue->frame_tx,subframe, Po_PUCCH, - phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - get_PL(phy_vars_ue->Mod_id,phy_vars_ue->CC_id,eNB_id), - phy_vars_ue->dlsch_ue[eNB_id][0]->g_pucch); + ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, + get_PL(ue->Mod_id,ue->CC_id,eNB_id), + ue->dlsch[eNB_id][0]->g_pucch); } else { LOG_I(PHY,"[UE %d][SR %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n", - phy_vars_ue->Mod_id, - phy_vars_ue->dlsch_ue[eNB_id][0]->rnti,phy_vars_ue->frame_tx,subframe, + ue->Mod_id, + ue->dlsch[eNB_id][0]->rnti,ue->frame_tx,subframe, Po_PUCCH, - phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - get_PL(phy_vars_ue->Mod_id,phy_vars_ue->CC_id,eNB_id), - phy_vars_ue->dlsch_ue[eNB_id][0]->g_pucch); + ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, + get_PL(ue->Mod_id,ue->CC_id,eNB_id), + ue->dlsch[eNB_id][0]->g_pucch); } return(Po_PUCCH); diff --git a/openair1/SCHED/pusch_pc.c b/openair1/SCHED/pusch_pc.c index 5fb1f7449c..074cd507ef 100644 --- a/openair1/SCHED/pusch_pc.c +++ b/openair1/SCHED/pusch_pc.c @@ -47,7 +47,7 @@ int16_t hundred_times_delta_TF[100] = {-32768,-1268,-956,-768,-631,-523,-431,-352,-282,-219,-161,-107,-57,-9,36,79,120,159,197,234,269,304,337,370,402,434,465,495,525,555,583,612,640,668,696,723,750,777,803,829,856,881,907,933,958,983,1008,1033,1058,1083,1108,1132,1157,1181,1205,1229,1254,1278,1302,1325,1349,1373,1397,1421,1444,1468,1491,1515,1538,1562,1585,1609,1632,1655,1679,1702,1725,1748,1772,1795,1818,1841,1864,1887,1910,1933,1956,1980,2003,2026,2049,2072,2095,2118,2141,2164,2186,2209,2232,2255}; uint16_t hundred_times_log10_NPRB[100] = {0,301,477,602,698,778,845,903,954,1000,1041,1079,1113,1146,1176,1204,1230,1255,1278,1301,1322,1342,1361,1380,1397,1414,1431,1447,1462,1477,1491,1505,1518,1531,1544,1556,1568,1579,1591,1602,1612,1623,1633,1643,1653,1662,1672,1681,1690,1698,1707,1716,1724,1732,1740,1748,1755,1763,1770,1778,1785,1792,1799,1806,1812,1819,1826,1832,1838,1845,1851,1857,1863,1869,1875,1880,1886,1892,1897,1903,1908,1913,1919,1924,1929,1934,1939,1944,1949,1954,1959,1963,1968,1973,1977,1982,1986,1991,1995,2000}; -int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t harq_pid, uint8_t bw_factor) +int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint8_t UE_id,uint8_t harq_pid, uint8_t bw_factor) { uint32_t Nre,sumKr,MPR_x100,Kr,r; @@ -56,16 +56,16 @@ int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id, DevAssert( UE_id < NUMBER_OF_UE_MAX+1 ); DevAssert( harq_pid < 8 ); - Nre = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Nsymb_initial * - phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb*12; + Nre = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_initial * + eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12; sumKr = 0; - for (r=0; rulsch_eNB[UE_id]->harq_processes[harq_pid]->C; r++) { - if (rulsch_eNB[UE_id]->harq_processes[harq_pid]->Cminus) - Kr = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Kminus; + for (r=0; rulsch[UE_id]->harq_processes[harq_pid]->C; r++) { + if (rulsch[UE_id]->harq_processes[harq_pid]->Cminus) + Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kminus; else - Kr = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Kplus; + Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus; sumKr += Kr; } @@ -78,16 +78,16 @@ int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id, // FK 20140908 sumKr is only set after the ulsch_encoding beta_offset_pusch = 8; - //(phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->control_only == 1) ? phy_vars_eNB->ulsch_eNB[UE_id]->beta_offset_cqi_times8:8; + //(eNB->ulsch[UE_id]->harq_processes[harq_pid]->control_only == 1) ? eNB->ulsch[UE_id]->beta_offset_cqi_times8:8; DevAssert( UE_id < NUMBER_OF_UE_MAX ); //#warning "This condition happens sometimes. Need more investigation" // navid //DevAssert( MPR_x100/6 < 100 ); - if (phy_vars_eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled == 1) { + if (eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled == 1) { // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch) if (bw_factor == 1) { - uint8_t nb_rb = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb; + uint8_t nb_rb = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb; return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)) + hundred_times_log10_NPRB[nb_rb-1]; } else return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)); @@ -108,23 +108,23 @@ int16_t get_hundred_times_delta_IF_mac(module_id_t module_idP, uint8_t CC_id, rn return get_hundred_times_delta_IF_eNB( PHY_vars_eNB_g[module_idP][CC_id], UE_id, harq_pid, 0 ); } -int16_t get_hundred_times_delta_IF(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t harq_pid) +int16_t get_hundred_times_delta_IF(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t harq_pid) { - uint32_t Nre = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->Nsymb_initial * - phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->nb_rb*12; + uint32_t Nre = ue->ulsch[eNB_id]->harq_processes[harq_pid]->Nsymb_initial * + ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb*12; if (Nre==0) return(0); - uint32_t MPR_x100 = 100*phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->sumKr/Nre; + uint32_t MPR_x100 = 100*ue->ulsch[eNB_id]->harq_processes[harq_pid]->sumKr/Nre; // Note: MPR=is the effective spectral efficiency of the PUSCH // FK 20140908 sumKr is only set after the ulsch_encoding - uint16_t beta_offset_pusch = (phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? - phy_vars_ue->ulsch_ue[eNB_id]->beta_offset_cqi_times8:8; + uint16_t beta_offset_pusch = (ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? + ue->ulsch[eNB_id]->beta_offset_cqi_times8:8; - if (phy_vars_ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled == 1) { + if (ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled == 1) { // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch) return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)); } else { @@ -136,15 +136,15 @@ int16_t get_hundred_times_delta_IF(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8 uint8_t alpha_lut[8] = {0,40,50,60,70,80,90,100}; -void pusch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag) +void pusch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag) { - uint8_t harq_pid = subframe2harq_pid(&phy_vars_ue->lte_frame_parms, - phy_vars_ue->frame_tx, + uint8_t harq_pid = subframe2harq_pid(&ue->frame_parms, + ue->frame_tx, subframe); - uint8_t nb_rb = phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->nb_rb; + uint8_t nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; int8_t PL; @@ -153,46 +153,46 @@ void pusch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id,u // P_opusch(0) = P_oPTR + deltaP_Msg3 if PUSCH is transporting Msg3 // else // P_opusch(0) = PO_NOMINAL_PUSCH(j) + P_O_UE_PUSCH(j) - PL = get_PL(phy_vars_ue->Mod_id,phy_vars_ue->CC_id,eNB_id); + PL = get_PL(ue->Mod_id,ue->CC_id,eNB_id); - phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH = (hundred_times_log10_NPRB[nb_rb-1]+ - get_hundred_times_delta_IF(phy_vars_ue,eNB_id,harq_pid) + - 100*phy_vars_ue->ulsch_ue[eNB_id]->f_pusch)/100; + ue->ulsch[eNB_id]->Po_PUSCH = (hundred_times_log10_NPRB[nb_rb-1]+ + get_hundred_times_delta_IF(ue,eNB_id,harq_pid) + + 100*ue->ulsch[eNB_id]->f_pusch)/100; - if( phy_vars_ue->ulsch_ue_Msg3_active[eNB_id] == 1) { // Msg3 PUSCH + if(ue->ulsch_Msg3_active[eNB_id] == 1) { // Msg3 PUSCH - phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH += (mac_xface->get_Po_NOMINAL_PUSCH(phy_vars_ue->Mod_id,0) + PL); + ue->ulsch[eNB_id]->Po_PUSCH += (mac_xface->get_Po_NOMINAL_PUSCH(ue->Mod_id,0) + PL); LOG_I(PHY,"[UE %d][RAPROC] frame %d, subframe %d: Msg3 Po_PUSCH %d dBm (%d,%d,100*PL=%d,%d,%d)\n", - phy_vars_ue->Mod_id,phy_vars_ue->frame_tx,subframe,phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH, - 100*mac_xface->get_Po_NOMINAL_PUSCH(phy_vars_ue->Mod_id,0), + ue->Mod_id,ue->frame_tx,subframe,ue->ulsch[eNB_id]->Po_PUSCH, + 100*mac_xface->get_Po_NOMINAL_PUSCH(ue->Mod_id,0), hundred_times_log10_NPRB[nb_rb-1], 100*PL, - get_hundred_times_delta_IF(phy_vars_ue,eNB_id,harq_pid), - 100*phy_vars_ue->ulsch_ue[eNB_id]->f_pusch); + get_hundred_times_delta_IF(ue,eNB_id,harq_pid), + 100*ue->ulsch[eNB_id]->f_pusch); } else if (j==0) { // SPS PUSCH } else if (j==1) { // Normal PUSCH - phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH += ((alpha_lut[phy_vars_ue->lte_frame_parms.ul_power_control_config_common.alpha]*PL)/100); - phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH += phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUSCH; - phy_vars_ue->ulsch_ue[eNB_id]->PHR = phy_vars_ue->tx_power_max_dBm-phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH; + ue->ulsch[eNB_id]->Po_PUSCH += ((alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha]*PL)/100); + ue->ulsch[eNB_id]->Po_PUSCH += ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH; + ue->ulsch[eNB_id]->PHR = ue->tx_power_max_dBm-ue->ulsch[eNB_id]->Po_PUSCH; - if (phy_vars_ue->ulsch_ue[eNB_id]->PHR < -23) - phy_vars_ue->ulsch_ue[eNB_id]->PHR = -23; - else if (phy_vars_ue->ulsch_ue[eNB_id]->PHR > 40) - phy_vars_ue->ulsch_ue[eNB_id]->PHR = 40; + if (ue->ulsch[eNB_id]->PHR < -23) + ue->ulsch[eNB_id]->PHR = -23; + else if (ue->ulsch[eNB_id]->PHR > 40) + ue->ulsch[eNB_id]->PHR = 40; LOG_D(PHY,"[UE %d][PUSCH %d] frame %d, subframe %d: Po_PUSCH %d dBm : tx power %d, Po_NOMINAL_PUSCH %d,log10(NPRB) %f,PHR %d, PL %d, alpha*PL %f,delta_IF %f,f_pusch %d\n", - phy_vars_ue->Mod_id,harq_pid,phy_vars_ue->frame_tx,subframe, - phy_vars_ue->ulsch_ue[eNB_id]->Po_PUSCH, - phy_vars_ue->tx_power_max_dBm, - phy_vars_ue->lte_frame_parms.ul_power_control_config_common.p0_NominalPUSCH, + ue->Mod_id,harq_pid,ue->frame_tx,subframe, + ue->ulsch[eNB_id]->Po_PUSCH, + ue->tx_power_max_dBm, + ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH, hundred_times_log10_NPRB[nb_rb-1]/100.0, - phy_vars_ue->ulsch_ue[eNB_id]->PHR, + ue->ulsch[eNB_id]->PHR, PL, - alpha_lut[phy_vars_ue->lte_frame_parms.ul_power_control_config_common.alpha]*PL/100.0, - get_hundred_times_delta_IF(phy_vars_ue,eNB_id,harq_pid)/100.0, - phy_vars_ue->ulsch_ue[eNB_id]->f_pusch); + alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha]*PL/100.0, + get_hundred_times_delta_IF(ue,eNB_id,harq_pid)/100.0, + ue->ulsch[eNB_id]->f_pusch); } } @@ -200,7 +200,7 @@ void pusch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id,u int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id,uint8_t eNB_index) { - return PHY_vars_UE_g[Mod_id][CC_id]->ulsch_ue[eNB_index]->PHR; + return PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->PHR; } // uint8_t eNB_id,uint8_t harq_pid, uint8_t UE_id, @@ -260,7 +260,7 @@ int16_t estimate_ue_tx_power(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, if (control_only == 1 ) beta_offset_pusch_x8=8; // fixme - //(beta_offset_pusch_x8=phy_vars_ue->ulsch_ue[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? phy_vars_ue->ulsch_ue[eNB_id]->beta_offset_cqi_times8:8; + //(beta_offset_pusch_x8=ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? ue->ulsch[eNB_id]->beta_offset_cqi_times8:8; // if deltamcs_enabledm delta_mcs = ((hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch_x8)>>3))/100.0); diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index a6c4eaeb16..65098e975f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -146,8 +146,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, LOG_D(MAC,"UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d) \n",i,rnti,UE_list->UE_sched_ctrl[i].ul_failure_timer); DLSCH_dci = (void *)UE_list->UE_template[CC_id][i].DLSCH_DCI[0]; *(uint32_t*)DLSCH_dci = 0; - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)DLSCH_dci)->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)DLSCH_dci)->rballoc = 31; @@ -175,7 +175,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { // FDD - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)DLSCH_dci)->type = 1; ((DCI1A_1_5MHz_FDD_t*)DLSCH_dci)->rballoc = 31; @@ -361,11 +361,11 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, schedule_RA(module_idP,frameP,subframeP,2); - if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD + if (mac_xface->frame_parms->frame_type == FDD) { //FDD schedule_ulsch(module_idP,frameP,cooperation_flag,0,4);//,calibration_flag); - } else if ((mac_xface->lte_frame_parms->tdd_config == TDD) || //TDD - (mac_xface->lte_frame_parms->tdd_config == 3) || - (mac_xface->lte_frame_parms->tdd_config == 6)) { + } else if ((mac_xface->frame_parms->tdd_config == TDD) || //TDD + (mac_xface->frame_parms->tdd_config == 3) || + (mac_xface->frame_parms->tdd_config == 6)) { //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag); } @@ -378,8 +378,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD, schedule UL for subframeP 7 (TDD config 0,1) / subframeP 8 (TDD Config 6) // FDD, schedule normal UL/DLSCH - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD - switch (mac_xface->lte_frame_parms->tdd_config) { + if (mac_xface->frame_parms->frame_type == TDD) { // TDD + switch (mac_xface->frame_parms->tdd_config) { case 0: case 1: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7); @@ -406,7 +406,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD, nothing // FDD, normal UL/DLSCH - if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD + if (mac_xface->frame_parms->frame_type == FDD) { //FDD schedule_ulsch(module_idP,frameP,cooperation_flag,2,6); schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); @@ -419,8 +419,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 2, ULSCH for subframeP 7 // TDD Config 2/5 normal DLSCH // FDD, normal UL/DLSCH - if (mac_xface->lte_frame_parms->frame_type == TDD) { - switch (mac_xface->lte_frame_parms->tdd_config) { + if (mac_xface->frame_parms->frame_type == TDD) { + switch (mac_xface->frame_parms->tdd_config) { case 2: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7); @@ -447,8 +447,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 1, ULSCH for subframeP 8 // TDD Config 1/2/4/5 DLSCH // FDD UL/DLSCH - if (mac_xface->lte_frame_parms->frame_type == 1) { // TDD - switch (mac_xface->lte_frame_parms->tdd_config) { + if (mac_xface->frame_parms->frame_type == 1) { // TDD + switch (mac_xface->frame_parms->tdd_config) { case 1: // schedule_RA(module_idP,frameP,subframeP); schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8); @@ -470,7 +470,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, break; } } else { - if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD + if (mac_xface->frame_parms->frame_type == FDD) { //FDD schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8); schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status); @@ -488,13 +488,13 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, schedule_SI(module_idP,frameP,subframeP); //schedule_RA(module_idP,frameP,subframeP,5); - if (mac_xface->lte_frame_parms->frame_type == FDD) { + if (mac_xface->frame_parms->frame_type == FDD) { schedule_RA(module_idP,frameP,subframeP,1); schedule_ulsch(module_idP,frameP,cooperation_flag,5,9); schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); - } else if ((mac_xface->lte_frame_parms->tdd_config == 0) || // TDD Config 0 - (mac_xface->lte_frame_parms->tdd_config == 6)) { // TDD Config 6 + } else if ((mac_xface->frame_parms->tdd_config == 0) || // TDD Config 0 + (mac_xface->frame_parms->tdd_config == 6)) { // TDD Config 6 //schedule_ulsch(module_idP,cooperation_flag,subframeP); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } else { @@ -509,8 +509,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 0,1,6 ULSCH for subframes 2,3 // TDD Config 3,4,5 Normal DLSCH // FDD normal ULSCH/DLSCH - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD - switch (mac_xface->lte_frame_parms->tdd_config) { + if (mac_xface->frame_parms->frame_type == TDD) { // TDD + switch (mac_xface->frame_parms->tdd_config) { case 0: break; @@ -553,8 +553,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 3,4,5 Normal DLSCH // FDD Normal UL/DLSCH - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD - switch (mac_xface->lte_frame_parms->tdd_config) { + if (mac_xface->frame_parms->frame_type == TDD) { // TDD + switch (mac_xface->frame_parms->tdd_config) { case 3: case 4: schedule_RA(module_idP,frameP,subframeP,3); // 3 = Msg3 subframeP, not @@ -583,8 +583,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 2,3,4,5 ULSCH for subframeP 2 // // FDD Normal UL/DLSCH - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD - switch (mac_xface->lte_frame_parms->tdd_config) { + if (mac_xface->frame_parms->frame_type == TDD) { // TDD + switch (mac_xface->frame_parms->tdd_config) { case 2: case 3: case 4: @@ -610,8 +610,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, case 9: // TDD Config 1,3,4,6 ULSCH for subframes 3,3,3,4 - if (mac_xface->lte_frame_parms->frame_type == TDD) { - switch (mac_xface->lte_frame_parms->tdd_config) { + if (mac_xface->frame_parms->frame_type == TDD) { + switch (mac_xface->frame_parms->tdd_config) { case 1: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); schedule_RA(module_idP,frameP,subframeP,7); // 7 = Msg3 subframeP, not diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index 3f9872a590..e673a33371 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -115,8 +115,8 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { + switch(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; @@ -126,7 +126,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -140,7 +140,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -154,7 +154,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -168,7 +168,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -182,13 +182,13 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; } } else { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + switch(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; @@ -198,7 +198,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -212,7 +212,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_UL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -226,7 +226,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -240,7 +240,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); break; @@ -307,7 +307,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un /* // randomize frequency allocation for RA while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4)); if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) break; @@ -324,9 +324,9 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un // Compute MCS for 3 PRB msg4_header = 1+6+1; // CR header, CR CE, SDU header - if (mac_xface->lte_frame_parms->frame_type == TDD) { + if (mac_xface->frame_parms->frame_type == TDD) { - switch (mac_xface->lte_frame_parms->N_RB_DL) { + switch (mac_xface->frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; @@ -355,7 +355,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); @@ -391,7 +391,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; @@ -425,7 +425,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); @@ -460,13 +460,13 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; } } else { // FDD DCI - switch (mac_xface->lte_frame_parms->N_RB_DL) { + switch (mac_xface->frame_parms->N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; @@ -496,7 +496,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; @@ -530,7 +530,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; @@ -564,7 +564,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; @@ -597,7 +597,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; @@ -668,7 +668,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un if (round>0) { //RA_template->wait_ack_Msg4++; // we have to schedule a retransmission - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; } else { ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; @@ -677,7 +677,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un /* // randomize frequency allocation for RA while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4)); if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) break; @@ -689,12 +689,12 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un vrb_map[first_rb+2] = 1; vrb_map[first_rb+3] = 1; - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_UL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); } else { - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_UL,first_rb,4); rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index f3774777a1..e24ac2f729 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -113,7 +113,7 @@ schedule_SI( // Allocate 4 PRBs in a random location /* while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL-4)); if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+1] != 1) && (vrb_map[first_rb+2] != 1) && @@ -121,7 +121,7 @@ schedule_SI( break; } */ - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: first_rb = 0; break; @@ -167,11 +167,11 @@ schedule_SI( - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; @@ -186,7 +186,7 @@ schedule_SI( case 25: ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; @@ -201,7 +201,7 @@ schedule_SI( case 50: ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; @@ -216,7 +216,7 @@ schedule_SI( case 100: ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; @@ -231,10 +231,10 @@ schedule_SI( } } else { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; @@ -250,7 +250,7 @@ schedule_SI( case 25: ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; @@ -266,7 +266,7 @@ schedule_SI( case 50: ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; @@ -282,7 +282,7 @@ schedule_SI( case 100: ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL,first_rb,4); ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; @@ -325,7 +325,7 @@ schedule_SI( LOG_D(OPT,"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", module_idP, frameP, CC_id, 0xffff, bcch_sdu_length); } - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { LOG_D(MAC,"[eNB] Frame %d : Scheduling BCCH->DLSCH (TDD) for CC_id %d SI %d bytes (mcs %d, rb 3, TBS %d)\n", frameP, CC_id, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 62422bf9ae..c5415b1d26 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -1527,7 +1527,7 @@ fill_DLSCH_dci( /// Synchronizing rballoc with rballoc_sub - for(i=0; ilte_frame_parms.N_RBG; i++) { + for(i=0; iframe_parms.N_RBG; i++) { rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; } @@ -1539,8 +1539,8 @@ fill_DLSCH_dci( case 2: LOG_D(MAC,"[eNB %d] CC_id %d Adding UE %d spec DCI for %d PRBS \n",module_idP, CC_id, UE_id, nb_rb); - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rah = 0; @@ -1579,7 +1579,7 @@ fill_DLSCH_dci( } else { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + switch(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rah = 0; @@ -1632,8 +1632,8 @@ fill_DLSCH_dci( LOG_D(MAC,"[eNB %d] CC_id %d Adding Format 2A UE %d spec DCI for %d PRBS (rb alloc: %x) \n", module_idP, CC_id, UE_id, nb_rb); - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI2A_1_5MHz_2A_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI2A_1_5MHz_2A_TDD_t*)DLSCH_dci)->rah = 0; @@ -1672,7 +1672,7 @@ fill_DLSCH_dci( } else { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + switch(PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ((DCI2A_1_5MHz_2A_FDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub); ((DCI2A_1_5MHz_2A_FDD_t*)DLSCH_dci)->rah = 0; @@ -1834,7 +1834,7 @@ update_ul_dci( int i; DCI0_5MHz_TDD_1_6_t *ULSCH_dci = NULL;; - if (mac_xface->lte_frame_parms->frame_type == TDD) { + if (mac_xface->frame_parms->frame_type == TDD) { for (i=0; iNum_common_dci+DCI_pdu->Num_ue_spec_dci; i++) { ULSCH_dci = (DCI0_5MHz_TDD_1_6_t *)DCI_pdu->dci_alloc[i].dci_pdu; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c index a6926e15ad..d13c42362c 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c @@ -159,7 +159,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra // Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 switch (subframeP) { case 1: - if (mac_xface->lte_frame_parms->frame_type == FDD) { + if (mac_xface->frame_parms->frame_type == FDD) { if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { if (msi_pos == 1) { msi_flag = 1; @@ -177,7 +177,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra break; case 2: - if (mac_xface->lte_frame_parms->frame_type == FDD) { + if (mac_xface->frame_parms->frame_type == FDD) { if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { if (msi_pos == 2) { msi_flag = 1; @@ -195,7 +195,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra break; case 3: - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD + if (mac_xface->frame_parms->frame_type == TDD) { // TDD if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) { if (msi_pos == 1) { msi_flag = 1; @@ -226,7 +226,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra break; case 4: - if (mac_xface->lte_frame_parms->frame_type == TDD) { + if (mac_xface->frame_parms->frame_type == TDD) { if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) { if (msi_pos == 2) { msi_flag = 1; @@ -244,7 +244,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra break; case 6: - if (mac_xface->lte_frame_parms->frame_type == FDD) { + if (mac_xface->frame_parms->frame_type == FDD) { if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { if (msi_pos == 4) { msi_flag = 1; @@ -262,7 +262,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra break; case 7: - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD + if (mac_xface->frame_parms->frame_type == TDD) { // TDD if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) { if (msi_pos == 3) { msi_flag = 1; @@ -293,7 +293,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra break; case 8: - if (mac_xface->lte_frame_parms->frame_type == TDD) { //TDD + if (mac_xface->frame_parms->frame_type == TDD) { //TDD if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) { if (msi_pos == 4) { msi_flag = 1; @@ -324,7 +324,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra break; case 9: - if (mac_xface->lte_frame_parms->frame_type == TDD) { + if (mac_xface->frame_parms->frame_type == TDD) { if ((eNB_mac_inst[module_idP].common_channels[CC_id].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) { if (msi_pos == 5) { msi_flag = 1; @@ -441,7 +441,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra header_len_mcch = 2; - if (mac_xface->lte_frame_parms->frame_type == TDD) { + if (mac_xface->frame_parms->frame_type == TDD) { LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n", module_idP, CC_id, frameP,subframeP, @@ -473,7 +473,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra } } - TBS = mac_xface->get_TBS_DL(eNB_mac_inst[module_idP].common_channels[CC_id].MCH_pdu.mcs, mac_xface->lte_frame_parms->N_RB_DL); + TBS = mac_xface->get_TBS_DL(eNB_mac_inst[module_idP].common_channels[CC_id].MCH_pdu.mcs, mac_xface->frame_parms->N_RB_DL); #ifdef Rel10 // do not let mcch and mtch multiplexing when relaying is active // for sync area 1, so not transmit data @@ -484,10 +484,10 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra if (mtch_flag == 1) { // Calculate TBS /* if ((msi_flag==1) || (mcch_flag==1)) { - TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->lte_frame_parms->N_RB_DL); + TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->frame_parms->N_RB_DL); } else { // only MTCH in this subframeP - TBS = mac_xface->get_TBS(eNB_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9, mac_xface->lte_frame_parms->N_RB_DL); + TBS = mac_xface->get_TBS(eNB_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9, mac_xface->frame_parms->N_RB_DL); } // get MTCH data from RLC (like for DTCH) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index ece06a5e09..25663bafdb 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -731,7 +731,7 @@ uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, uint32_t *rballoc) uint32_t rballoc_dci=0; unsigned char nb_rb_alloc=0; - for (i=0; i<(mac_xface->lte_frame_parms->N_RB_DL-2); i+=2) { + for (i=0; i<(mac_xface->frame_parms->N_RB_DL-2); i+=2) { if (((*rballoc>>i)&3)==0) { *rballoc |= (3<>1)); @@ -743,10 +743,10 @@ uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, uint32_t *rballoc) } } - if ((mac_xface->lte_frame_parms->N_RB_DL&1)==1) { - if ((*rballoc>>(mac_xface->lte_frame_parms->N_RB_DL-1)&1)==0) { - *rballoc |= (1<<(mac_xface->lte_frame_parms->N_RB_DL-1)); - rballoc_dci |= 1;//(1<<(mac_xface->lte_frame_parms->N_RB_DL>>1)); + if ((mac_xface->frame_parms->N_RB_DL&1)==1) { + if ((*rballoc>>(mac_xface->frame_parms->N_RB_DL-1)&1)==0) { + *rballoc |= (1<<(mac_xface->frame_parms->N_RB_DL-1)); + rballoc_dci |= 1;//(1<<(mac_xface->frame_parms->N_RB_DL>>1)); } } @@ -793,20 +793,20 @@ uint32_t allocate_prbs_sub(int nb_rb, uint8_t *rballoc) //uint8_t number_of_subbands=13; LOG_T(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n", - rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,mac_xface->lte_frame_parms->N_RBG); + rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,mac_xface->frame_parms->N_RBG); - while((nb_rb >0) && (check < mac_xface->lte_frame_parms->N_RBG)) { + while((nb_rb >0) && (check < mac_xface->frame_parms->N_RBG)) { //printf("rballoc[%d] %d\n",check,rballoc[check]); if(rballoc[check] == 1) { - rballoc_dci |= (1<<((mac_xface->lte_frame_parms->N_RBG-1)-check)); + rballoc_dci |= (1<<((mac_xface->frame_parms->N_RBG-1)-check)); - switch (mac_xface->lte_frame_parms->N_RB_DL) { + switch (mac_xface->frame_parms->N_RB_DL) { case 6: nb_rb--; break; case 25: - if ((check == mac_xface->lte_frame_parms->N_RBG-1)) { + if ((check == mac_xface->frame_parms->N_RBG-1)) { nb_rb--; } else { nb_rb-=2; @@ -815,7 +815,7 @@ uint32_t allocate_prbs_sub(int nb_rb, uint8_t *rballoc) break; case 50: - if ((check == mac_xface->lte_frame_parms->N_RBG-1)) { + if ((check == mac_xface->frame_parms->N_RBG-1)) { nb_rb-=2; } else { nb_rb-=3; @@ -846,7 +846,7 @@ int get_nb_subband(void) int nb_sb=0; - switch (mac_xface->lte_frame_parms->N_RB_DL) { + switch (mac_xface->frame_parms->N_RB_DL) { case 6: nb_sb=0; break; diff --git a/openair2/LAYER2/MAC/lte_transport_init.c b/openair2/LAYER2/MAC/lte_transport_init.c index fa446a4aee..43343ad8ee 100755 --- a/openair2/LAYER2/MAC/lte_transport_init.c +++ b/openair2/LAYER2/MAC/lte_transport_init.c @@ -27,9 +27,9 @@ *******************************************************************************/ -#define UL_RB_ALLOC mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL,0,24) -#define BCCH_RB_ALLOC mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL,0,4) -#define RA_RB_ALLOC mac_xface->computeRIV(mac_xface->lte_frame_parms->N_RB_UL,0,4) +#define UL_RB_ALLOC mac_xface->computeRIV(mac_xface->frame_parms->N_RB_UL,0,24) +#define BCCH_RB_ALLOC mac_xface->computeRIV(mac_xface->frame_parms->N_RB_UL,0,4) +#define RA_RB_ALLOC mac_xface->computeRIV(mac_xface->frame_parms->N_RB_UL,0,4) #define DLSCH_RB_ALLOC 0x1fff #include "extern.h" diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index d5a445744d..7480babd24 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -224,8 +224,8 @@ int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, ui RA_template = (RA_TEMPLATE *)&eNB_mac_inst[i].common_channels[CC_id].RA_template[0]; for (j=0; jlte_frame_parms->frame_type == TDD) { - switch (mac_xface->lte_frame_parms->N_RB_DL) { + if (mac_xface->frame_parms->frame_type == TDD) { + switch (mac_xface->frame_parms->N_RB_DL) { case 6: size_bytes1 = sizeof(DCI1A_1_5MHz_TDD_1_6_t); size_bytes2 = sizeof(DCI1A_1_5MHz_TDD_1_6_t); @@ -263,7 +263,7 @@ int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, ui } } else { - switch (mac_xface->lte_frame_parms->N_RB_DL) { + switch (mac_xface->frame_parms->N_RB_DL) { case 6: size_bytes1 = sizeof(DCI1A_1_5MHz_FDD_t); size_bytes2 = sizeof(DCI1A_1_5MHz_FDD_t); @@ -326,7 +326,7 @@ int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, ui //ICIC init param #ifdef ICIC uint8_t SB_size; - SB_size=mac_xface->get_SB_size(mac_xface->lte_frame_parms->N_RB_DL); + SB_size=mac_xface->get_SB_size(mac_xface->frame_parms->N_RB_DL); srand (time(NULL)); @@ -465,7 +465,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui mac_xface->UL_failure_indication = UL_failure_indication; mac_xface->rx_sdu = rx_sdu; mac_xface->get_dlsch_sdu = get_dlsch_sdu; - mac_xface->get_eNB_UE_stats = get_eNB_UE_stats; + mac_xface->get_eNB_UE_stats = get_UE_stats; mac_xface->get_transmission_mode = get_transmission_mode; mac_xface->get_rballoc = get_rballoc; mac_xface->get_nb_rb = conv_nprb; @@ -494,7 +494,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui LOG_I(MAC,"[MAIN] PHY Frame configuration \n"); - mac_xface->lte_frame_parms = frame_parms; + mac_xface->frame_parms = frame_parms; mac_xface->get_ue_active_harq_pid = get_ue_active_harq_pid; mac_xface->get_PL = get_PL; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index d28614699b..a3e2b2699b 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -198,7 +198,7 @@ void assign_rbs_required (module_id_t Mod_id, /* if ((mac_get_rrc_status(Mod_id,1,UE_id) < RRC_RECONFIGURED)){ // If we still don't have a default radio bearer - nb_rbs_required[pCCid][UE_id] = PHY_vars_eNB_g[Mod_id][pCCid]->lte_frame_parms.N_RB_DL; + nb_rbs_required[pCCid][UE_id] = PHY_vars_eNB_g[Mod_id][pCCid]->frame_parms.N_RB_DL; continue; } */ @@ -649,8 +649,8 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, if ((j == N_RBG[CC_id]-1) && - ((PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms.N_RB_DL == 25) || - (PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms.N_RB_DL == 50))) { + ((PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms.N_RB_DL == 25) || + (PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms.N_RB_DL == 50))) { nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit[CC_id]+1; ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit[CC_id]-1; @@ -759,7 +759,7 @@ void dlsch_scheduler_pre_processor_reset (int module_idP, UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; rnti_t rnti = UE_RNTI(module_idP,UE_id); uint8_t *vrb_map = eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map; - int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL/N_RBG; + int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL/N_RBG; #ifdef SF05_LIMIT //int subframe05_limit=0; int sf05_upper=-1,sf05_lower=-1; @@ -776,7 +776,7 @@ void dlsch_scheduler_pre_processor_reset (int module_idP, // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) { case 6: ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; break; diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c index 669077bf4f..7c9c96f01e 100644 --- a/openair2/LAYER2/MAC/ra_procedures.c +++ b/openair2/LAYER2/MAC/ra_procedures.c @@ -252,13 +252,13 @@ void get_prach_resources(module_id_t module_idP, // choose random PRACH resource in TDD if (UE_mac_inst[module_idP].tdd_Config) { - num_prach = mac_xface->get_num_prach_tdd(mac_xface->lte_frame_parms); + num_prach = mac_xface->get_num_prach_tdd(mac_xface->frame_parms); if ((num_prach>0) && (num_prach<6)) { UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index = (taus()%num_prach); } - f_id = mac_xface->get_fid_prach_tdd(mac_xface->lte_frame_parms, + f_id = mac_xface->get_fid_prach_tdd(mac_xface->frame_parms, UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index); } diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index ee6340cb43..1d7e49070b 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -728,7 +728,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 switch (subframe) { case 1: - if (mac_xface->lte_frame_parms->frame_type == FDD) { + if (mac_xface->frame_parms->frame_type == FDD) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { if (msi_pos == 1) { msi_flag = 1; @@ -746,7 +746,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; case 2: - if (mac_xface->lte_frame_parms->frame_type == FDD) { + if (mac_xface->frame_parms->frame_type == FDD) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { if (msi_pos == 2) { msi_flag = 1; @@ -764,7 +764,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; case 3: - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD + if (mac_xface->frame_parms->frame_type == TDD) { // TDD if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) { if (msi_pos == 1) { msi_flag = 1; @@ -795,7 +795,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; case 4: - if (mac_xface->lte_frame_parms->frame_type == TDD) { + if (mac_xface->frame_parms->frame_type == TDD) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) { if (msi_pos == 2) { msi_flag = 1; @@ -813,7 +813,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; case 6: - if (mac_xface->lte_frame_parms->frame_type == FDD) { + if (mac_xface->frame_parms->frame_type == FDD) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { if (msi_pos == 4) { msi_flag = 1; @@ -831,7 +831,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; case 7: - if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD + if (mac_xface->frame_parms->frame_type == TDD) { // TDD if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) { if (msi_pos == 3) { msi_flag = 1; @@ -862,7 +862,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; case 8: - if (mac_xface->lte_frame_parms->frame_type == TDD) { //TDD + if (mac_xface->frame_parms->frame_type == TDD) { //TDD if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) { if (msi_pos == 4) { msi_flag = 1; @@ -893,7 +893,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; case 9: - if (mac_xface->lte_frame_parms->frame_type == TDD) { + if (mac_xface->frame_parms->frame_type == TDD) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) { if (msi_pos == 5) { msi_flag = 1; diff --git a/openair2/PHY_INTERFACE/defs.h b/openair2/PHY_INTERFACE/defs.h index a85c2b15f2..5d933094f3 100755 --- a/openair2/PHY_INTERFACE/defs.h +++ b/openair2/PHY_INTERFACE/defs.h @@ -332,7 +332,7 @@ typedef struct { unsigned char cluster_head_index; /// PHY Frame Configuration - LTE_DL_FRAME_PARMS *lte_frame_parms; + LTE_DL_FRAME_PARMS *frame_parms; uint8_t (*get_prach_prb_offset)(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf); diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c index 01c1ee6ca9..c72c106e0f 100644 --- a/openair2/RRC/LITE/rrc_UE.c +++ b/openair2/RRC/LITE/rrc_UE.c @@ -3467,7 +3467,7 @@ void ue_meas_filtering( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_ UE_rrc_inst[ctxt_pP->module_id].rsrp_db[eNB_offset] = (dB_fixed_times10(mac_xface->get_RSRP(ctxt_pP->module_id,0,eNB_offset))/10.0) - mac_xface->get_rx_total_gain_dB(ctxt_pP->module_id,0) - - dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12); + dB_fixed(mac_xface->frame_parms->N_RB_DL*12); UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[eNB_offset] = (1.0-a)*UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[eNB_offset] + a*UE_rrc_inst[ctxt_pP->module_id].rsrp_db[eNB_offset]; @@ -3478,7 +3478,7 @@ void ue_meas_filtering( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_ LOG_D(RRC,"RSRP_dBm: %3.2f \n",(dB_fixed_times10(mac_xface->get_RSRP(ctxt_pP->module_id,0,eNB_offset))/10.0)); LOG_D(RRC,"gain_loss_dB: %d \n",mac_xface->get_rx_total_gain_dB(ctxt_pP->module_id,0)); - LOG_D(RRC,"gain_fixed_dB: %d \n",dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12)); + LOG_D(RRC,"gain_fixed_dB: %d \n",dB_fixed(mac_xface->frame_parms->N_RB_DL*12)); LOG_D(PHY,"[UE %d] Frame %d, RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB)\n", ctxt_pP->module_id, ctxt_pP->frame, @@ -3736,7 +3736,7 @@ static uint8_t check_trigger_meas_event( TimeToTrigger_t ttt ) { uint8_t eNB_offset; - uint8_t currentCellIndex = mac_xface->lte_frame_parms->Nid_cell; + uint8_t currentCellIndex = mac_xface->frame_parms->Nid_cell; uint8_t tmp_offset; LOG_I(RRC,"[UE %d] ofn(%d) ocn(%d) hys(%d) ofs(%d) ocs(%d) a3_offset(%d) ttt(%d) rssi %3.1f\n", @@ -3769,9 +3769,9 @@ static uint8_t check_trigger_meas_event( LOG_D(RRC,"[UE %d] Frame %d eNB %d: Handover triggered: targetCellId: %d currentCellId: %d eNB_offset: %d rsrp source: %3.1f rsrp target: %3.1f\n", \ ue_mod_idP, frameP, eNB_index, UE_rrc_inst->HandoverInfoUe.targetCellId,ue_cnx_index,eNB_offset, - (dB_fixed_times10(UE_rrc_inst[ue_mod_idP].rsrp_db[0])/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0)-dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12), + (dB_fixed_times10(UE_rrc_inst[ue_mod_idP].rsrp_db[0])/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0)-dB_fixed(mac_xface->frame_parms->N_RB_DL*12), (dB_fixed_times10(UE_rrc_inst[ue_mod_idP].rsrp_db[eNB_offset])/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP, - 0)-dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12)); + 0)-dB_fixed(mac_xface->frame_parms->N_RB_DL*12)); UE_rrc_inst->Info[0].handoverTarget = eNB_offset; //LOG_D(RRC,"PHY_ID: %d \n",UE_rrc_inst->HandoverInfoUe.targetCellId); return 1; diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index 0d7c8f915e..dcc3264828 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -194,7 +194,7 @@ init_SI( eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1 = do_SIB1( ctxt_pP->module_id, CC_id, - mac_xface->lte_frame_parms, + mac_xface->frame_parms, (uint8_t*)eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].SIB1, &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].siblock1, &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib1 @@ -224,7 +224,7 @@ init_SI( eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23 = do_SIB23( ctxt_pP->module_id, CC_id, - mac_xface->lte_frame_parms, + mac_xface->frame_parms, eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].SIB23, &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].systemInformation, &eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2, @@ -390,7 +390,7 @@ init_MCCH( mac_xface->macphy_exit("[RRC][init_MCCH] not enough memory\n"); } else { eNB_rrc_inst[enb_mod_idP].carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] = do_MBSFNAreaConfig(enb_mod_idP, - mac_xface->lte_frame_parms, + mac_xface->frame_parms, sync_area, (uint8_t *)eNB_rrc_inst[enb_mod_idP].carrier[CC_id].MCCH_MESSAGE[sync_area], &eNB_rrc_inst[enb_mod_idP].carrier[CC_id].mcch, @@ -571,7 +571,7 @@ rrc_eNB_ue_context_stmsi_exist( m_tmsiP, mme_codeP, ue_context_p, ue_context_p->ue_context.rnti); if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { - printf("S-TMSI %x, MME %x\n", + printf("=> S-TMSI %x, MME %x\n", ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code); if (ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi == m_tmsiP) @@ -2322,11 +2322,11 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( physicalConfigDedicated2->schedulingRequestConfig->present = SchedulingRequestConfig_PR_setup; physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = ue_context_pP->local_uid; - if (mac_xface->lte_frame_parms->frame_type == 0) { // FDD + if (mac_xface->frame_parms->frame_type == 0) { // FDD physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 5 + (ue_context_pP->local_uid % 10); // Isr = 5 (every 10 subframes, offset=2+UE_id mod3) } else { - switch (mac_xface->lte_frame_parms->tdd_config) { + switch (mac_xface->frame_parms->tdd_config) { case 1: physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7 + (ue_context_pP->local_uid & 1) + (( ue_context_pP->local_uid & 3) >> 1) * 5; // Isr = 5 (every 10 subframes, offset=2 for UE0, 3 for UE1, 7 for UE2, 8 for UE3 , 2 for UE4 etc..) @@ -3299,9 +3299,9 @@ rrc_eNB_generate_RRCConnectionSetup( do_RRCConnectionSetup(ctxt_pP, ue_context_pP, (uint8_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload, - (mac_xface->lte_frame_parms->nb_antennas_tx==2)?2:1, + (mac_xface->frame_parms->nb_antennas_tx==2)?2:1, rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), - mac_xface->lte_frame_parms, + mac_xface->frame_parms, SRB_configList, &ue_context_pP->ue_context.physicalConfigDedicated); @@ -3742,7 +3742,7 @@ rrc_eNB_decode_ccch( if ((ue_context_p = rrc_eNB_ue_context_stmsi_exist(ctxt_pP, mme_code, m_tmsi))) { //#warning "TODO: stmsi_exist: remove UE from MAC/PHY (how?)" - LOG_I(RRC," S-TMSI exists, ue_context_p %p\n",ue_context_p); + LOG_I(RRC," S-TMSI exists, ue_context_p %p, old rnti %x => %x\n",ue_context_p,ue_context_p->ue_context.rnti); stmsi_received=1; ue_context_p->ue_context.rnti = ctxt_pP->rnti; // AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 7234cf4f08..582610c5c2 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -135,19 +135,7 @@ extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; extern int sync_var; -pthread_attr_t attr_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS]; -pthread_attr_t attr_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS]; - -#ifndef LOWLATENCY -struct sched_param sched_param_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS]; -struct sched_param sched_param_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS]; -#endif - -pthread_t main_eNB_thread; -pthread_attr_t attr_dlsch_threads; -#ifndef LOWLATENCY -struct sched_param sched_param_dlsch; -#endif +//pthread_t main_eNB_thread; time_stats_t softmodem_stats_mt; // main thread time_stats_t softmodem_stats_hw; // hw acquisition @@ -171,7 +159,7 @@ static struct { void exit_fun(const char* s); -void init_eNB(void); +void init_eNB(eNB_func_t node_function); void stop_eNB(void); void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) @@ -180,51 +168,51 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) unsigned int aa,slot_offset, slot_offset_F; int dummy_tx_b[7680*4] __attribute__((aligned(32))); int i, tx_offset; - int slot_sizeF = (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)* - ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7); + int slot_sizeF = (phy_vars_eNB->frame_parms.ofdm_symbol_size)* + ((phy_vars_eNB->frame_parms.Ncp==1) ? 6 : 7); int len; slot_offset_F = (subframe<<1)*slot_sizeF; - slot_offset = subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti; + slot_offset = subframe*phy_vars_eNB->frame_parms.samples_per_tti; - if ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_DL)|| - ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_S))) { + if ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_DL)|| + ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_S))) { // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { - if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED) { - PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + if (phy_vars_eNB->frame_parms.Ncp == EXTENDED) { + PHY_ofdm_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F], dummy_tx_b, - phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, + phy_vars_eNB->frame_parms.ofdm_symbol_size, 6, - phy_vars_eNB->lte_frame_parms.nb_prefix_samples, + phy_vars_eNB->frame_parms.nb_prefix_samples, CYCLIC_PREFIX); - PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], - dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1), - phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, + PHY_ofdm_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], + dummy_tx_b+(phy_vars_eNB->frame_parms.samples_per_tti>>1), + phy_vars_eNB->frame_parms.ofdm_symbol_size, 6, - phy_vars_eNB->lte_frame_parms.nb_prefix_samples, + phy_vars_eNB->frame_parms.nb_prefix_samples, CYCLIC_PREFIX); } else { - normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], + normal_prefix_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F], dummy_tx_b, 7, - &(phy_vars_eNB->lte_frame_parms)); + &(phy_vars_eNB->frame_parms)); // if S-subframe generate first slot only - if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_DL) - normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], - dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1), + if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) + normal_prefix_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], + dummy_tx_b+(phy_vars_eNB->frame_parms.samples_per_tti>>1), 7, - &(phy_vars_eNB->lte_frame_parms)); + &(phy_vars_eNB->frame_parms)); } // if S-subframe generate first slot only - if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) - len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1; + if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S) + len = phy_vars_eNB->frame_parms.samples_per_tti>>1; else - len = phy_vars_eNB->lte_frame_parms.samples_per_tti; + len = phy_vars_eNB->frame_parms.samples_per_tti; /* for (i=0;ilte_frame_parms.samples_per_tti; + tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) + tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; - ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_frame_parms,subframe) == SF_S) { + if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S) { for (i=0; ilte_eNB_common_vars.txdata[0][aa][tx_offset++] = 0x00010001; + phy_vars_eNB->common_vars.txdata[0][aa][tx_offset++] = 0x00010001; } } - if ((((phy_vars_eNB->lte_frame_parms.tdd_config==0) || - (phy_vars_eNB->lte_frame_parms.tdd_config==1) || - (phy_vars_eNB->lte_frame_parms.tdd_config==2) || - (phy_vars_eNB->lte_frame_parms.tdd_config==6)) && + if ((((phy_vars_eNB->frame_parms.tdd_config==0) || + (phy_vars_eNB->frame_parms.tdd_config==1) || + (phy_vars_eNB->frame_parms.tdd_config==2) || + (phy_vars_eNB->frame_parms.tdd_config==6)) && (subframe==0)) || (subframe==5)) { // turn on tx switch N_TA_offset before //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset); for (i=0; iN_TA_offset; i++) { tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset/2; if (tx_offset<0) - tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) + tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; - phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset] = 0x00000000; + phy_vars_eNB->common_vars.txdata[0][aa][tx_offset] = 0x00000000; } } } @@ -290,11 +278,11 @@ static void* eNB_thread_tx( void* param ) char tx_time_name[101]; if (opp_enabled == 1) { - snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->subframe); + snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->thread_index); tx_time_file = fopen(tx_time_name,"w"); } // set default return value - eNB_thread_tx_status[proc->subframe] = 0; + eNB_thread_tx_status[proc->thread_index] = 0; MSC_START_USE(); @@ -317,10 +305,10 @@ static void* eNB_thread_tx( void* param ) if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB tx thread: sched_setattr failed\n"); - return &eNB_thread_tx_status[proc->subframe]; + return &eNB_thread_tx_status[proc->thread_index]; } - LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->thread_index, gettid(), sched_getcpu() ); #else //LOW_LATENCY int policy, s, j; @@ -383,7 +371,7 @@ static void* eNB_thread_tx( void* param ) } - LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n", proc->subframe, sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n", proc->thread_index, sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -396,12 +384,13 @@ static void* eNB_thread_tx( void* param ) mlockall(MCL_CURRENT | MCL_FUTURE); + while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->thread_index), 0 ); if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe ); + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->thread_index ); exit_fun("nothing to add"); break; } @@ -413,66 +402,68 @@ static void* eNB_thread_tx( void* param ) } if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe); + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->thread_index); exit_fun("nothing to add"); break; } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->thread_index), 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); - start_meas( &softmodem_stats_tx_sf[proc->subframe] ); - + start_meas( &softmodem_stats_tx_sf[proc->thread_index] ); + if (oai_exit) break; - if (((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD) && - ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_DL) || - (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S))) || - (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD)) { + if (((PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.frame_type == TDD) && + ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_DL) || + (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_S))) || + (PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.frame_type == FDD)) { /* run PHY TX procedures the one after the other for all CCs to avoid race conditions * (may be relaxed in the future for performance reasons) */ - if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe); + if (pthread_mutex_lock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); exit_fun("nothing to add"); break; } /* wait for our turn or oai_exit */ - while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id && !oai_exit) { - pthread_cond_wait(&sync_phy_proc[proc->subframe].cond_phy_proc_tx, - &sync_phy_proc[proc->subframe].mutex_phy_proc_tx); + while (sync_phy_proc[proc->thread_index].phy_proc_CC_id != proc->CC_id && !oai_exit) { + pthread_cond_wait(&sync_phy_proc[proc->thread_index].cond_phy_proc_tx, + &sync_phy_proc[proc->thread_index].mutex_phy_proc_tx); } - if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe); + if (pthread_mutex_unlock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); exit_fun("nothing to add"); } if (oai_exit) break; - - phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); - - /* we're done, let the next one proceed */ - if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe); - exit_fun("nothing to add"); - break; - } - sync_phy_proc[proc->subframe].phy_proc_CC_id++; - sync_phy_proc[proc->subframe].phy_proc_CC_id %= MAX_NUM_CCs; - pthread_cond_broadcast(&sync_phy_proc[proc->subframe].cond_phy_proc_tx); - if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->subframe); - exit_fun("nothing to add"); - break; + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { + phy_procedures_eNB_TX( proc->thread_index, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); + + /* we're done, let the next one proceed */ + if (pthread_mutex_lock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); + exit_fun("nothing to add"); + break; + } + sync_phy_proc[proc->thread_index].phy_proc_CC_id++; + sync_phy_proc[proc->thread_index].phy_proc_CC_id %= MAX_NUM_CCs; + pthread_cond_broadcast(&sync_phy_proc[proc->thread_index].cond_phy_proc_tx); + if (pthread_mutex_unlock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); + exit_fun("nothing to add"); + break; + } } } - do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RCC_IF4) { + do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); /* - short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->lte_eNB_common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.samples_per_tti]; - int i; - for (i=0;iCC_id]->lte_frame_parms.samples_per_tti*2;i+=8) { + short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; + int i; + for (i=0;iCC_id]->frame_parms.samples_per_tti*2;i+=8) { txdata[i] = 2047; txdata[i+1] = 0; txdata[i+2] = 0; @@ -481,10 +472,12 @@ static void* eNB_thread_tx( void* param ) txdata[i+5] = 0; txdata[i+6] = 0; txdata[i+7] = -2047; - } + } */ + } + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe ); + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->thread_index ); exit_fun("nothing to add"); break; } @@ -492,39 +485,56 @@ static void* eNB_thread_tx( void* param ) proc->instance_cnt_tx--; if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->subframe ); + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->thread_index ); exit_fun("nothing to add"); break; } - proc->frame_tx++; - - if (proc->frame_tx==1024) - proc->frame_tx=0; - stop_meas( &softmodem_stats_tx_sf[proc->subframe] ); + stop_meas( &softmodem_stats_tx_sf[proc->thread_index] ); #ifdef LOWLATENCY if (opp_enabled){ - if(softmodem_stats_tx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0); + if(softmodem_stats_tx_sf[proc->thread_index].diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->thread_index].diff_now/cpuf - attr.sched_runtime)/1000000.0); } } #endif - print_meas_now(&softmodem_stats_tx_sf[proc->subframe],"eNB_TX_SF",proc->subframe, tx_time_file); + print_meas_now(&softmodem_stats_tx_sf[proc->thread_index],"eNB_TX_SF",proc->thread_index, tx_time_file); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->thread_index), 0 ); #ifdef DEBUG_THREADS - printf( "Exiting eNB thread TX %d\n", proc->subframe ); + printf( "Exiting eNB thread TX %d\n", proc->thread_index ); #endif - eNB_thread_tx_status[proc->subframe] = 0; - return &eNB_thread_tx_status[proc->subframe]; + eNB_thread_tx_status[proc->thread_index] = 0; + return &eNB_thread_tx_status[proc->thread_index]; } +#if defined(ENABLE_ITTI) +static void wait_system_ready (char *message, volatile int *start_flag) +{ + /* Wait for eNB application initialization to be complete (eNB registration to MME) */ + { + static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", + " ....", " ...", " ..", " .", " " + }; + int i = 0; + + while ((!oai_exit) && (*start_flag == 0)) { + LOG_N(EMU, message, indicator[i]); + fflush(stdout); + i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); + usleep(200000); + } + + LOG_D(EMU,"\n"); + } +} +#endif /*! * \brief The receive thread of eNB. @@ -537,17 +547,19 @@ static void* eNB_thread_rx( void* param ) static int eNB_thread_rx_status[NUM_ENB_THREADS]; eNB_proc_t *proc = (eNB_proc_t*)param; + PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; FILE *rx_time_file = NULL; char rx_time_name[101]; //int i; if (opp_enabled == 1){ - snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf_%d", "eNB", proc->subframe); + snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf_%d", "eNB", proc->thread_index); rx_time_file = fopen(rx_time_name,"w"); } // set default return value - eNB_thread_rx_status[proc->subframe] = 0; + eNB_thread_rx_status[proc->thread_index] = 0; MSC_START_USE(); @@ -570,10 +582,10 @@ static void* eNB_thread_rx( void* param ) if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB RX sched_setattr failed\n"); - return &eNB_thread_rx_status[proc->subframe]; + return &eNB_thread_rx_status[proc->thread_index]; } - LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->thread_index, gettid(), sched_getcpu() ); #else // LOW_LATENCY int policy, s, j; struct sched_param sparam; @@ -640,7 +652,193 @@ static void* eNB_thread_rx( void* param ) } - LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", proc->subframe, sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", proc->thread_index, sched_getcpu(),gettid(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, cpu_affinity); + + +#endif // LOWLATENCY + + mlockall(MCL_CURRENT | MCL_FUTURE); + + + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe of TX and RX threads + printf( "waiting for sync (eNB_thread_rx %d)\n",proc->thread_index); + pthread_mutex_lock( &sync_mutex ); + + while (sync_var<0) + pthread_cond_wait( &sync_cond, &sync_mutex ); + + pthread_mutex_unlock(&sync_mutex); + + printf( "got sync (eNB_thread)\n" ); + +#if defined(ENABLE_ITTI) + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); +#endif + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 1 ); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + start_meas( &softmodem_stats_rx_sf[proc->thread_index] ); + + if (oai_exit) break; + + if ((((fp->frame_type == TDD )&&(subframe_select(fp,proc->subframe_rx)==SF_UL)) || + (fp->frame_type == FDD))) { + // this spawns the prach and TX threads inside and updates the frame and subframe counters + phy_procedures_eNB_common_RX(proc->thread_index, eNB, 0); + if (eNB->node_function != NGFI_RRU_IF4) + // this is the ue-specific processing for the subframe and can be multi-threaded later + phy_procedures_eNB_uespec_RX(proc->thread_index, eNB, 0, no_relay ); + } + + if ((subframe_select(fp,proc->subframe_rx) == SF_S)) { + phy_procedures_eNB_S_RX(proc->thread_index, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); + } + + stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); +#ifdef LOWLATENCY + if (opp_enabled){ + if(softmodem_stats_rx_sf[proc->thread_index].diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->thread_index].diff_now/cpuf - attr.sched_runtime)/1000000.0); + } + } +#endif // LOWLATENCY + print_meas_now(&softmodem_stats_rx_sf[proc->thread_index],"eNB_RX_SF",proc->thread_index, rx_time_file); + } + + //stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 0 ); + + +#ifdef DEBUG_THREADS + printf( "Exiting eNB thread RX %d\n", proc->thread_index ); +#endif + + eNB_thread_rx_status[proc->thread_index] = 0; + return &eNB_thread_rx_status[proc->thread_index]; +} + + + +/*! + * \brief The prach receive thread of eNB. + * \param param is a \ref eNB_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +static void* eNB_thread_prach( void* param ) +{ + static int eNB_thread_prach_status; + + eNB_proc_t *proc = (eNB_proc_t*)param; + PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id]; + // set default return value + eNB_thread_prach_status = 0; + + MSC_START_USE(); + + AssertFatal(proc->thread_index!=0,"Invalid thread index %d for PRACH thread\n",proc->thread_index); + +#ifdef LOWLATENCY + struct sched_attr attr; + unsigned int flags = 0; + uint64_t runtime = 870000 ; + uint64_t deadline = 1 * 1000000; + uint64_t period = 1 * 10000000; // each prach thread has a period of 10ms from the starting point + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0; + + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = runtime; + attr.sched_deadline = deadline; + attr.sched_period = period; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] eNB PRACH sched_setattr failed\n"); + return &eNB_thread_prach_status; + } + + LOG_I( HW, "[SCHED] eNB PRACH deadline thread (TID %ld) started on CPU %d\n", 0, gettid(), sched_getcpu() ); +#else // LOW_LATENCY + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD */ + /* CPU 1 is reserved for all TX threads */ + /* CPU 2..MAX_CPUS is reserved for all RX threads */ + /* Set CPU Affinity only if number of CPUs >2 */ + CPU_ZERO(&cpuset); +#ifdef CPU_AFFINITY + if (get_nprocs() >2) + { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_setaffinity_np"); + exit_fun (" Error setting processor affinity :"); + } + } +#endif //CPU_AFFINITY + /* Check the actual affinity mask assigned to the thread */ + + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror ("pthread_getaffinity_np"); + exit_fun (" Error getting processor affinity :"); + } + memset(cpu_affinity,0, sizeof(cpu_affinity)); + + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) + { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } + + + memset(&sparam, 0 , sizeof (sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + + policy = SCHED_FIFO ; + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) + { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + + memset(&sparam, 0 , sizeof (sparam)); + + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) + { + perror("pthread_getschedparam"); + exit_fun("Error getting thread priority"); + } + + + LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", proc->thread_index, sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -654,83 +852,53 @@ static void* eNB_thread_rx( void* param ) while (!oai_exit) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 ); - - if (pthread_mutex_lock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe ); - exit_fun( "error locking mutex" ); - break; - } - - while (proc->instance_cnt_rx < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_rx is -1 - pthread_cond_wait( &proc->cond_rx, &proc->mutex_rx ); // this unlocks mutex_rx while waiting and then locks it again - } - - if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe ); - exit_fun( "error unlocking mutex" ); - break; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 1 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - start_meas( &softmodem_stats_rx_sf[proc->subframe] ); + if (oai_exit) break; - - if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_UL)) || - (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) { - - phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); - } - - if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx) == SF_S)) { - phy_procedures_eNB_S_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); - } - - if (pthread_mutex_lock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe ); + + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n", proc->thread_index ); exit_fun( "error locking mutex" ); break; } - - proc->instance_cnt_rx--; - - if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe ); + + while (proc->instance_cnt_prach < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_tx is -1 + pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_tx while waiting and then locks it again + } + + if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH proc %d\n", proc->thread_index ); exit_fun( "error unlocking mutex" ); break; } - proc->frame_rx++; - - if (proc->frame_rx==1024) - proc->frame_rx=0; - - stop_meas( &softmodem_stats_rx_sf[proc->subframe] ); -#ifdef LOWLATENCY - if (opp_enabled){ - if(softmodem_stats_rx_sf[proc->subframe].diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->subframe].diff_now/cpuf - attr.sched_runtime)/1000000.0); - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); + prach_procedures(eNB,proc->thread_index,0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); + + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n", proc->thread_index ); + exit_fun( "error locking mutex" ); + break; } -#endif // LOWLATENCY - print_meas_now(&softmodem_stats_rx_sf[proc->subframe],"eNB_RX_SF",proc->subframe, rx_time_file); - } - - //stop_meas( &softmodem_stats_rx_sf[proc->subframe] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 ); - + + proc->instance_cnt_prach--; + + if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->thread_index ); + exit_fun( "error unlocking mutex" ); + break; + } + } #ifdef DEBUG_THREADS - printf( "Exiting eNB thread RX %d\n", proc->subframe ); + printf( "Exiting eNB thread PRACH\n"); #endif - eNB_thread_rx_status[proc->subframe] = 0; - return &eNB_thread_rx_status[proc->subframe]; + eNB_thread_prach_status = 0; + return &eNB_thread_prach_status; } @@ -740,9 +908,14 @@ void init_eNB_proc(void) { int i; int CC_id; + PHY_VARS_eNB *eNB; + eNB_proc_t *proc; for (CC_id=0; CC_idproc[i]; // set the stack size @@ -757,48 +930,41 @@ void init_eNB_proc(void) perror("[ENB_PROC_RX] setting thread stack size failed\n"); */ // set the kernel scheduling policy and priority - sched_param_eNB_proc_tx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&attr_eNB_proc_tx[CC_id][i], &sched_param_eNB_proc_tx[CC_id][i]); - pthread_attr_setschedpolicy (&attr_eNB_proc_tx[CC_id][i], SCHED_FIFO); - sched_param_eNB_proc_rx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&attr_eNB_proc_rx[CC_id][i], &sched_param_eNB_proc_rx[CC_id][i]); - pthread_attr_setschedpolicy (&attr_eNB_proc_rx[CC_id][i], SCHED_FIFO); + proc->sched_param_tx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_tx, &proc->sched_param_tx); + pthread_attr_setschedpolicy (&proc->attr_tx, SCHED_FIFO); + + proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_rx, &proc->sched_param_rx); + pthread_attr_setschedpolicy (&proc->attr_rx, SCHED_FIFO); + + proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); + pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); + printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); #endif - PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx = -1; - PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = -1; - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe = i; - PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id; - pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx, NULL); - pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx, NULL); - pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx, NULL); - pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx, NULL); + proc->instance_cnt_tx = -1; + proc->instance_cnt_prach = -1; + proc->CC_id = CC_id; + pthread_mutex_init( &proc->mutex_tx, NULL); + pthread_cond_init( &proc->cond_tx, NULL); + pthread_cond_init( &proc->cond_prach, NULL); #ifndef LOWLATENCY - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, &attr_eNB_proc_tx[CC_id][i], eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, &attr_eNB_proc_rx[CC_id][i], eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); + pthread_create( &proc->pthread_tx, &proc->attr_tx, eNB_thread_tx, &eNB->proc[i] ); + pthread_create( &proc->pthread_rx, &proc->attr_rx, eNB_thread_rx, &eNB->proc[i] ); + pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc[i] ); #else - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, NULL, eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); - pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, NULL, eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] ); + pthread_create( &proc->pthread_tx, NULL, eNB_thread_tx, &eNB->proc[i] ); + pthread_create( &proc->pthread_rx, NULL, eNB_thread_rx, &eNB->proc[i] ); + pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc[i] ); #endif char name[16]; snprintf( name, sizeof(name), "TX %d", i ); - pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, name ); + pthread_setname_np( proc->pthread_tx, name ); snprintf( name, sizeof(name), "RX %d", i ); - pthread_setname_np( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, name ); - PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0; - PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0; - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_rx = i; - PHY_vars_eNB_g[0][CC_id]->proc[i].subframe_tx = (i+2)%10; + pthread_setname_np( proc->pthread_rx, name ); } - - - - // TX processes subframe +2, RX subframe - // Note this inialization is because the first process awoken for frame 0 is number 1 and so processes 8,9 and 0 have to start with frame 1 - // PHY_vars_eNB_g[0][CC_id]->proc[7].frame_tx = 1; - PHY_vars_eNB_g[0][CC_id]->proc[8].frame_tx = 1; - PHY_vars_eNB_g[0][CC_id]->proc[9].frame_tx = 1; - // PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1; } /* setup PHY proc TX sync mechanism */ @@ -815,22 +981,25 @@ void init_eNB_proc(void) void kill_eNB_proc(void) { int *status; - - for (int CC_id=0; CC_idproc[i]; + #ifdef DEBUG_THREADS printf( "Killing TX CC_id %d thread %d\n", CC_id, i ); #endif - PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx = 0; // FIXME data race! - pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx ); + proc->instance_cnt_tx = 0; // FIXME data race! + pthread_cond_signal( &proc->cond_tx ); pthread_cond_broadcast(&sync_phy_proc[i].cond_phy_proc_tx); #ifdef DEBUG_THREADS printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i ); #endif - int result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, (void**)&status ); + int result = pthread_join( proc->pthread_tx, (void**)&status ); #ifdef DEBUG_THREADS @@ -852,13 +1021,10 @@ void kill_eNB_proc(void) printf( "Killing RX CC_id %d thread %d\n", CC_id, i ); #endif - PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = 0; // FIXME data race! - pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx ); - #ifdef DEBUG_THREADS printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i ); #endif - result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, (void**)&status ); + result = pthread_join( proc->pthread_rx, (void**)&status ); #ifdef DEBUG_THREADS @@ -876,14 +1042,12 @@ void kill_eNB_proc(void) UNUSED(result) #endif - pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx ); - pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx ); - pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx ); - pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx ); + pthread_mutex_destroy( &proc->mutex_tx ); + pthread_cond_destroy( &proc->cond_tx ); } + } } - /* this function maps the phy_vars_eNB tx and rx buffers to the available rf chains. Each rf chain is is addressed by the card number and the chain on the card. The rf_map specifies for each CC, on which rf chain the mapping should start. Multiple @@ -902,7 +1066,7 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c for (CC_id=0; CC_idlte_frame_parms); + frame_parms = &(phy_vars_eNB[CC_id]->frame_parms); printf("setup_eNB_buffers: frame_parms = %p\n",frame_parms); } else { printf("phy_vars_eNB[%d] not initialized\n", CC_id); @@ -929,8 +1093,8 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c for (i=0; inb_antennas_rx; i++) { printf("Mapping eNB CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i]; + free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); + phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i]; if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) { printf("Error with rf_map! A channel has already been allocated!\n"); @@ -941,18 +1105,18 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c openair0_cfg[rf_map[CC_id].card].rx_num_channels++; } - printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); + printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i][j] = 16-j; + printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j]); + phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j] = 16-j; } } for (i=0; inb_antennas_tx; i++) { printf("Mapping eNB CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i]; + free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); + phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i]; if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) { printf("Error with rf_map! A channel has already been allocated!\n"); @@ -963,11 +1127,11 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c openair0_cfg[rf_map[CC_id].card].tx_num_channels++; } - printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); + printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j]); - phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i][j] = 16-j; + printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j]); + phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j] = 16-j; } } @@ -976,20 +1140,20 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); for (i=0; inb_antennas_rx; i++) { - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i]); + free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation - phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory + phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); - printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.rxdata[0][i],rxdata[i],N_TA_offset); + printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset); } for (i=0; inb_antennas_tx; i++) { - free(phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); + free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation - phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i] = txdata[i]; + phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i]; memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); - printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->lte_eNB_common_vars.txdata[0][i]); + printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); } @@ -1000,33 +1164,14 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c } -#if defined(ENABLE_ITTI) -static void wait_system_ready (char *message, volatile int *start_flag) -{ - /* Wait for eNB application initialization to be complete (eNB registration to MME) */ - { - static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", - " ....", " ...", " ..", " .", " " - }; - int i = 0; - while ((!oai_exit) && (*start_flag == 0)) { - LOG_N(EMU, message, indicator[i]); - fflush(stdout); - i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); - usleep(200000); - } - - LOG_D(EMU,"\n"); - } -} -#endif /*! * \brief This is the main eNB thread. * \param arg unused * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ +/* static void* eNB_thread( void* arg ) { UNUSED(arg); @@ -1035,13 +1180,14 @@ static void* eNB_thread( void* arg ) unsigned char slot; // the USRP implementation operates on subframes, not slots // one subframe consists of one even and one odd slot + slot = 1; int spp; int tx_launched = 0; int card=0; - void *rxp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_rx - void *txp[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_tx + void *rxp[2]; // FIXME hard coded array size; indexed by frame_parms.nb_antennas_rx + void *txp[2]; // FIXME hard coded array size; indexed by frame_parms.nb_antennas_tx int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9 @@ -1051,7 +1197,7 @@ static void* eNB_thread( void* arg ) int CC_id=0; struct timespec trx_time0, trx_time1, trx_time2; - /* avoid gcc warnings */ + //avoid gcc warnings (void)trx_time0; (void)trx_time1; (void)trx_time2; @@ -1065,7 +1211,7 @@ static void* eNB_thread( void* arg ) attr.sched_nice = 0; attr.sched_priority = 0; - /* This creates a .2 ms reservation */ + //This creates a .2 ms reservation attr.sched_policy = SCHED_DEADLINE; attr.sched_runtime = (0.3 * 100) * 10000; attr.sched_deadline = (0.9 * 100) * 10000; @@ -1086,8 +1232,8 @@ static void* eNB_thread( void* arg ) char cpu_affinity[1024]; cpu_set_t cpuset; - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ + //Set affinity mask to include CPUs 1 to MAX_CPUS + //CPU 0 is reserved for UHD threads CPU_ZERO(&cpuset); #ifdef CPU_AFFINITY if (get_nprocs() >2) @@ -1104,7 +1250,7 @@ static void* eNB_thread( void* arg ) } #endif // CPU_AFFINITY - /* Check the actual affinity mask assigned to the thread */ + //Check the actual affinity mask assigned to the thread s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); if (s != 0) @@ -1192,7 +1338,7 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame ); tx_launched = 0; - while (rx_pos < ((1+hw_subframe)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti)) { + while (rx_pos < ((1+hw_subframe)*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti)) { unsigned int rxs; #ifndef USRP_DEBUG @@ -1202,12 +1348,12 @@ static void* eNB_thread( void* arg ) clock_gettime( CLOCK_MONOTONIC, &trx_time0 ); - start_meas( &softmodem_stats_hw ); + start_meas( &softmodem_stats_hw ); openair0_timestamp timestamp; int i=0; // prepare rx buffer pointers - for (i=0; ilte_frame_parms.nb_antennas_rx; i++) + for (i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (void*)&rxdata[i][rx_pos]; // check if nsymb_read == spp // map antenna port i to the cc_id. Now use the 1:1 mapping @@ -1215,7 +1361,7 @@ static void* eNB_thread( void* arg ) ×tamp, rxp, spp, - PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx); + PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx); stop_meas( &softmodem_stats_hw ); if (frame > 50) { @@ -1232,7 +1378,7 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers - for (i=0; ilte_frame_parms.nb_antennas_tx; i++) + for (i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void*)&txdata[i][tx_pos]; // if symb_written < spp ==> error if (frame > 50) { @@ -1240,7 +1386,7 @@ static void* eNB_thread( void* arg ) (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance), txp, spp, - PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx, + PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, 1); } @@ -1259,16 +1405,11 @@ static void* eNB_thread( void* arg ) // USRP_DEBUG is active rt_sleep_ns(1000000); #endif - /* FT configurable tx lauch delay (in slots): txlaunch_wait, txlaunch_wait_slotcount is device specific and - set in the corresponding library (with txlaunch_wait=1 and txlaunch_wait_slotcount=1 the check is as it previously was) */ - /* old check: - if ((frame>50) && - (tx_launched == 0) && - (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/ + if ( (frame>50) && (tx_launched == 0) && ((openair0_cfg[card].txlaunch_wait == 0) || ((openair0_cfg[card].txlaunch_wait == 1) && - (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { + (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti>>1))))) { tx_launched = 1; @@ -1339,7 +1480,7 @@ static void* eNB_thread( void* arg ) exit_fun( "error locking mutex_rx" ); break; } - + int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx; pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx ); @@ -1390,6 +1531,7 @@ eNB_thread_cleanup: return &eNB_thread_status; } +*/ void reset_opp_meas(void) { int sfn; @@ -1415,25 +1557,19 @@ void print_opp_meas(void) { } -void init_eNB() { +void init_eNB(eNB_func_t node_function) { - int error_code; - pthread_attr_init (&attr_dlsch_threads); - pthread_attr_setstacksize(&attr_dlsch_threads,4*PTHREAD_STACK_MIN); + int CC_id; -#ifndef LOWLATENCY - 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); - printf("Setting eNB_thread FIFO scheduling policy with priority %d \n", sched_param_dlsch.sched_priority); -#endif + for (CC_id=0;CC_idnode_function = node_function; init_eNB_proc(); sleep(1); LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); - + /* printf("Creating main eNB_thread \n"); error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL ); @@ -1443,16 +1579,19 @@ void init_eNB() { LOG_D( HW, "[lte-softmodem.c] Allocate eNB_thread successful\n" ); pthread_setname_np( main_eNB_thread, "main eNB" ); } + */ } void stop_eNB() { + /* #ifdef DEBUG_THREADS printf("Joining eNB_thread ..."); #endif - int *eNB_thread_status_p; - int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p ); + int *eNB_thread_status_p; + int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p ); + #ifdef DEBUG_THREADS if (result != 0) { @@ -1468,6 +1607,7 @@ void stop_eNB() { #else UNUSED(result); #endif // DEBUG_THREADS + */ printf("Killing eNB processing threads\n"); kill_eNB_proc(); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index e903fd0c9a..26c4a9ae88 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -115,7 +115,7 @@ unsigned short config_frames[4] = {2,9,11,13}; // In lte-enb.c extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); -extern void init_eNB(void); +extern void init_eNB(eNB_func_t); extern void stop_eNB(void); extern void kill_eNB_proc(void); @@ -427,27 +427,27 @@ void reset_stats(FL_OBJECT *button, long arg) for (i=0; idlsch_eNB[i][0]->Mlimit; j++) { - phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0; + for (j=0; jdlsch[i][0]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0; } - phy_vars_eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[k]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0; + phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0; - for (j=0; julsch_eNB[i]->Mlimit; j++) { - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0; - phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0; + for (j=0; julsch[i]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0; } } - phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK_round0=0; - phy_vars_eNB->eNB_UE_stats[i].dlsch_mcs_offset=0; + phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0; + phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0; + phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0; } } @@ -507,7 +507,7 @@ static void *scope_thread(void *arg) ue_cnt=0; for(UE_id=0; UE_iddlsch_eNB[UE_id][0]->rnti>0) && (ue_cntdlsch[UE_id][0]->rnti>0) && (ue_cntUE_scan_carrier = UE_scan_carrier; UE[CC_id]->mode = mode; - compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common, - UE[CC_id]->lte_frame_parms.frame_type, + compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common, + UE[CC_id]->frame_parms.frame_type, UE[CC_id]->X_u); if (UE[CC_id]->mac_enabled == 1) - UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234; + UE[CC_id]->pdcch_vars[0]->crnti = 0x1234; else - UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235; + UE[CC_id]->pdcch_vars[0]->crnti = 0x1235; UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0]; UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; @@ -1398,11 +1399,11 @@ int main( int argc, char **argv ) } } - compute_prach_seq(&PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.prach_config_common, - PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.frame_type, + compute_prach_seq(&PHY_vars_eNB_g[0][CC_id]->frame_parms.prach_config_common, + PHY_vars_eNB_g[0][CC_id]->frame_parms.frame_type, PHY_vars_eNB_g[0][CC_id]->X_u); - PHY_vars_eNB_g[0][CC_id]->rx_total_gain_eNB_dB = (int)rx_gain[CC_id][0]; + PHY_vars_eNB_g[0][CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0]; PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0; @@ -1466,8 +1467,8 @@ int main( int argc, char **argv ) } printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, - ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx), - ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx)); + ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx), + ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); openair0_cfg[card].Mod_id = 0; #ifdef ETHERNET @@ -1484,8 +1485,8 @@ int main( int argc, char **argv ) // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC. // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer - openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx)); - openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx)); + openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx)); + openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); for (i=0; i<4; i++) { @@ -1500,7 +1501,7 @@ int main( int argc, char **argv ) openair0_cfg[card].autocal[i] = 1; openair0_cfg[card].tx_gain[i] = tx_gain[0][i]; if (UE_flag == 0) { - openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_eNB_dB; + openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_dB; } else { openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB; @@ -1650,12 +1651,12 @@ int main( int argc, char **argv ) for (CC_id=0; CC_idsamples_per_tti*10; i++) for (aa=0; aanb_antennas_tx; aa++) - UE[CC_id]->lte_ue_common_vars.txdata[aa][i] = 0x00010001; + UE[CC_id]->common_vars.txdata[aa][i] = 0x00010001; } if (input_fd) { printf("Reading in from file to antenna buffer %d\n",0); - if (fread(UE[0]->lte_ue_common_vars.rxdata[0], + if (fread(UE[0]->common_vars.rxdata[0], sizeof(int32_t), frame_parms[0]->samples_per_tti*10, input_fd) != frame_parms[0]->samples_per_tti*10) @@ -1678,7 +1679,7 @@ int main( int argc, char **argv ) PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0; for (i=0; isamples_per_tti*10; i++) for (aa=0; aanb_antennas_tx; aa++) - PHY_vars_eNB_g[0][CC_id]->lte_eNB_common_vars.txdata[0][aa][i] = 0x00010001; + PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; } } @@ -1751,7 +1752,7 @@ int main( int argc, char **argv ) // start the main thread if (UE_flag == 1) init_UE(); - else init_eNB(); + else init_eNB(node_function); // Sleep to allow all threads to setup sleep(1); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 865f257135..1fc3088598 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -361,7 +361,7 @@ static void *UE_thread_synch(void *arg) openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; #if 0 // UHD 3.8 - switch(UE->lte_frame_parms.N_RB_DL) { + switch(UE->frame_parms.N_RB_DL) { case 6: openair0_cfg[card].rx_gain[i] -= 12; break; @@ -379,7 +379,7 @@ static void *UE_thread_synch(void *arg) break; default: - printf( "Unknown number of RBs %d\n", UE->lte_frame_parms.N_RB_DL ); + printf( "Unknown number of RBs %d\n", UE->frame_parms.N_RB_DL ); break; } #endif @@ -440,7 +440,7 @@ static void *UE_thread_synch(void *arg) openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; // 65 calibrated for USRP B210 @ 2.6 GHz #if 0 // UHD 3.8 - switch(UE->lte_frame_parms.N_RB_DL) { + switch(UE->frame_parms.N_RB_DL) { case 6: openair0_cfg[card].rx_gain[i] -= 12; break; @@ -458,7 +458,7 @@ static void *UE_thread_synch(void *arg) break; default: - printf("Unknown number of RBs %d\n",UE->lte_frame_parms.N_RB_DL); + printf("Unknown number of RBs %d\n",UE->frame_parms.N_RB_DL); break; } #endif @@ -485,7 +485,7 @@ static void *UE_thread_synch(void *arg) LOG_I(PHY,"[UE thread Synch] Running Initial Synch\n"); if (initial_sync( UE, UE->mode ) == 0) { - hw_slot_offset = (UE->rx_offset<<1) / UE->lte_frame_parms.samples_per_tti; + hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti; LOG_I( HW, "Got synch: hw_slot_offset %d\n", hw_slot_offset ); if (UE->UE_scan_carrier == 1) { @@ -493,14 +493,14 @@ static void *UE_thread_synch(void *arg) // rerun with new cell parameters and frequency-offset for (i=0;irx_total_gain_dB;//-USRP_GAIN_OFFSET; - openair0_cfg[0].rx_freq[i] -= UE->lte_ue_common_vars.freq_offset; + openair0_cfg[0].rx_freq[i] -= UE->common_vars.freq_offset; openair0_cfg[0].tx_freq[i] = openair0_cfg[0].rx_freq[i]+uplink_frequency_offset[0][i]; downlink_frequency[0][i] = openair0_cfg[0].rx_freq[i]; freq_offset=0; } // reconfigure for potentially different bandwidth - switch(UE->lte_frame_parms.N_RB_DL) { + switch(UE->frame_parms.N_RB_DL) { case 6: openair0_cfg[0].sample_rate =1.92e6; openair0_cfg[0].rx_bw =.96e6; @@ -531,7 +531,7 @@ static void *UE_thread_synch(void *arg) //openair0.trx_set_gains_func(&openair0,&openair0_cfg[0]); //openair0.trx_stop_func(0); sleep(1); - init_frame_parms(&UE->lte_frame_parms,1); + init_frame_parms(&UE->frame_parms,1); } else { UE->is_synchronized = 1; @@ -540,9 +540,9 @@ static void *UE_thread_synch(void *arg) FILE *fd; if ((UE->frame_rx&1) == 0) { // this guarantees SIB1 is present if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { - fwrite((void*)&UE->lte_ue_common_vars.rxdata[0][0], + fwrite((void*)&UE->common_vars.rxdata[0][0], sizeof(int32_t), - 10*UE->lte_frame_parms.samples_per_tti, + 10*UE->frame_parms.samples_per_tti, fd); LOG_I(PHY,"Dummping Frame ... bye bye \n"); fclose(fd); @@ -578,9 +578,9 @@ static void *UE_thread_synch(void *arg) LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" ); FILE *fd; if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) { - fwrite((void*)&UE->lte_ue_common_vars.rxdata[0][0], + fwrite((void*)&UE->common_vars.rxdata[0][0], sizeof(int32_t), - 10*UE->lte_frame_parms.samples_per_tti, + 10*UE->frame_parms.samples_per_tti, fd); LOG_I(PHY,"Dummping Frame ... bye bye \n"); fclose(fd); @@ -793,12 +793,12 @@ static void *UE_thread_tx(void *arg) } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX, 1 ); - if ((subframe_select( &UE->lte_frame_parms, UE->slot_tx>>1 ) == SF_UL) || - (UE->lte_frame_parms.frame_type == FDD)) { + if ((subframe_select( &UE->frame_parms, UE->slot_tx>>1 ) == SF_UL) || + (UE->frame_parms.frame_type == FDD)) { phy_procedures_UE_TX( UE, 0, 0, UE->mode, no_relay ); } - if ((subframe_select( &UE->lte_frame_parms, UE->slot_tx>>1 ) == SF_S) && + if ((subframe_select( &UE->frame_parms, UE->slot_tx>>1 ) == SF_S) && ((UE->slot_tx&1) == 1)) { phy_procedures_UE_S_TX( UE, 0, 0, no_relay ); } @@ -999,14 +999,14 @@ static void *UE_thread_rx(void *arg) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, 1 ); for (i=0; i<2; i++) { - if ((subframe_select( &UE->lte_frame_parms, UE->slot_rx>>1 ) == SF_DL) || - (UE->lte_frame_parms.frame_type == FDD)) { + if ((subframe_select( &UE->frame_parms, UE->slot_rx>>1 ) == SF_DL) || + (UE->frame_parms.frame_type == FDD)) { /* #ifdef OAI_USRP // this does the adjustments of RX signal amplitude to bring into least 12 significant bits - int slot_length = UE->lte_frame_parms.samples_per_tti>>1; + int slot_length = UE->frame_parms.samples_per_tti>>1; int rx_offset = (UE->slot_rx)*slot_length + UE->rx_offset; - int frame_length = UE->lte_frame_parms.samples_per_tti*10; + int frame_length = UE->frame_parms.samples_per_tti*10; int aa; if (rx_offset > frame_length) rx_offset-=frame_length; @@ -1014,24 +1014,24 @@ static void *UE_thread_rx(void *arg) if (rx_offset >= 0) { if (rx_offset + slot_length < frame_length) - for (aa=0;aalte_frame_parms.nb_antennas_rx;aa++) - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][rx_offset&(~0x3)], + for (aa=0;aaframe_parms.nb_antennas_rx;aa++) + rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], slot_length); else { int diff = rx_offset + slot_length - frame_length; - for (aa=0;aalte_frame_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][rx_offset&(~0x3)], + for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ + rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], slot_length-diff); - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][0], + rescale((int16_t*)&UE->common_vars.rxdata[aa][0], diff); } } } else { - for (aa=0;aalte_frame_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)], + for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ + rescale((int16_t*)&UE->common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)], -rx_offset); - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][0], + rescale((int16_t*)&UE->common_vars.rxdata[aa][0], slot_length+rx_offset); } } @@ -1040,38 +1040,38 @@ static void *UE_thread_rx(void *arg) phy_procedures_UE_RX( UE, 0, 0, UE->mode, no_relay, NULL ); } - if ((subframe_select( &UE->lte_frame_parms, UE->slot_rx>>1 ) == SF_S) && + if ((subframe_select( &UE->frame_parms, UE->slot_rx>>1 ) == SF_S) && ((UE->slot_rx&1) == 0)) { /* #ifdef OAI_USRP // this does the adjustments of RX signal amplitude to bring into least 12 significant bits - int slot_length = UE->lte_frame_parms.samples_per_tti>>1; + int slot_length = UE->frame_parms.samples_per_tti>>1; int rx_offset = (UE->slot_rx)*slot_length + UE->rx_offset; - int frame_length = UE->lte_frame_parms.samples_per_tti*10; + int frame_length = UE->frame_parms.samples_per_tti*10; if (rx_offset > frame_length) rx_offset-=frame_length; int aa; if (rx_offset >= 0) { if (rx_offset + slot_length < frame_length) - for (aa=0;aalte_frame_parms.nb_antennas_rx;aa++) - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][rx_offset&(~0x3)], + for (aa=0;aaframe_parms.nb_antennas_rx;aa++) + rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], slot_length); else { int diff = rx_offset + slot_length - frame_length; - for (aa=0;aalte_frame_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][rx_offset&(~0x3)], + for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ + rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], slot_length-diff); - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][0], + rescale((int16_t*)&UE->common_vars.rxdata[aa][0], diff); } } } else { - for (aa=0;aalte_frame_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)], + for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ + rescale((int16_t*)&UE->common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)], -rx_offset); - rescale((int16_t*)&UE->lte_ue_common_vars.rxdata[aa][0], + rescale((int16_t*)&UE->common_vars.rxdata[aa][0], slot_length+rx_offset); } } @@ -1084,7 +1084,7 @@ static void *UE_thread_rx(void *arg) ret = mac_xface->ue_scheduler(UE->Mod_id, UE->frame_tx, UE->slot_rx>>1, - subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1), + subframe_select(&UE->frame_parms,UE->slot_tx>>1), 0, 0/*FIXME CC_id*/); @@ -1238,15 +1238,15 @@ void *UE_thread(void *arg) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP, dummy_dump ); - while (rxpos < (1+hw_subframe)*UE->lte_frame_parms.samples_per_tti) { + while (rxpos < (1+hw_subframe)*UE->frame_parms.samples_per_tti) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); #ifndef USRP_DEBUG - DevAssert( UE->lte_frame_parms.nb_antennas_rx <= 2 ); + DevAssert( UE->frame_parms.nb_antennas_rx <= 2 ); void* rxp[2]; - for (int i=0; ilte_frame_parms.nb_antennas_rx; i++) + for (int i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rxpos] : (void*)dummy[i]; /* if (dummy_dump == 0) @@ -1257,7 +1257,7 @@ void *UE_thread(void *arg) ×tamp, rxp, spp - ((first_rx==1) ? rx_off_diff : 0), - UE->lte_frame_parms.nb_antennas_rx); + UE->frame_parms.nb_antennas_rx); if (rxs != (spp- ((first_rx==1) ? rx_off_diff : 0))) { printf("rx error: asked %d got %d ",spp - ((first_rx==1) ? rx_off_diff : 0),rxs); @@ -1277,17 +1277,17 @@ void *UE_thread(void *arg) if ((tx_enabled==1) && (UE->mode!=loop_through_memory)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - DevAssert( UE->lte_frame_parms.nb_antennas_tx <= 2 ); + DevAssert( UE->frame_parms.nb_antennas_tx <= 2 ); void* txp[2]; - for (int i=0; ilte_frame_parms.nb_antennas_tx; i++) + for (int i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void*)&txdata[i][txpos]; openair0.trx_write_func(&openair0, (timestamp+openair0_cfg[0].tx_scheduling_advance-openair0_cfg[0].tx_sample_advance), txp, spp - ((first_rx==1) ? rx_off_diff : 0), - UE->lte_frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_tx, 1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); @@ -1305,12 +1305,12 @@ void *UE_thread(void *arg) rxpos += spp; txpos += spp; - if (txpos >= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti) - txpos -= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti; + if (txpos >= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti) + txpos -= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti; } - if (rxpos >= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti) - rxpos -= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti; + if (rxpos >= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti) + rxpos -= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti; if (UE->is_synchronized == 1) { LOG_D( HW, "UE_thread: hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 ); @@ -1353,14 +1353,14 @@ void *UE_thread(void *arg) if (frame == 10) { LOG_D(PHY, "[SCHED][UE] Found cell with N_RB_DL %"PRIu8", PHICH CONFIG (%d,%d), Nid_cell %"PRIu16", NB_ANTENNAS_TX %"PRIu8", frequency offset "PRIi32" Hz, RSSI (digital) %hu dB, measured Gain %d dB, total_rx_gain %"PRIu32" dB, USRP rx gain %f dB\n", - UE->lte_frame_parms.N_RB_DL, - UE->lte_frame_parms.phich_config_common.phich_duration, - UE->lte_frame_parms.phich_config_common.phich_resource, - UE->lte_frame_parms.Nid_cell, - UE->lte_frame_parms.nb_antennas_tx_eNB, - UE->lte_ue_common_vars.freq_offset, - UE->PHY_measurements.rx_power_avg_dB[0], - UE->PHY_measurements.rx_power_avg_dB[0] - rx_input_level_dBm, + UE->frame_parms.N_RB_DL, + UE->frame_parms.phich_config_common.phich_duration, + UE->frame_parms.phich_config_common.phich_resource, + UE->frame_parms.Nid_cell, + UE->frame_parms.nb_antennas_tx_eNB, + UE->common_vars.freq_offset, + UE->measurements.rx_power_avg_dB[0], + UE->measurements.rx_power_avg_dB[0] - rx_input_level_dBm, UE->rx_total_gain_dB, openair0_cfg[0].rx_gain[0] ); @@ -1471,7 +1471,7 @@ void *UE_thread(void *arg) // the UE_thread_synch is ready if (UE->is_synchronized == 1) { rx_off_diff = 0; - LTE_DL_FRAME_PARMS *frame_parms = &UE->lte_frame_parms; // for macro FRAME_LENGTH_COMPLEX_SAMPLES + LTE_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; // for macro FRAME_LENGTH_COMPLEX_SAMPLES // LOG_I(PHY,"UE->rx_offset %d\n",UE->rx_offset); if ((UE->rx_offset > RX_OFF_MAX) && (start_rx_stream == 0)) { @@ -1486,7 +1486,7 @@ void *UE_thread(void *arg) ×tamp, (void**)rxdata, UE->rx_offset, - UE->lte_frame_parms.nb_antennas_rx); + UE->frame_parms.nb_antennas_rx); if (rxs != UE->rx_offset) { exit_fun("problem in rx"); return &UE_thread_retval; @@ -1616,7 +1616,7 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, for (CC_id=0; CC_idlte_frame_parms); + frame_parms = &(phy_vars_ue[CC_id]->frame_parms); } else { printf("phy_vars_UE[%d] not initialized\n", CC_id); return(-1); @@ -1639,20 +1639,20 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, for (i=0; inb_antennas_rx; i++) { printf( "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); - free( phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] ); + free( phy_vars_ue[CC_id]->common_vars.rxdata[i] ); rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); - phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD + phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD } for (i=0; inb_antennas_tx; i++) { printf( "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); - free( phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] ); + free( phy_vars_ue[CC_id]->common_vars.txdata[i] ); txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); - phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = txdata[i]; + phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i]; } - // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[x] - // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[x] + // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x] + // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x] // be careful when releasing memory! // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes) diff --git a/targets/SIMU/USER/init_lte.c b/targets/SIMU/USER/init_lte.c index 861bfa6cbf..583891f1ac 100644 --- a/targets/SIMU/USER/init_lte.c +++ b/targets/SIMU/USER/init_lte.c @@ -59,9 +59,9 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, memset(PHY_vars_eNB,0,sizeof(PHY_VARS_eNB)); PHY_vars_eNB->Mod_id=eNB_id; PHY_vars_eNB->cooperation_flag=cooperation_flag; - memcpy(&(PHY_vars_eNB->lte_frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNB->lte_frame_parms.Nid_cell = ((Nid_cell/3)*3)+((eNB_id+Nid_cell)%3); - PHY_vars_eNB->lte_frame_parms.nushift = PHY_vars_eNB->lte_frame_parms.Nid_cell%6; + memcpy(&(PHY_vars_eNB->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS)); + PHY_vars_eNB->frame_parms.Nid_cell = ((Nid_cell/3)*3)+((eNB_id+Nid_cell)%3); + PHY_vars_eNB->frame_parms.nushift = PHY_vars_eNB->frame_parms.Nid_cell%6; phy_init_lte_eNB(PHY_vars_eNB,0,cooperation_flag,abstraction_flag); LOG_I(PHY,"init eNB: Nid_cell %d\n", frame_parms->Nid_cell); @@ -73,20 +73,20 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, for (i=0; idlsch_eNB[i][j] = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL,abstraction_flag); + PHY_vars_eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL,abstraction_flag); - if (!PHY_vars_eNB->dlsch_eNB[i][j]) { + if (!PHY_vars_eNB->dlsch[i][j]) { LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i); exit(-1); } else { - LOG_D(PHY,"dlsch_eNB[%d][%d] => %p\n",i,j,PHY_vars_eNB->dlsch_eNB[i][j]); - PHY_vars_eNB->dlsch_eNB[i][j]->rnti=0; + LOG_D(PHY,"dlsch[%d][%d] => %p\n",i,j,PHY_vars_eNB->dlsch[i][j]); + PHY_vars_eNB->dlsch[i][j]->rnti=0; } } - PHY_vars_eNB->ulsch_eNB[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,frame_parms->N_RB_UL, abstraction_flag); + PHY_vars_eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,frame_parms->N_RB_UL, abstraction_flag); - if (!PHY_vars_eNB->ulsch_eNB[1+i]) { + if (!PHY_vars_eNB->ulsch[1+i]) { LOG_E(PHY,"Can't get eNB ulsch structures\n"); exit(-1); } @@ -95,45 +95,45 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, // this will be overwritten with the real transmission mode by the RRC once the UE is connected PHY_vars_eNB->transmission_mode[i] = transmission_mode; #ifdef LOCALIZATION - PHY_vars_eNB->ulsch_eNB[1+i]->aggregation_period_ms = 5000; // 5000 milliseconds // could be given as an argument (TBD)) + PHY_vars_eNB->ulsch[1+i]->aggregation_period_ms = 5000; // 5000 milliseconds // could be given as an argument (TBD)) struct timeval ts; gettimeofday(&ts, NULL); - PHY_vars_eNB->ulsch_eNB[1+i]->reference_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000; + PHY_vars_eNB->ulsch[1+i]->reference_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000; int j; for (j=0; j<10; j++) { - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->loc_rss_list[j]); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->loc_rssi_list[j]); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->loc_subcarrier_rss_list[j]); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->loc_timing_advance_list[j]); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->loc_timing_update_list[j]); + initialize(&PHY_vars_eNB->ulsch[1+i]->loc_rss_list[j]); + initialize(&PHY_vars_eNB->ulsch[1+i]->loc_rssi_list[j]); + initialize(&PHY_vars_eNB->ulsch[1+i]->loc_subcarrier_rss_list[j]); + initialize(&PHY_vars_eNB->ulsch[1+i]->loc_timing_advance_list[j]); + initialize(&PHY_vars_eNB->ulsch[1+i]->loc_timing_update_list[j]); } - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->tot_loc_rss_list); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->tot_loc_rssi_list); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->tot_loc_subcarrier_rss_list); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->tot_loc_timing_advance_list); - initialize(&PHY_vars_eNB->ulsch_eNB[1+i]->tot_loc_timing_update_list); + initialize(&PHY_vars_eNB->ulsch[1+i]->tot_loc_rss_list); + initialize(&PHY_vars_eNB->ulsch[1+i]->tot_loc_rssi_list); + initialize(&PHY_vars_eNB->ulsch[1+i]->tot_loc_subcarrier_rss_list); + initialize(&PHY_vars_eNB->ulsch[1+i]->tot_loc_timing_advance_list); + initialize(&PHY_vars_eNB->ulsch[1+i]->tot_loc_timing_update_list); #endif } // ULSCH for RA - PHY_vars_eNB->ulsch_eNB[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, frame_parms->N_RB_UL, abstraction_flag); + PHY_vars_eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, frame_parms->N_RB_UL, abstraction_flag); - if (!PHY_vars_eNB->ulsch_eNB[0]) { + if (!PHY_vars_eNB->ulsch[0]) { LOG_E(PHY,"Can't get eNB ulsch structures\n"); exit(-1); } - PHY_vars_eNB->dlsch_eNB_SI = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag); - LOG_D(PHY,"eNB %d : SI %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_SI); - PHY_vars_eNB->dlsch_eNB_ra = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag); - LOG_D(PHY,"eNB %d : RA %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_ra); - PHY_vars_eNB->dlsch_eNB_MCH = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, 0); - LOG_D(PHY,"eNB %d : MCH %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_MCH); + PHY_vars_eNB->dlsch_SI = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag); + LOG_D(PHY,"eNB %d : SI %p\n",eNB_id,PHY_vars_eNB->dlsch_SI); + PHY_vars_eNB->dlsch_ra = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag); + LOG_D(PHY,"eNB %d : RA %p\n",eNB_id,PHY_vars_eNB->dlsch_ra); + PHY_vars_eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, 0); + LOG_D(PHY,"eNB %d : MCH %p\n",eNB_id,PHY_vars_eNB->dlsch_MCH); - PHY_vars_eNB->rx_total_gain_eNB_dB=130; + PHY_vars_eNB->rx_total_gain_dB=130; for(i=0; imu_mimo_mode[i].dl_pow_off = 2; @@ -146,7 +146,7 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, PHY_vars_eNB->check_for_SUMIMO_transmissions = 0; - PHY_vars_eNB->lte_frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; + PHY_vars_eNB->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; return (PHY_vars_eNB); } @@ -161,38 +161,38 @@ PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms, PHY_VARS_UE* PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); memset(PHY_vars_UE,0,sizeof(PHY_VARS_UE)); PHY_vars_UE->Mod_id=UE_id; - memcpy(&(PHY_vars_UE->lte_frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS)); + memcpy(&(PHY_vars_UE->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS)); phy_init_lte_ue(PHY_vars_UE,1,abstraction_flag); for (i=0; idlsch_ue[i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch[i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); - if (!PHY_vars_UE->dlsch_ue[i][j]) { + if (!PHY_vars_UE->dlsch[i][j]) { LOG_E(PHY,"Can't get ue dlsch structures\n"); exit(-1); } else - LOG_D(PHY,"dlsch_ue[%d][%d] => %p\n",UE_id,i,PHY_vars_UE->dlsch_ue[i][j]); + LOG_D(PHY,"dlsch[%d][%d] => %p\n",UE_id,i,PHY_vars_UE->dlsch[i][j]); } - PHY_vars_UE->ulsch_ue[i] = new_ue_ulsch(frame_parms->N_RB_UL, abstraction_flag); + PHY_vars_UE->ulsch[i] = new_ue_ulsch(frame_parms->N_RB_UL, abstraction_flag); - if (!PHY_vars_UE->ulsch_ue[i]) { + if (!PHY_vars_UE->ulsch[i]) { LOG_E(PHY,"Can't get ue ulsch structures\n"); exit(-1); } - PHY_vars_UE->dlsch_ue_SI[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); - PHY_vars_UE->dlsch_ue_ra[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_SI[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ra[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); PHY_vars_UE->transmission_mode[i] = transmission_mode; } - PHY_vars_UE->lte_frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; + PHY_vars_UE->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; - PHY_vars_UE->dlsch_ue_MCH[0] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL,0); + PHY_vars_UE->dlsch_MCH[0] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL,0); return (PHY_vars_UE); } From 2b6c7a52a071d8cc21302724281a02ac14566a5d Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 27 May 2016 13:33:19 +0200 Subject: [PATCH 012/206] intermediate save to switch machines --- openair1/SCHED/phy_procedures_lte_eNb.c | 32 ++++++++++---- openair2/UTIL/LOG/vcd_signal_dumper.c | 4 ++ openair2/UTIL/LOG/vcd_signal_dumper.h | 4 ++ targets/RT/USER/eNB_usrp.gtkw | 44 ++++++-------------- targets/RT/USER/lte-enb.c | 55 +++++++++++++++++++------ 5 files changed, 87 insertions(+), 52 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index d26980b0f8..9dd3d98e00 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2492,8 +2492,6 @@ void cba_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,in void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { eNB_proc_t *proc = &eNB->proc[thread_id]; - const int subframe = proc->subframe_rx; - const int frame = proc->frame_rx; int i,l; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; void *rxp[fp->nb_antennas_rx]; @@ -2504,15 +2502,18 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_COMMON_RX,1); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,proc->frame_rx, proc->subframe_rx); #endif if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) - for (i=0; inb_antennas_rx; i++) + if ((eNB->node_function == NGFI_RRU_IF4) || (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF and front-end processing - rxp[i] = (void*)&eNB->common_vars.rxdata[i][subframe*fp->samples_per_tti]; + for (i=0; inb_antennas_rx; i++) + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][proc->subframe*fp->samples_per_tti]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); rxs = openair0.trx_read_func(&openair0, &proc->timestamp_rx, rxp, @@ -2520,7 +2521,10 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN fp->nb_antennas_rx); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); + if (frame > 20){ if (rxs != fp->samples_per_tti>>1) exit_fun( "problem receiving samples" ); @@ -2541,6 +2545,17 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN //send_IF4(eNB,subframe<<1); } + for (i=0; inb_antennas_rx; i++) + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][(fp->samples_per_tti>>1)+(subframe*fp->samples_per_tti)]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); + rxs = openair0.trx_read_func(&openair0, + &proc->timestamp_rx, + rxp, + fp->samples_per_tti>>1, + fp->nb_antennas_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); remove_7_5_kHz(eNB,(subframe<<1)+1); for (l=0; lsymbols_per_tti/2; l++) slot_fep_ul(fp, @@ -2568,7 +2583,7 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { + if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) { // wake up thread for PRACH RX if (pthread_mutex_lock(&proc->mutex_prach) != 0) { LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", thread_id, proc->instance_cnt_prach ); @@ -2613,7 +2628,7 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // and proc->subframe_tx = proc->subframe_rx+3 proc->timestamp_tx = proc->timestamp_rx + (fp->samples_per_tti<<1) + (fp->samples_per_tti>>1); proc->frame_tx = (proc->subframe_rx > 6) ? (proc->frame_rx+1) : proc->frame_rx; - proc->subframe_rx = (proc->subframe_rx + 3)%10; + proc->subframe_tx = (proc->subframe_rx + 3)%10; pthread_mutex_unlock( &proc->mutex_tx ); @@ -2850,7 +2865,6 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1], ret); - //compute the expected ULSCH RX power (for the stats) eNB->ulsch[(uint32_t)i]->harq_processes[harq_pid]->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 78e481f3d6..1972993a94 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -77,6 +77,8 @@ struct vcd_module_s { const char* eurecomVariablesNames[] = { "frame_number_TX_eNB", "frame_number_RX_eNB", + "subframe_number_TX_eNB", + "subframe_number_RX_eNB", "runtime_TX_eNB", "runtime_RX_eNB", "frame_number_TX_UE", @@ -226,6 +228,8 @@ const char* eurecomFunctionsNames[] = { "lte_ue_pbch_procedures", "phy_procedures_eNb_tx", "phy_procedures_eNb_rx", + "phy_procedures_eNb_rx_common", + "phy_procedures_eNb_rx_uespec", "phy_procedures_ue_tx", "phy_procedures_ue_rx", "phy_procedures_eNB_lte", diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index a9e4339368..f0a3e70274 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -49,6 +49,8 @@ typedef enum { VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB = 0, VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_UE, @@ -200,6 +202,8 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX, + VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, + VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE, diff --git a/targets/RT/USER/eNB_usrp.gtkw b/targets/RT/USER/eNB_usrp.gtkw index 935bf68b2e..677e214f31 100644 --- a/targets/RT/USER/eNB_usrp.gtkw +++ b/targets/RT/USER/eNB_usrp.gtkw @@ -1,54 +1,36 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sun Apr 10 20:34:38 2016 +[*] Fri May 27 01:34:58 2016 [*] [dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Sun Apr 10 20:26:57 2016" -[dumpfile_size] 181182776 +[dumpfile_mtime] "Fri May 27 01:33:50 2016" +[dumpfile_size] 12743642 [savefile] "/home/papillon/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw" -[timestart] 19787100000 -[size] 1535 876 +[timestart] 10801070000 +[size] 1535 845 [pos] -1 -1 -*-21.793451 19795882832 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +*-21.793451 10817350000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [sst_width] 284 -[signals_width] 238 +[signals_width] 254 [sst_expanded] 1 [sst_vpaned_height] 294 -@24 -variables.hw_frame[63:0] -variables.hw_subframe[63:0] @28 functions.trx_read functions.trx_write @24 -variables.txcnt[63:0] -variables.rxcnt[63:0] variables.trx_ts[63:0] variables.trx_tst[63:0] variables.frame_number_TX_eNB[63:0] variables.frame_number_RX_eNB[63:0] +variables.subframe_number_TX_eNB[63:0] +variables.subframe_number_RX_eNB[63:0] @28 functions.eNB_thread_rx0 functions.eNB_thread_tx0 -functions.eNB_thread_rx1 -functions.eNB_thread_tx1 -functions.eNB_thread_rx2 -functions.eNB_thread_tx2 -functions.eNB_thread_rx3 -functions.eNB_thread_tx3 -functions.eNB_thread_rx4 -functions.eNB_thread_tx4 -functions.eNB_thread_rx5 -functions.eNB_thread_tx5 -functions.eNB_thread_rx6 -functions.eNB_thread_tx6 -functions.eNB_thread_rx7 -functions.eNB_thread_tx7 -functions.eNB_thread_rx8 -functions.eNB_thread_tx8 -functions.eNB_thread_rx9 -functions.eNB_thread_tx9 functions.phy_procedures_eNb_tx +@29 +functions.phy_enb_sfgen +@28 functions.phy_procedures_eNb_rx @24 variables.dci_info[63:0] @@ -64,7 +46,7 @@ functions.macxface_SR_indication @420 variables.ue0_SR_ENERGY[63:0] variables.ue0_SR_THRES[63:0] -@25 +@24 variables.dci_info[63:0] @28 functions.phy_enb_ulsch_decoding0 diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 582610c5c2..1f7d08c13d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -276,6 +276,7 @@ static void* eNB_thread_tx( void* param ) eNB_proc_t *proc = (eNB_proc_t*)param; FILE *tx_time_file = NULL; char tx_time_name[101]; + void *txp[PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx]; if (opp_enabled == 1) { snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->thread_index); @@ -408,7 +409,6 @@ static void* eNB_thread_tx( void* param ) } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->thread_index), 1 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); start_meas( &softmodem_stats_tx_sf[proc->thread_index] ); if (oai_exit) break; @@ -436,6 +436,9 @@ static void* eNB_thread_tx( void* param ) exit_fun("nothing to add"); } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_ENB, proc->subframe_tx ); if (oai_exit) break; if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { @@ -459,7 +462,9 @@ static void* eNB_thread_tx( void* param ) } if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RCC_IF4) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); /* short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; int i; @@ -471,9 +476,30 @@ static void* eNB_thread_tx( void* param ) txdata[i+4] = -2047; txdata[i+5] = 0; txdata[i+6] = 0; - txdata[i+7] = -2047; - } + txdata[i+7] = -2047; } */ + + + // Transmit TX buffer based on timestamp from RX + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + int i; + for (i=0; iframe_parms.nb_antennas_tx; i++) + txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; + // if symb_written < spp ==> error + if (proc->frame_tx > 50) { + openair0.trx_write_func(&openair0, + (proc->timestamp_tx+openair0_cfg[0].tx_sample_advance), + txp, + PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, + PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, + 1); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + } if (pthread_mutex_lock(&proc->mutex_tx) != 0) { @@ -683,23 +709,25 @@ static void* eNB_thread_rx( void* param ) // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 1 ); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); start_meas( &softmodem_stats_rx_sf[proc->thread_index] ); if (oai_exit) break; if ((((fp->frame_type == TDD )&&(subframe_select(fp,proc->subframe_rx)==SF_UL)) || (fp->frame_type == FDD))) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); // this spawns the prach and TX threads inside and updates the frame and subframe counters phy_procedures_eNB_common_RX(proc->thread_index, eNB, 0); - if (eNB->node_function != NGFI_RRU_IF4) + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); + if (eNB->node_function != NGFI_RRU_IF4) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); // this is the ue-specific processing for the subframe and can be multi-threaded later phy_procedures_eNB_uespec_RX(proc->thread_index, eNB, 0, no_relay ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); + } } if ((subframe_select(fp,proc->subframe_rx) == SF_S)) { @@ -714,8 +742,11 @@ static void* eNB_thread_rx( void* param ) } } #endif // LOWLATENCY - print_meas_now(&softmodem_stats_rx_sf[proc->thread_index],"eNB_RX_SF",proc->thread_index, rx_time_file); - } + print_meas_now(&softmodem_stats_rx_sf[proc->thread_index],"eNB_RX_SF",proc->thread_index, rx_time_file); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 0 ); + + + } //stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 0 ); @@ -747,7 +778,7 @@ static void* eNB_thread_prach( void* param ) MSC_START_USE(); - AssertFatal(proc->thread_index!=0,"Invalid thread index %d for PRACH thread\n",proc->thread_index); + AssertFatal(proc->thread_index==0,"Invalid thread index %d for PRACH thread\n",proc->thread_index); #ifdef LOWLATENCY struct sched_attr attr; From e198a7423f2c91fe5e0d3a16b8369a6e41f89b3b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 27 May 2016 10:21:23 -0700 Subject: [PATCH 013/206] updated unitary simulations and corrected bugs in threading and scheduling of L1 procedures. --- openair1/PHY/INIT/defs.h | 31 +- openair1/PHY/INIT/lte_init.c | 10 +- openair1/PHY/INIT/lte_param_init.c | 50 +- openair1/PHY/LTE_ESTIMATION/defs.h | 3 +- openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c | 4 +- .../lte_ul_channel_estimation.c | 5 +- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 14 +- openair1/PHY/LTE_TRANSPORT/phich.c | 15 +- openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c | 6 +- openair1/PHY/LTE_TRANSPORT/pmch.c | 12 +- openair1/PHY/LTE_TRANSPORT/prach.c | 3 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 6 +- openair1/PHY/LTE_TRANSPORT/proto.h | 39 +- openair1/PHY/LTE_TRANSPORT/pucch.c | 8 +- openair1/PHY/LTE_TRANSPORT/ulsch_coding.c | 48 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 10 +- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 15 +- openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c | 60 +- openair1/PHY/TOOLS/lte_phy_scope.c | 2 +- openair1/PHY/TOOLS/time_meas.c | 2 +- openair1/PHY/TOOLS/time_meas.h | 2 +- openair1/PHY/defs.h | 7 +- openair1/SCHED/defs.h | 45 +- openair1/SCHED/phy_mac_stub.c | 44 +- openair1/SCHED/phy_procedures_lte_eNb.c | 299 +++-- openair1/SIMULATION/LTE_PHY/dlsim.c | 1138 ++++++++--------- openair1/SIMULATION/LTE_PHY/pdcchsim.c | 275 ++-- openair1/SIMULATION/LTE_PHY/prachsim.c | 90 +- openair1/SIMULATION/LTE_PHY/pucchsim.c | 118 +- openair1/SIMULATION/LTE_PHY/ulsim.c | 688 +++++----- openair2/LAYER2/MAC/proto.h | 2 +- targets/RT/USER/lte-enb.c | 717 +++-------- 32 files changed, 1660 insertions(+), 2108 deletions(-) diff --git a/openair1/PHY/INIT/defs.h b/openair1/PHY/INIT/defs.h index f08ca678db..f21ea458dd 100644 --- a/openair1/PHY/INIT/defs.h +++ b/openair1/PHY/INIT/defs.h @@ -31,7 +31,7 @@ #include "PHY/defs.h" -#ifdef OPENAIR_LTE + #include "SystemInformationBlockType2.h" //#include "RadioResourceConfigCommonSIB.h" #include "RadioResourceConfigDedicated.h" @@ -41,18 +41,6 @@ #ifdef Rel10 #include "SCellToAddMod-r10.h" #endif -#else - -/** -\fn int phy_init(unsigned char nb_antennas_tx) -\brief Allocate and Initialize the PHY variables after receiving static configuration -@param nb_antennas_tx Number of TX antennas -*/ -int phy_init(unsigned char nb_antennas_tx); -#endif - -#ifdef OPENAIR_LTE - /** @addtogroup _PHY_STRUCTURES_ * @{ */ @@ -325,17 +313,28 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, int CC_id); #endif -#endif + /*! !\fn void phy_cleanup(void) \brief Cleanup the PHY variables*/ void phy_cleanup(void); -#ifdef OPENAIR_LTE + int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf); void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms); -#endif + +void lte_param_init(unsigned char N_tx, + unsigned char N_rx, + unsigned char transmission_mode, + uint8_t extended_prefix_flag, + frame_t frame_type, + uint16_t Nid_cell, + uint8_t tdd_config, + uint8_t N_RB_DL, + uint8_t threequarter_fs, + uint8_t osf, + uint32_t perfect_ce); /** @} */ #endif diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 9787c476a6..5c8a5ec436 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -121,7 +121,7 @@ void phy_config_sib2_eNB(uint8_t Mod_id, //int32_t rx_total_gain_eNB_dB = PHY_vars_eNB_g[Mod_id][CC_id]->rx_total_gain_eNB_dB; int i; - LOG_D(PHY,"[eNB%d] CCid %d Frame %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc[0].frame_tx); + LOG_D(PHY,"[eNB%d] CCid %d Frame %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc.frame_tx); frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; LOG_D(PHY,"prach_config_common.rootSequenceIndex = %d\n",frame_parms->prach_config_common.rootSequenceIndex ); @@ -388,7 +388,7 @@ void phy_config_sib13_eNB(uint8_t Mod_id,int CC_id,int mbsfn_Area_idx, LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; - LOG_I(PHY,"[eNB%d] Frame %d: Applying MBSFN_Area_id %d for index %d\n",Mod_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc[0].frame_tx,mbsfn_AreaId_r9,mbsfn_Area_idx); + LOG_I(PHY,"[eNB%d] Frame %d: Applying MBSFN_Area_id %d for index %d\n",Mod_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc.frame_tx,mbsfn_AreaId_r9,mbsfn_Area_idx); if (mbsfn_Area_idx == 0) { frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; @@ -409,7 +409,7 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB) physicalConfigDedicated = eNB->physicalConfigDedicated[UE_id]; if (physicalConfigDedicated != NULL) { - LOG_I(PHY,"[eNB %d] Frame %d: Sent physicalConfigDedicated=%p for UE %d\n",eNB->Mod_id, eNB->proc[0].frame_tx,physicalConfigDedicated,UE_id); + LOG_I(PHY,"[eNB %d] Frame %d: Sent physicalConfigDedicated=%p for UE %d\n",eNB->Mod_id, eNB->proc.frame_tx,physicalConfigDedicated,UE_id); LOG_D(PHY,"------------------------------------------------------------------------\n"); if (physicalConfigDedicated->pdsch_ConfigDedicated) { @@ -644,7 +644,7 @@ void phy_config_dedicated_eNB(uint8_t Mod_id, int8_t UE_id = find_ue(rnti,eNB); if (UE_id == -1) { - LOG_E( PHY, "[eNB %"PRIu8"] Frame %d: find_ue() returns -1\n", Mod_id, eNB->proc[0].frame_tx ); + LOG_E( PHY, "[eNB %"PRIu8"] Frame %d: find_ue() returns -1\n", Mod_id, eNB->proc.frame_tx ); return; } @@ -653,7 +653,7 @@ void phy_config_dedicated_eNB(uint8_t Mod_id, eNB->physicalConfigDedicated[UE_id] = physicalConfigDedicated; LOG_I(PHY,"phy_config_dedicated_eNB: physicalConfigDedicated=%p\n",physicalConfigDedicated); } else { - LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, eNB->proc[0].frame_tx,UE_id); + LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, eNB->proc.frame_tx,UE_id); return; } diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c index d13b624cfd..0e18537965 100644 --- a/openair1/PHY/INIT/lte_param_init.c +++ b/openair1/PHY/INIT/lte_param_init.c @@ -9,8 +9,8 @@ #include "PHY/defs.h" #include "PHY/extern.h" -extern PHY_VARS_eNB *PHY_vars_eNB; -extern PHY_VARS_UE *PHY_vars_UE; +extern PHY_VARS_eNB *eNB; +extern PHY_VARS_UE *UE; void lte_param_init(unsigned char N_tx, unsigned char N_rx, @@ -30,8 +30,8 @@ void lte_param_init(unsigned char N_tx, printf("Start lte_param_init\n"); - PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); + eNB = malloc(sizeof(PHY_VARS_eNB)); + UE = malloc(sizeof(PHY_VARS_UE)); //PHY_config = malloc(sizeof(PHY_CONFIG)); mac_xface = malloc(sizeof(MAC_xface)); @@ -39,7 +39,7 @@ void lte_param_init(unsigned char N_tx, randominit(0); set_taus_seed(0); - frame_parms = &(PHY_vars_eNB->frame_parms); + frame_parms = &(eNB->frame_parms); frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz frame_parms->N_RB_UL = N_RB_DL; @@ -66,40 +66,40 @@ void lte_param_init(unsigned char N_tx, // phy_init_top(frame_parms); //allocation - PHY_vars_UE->is_secondary_ue = 0; - PHY_vars_UE->frame_parms = *frame_parms; - PHY_vars_eNB->frame_parms = *frame_parms; + UE->is_secondary_ue = 0; + UE->frame_parms = *frame_parms; + eNB->frame_parms = *frame_parms; phy_init_lte_top(frame_parms); dump_frame_parms(frame_parms); - PHY_vars_UE->measurements.n_adj_cells=0; - PHY_vars_UE->measurements.adj_cell_id[0] = Nid_cell+1; - PHY_vars_UE->measurements.adj_cell_id[1] = Nid_cell+2; + UE->measurements.n_adj_cells=0; + UE->measurements.adj_cell_id[0] = Nid_cell+1; + UE->measurements.adj_cell_id[1] = Nid_cell+2; for (i=0; i<3; i++) - lte_gold(frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); + lte_gold(frame_parms,UE->lte_gold_table[i],Nid_cell+i); - phy_init_lte_ue(PHY_vars_UE,1,0); - phy_init_lte_eNB(PHY_vars_eNB,0,0,0); + phy_init_lte_ue(UE,1,0); + phy_init_lte_eNB(eNB,0,0,0); - generate_pcfich_reg_mapping(&PHY_vars_UE->frame_parms); - generate_phich_reg_mapping(&PHY_vars_UE->frame_parms); + generate_pcfich_reg_mapping(&UE->frame_parms); + generate_phich_reg_mapping(&UE->frame_parms); // DL power control init if (transmission_mode == 1) { - PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_eNB->frame_parms).pdsch_config_common).p_b = 0; - PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_UE->frame_parms).pdsch_config_common).p_b = 0; + eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((eNB->frame_parms).pdsch_config_common).p_b = 0; + UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((UE->frame_parms).pdsch_config_common).p_b = 0; } else { // rho_a = rhob - PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_eNB->frame_parms).pdsch_config_common).p_b = 1; - PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_UE->frame_parms).pdsch_config_common).p_b = 1; + eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((eNB->frame_parms).pdsch_config_common).p_b = 1; + UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((UE->frame_parms).pdsch_config_common).p_b = 1; } - PHY_vars_UE->perfect_ce = perfect_ce; + UE->perfect_ce = perfect_ce; printf("Done lte_param_init\n"); diff --git a/openair1/PHY/LTE_ESTIMATION/defs.h b/openair1/PHY/LTE_ESTIMATION/defs.h index c20d24e34f..ebba52670d 100644 --- a/openair1/PHY/LTE_ESTIMATION/defs.h +++ b/openair1/PHY/LTE_ESTIMATION/defs.h @@ -219,7 +219,6 @@ void phy_adjust_gain (PHY_VARS_UE *phy_vars_ue, int lte_ul_channel_estimation(PHY_VARS_eNB *phy_vars_eNB, module_id_t eNB_id, module_id_t UE_id, - uint8_t subframe, uint8_t l, uint8_t Ns, uint8_t cooperation_flag); @@ -242,7 +241,7 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, unsigned char number_of_cards, short coef); -int lte_est_timing_advance_pusch(PHY_VARS_eNB* phy_vars_eNB,module_id_t UE_id,uint8_t subframe); +int lte_est_timing_advance_pusch(PHY_VARS_eNB* phy_vars_eNB,module_id_t UE_id); void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, int subframe, diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c index 7467dd38a5..6980ca358c 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c @@ -195,7 +195,7 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, } -int lte_est_timing_advance_pusch(PHY_VARS_eNB* eNB,uint8_t UE_id,uint8_t thread_id) +int lte_est_timing_advance_pusch(PHY_VARS_eNB* eNB,uint8_t UE_id) { static int first_run=1; static int max_pos_fil2=0; @@ -236,7 +236,7 @@ int lte_est_timing_advance_pusch(PHY_VARS_eNB* eNB,uint8_t UE_id,uint8_t thread_ max_pos_fil2 = ((max_pos_fil2 * coef) + (max_pos * ncoef)) >> 15; #ifdef DEBUG_PHY - LOG_D(PHY,"frame %d: max_pos = %d, max_pos_fil = %d, sync_pos=%d\n",eNB->proc[thread_id].frame_rx,max_pos,max_pos_fil2,sync_pos); + LOG_D(PHY,"frame %d: max_pos = %d, max_pos_fil = %d, sync_pos=%d\n",eNB->proc.frame_rx,max_pos,max_pos_fil2,sync_pos); #endif //DEBUG_PHY return(max_pos_fil2-sync_pos); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 723b143d26..84975c1deb 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -55,7 +55,6 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32 int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, uint8_t eNB_id, uint8_t UE_id, - uint8_t thread_id, unsigned char l, unsigned char Ns, uint8_t cooperation_flag) @@ -68,8 +67,8 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, int32_t **ul_ch_estimates_0= pusch_vars->drs_ch_estimates_0[eNB_id]; int32_t **ul_ch_estimates_1= pusch_vars->drs_ch_estimates_1[eNB_id]; int32_t **rxdataF_ext= pusch_vars->rxdataF_ext[eNB_id]; - int subframe = eNB->proc[thread_id].subframe_rx; - uint8_t harq_pid = subframe2harq_pid(frame_parms,eNB->proc[thread_id].frame_rx,subframe); + int subframe = eNB->proc.subframe_rx; + uint8_t harq_pid = subframe2harq_pid(frame_parms,eNB->proc.frame_rx,subframe); int16_t delta_phase = 0; int16_t *ru1 = ru_90; int16_t *ru2 = ru_90; diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 90c67ed70f..4538deee13 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -2,7 +2,7 @@ OpenAirInterface Copyright(c) 1999 - 2014 Eurecom - OpenAirInterface is free software: you can redistribute it and/or modify + OpenAirInterface is free software: you can redistrirbute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. @@ -7077,12 +7077,11 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, } -int generate_eNB_ulsch_params_from_dci(void *dci_pdu, +int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, + void *dci_pdu, uint16_t rnti, - uint8_t thread_id, DCI_format_t dci_format, uint8_t UE_id, - PHY_VARS_eNB *eNB, uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, @@ -7096,7 +7095,7 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, ANFBmode_t AckNackFBMode = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode; LTE_eNB_ULSCH_t *ulsch=eNB->ulsch[UE_id]; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; - int subframe = eNB->proc[thread_id].subframe_tx; + int subframe = eNB->proc.subframe_tx; uint32_t cqi_req = 0; uint32_t dai = 0; @@ -7117,11 +7116,10 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, harq_pid = subframe2harq_pid(frame_parms, pdcch_alloc2ul_frame(frame_parms, - eNB->proc[thread_id].frame_tx, + eNB->proc.frame_tx, subframe), pdcch_alloc2ul_subframe(frame_parms,subframe)); - // printf("eNB: thread_id %d, subframe %d, frame_tx %d\n",thread_id,subframe,eNB->proc[thread_id].frame_tx); switch (frame_parms->N_RB_DL) { case 6: @@ -7639,7 +7637,7 @@ int generate_eNB_ulsch_params_from_dci(void *dci_pdu, LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d)\n", - eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift); + eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift); diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index e46fb1756a..54564637d6 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -1416,7 +1416,6 @@ void rx_phich(PHY_VARS_UE *ue, } void generate_phich_top(PHY_VARS_eNB *eNB, - unsigned char thread_id, int16_t amp, uint8_t sect_id, uint8_t abstraction_flag) @@ -1432,7 +1431,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, uint8_t pusch_subframe; uint8_t UE_id; uint32_t pusch_frame; - int subframe = eNB->proc[thread_id].subframe_tx; + int subframe = eNB->proc.subframe_tx; // compute Ngroup_PHICH (see formula at beginning of Section 6.9 in 36-211 @@ -1444,7 +1443,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, if (frame_parms->Ncp == 1) NSF_PHICH = 2; - pusch_frame = phich_frame2_pusch_frame(frame_parms,eNB->proc[thread_id].frame_tx,subframe); + pusch_frame = phich_frame2_pusch_frame(frame_parms,eNB->proc.frame_tx,subframe); pusch_subframe = phich_subframe2_pusch_subframe(frame_parms,subframe); harq_pid = subframe2harq_pid(frame_parms,pusch_frame,pusch_subframe); @@ -1453,7 +1452,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, if (ulsch[UE_id]->harq_processes[harq_pid]->phich_active == 1) { LOG_D(PHY,"[eNB][PUSCH %d/%x] Frame %d subframe %d (pusch_subframe %d,pusch_frame %d) phich active %d\n", - harq_pid,ulsch[UE_id]->rnti,eNB->proc[thread_id].frame_tx,subframe,pusch_subframe,pusch_frame,ulsch[UE_id]->harq_processes[harq_pid]->phich_active); + harq_pid,ulsch[UE_id]->rnti,eNB->proc.frame_tx,subframe,pusch_subframe,pusch_frame,ulsch[UE_id]->harq_processes[harq_pid]->phich_active); ngroup_PHICH = (ulsch[UE_id]->harq_processes[harq_pid]->first_rb + ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%Ngroup_PHICH; @@ -1467,7 +1466,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, nseq_PHICH = ((ulsch[UE_id]->harq_processes[harq_pid]->first_rb/Ngroup_PHICH) + ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%(2*NSF_PHICH); LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Generating PHICH, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d dci_alloc %d)\n", - eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx, + eNB->Mod_id,harq_pid,eNB->proc.frame_tx, subframe,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH, ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, ulsch[UE_id]->harq_processes[harq_pid]->first_rb, @@ -1475,7 +1474,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, if (ulsch[UE_id]->Msg3_active == 1) { LOG_D(PHY,"[eNB %d][PUSCH %d][RAPROC] Frame %d, subframe %d: Generating Msg3 PHICH for UE %d, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d\n", - eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe, + eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe, UE_id,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, ulsch[UE_id]->harq_processes[harq_pid]->first_rb); } @@ -1505,7 +1504,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, (ulsch[UE_id]->harq_processes[harq_pid]->rar_alloc == 0) ) { if (ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK==0 ) { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d, subframe %d : PHICH NACK / (no format0 DCI) Setting subframe_scheduling_flag\n", - eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe); + eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe); ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; ulsch[UE_id]->harq_processes[harq_pid]->rvidx = rv_table[ulsch[UE_id]->harq_processes[harq_pid]->round&3]; ulsch[UE_id]->harq_processes[harq_pid]->O_RI = 0; @@ -1515,7 +1514,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, } else { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d PHICH ACK (no format0 DCI) Clearing subframe_scheduling_flag, setting round to 0\n", - eNB->Mod_id,harq_pid,eNB->proc[thread_id].frame_tx,subframe); + eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe); ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; ulsch[UE_id]->harq_processes[harq_pid]->round=0; } diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c index 4e0d6bba02..b32d56f5be 100644 --- a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c +++ b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c @@ -43,13 +43,13 @@ int generate_mbsfn_pilot(PHY_VARS_eNB *eNB, int32_t **txdataF, - int16_t amp, - uint16_t subframe) + int16_t amp) + { LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; uint32_t subframe_offset,Nsymb,samples_per_symbol; - + int subframe = eNB->proc.subframe_tx; if (subframe<0 || subframe>= 10) { diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 56a01b940e..084b2b1793 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -286,11 +286,11 @@ void fill_UE_dlsch_MCH(PHY_VARS_UE *ue,int mcs,int ndi,int rvidx,int eNB_id) } } -void generate_mch(PHY_VARS_eNB *eNB,int thread_id,uint8_t *a,int abstraction_flag) +void generate_mch(PHY_VARS_eNB *eNB,uint8_t *a,int abstraction_flag) { int G; - int subframe = eNB->proc[thread_id].subframe_tx; + int subframe = eNB->proc.subframe_tx; if (abstraction_flag != 0) { if (eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]!=0) @@ -312,18 +312,18 @@ void generate_mch(PHY_VARS_eNB *eNB,int thread_id,uint8_t *a,int abstraction_fla eNB->frame_parms.N_RB_DL, eNB->dlsch_MCH->harq_processes[0]->rb_alloc, get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1, - 2,eNB->proc[thread_id].frame_tx,subframe); + 2,eNB->proc.frame_tx,subframe); generate_mbsfn_pilot(eNB, eNB->common_vars.txdataF[0], - AMP, - subframe); + AMP); + if (dlsch_encoding(a, &eNB->frame_parms, 1, eNB->dlsch_MCH, - eNB->proc[thread_id].frame_tx, + eNB->proc.frame_tx, subframe, &eNB->dlsch_rate_matching_stats, &eNB->dlsch_turbo_encoding_stats, diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index c18982f170..15c7bda045 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1056,7 +1056,6 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 //__m128i mmtmpX0,mmtmpX1,mmtmpX2,mmtmpX3; void rx_prach(PHY_VARS_eNB *eNB, - uint8_t subframe, uint16_t *preamble_energy_list, uint16_t *preamble_delay_list, uint16_t Nf, @@ -1065,7 +1064,7 @@ void rx_prach(PHY_VARS_eNB *eNB, int i; lte_frame_type_t frame_type = eNB->frame_parms.frame_type; - + int subframe = eNB->proc.subframe_rx; uint16_t rootSequenceIndex = eNB->frame_parms.prach_config_common.rootSequenceIndex; uint8_t prach_ConfigIndex = eNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex; uint8_t Ncs_config = eNB->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 9297d91376..829b05530e 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -583,7 +583,7 @@ int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length) for (eNB_id=0; eNB_idproc[0].frame_tx, + eNB->proc.frame_tx, eNB->rx_total_gain_dB, eNB->measurements[eNB_id].n0_power_tot_dBm, eNB->measurements[eNB_id].n0_power_dB[0], @@ -621,9 +621,9 @@ int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length) - len += sprintf(&buffer[len],"Total DLSCH %d kbits / %d frames ",(eNB->total_transmitted_bits/1000),eNB->proc[0].frame_tx+1); + len += sprintf(&buffer[len],"Total DLSCH %d kbits / %d frames ",(eNB->total_transmitted_bits/1000),eNB->proc.frame_tx+1); len += sprintf(&buffer[len],"Total DLSCH throughput %d kbps ",(eNB->total_dlsch_bitrate/1000)); - len += sprintf(&buffer[len],"Total DLSCH trans %d / %d frames\n",success,eNB->proc[0].frame_tx+1); + len += sprintf(&buffer[len],"Total DLSCH trans %d / %d frames\n",success,eNB->proc.frame_tx+1); //len += sprintf(&buffer[len],"[eNB PROC] FULL MU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->FULL_MUMIMO_transmissions,eNB->check_for_total_transmissions); //len += sprintf(&buffer[len],"[eNB PROC] MU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->check_for_MUMIMO_transmissions,eNB->check_for_total_transmissions); //len += sprintf(&buffer[len],"[eNB PROC] SU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->check_for_SUMIMO_transmissions,eNB->check_for_total_transmissions); diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 6b10a115df..fc9e800760 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -228,12 +228,11 @@ int mch_modulation(int32_t **txdataF, /** \brief Top-level generation function for eNB TX of MBSFN @param phy_vars_eNB Pointer to eNB variables - @param subframe Subframe for PMCH @param a Pointer to transport block @param abstraction_flag */ -void generate_mch(PHY_VARS_eNB *phy_vars_eNB,int subframe,uint8_t *a,int abstraction_flag); +void generate_mch(PHY_VARS_eNB *phy_vars_eNB,uint8_t *a,int abstraction_flag); /** \brief This function generates the frequency-domain pilots (cell-specific downlink reference signals) @param phy_vars_eNB Pointer to eNB variables @@ -301,8 +300,7 @@ int32_t generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, int32_t generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB, int32_t **txdataF, - int16_t amp, - uint16_t subframe); + int16_t amp); int32_t generate_pss(int32_t **txdataF, int16_t amp, @@ -1409,27 +1407,26 @@ int32_t generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id); double sinr_eff_cqi_calc(PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id); -int generate_eNB_ulsch_params_from_dci(void *dci_pdu, +int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB, + void *dci_pdu, rnti_t rnti, - uint8_t subframe, - DCI_format_t dci_format, + DCI_format_t dci_format, uint8_t UE_id, - PHY_VARS_eNB *PHY_vars_eNB, - uint16_t si_rnti, + uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, uint16_t cba_rnti, uint8_t use_srs); -#ifdef USER_MODE -void dump_ulsch(PHY_VARS_eNB *phy_vars_eNb,uint8_t subframe, uint8_t UE_id); + +void dump_ulsch(PHY_VARS_eNB *phy_vars_eNb,uint8_t UE_id); void dump_dlsch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); void dump_dlsch2(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int round); -#endif + int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci); @@ -1477,14 +1474,12 @@ void generate_RIV_tables(void); int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode); void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, - uint32_t subframe, uint8_t eNB_id, // this is the effective sector id uint8_t UE_id, LTE_eNB_ULSCH_t **ulsch, uint8_t cooperation_flag); void rx_ulsch_emul(PHY_VARS_eNB *phy_vars_eNB, - uint8_t subframe, uint8_t sect_id, uint8_t UE_index); @@ -1532,18 +1527,15 @@ int32_t ulsch_encoding_emul(uint8_t *ulsch_buffer, */ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, uint8_t UE_id, - uint8_t subframe, uint8_t control_only_flag, uint8_t Nbundled, uint8_t llr8_flag); uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, - uint8_t subframe, uint8_t UE_index, uint16_t *crnti); void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, - uint8_t subframe, int16_t amp, uint8_t sect_id, uint8_t abstraction_flag); @@ -1671,11 +1663,11 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, uint8_t pucch1_thres); int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, - uint8_t UE_index, - PUCCH_FMT_t fmt, - uint8_t n1_pucch_sel, - uint8_t *payload, - uint8_t subframe); + uint8_t UE_index, + PUCCH_FMT_t fmt, + uint8_t n1_pucch_sel, + uint8_t *payload); + /*! @@ -1702,7 +1694,6 @@ int32_t generate_prach(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe, /*! \brief Process PRACH waveform @param phy_vars_eNB Pointer to eNB top-level descriptor - @param subframe subframe index to operate on @param preamble_energy_list List of energies for each candidate preamble @param preamble_delay_list List of delays for each candidate preamble @param Nf System frame number @@ -1710,7 +1701,7 @@ int32_t generate_prach(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe, @returns 0 on success */ -void rx_prach(PHY_VARS_eNB *phy_vars_eNB,uint8_t subframe,uint16_t *preamble_energy_list, uint16_t *preamble_delay_list, uint16_t Nf, uint8_t tdd_mapindex); +void rx_prach(PHY_VARS_eNB *phy_vars_eNB,uint16_t *preamble_energy_list, uint16_t *preamble_delay_list, uint16_t Nf, uint8_t tdd_mapindex); /*! \brief Helper for MAC, returns number of available PRACH in TDD for a particular configuration index diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 75ebcdfbfe..547a0f2217 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -1067,12 +1067,12 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *eNB, uint8_t UE_index, PUCCH_FMT_t fmt, uint8_t n1_pucch_sel, - uint8_t *payload, - uint8_t thread_id) + uint8_t *payload) + { uint8_t UE_id; uint16_t rnti; - int subframe = eNB->proc[thread_id].subframe_rx; + int subframe = eNB->proc.subframe_rx; uint8_t CC_id = eNB->CC_id; rnti = eNB->ulsch[UE_index]->rnti; @@ -1095,7 +1095,7 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *eNB, payload[0] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[0]; payload[1] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[1]; } else - LOG_E(PHY,"[eNB] Frame %d: Can't handle formats 2/2a/2b\n",eNB->proc[thread_id].frame_rx); + LOG_E(PHY,"[eNB] Frame %d: Can't handle formats 2/2a/2b\n",eNB->proc.frame_rx); if (PHY_vars_UE_g[UE_id][CC_id]->pucch_sel[subframe] == n1_pucch_sel) return(99); diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c index 4e45a856bd..035b3bce61 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c @@ -70,35 +70,35 @@ void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) if (ulsch) { #ifdef DEBUG_ULSCH_FREE - msg("Freeing ulsch %p\n",ulsch); + printf("Freeing ulsch %p\n",ulsch); #endif for (i=0; i<8; i++) { #ifdef DEBUG_ULSCH_FREE - msg("Freeing ulsch process %d\n",i); + printf("Freeing ulsch process %d\n",i); #endif if (ulsch->harq_processes[i]) { #ifdef DEBUG_ULSCH_FREE - msg("Freeing ulsch process %d (%p)\n",i,ulsch->harq_processes[i]); + printf("Freeing ulsch process %d (%p)\n",i,ulsch->harq_processes[i]); #endif if (ulsch->harq_processes[i]->b) { free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); ulsch->harq_processes[i]->b = NULL; #ifdef DEBUG_ULSCH_FREE - msg("Freeing ulsch process %d b (%p)\n",i,ulsch->harq_processes[i]->b); + printf("Freeing ulsch process %d b (%p)\n",i,ulsch->harq_processes[i]->b); #endif } #ifdef DEBUG_ULSCH_FREE - msg("Freeing ulsch process %d c (%p)\n",i,ulsch->harq_processes[i]->c); + printf("Freeing ulsch process %d c (%p)\n",i,ulsch->harq_processes[i]->c); #endif for (r=0; rharq_processes[i]->c[r]); + printf("Freeing ulsch process %d c[%d] (%p)\n",i,r,ulsch->harq_processes[i]->c[r]); #endif if (ulsch->harq_processes[i]->c[r]) { @@ -302,7 +302,7 @@ uint32_t ulsch_encoding(uint8_t *a, ulsch->harq_processes[harq_pid]->control_only = 0; #ifdef DEBUG_ULSCH_CODING - msg("[PHY][UE] ULSCH coding : A %d, Qm %d, mcs %d, harq_pid %d, round %d, RV %d\n", + printf("[PHY][UE] ULSCH coding : A %d, Qm %d, mcs %d, harq_pid %d, round %d, RV %d\n", ulsch->harq_processes[harq_pid]->TBS, Q_m, ulsch->harq_processes[harq_pid]->mcs, @@ -311,16 +311,16 @@ uint32_t ulsch_encoding(uint8_t *a, ulsch->harq_processes[harq_pid]->rvidx); for (i=0; iharq_processes[harq_pid]->O_ACK; i++) - msg("ulsch_coding: o_ACK[%d] %d\n",i,ulsch->o_ACK[i]); + printf("ulsch_coding: o_ACK[%d] %d\n",i,ulsch->o_ACK[i]); for (i=0; iO_RI; i++) - msg("ulsch_coding: o_RI[%d] %d\n",i,ulsch->o_RI[i]); + printf("ulsch_coding: o_RI[%d] %d\n",i,ulsch->o_RI[i]); - msg("ulsch_coding: O=%d\n",ulsch->O); + printf("ulsch_coding: O=%d\n",ulsch->O); for (i=0; i<1+((8+ulsch->O)/8); i++) { // ulsch->o[i] = i; - msg("ulsch_coding: O[%d] %d\n",i,ulsch->o[i]); + printf("ulsch_coding: O[%d] %d\n",i,ulsch->o[i]); } if ((tmode != 4)) @@ -380,20 +380,20 @@ uint32_t ulsch_encoding(uint8_t *a, #ifdef DEBUG_ULSCH_CODING - msg("Generating Code Segment %d (%d bits)\n",r,Kr); + printf("Generating Code Segment %d (%d bits)\n",r,Kr); // generate codewords - msg("bits_per_codeword (Kr)= %d\n",Kr); - msg("N_RB = %d\n",ulsch->harq_processes[harq_pid]->nb_rb); - msg("Ncp %d\n",frame_parms->Ncp); - msg("Qm %d\n",Q_m); + printf("bits_per_codeword (Kr)= %d\n",Kr); + printf("N_RB = %d\n",ulsch->harq_processes[harq_pid]->nb_rb); + printf("Ncp %d\n",frame_parms->Ncp); + printf("Qm %d\n",Q_m); #endif // offset=0; #ifdef DEBUG_ULSCH_CODING - msg("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]); + printf("Encoding ... iind %d f1 %d, f2 %d\n",iind,f1f2mat_old[iind*2],f1f2mat_old[(iind*2)+1]); #endif start_meas(te_stats); threegpplte_turbo_encoder(ulsch->harq_processes[harq_pid]->c[r], @@ -526,7 +526,7 @@ uint32_t ulsch_encoding(uint8_t *a, for (r=0; rharq_processes[harq_pid]->C; r++) { #ifdef DEBUG_ULSCH_CODING - msg("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", + printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", r, G, Kr*3, @@ -633,7 +633,7 @@ uint32_t ulsch_encoding(uint8_t *a, // Do ACK coding, Section 5.2.2.6 36.213 (p.23-24 in v8.6) wACK_idx = (ulsch->bundling==0) ? 4 : ((Nbundled-1)&3); #ifdef DEBUG_ULSCH_CODING - msg("ulsch_coding.c: Bundling %d, Nbundled %d, wACK_idx %d\n", + printf("ulsch_coding.c: Bundling %d, Nbundled %d, wACK_idx %d\n", ulsch->bundling,Nbundled,wACK_idx); #endif @@ -865,7 +865,7 @@ uint32_t ulsch_encoding(uint8_t *a, for (q=0; qq_ACK[(q+(Q_m*i))%len_ACK]; #ifdef DEBUG_ULSCH_CODING - msg("ulsch_coding.c: ACK %d => y[%d]=%d (i %d, r*Cmux %d, columnset %d)\n",q+(Q_m*i), + printf("ulsch_coding.c: ACK %d => y[%d]=%d (i %d, r*Cmux %d, columnset %d)\n",q+(Q_m*i), q+(Q_m*((r*Cmux) + columnset[j])),ulsch->q_ACK[(q+(Q_m*i))%len_ACK], i,r*Cmux,columnset[j]); #endif @@ -965,7 +965,7 @@ int ulsch_encoding_emul(uint8_t *ulsch_buffer, // print_CQI(ulsch->o,ulsch->uci_format,eNB_id); // save PUSCH pmi for later (transmission modes 4,5,6) - // msg("ulsch: saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi)); + // printf("ulsch: saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi)); // if (ulsch->uci_format != HLC_subband_cqi_mcs_CBA) dlsch[0]->harq_processes[harq_pid]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi; } @@ -986,20 +986,20 @@ int ulsch_encoding_emul(uint8_t *ulsch_buffer, UE_transport_info[ue->Mod_id][ue->CC_id].eNB_id[0] = eNB_id; UE_transport_info[ue->Mod_id][ue->CC_id].harq_pid[0] = harq_pid; UE_transport_info[ue->Mod_id][ue->CC_id].tbs[0] = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3 ; - // msg("\nue->Mod_id%d\n",ue->Mod_id); + // printf("\nue->Mod_id%d\n",ue->Mod_id); UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_flag = 1; //UE_transport_info[ue->Mod_id].cntl.pusch_uci = *(uint32_t *)ulsch->o; memcpy(UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_uci, ulsch->o, MAX_CQI_BYTES); - // msg("[UE]cqi is %d \n", ((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1); + // printf("[UE]cqi is %d \n", ((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1); UE_transport_info[ue->Mod_id][ue->CC_id].cntl.length_uci = ulsch->O; UE_transport_info[ue->Mod_id][ue->CC_id].cntl.uci_format = ulsch->uci_format; UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_ri = (ulsch->o_RI[0]&1)+((ulsch->o_RI[1]&1)<<1); UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pusch_ack = (ulsch->o_ACK[0]&1) + ((ulsch->o_ACK[1]&1)<<1); - //msg("ack is %d %d %d\n",UE_transport_info[ue->Mod_id].cntl.pusch_ack, (ulsch->o_ACK[1]&1)<<1, ulsch->o_ACK[0]&1); + //printf("ack is %d %d %d\n",UE_transport_info[ue->Mod_id].cntl.pusch_ack, (ulsch->o_ACK[1]&1)<<1, ulsch->o_ACK[0]&1); return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 4a6bfa5f52..0850836b36 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -220,7 +220,6 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, uint8_t UE_id, - uint8_t thread_id, uint8_t control_only_flag, uint8_t Nbundled, uint8_t llr8_flag) @@ -260,7 +259,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, int16_t cseq[6*14*1200]; int off; int status[20]; - int subframe = eNB->proc[thread_id].subframe_rx; + int subframe = eNB->proc.subframe_rx; LTE_UL_eNB_HARQ_t *ulsch_harq; uint8_t (*tc)(int16_t *y, @@ -279,7 +278,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, time_stats_t *, time_stats_t *); - harq_pid = subframe2harq_pid(frame_parms,eNB->proc[thread_id].frame_rx,subframe); + harq_pid = subframe2harq_pid(frame_parms,eNB->proc.frame_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1); @@ -1501,18 +1500,17 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb #endif uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, - uint8_t thread_id, uint8_t UE_index, uint16_t *crnti) { uint8_t UE_id; uint16_t rnti; - int subframe = eNB->proc[thread_id].subframe_rx; + int subframe = eNB->proc.subframe_rx; uint8_t harq_pid; uint8_t CC_id = eNB->CC_id; - harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc[thread_id].frame_rx,subframe); + harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc.frame_rx,subframe); rnti = eNB->ulsch[UE_index]->rnti; #ifdef DEBUG_PHY diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 87c21b6a6b..53cab326f1 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1577,7 +1577,6 @@ int32_t avgU[2]; int32_t avgU_0[2],avgU_1[2]; // For the Distributed Alamouti Scheme void rx_ulsch(PHY_VARS_eNB *eNB, - uint32_t thread_id, uint8_t eNB_id, // this is the effective sector id uint8_t UE_id, LTE_eNB_ULSCH_t **ulsch, @@ -1603,9 +1602,9 @@ void rx_ulsch(PHY_VARS_eNB *eNB, uint8_t Qm; uint16_t rx_power_correction; int16_t *llrp; - int subframe = eNB->proc[thread_id].subframe_rx; + int subframe = eNB->proc.subframe_rx; - harq_pid = subframe2harq_pid(frame_parms,eNB->proc[thread_id].frame_rx,subframe); + harq_pid = subframe2harq_pid(frame_parms,eNB->proc.frame_rx,subframe); Qm = get_Qm_ul(ulsch[UE_id]->harq_processes[harq_pid]->mcs); #ifdef DEBUG_ULSCH msg("rx_ulsch: eNB_id %d, harq_pid %d, nb_rb %d first_rb %d, cooperation %d\n",eNB_id,harq_pid,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,ulsch[UE_id]->harq_processes[harq_pid]->first_rb, @@ -1640,7 +1639,6 @@ void rx_ulsch(PHY_VARS_eNB *eNB, lte_ul_channel_estimation(eNB, eNB_id, UE_id, - thread_id, l%(frame_parms->symbols_per_tti/2), l/(frame_parms->symbols_per_tti/2), cooperation_flag); @@ -1887,25 +1885,24 @@ void rx_ulsch(PHY_VARS_eNB *eNB, } void rx_ulsch_emul(PHY_VARS_eNB *eNB, - uint8_t subframe, uint8_t sect_id, uint8_t UE_index) { - msg("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",eNB->Mod_id,subframe,sect_id,UE_index); + msg("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",eNB->Mod_id,eNB->proc.subframe_rx,sect_id,UE_index); eNB->pusch_vars[UE_index]->ulsch_power[0] = 31622; //=45dB; eNB->pusch_vars[UE_index]->ulsch_power[1] = 31622; //=45dB; } -void dump_ulsch(PHY_VARS_eNB *eNB,uint8_t thread_id, uint8_t UE_id) +void dump_ulsch(PHY_VARS_eNB *eNB,uint8_t UE_id) { uint32_t nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; uint8_t harq_pid; - int subframe = eNB->proc[thread_id].subframe_rx; + int subframe = eNB->proc.subframe_rx; - harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc[thread_id].frame_rx,subframe); + harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc.frame_rx,subframe); printf("Dumping ULSCH in subframe %d with harq_pid %d, for NB_rb %d, mcs %d, Qm %d, N_symb %d\n", subframe,harq_pid,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,get_Qm_ul(eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs), diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c index b4f7f02480..32d3f3e34d 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c @@ -45,7 +45,7 @@ #include "defs.h" #include "UTIL/LOG/vcd_signal_dumper.h" -//#define OFDMA_ULSCH + //#define DEBUG_ULSCH_MODULATION @@ -72,7 +72,7 @@ void dft_lte(int32_t *z,int32_t *d, int32_t Msc_PUSCH, uint8_t Nsymb) #elif defined(__arm__) int16x8_t norm128; #endif - // msg("Doing lte_dft for Msc_PUSCH %d\n",Msc_PUSCH); + // printf("Doing lte_dft for Msc_PUSCH %d\n",Msc_PUSCH); d0 = (uint32_t *)d; d1 = d0+Msc_PUSCH; @@ -87,7 +87,7 @@ void dft_lte(int32_t *z,int32_t *d, int32_t Msc_PUSCH, uint8_t Nsymb) d10 = d9+Msc_PUSCH; d11 = d10+Msc_PUSCH; - // msg("symbol 0 (d0 %p, d %p)\n",d0,d); + // printf("symbol 0 (d0 %p, d %p)\n",d0,d); for (i=0,ip=0; irnti<<14) + (subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 if (harq_pid > 7) { - msg("ulsch_modulation.c: Illegal harq_pid %d\n",harq_pid); + printf("ulsch_modulation.c: Illegal harq_pid %d\n",harq_pid); return; } @@ -419,12 +419,12 @@ void ulsch_modulation(int32_t **txdataF, nb_rb = ulsch->harq_processes[harq_pid]->nb_rb; if (nb_rb == 0) { - msg("ulsch_modulation.c: Frame %d, Subframe %d Illegal nb_rb %d\n",frame,subframe,nb_rb); + printf("ulsch_modulation.c: Frame %d, Subframe %d Illegal nb_rb %d\n",frame,subframe,nb_rb); return; } if (first_rb >25 ) { - msg("ulsch_modulation.c: Frame %d, Subframe %d Illegal first_rb %d\n",frame,subframe,first_rb); + printf("ulsch_modulation.c: Frame %d, Subframe %d Illegal first_rb %d\n",frame,subframe,first_rb); return; } @@ -439,12 +439,12 @@ void ulsch_modulation(int32_t **txdataF, Msc_PUSCH = ulsch->harq_processes[harq_pid]->nb_rb*12; #ifdef DEBUG_ULSCH_MODULATION - msg("ulsch_modulation.c: Doing modulation (rnti %x,x2 %x) for G=%d bits, harq_pid %d , nb_rb %d, Q_m %d, Nsymb_pusch %d (nsymb %d), subframe %d\n", + printf("ulsch_modulation.c: Doing modulation (rnti %x,x2 %x) for G=%d bits, harq_pid %d , nb_rb %d, Q_m %d, Nsymb_pusch %d (nsymb %d), subframe %d\n", ulsch->rnti,x2,G,harq_pid,ulsch->harq_processes[harq_pid]->nb_rb,Q_m, ulsch->Nsymb_pusch,nsymb,subframe); #endif // scrambling (Note the placeholding bits are handled in ulsch_coding.c directly!) - //msg("ulsch bits: "); + //printf("ulsch bits: "); s = lte_gold_generic(&x1, &x2, 1); k=0; @@ -454,14 +454,14 @@ void ulsch_modulation(int32_t **txdataF, c = (uint8_t)((s>>j)&1); if (ulsch->h[k] == PUSCH_x) { - // msg("i %d: PUSCH_x\n",i); + // printf("i %d: PUSCH_x\n",i); ulsch->b_tilde[k] = 1; } else if (ulsch->h[k] == PUSCH_y) { - // msg("i %d: PUSCH_y\n",i); + // printf("i %d: PUSCH_y\n",i); ulsch->b_tilde[k] = ulsch->b_tilde[k-1]; } else { ulsch->b_tilde[k] = (ulsch->h[k]+c)&1; - // msg("i %d : %d (h %d c %d)\n", (i<<5)+j,ulsch->b_tilde[k],ulsch->h[k],c); + // printf("i %d : %d (h %d c %d)\n", (i<<5)+j,ulsch->b_tilde[k],ulsch->h[k],c); } } @@ -469,7 +469,7 @@ void ulsch_modulation(int32_t **txdataF, s = lte_gold_generic(&x1, &x2, 0); } - //msg("\n"); + //printf("\n"); gain_lin_QPSK = (short)((amp*ONE_OVER_SQRT2_Q15)>>15); @@ -493,7 +493,7 @@ void ulsch_modulation(int32_t **txdataF, ((int16_t*)&ulsch->d[i])[0] = (ulsch->b_tilde[j] == 1) ? (gain_lin_QPSK) : -gain_lin_QPSK; ((int16_t*)&ulsch->d[i])[1] = (ulsch->b_tilde[j+1] == 1)? (-gain_lin_QPSK) : gain_lin_QPSK; // if (id[i],((int16_t*)&ulsch->d[i])[0],((int16_t*)&ulsch->d[i])[1]); + // printf("input %d (%p): %d,%d\n", i,&ulsch->d[i],((int16_t*)&ulsch->d[i])[0],((int16_t*)&ulsch->d[i])[1]); // UE1, x0* ((int16_t*)&ulsch->d[i+1])[0] = (ulsch->b_tilde[j-2] == 1) ? (-gain_lin_QPSK) : gain_lin_QPSK; @@ -626,7 +626,7 @@ void ulsch_modulation(int32_t **txdataF, ((int16_t*)&ulsch->d[i])[0] = (ulsch->b_tilde[j] == 1) ? (-gain_lin_QPSK) : gain_lin_QPSK; ((int16_t*)&ulsch->d[i])[1] = (ulsch->b_tilde[j+1] == 1)? (-gain_lin_QPSK) : gain_lin_QPSK; // if (id[i],((int16_t*)&ulsch->d[i])[0],((int16_t*)&ulsch->d[i])[1]); + // printf("input %d/%d Msc_PUSCH %d (%p): %d,%d\n", i,Msymb,Msc_PUSCH,&ulsch->d[i],((int16_t*)&ulsch->d[i])[0],((int16_t*)&ulsch->d[i])[1]); break; @@ -650,7 +650,7 @@ void ulsch_modulation(int32_t **txdataF, ((int16_t*)&ulsch->d[i])[0]=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15); ((int16_t*)&ulsch->d[i])[1]=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15); - // msg("input(16qam) %d (%p): %d,%d\n", i,&ulsch->d[i],((int16_t*)&ulsch->d[i])[0],((int16_t*)&ulsch->d[i])[1]); + // printf("input(16qam) %d (%p): %d,%d\n", i,&ulsch->d[i],((int16_t*)&ulsch->d[i])[0],((int16_t*)&ulsch->d[i])[1]); break; case 6: @@ -710,14 +710,14 @@ void ulsch_modulation(int32_t **txdataF, // re_offset0++; } - // msg("re_offset0 %d\n",re_offset0); + // printf("re_offset0 %d\n",re_offset0); for (j=0,l=0; l<(nsymb-ulsch->srs_active); l++) { re_offset = re_offset0; symbol_offset = (int)frame_parms->ofdm_symbol_size*(l+(subframe*nsymb)); #ifdef DEBUG_ULSCH_MODULATION - msg("symbol %d (subframe %d): symbol_offset %d\n",l,subframe,symbol_offset); + printf("symbol %d (subframe %d): symbol_offset %d\n",l,subframe,symbol_offset); #endif txptr = &txdataF[0][symbol_offset]; @@ -727,10 +727,10 @@ void ulsch_modulation(int32_t **txdataF, // Skip reference symbols else { - // msg("copying %d REs\n",Msc_PUSCH); + // printf("copying %d REs\n",Msc_PUSCH); for (i=0; iz[j],((int16_t*)&ulsch->z[j])[0],((int16_t*)&ulsch->z[j])[1]); + printf("re_offset %d (%p): %d,%d\n", re_offset,&ulsch->z[j],((int16_t*)&ulsch->z[j])[0],((int16_t*)&ulsch->z[j])[1]); #endif txptr[re_offset++] = ulsch->z[j]; @@ -748,13 +748,13 @@ void ulsch_modulation(int32_t **txdataF, // re_offset0++; } - // msg("re_offset0 %d\n",re_offset0); + // printf("re_offset0 %d\n",re_offset0); // printf("txdataF %p\n",&txdataF[0][0]); for (j=0,l=0; l<(nsymb-ulsch->srs_active); l++) { re_offset = re_offset0; symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe*nsymb)); #ifdef DEBUG_ULSCH_MODULATION - msg("ulsch_mod (OFDMA) symbol %d (subframe %d): symbol_offset %d\n",l,subframe,symbol_offset); + printf("ulsch_mod (OFDMA) symbol %d (subframe %d): symbol_offset %d\n",l,subframe,symbol_offset); #endif txptr = &txdataF[0][symbol_offset]; @@ -763,11 +763,11 @@ void ulsch_modulation(int32_t **txdataF, } // Skip reference symbols else { - // msg("copying %d REs\n",Msc_PUSCH); + // printf("copying %d REs\n",Msc_PUSCH); for (i=0; i %p\n", re_offset,&ulsch->z[j],((int16_t*)&ulsch->z[j])[0],((int16_t*)&ulsch->z[j])[1],&txptr[re_offset]); + printf("re_offset %d (%p): %d,%d => %p\n", re_offset,&ulsch->z[j],((int16_t*)&ulsch->z[j])[0],((int16_t*)&ulsch->z[j])[1],&txptr[re_offset]); #endif //DEBUG_ULSCH_MODULATION txptr[re_offset++] = ulsch->z[j]; diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 601e2fb199..28c407b088 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -183,7 +183,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, float time[FRAME_LENGTH_COMPLEX_SAMPLES]; float time2[2048]; float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; - int frame = phy_vars_enb->proc[0].frame_tx; + int frame = phy_vars_enb->proc.frame_tx; uint32_t total_dlsch_bitrate = phy_vars_enb->total_dlsch_bitrate; int coded_bits_per_codeword = 0; uint8_t harq_pid; // in TDD config 3 it is sf-2, i.e., can be 0,1,2 diff --git a/openair1/PHY/TOOLS/time_meas.c b/openair1/PHY/TOOLS/time_meas.c index ba1014e9a0..d7328f20cc 100644 --- a/openair1/PHY/TOOLS/time_meas.c +++ b/openair1/PHY/TOOLS/time_meas.c @@ -48,7 +48,7 @@ double get_cpu_freq_GHz(void) { return cpu_freq_GHz; } -void print_meas_now(time_stats_t *ts, const char* name, int subframe, FILE* file_name){ +void print_meas_now(time_stats_t *ts, const char* name, FILE* file_name){ if (opp_enabled) { diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h index 3e621ac281..a0f674113b 100644 --- a/openair1/PHY/TOOLS/time_meas.h +++ b/openair1/PHY/TOOLS/time_meas.h @@ -69,7 +69,7 @@ static inline void start_meas(time_stats_t *ts) __attribute__((always_inline)); static inline void stop_meas(time_stats_t *ts) __attribute__((always_inline)); -void print_meas_now(time_stats_t *ts, const char* name, int subframe, FILE* file_name); +void print_meas_now(time_stats_t *ts, const char* name, FILE* file_name); void print_meas(time_stats_t *ts, const char* name, time_stats_t * total_exec_time, time_stats_t * sf_exec_time); double get_time_meas_us(time_stats_t *ts); double get_cpu_freq_GHz(void); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index dd543bbbf8..c483035abc 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -192,10 +192,14 @@ typedef struct { int subframe_tx; /// subframe to act upon for reception int subframe_rx; + /// subframe to act upon for PRACH + int subframe_prach; /// frame to act upon for transmission int frame_tx; /// frame to act upon for reception int frame_rx; + /// frame to act upon for PRACH + int frame_prach; /// \brief Instance count for tx processing thread. /// \internal This variable is protected by \ref mutex_tx. int instance_cnt_tx; @@ -232,14 +236,13 @@ typedef struct { //! \brief Number of eNB TX and RX threads. //! This number must be equal to the number of LTE subframes (10). Each thread is responsible for a single subframe. -#define NUM_ENB_THREADS 1 /// Top-level PHY Data Structure for eNB typedef struct PHY_VARS_eNB_s { /// Module ID indicator for this instance module_id_t Mod_id; uint8_t CC_id; - eNB_proc_t proc[NUM_ENB_THREADS]; + eNB_proc_t proc; eNB_func_t node_function; uint8_t local_flag; uint32_t rx_total_gain_dB; diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index fa6239d930..2174684126 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -161,8 +161,6 @@ void cleanup_dlsch_threads(void); void phy_procedures_eNB_lte(uint8_t subframe,PHY_VARS_eNB **phy_vars_eNB,uint8_t abstraction_flag, relaying_type_t r_type, PHY_VARS_RN *phy_vars_rn); /*! \brief Top-level entry routine for UE procedures. Called every slot by process scheduler. In even slots, it performs RX functions from previous subframe (if required). On odd slots, it generate TX waveform for the following subframe. - @param last_slot Index of last slot (0-19) - @param next_slot Index of next_slot (0-19) @param phy_vars_ue Pointer to UE variables on which to act @param eNB_id ID of eNB on which to act @param abstraction_flag Indicator of PHY abstraction @@ -215,61 +213,60 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac void phy_procedures_UE_S_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for UE RX procedures in TDD S-subframes. - @param thread_index Thread index in proc vector @param phy_vars_ue Pointer to UE variables on which to act @param eNB_id Local id of eNB on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_UE_S_RX(uint8_t thread_index,PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag, relaying_type_t r_type); +void phy_procedures_UE_S_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag, relaying_type_t r_type); /*! \brief Scheduling for eNB TX procedures in normal subframes. - @param thread_index Index of thread in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param phy_vars_rn pointer to the RN variables */ -void phy_procedures_eNB_TX(uint8_t thread_index,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); +void phy_procedures_eNB_TX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); /*! \brief Scheduling for eNB RX UE-specific procedures in normal subframes. - @param thread_index Thread index in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_uespec_RX(uint8_t thread_index,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for eNB TX procedures in TDD S-subframes. - @param thread_index Index of thread in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ /*! \brief Scheduling for eNB RX common procedures in normal subframes. - @param thread_index Thread index in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction */ -void phy_procedures_eNB_common_RX(uint8_t thread_index,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag); +void phy_procedures_eNB_common_RX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag); /*! \brief Scheduling for eNB TX procedures in TDD S-subframes. - @param thread_index Index of thread in proc vector @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_S_TX(uint8_t next_slot,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_S_TX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for eNB RX procedures in TDD S-subframes. - @param last_slot Index of next slot (0-19) @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_S_RX(uint8_t last_slot,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); + +/*! \brief Scheduling for eNB PRACH RX procedures + @param phy_vars_eNB Pointer to eNB variables on which to act + @param abstraction_flag Indicator of PHY abstraction +*/ +void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag); /*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. @param frame_parms Pointer to DL frame parameter descriptor @@ -277,12 +274,6 @@ void phy_procedures_eNB_S_RX(uint8_t last_slot,PHY_VARS_eNB *phy_vars_eNB,uint8_ @returns Subframe type (DL,UL,S) */ -/*! \brief Scheduling for eNB PRACH RX procedures - @param phy_vars_eNB Pointer to eNB variables on which to act - @param thread_id Index of thread in proc vector - @param abstraction_flag Indicator of PHY abstraction -*/ -void prach_procedures(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t abstraction_flag); lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); @@ -400,10 +391,9 @@ uint8_t is_SR_TXOp(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); /*! \brief Indicates the SR TXOp in current subframe for eNB and particular UE index. Implements Table 10.1-5 from 36.213. @param phy_vars_eNB Pointer to eNB variables @param UE_id ID of UE which may be issuing the SR - @param subframe index of last subframe @returns 1 if TXOp is active. */ -uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t subframe); +uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id); /*! \brief Gives the UL subframe corresponding to a PDDCH order in subframe n @param frame_parms Pointer to DL frame parameters @@ -443,14 +433,14 @@ subframe n-4 which is acknowledged in subframe n (for FDD) according to n1_pucch TDD, this routine computes the complex procedure described in Section 10.1 of 36.213 (through tables 10.1-1,10.1-2) @param phy_vars_ue Pointer to UE variables @param eNB_id Index of eNB -@param thread_id Index of thread where procedures are executed +@param subframe subframe on which to act @param b Pointer to PUCCH payload (b[0],b[1]) @param SR 1 means there's a positive SR in parallel to ACK/NAK @returns n1_pucch */ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id, - uint8_t thread_id, + uint8_t subframe, uint8_t *b, uint8_t SR); @@ -468,7 +458,6 @@ TDD, this routine computes the procedure described in Section 10.1 of 36.213 (th */ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, uint8_t UE_id, - uint8_t subframe, int16_t *n1_pucch0, int16_t *n1_pucch1, int16_t *n1_pucch2, @@ -477,7 +466,6 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, /*! \brief This function retrieves the harq_pid of the corresponding DLSCH process and updates the error statistics of the DLSCH based on the received ACK info from UE along with the round index. It also performs the fine-grain rate-adaptation based on the error statistics derived from the ACK/NAK process. @param UE_id Local UE index on which to act - @param subframe Index of subframe @param phy_vars_eNB Pointer to eNB variables on which to act @param pusch_flag Indication that feedback came from PUSCH @param pucch_payload Resulting payload from pucch @@ -485,7 +473,6 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, @param SR_payload Indication of SR presence (TDD specific) */ void process_HARQ_feedback(uint8_t UE_id, - uint8_t subframe, PHY_VARS_eNB *phy_vars_eNB, uint8_t pusch_flag, uint8_t *pucch_payload, @@ -548,8 +535,6 @@ int16_t get_target_pucch_rx_power(module_id_t module_idP, uint8_t CC_id); int get_ue_active_harq_pid(uint8_t Mod_id,uint8_t CC_id,uint16_t rnti,int frame, uint8_t subframe,uint8_t *harq_pid,uint8_t *round,uint8_t ul_flag); -void ulsch_decoding_procedures(unsigned char last_slot, unsigned int i, PHY_VARS_eNB *phy_vars_eNB, unsigned char abstraction_flag); - void dump_dlsch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c index 0b4fffe3d3..564a7951c6 100644 --- a/openair1/SCHED/phy_mac_stub.c +++ b/openair1/SCHED/phy_mac_stub.c @@ -48,7 +48,7 @@ #include "SCHED/phy_procedures_emos.h" #endif -void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) +void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) { @@ -57,7 +57,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) uint32_t rballoc = 0x7FFF; //uint32_t rballoc2 = 0x000F; - int subframe = eNB->proc[thread_id].subframe_tx; + int subframe = eNB->proc.subframe_tx; LTE_eNB_DLSCH_t *DLSCH_ptr = eNB->dlsch[0][0]; @@ -89,7 +89,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -100,7 +100,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -117,7 +117,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -128,7 +128,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -144,7 +144,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -155,7 +155,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; @@ -171,7 +171,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -182,7 +182,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -236,7 +236,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -267,7 +267,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -303,7 +303,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t)); @@ -334,7 +334,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t)); @@ -369,7 +369,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -400,7 +400,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc[thread_id].frame_tx&1; + ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_20MHz_TDD_t)); @@ -437,10 +437,10 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tpmi = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv1 = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi1 = eNB->proc[thread_id].frame_tx&1; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi1 = eNB->proc.frame_tx&1; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs1 = eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv2 = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi2 = eNB->proc[thread_id].frame_tx&1; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi2 = eNB->proc.frame_tx&1; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs2 = eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tb_swap = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; @@ -459,7 +459,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback DLSCH_alloc_pdu1E.rv = 0; - DLSCH_alloc_pdu1E.ndi = eNB->proc[thread_id].frame_tx&1; + DLSCH_alloc_pdu1E.ndi = eNB->proc.frame_tx&1; //DLSCH_alloc_pdu1E.mcs = cqi_to_mcs[eNB->eNB_UE_stats->DL_cqi[0]]; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); DLSCH_alloc_pdu1E.mcs = eNB->target_ue_dl_mcs; @@ -482,7 +482,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) //DLSCH_alloc_pdu1E.mcs = eNB->target_ue_dl_mcs; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((eNB->frame%1024)%28); - DLSCH_alloc_pdu1E.mcs = (unsigned char) (((eNB->proc[thread_id].frame_tx%1024)/3)%28); + DLSCH_alloc_pdu1E.mcs = (unsigned char) (((eNB->proc.frame_tx%1024)/3)%28); eNB->UE_stats[1].dlsch_mcs1 = DLSCH_alloc_pdu1E.mcs; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); @@ -533,7 +533,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) UL_alloc_pdu.hopping = 0; UL_alloc_pdu.rballoc = computeRIV(25,2,eNB->ue_ul_nb_rb); UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; - UL_alloc_pdu.ndi = eNB->proc[thread_id].frame_tx&1; + UL_alloc_pdu.ndi = eNB->proc.frame_tx&1; UL_alloc_pdu.TPC = 0; UL_alloc_pdu.cshift = 0; UL_alloc_pdu.dai = 0; @@ -555,7 +555,7 @@ void fill_dci(DCI_PDU *DCI_pdu, uint8_t thread_id, PHY_VARS_eNB *eNB) else UL_alloc_pdu.rballoc = computeRIV(25,0,eNB->ue_ul_nb_rb); UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; - UL_alloc_pdu.ndi = eNB->proc[thread_id].frame_tx&1; + UL_alloc_pdu.ndi = eNB->proc.frame_tx&1; UL_alloc_pdu.TPC = 0; if ((cooperation_flag==0) || (cooperation_flag==1)) UL_alloc_pdu.cshift = 0; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 9dd3d98e00..c2dc89c2c5 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -101,10 +101,10 @@ extern uint8_t smbv_frame_cnt; extern int rx_sig_fifo; #endif -uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,uint8_t UE_id,uint8_t thread_id) +uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,uint8_t UE_id) { - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; @@ -339,10 +339,10 @@ void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB) -void phy_procedures_eNB_S_RX(unsigned char thread_id,PHY_VARS_eNB *eNB,uint8_t abstraction_flag,relaying_type_t r_type) +void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,uint8_t abstraction_flag,relaying_type_t r_type) { UNUSED(r_type); - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; #ifdef DEBUG_PHY_PROC @@ -435,14 +435,15 @@ int QPSK2[4]= {AMP_OVER_2|(AMP_OVER_2<<16),AMP_OVER_2|((65536-AMP_OVER_2)<<16),( unsigned int taus(void); -void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int thread_id,int abstraction_flag,relaying_type_t r_type) { +void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) { #ifdef Rel10 MCH_PDU *mch_pduP; MCH_PDU mch_pdu; // uint8_t sync_area=255; #endif - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; + int subframe = proc->subframe_tx; if (abstraction_flag==0) { // This is DL-Cell spec pilots in Control region @@ -507,7 +508,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int thread_ if (mch_pduP) { fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0, abstraction_flag); // Generate PMCH - generate_mch(eNB,thread_id,(uint8_t*)mch_pduP->payload,abstraction_flag); + generate_mch(eNB,(uint8_t*)mch_pduP->payload,abstraction_flag); } else { LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe); } @@ -515,12 +516,14 @@ void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int subframe,int thread_ #endif } -void common_signal_procedures (int subframe,int thread_id,PHY_VARS_eNB *eNB,int abstraction_flag) { +void common_signal_procedures (PHY_VARS_eNB *eNB,int abstraction_flag) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int **txdataF = eNB->common_vars.txdataF[0]; uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; + int subframe = proc->subframe_tx; + int frame = proc->frame_tx; // generate Cell-Specific Reference Signals for both slots if (abstraction_flag==0) { @@ -557,7 +560,7 @@ void common_signal_procedures (int subframe,int thread_id,PHY_VARS_eNB *eNB,int } // generate PBCH (Physical Broadcast CHannel) info - if ((proc->frame_tx&3) == 0) { + if ((frame&3) == 0) { pbch_pdu[2] = 0; // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators @@ -617,8 +620,8 @@ void common_signal_procedures (int subframe,int thread_id,PHY_VARS_eNB *eNB,int break; } - pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((proc->frame_tx>>8)&0x3); - pbch_pdu[1] = proc->frame_tx&0xfc; + pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((frame>>8)&0x3); + pbch_pdu[1] = frame&0xfc; pbch_pdu[0] = 0; } @@ -640,7 +643,7 @@ void common_signal_procedures (int subframe,int thread_id,PHY_VARS_eNB *eNB,int AMP, fp, pbch_pdu, - proc->frame_tx&3); + frame&3); } #ifdef PHY_ABSTRACTION else { @@ -700,10 +703,12 @@ void common_signal_procedures (int subframe,int thread_id,PHY_VARS_eNB *eNB,int } -void generate_eNB_dlsch_params(const int frame,const int subframe,int thread_id,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { +void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; + int frame = proc->frame_tx; + int subframe = proc->subframe_tx; // if we have SI_RNTI, configure dlsch parameters and CCE index if (dci_alloc->rnti == SI_RNTI) { @@ -724,14 +729,14 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int thread_id, eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE; - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"\n",eNB->Mod_id,proc->frame_tx,subframe, + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"\n",eNB->Mod_id,frame,subframe, eNB->dlsch_SI->nCCE[subframe]); #if defined(SMBV) // configure SI DCI - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",proc->frame_tx,subframe,i); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",frame,subframe,i); smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", dci_alloc, i); } @@ -757,13 +762,13 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int thread_id, eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE; - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"\n",eNB->Mod_id,proc->frame_tx,subframe, + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"\n",eNB->Mod_id,frame,subframe, eNB->dlsch_ra->nCCE[subframe]); #if defined(SMBV) // configure RA DCI - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",proc->frame_tx,subframe,i); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",frame,subframe,i); smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", dci_alloc, i); } @@ -781,8 +786,8 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int thread_id, if (UE_id>=0) { #if defined(SMBV) // Configure this user - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %"PRIu16" in TM%"PRIu8"\n",proc->frame_tx,subframe,(smbv_frame_cnt*10) + (subframe),UE_id+1, + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %"PRIu16" in TM%"PRIu8"\n",frame,subframe,(smbv_frame_cnt*10) + (subframe),UE_id+1, dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]); smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti); } @@ -803,19 +808,19 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int thread_id, P_RNTI, eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single); LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n", - eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,proc->frame_tx,subframe); + eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe); eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE; - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",eNB->Mod_id,proc->frame_tx,subframe, + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe, dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]); #if defined(SMBV) // configure UE-spec DCI - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",proc->frame_tx,subframe,i); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",frame,subframe,i); smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1,dci_alloc, i); } @@ -823,43 +828,44 @@ void generate_eNB_dlsch_params(const int frame,const int subframe,int thread_id, LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n", eNB->Mod_id, dci_alloc->rnti, - proc->frame_tx, subframe,UE_id, + frame, subframe,UE_id, dci_alloc->format, 1<L); } else { LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n", - eNB->Mod_id,proc->frame_tx,dci_alloc->rnti); + eNB->Mod_id,frame,dci_alloc->rnti); } } } -void generate_eNB_ulsch_params(const int frame,const int subframe,int thread_id,PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { +void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { int harq_pid; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - eNB_proc_t *proc = &eNB->proc[thread_id]; - + eNB_proc_t *proc = &eNB->proc; + int frame = proc->frame_tx; + int subframe = proc->frame_rx; + LOG_D(PHY, "[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8"), aggregation %d\n", eNB->Mod_id, subframe2harq_pid(fp, - pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe), + pdcch_alloc2ul_frame(fp,frame,subframe), pdcch_alloc2ul_subframe(fp,subframe)), - proc->frame_tx, + frame, subframe, - pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe), + pdcch_alloc2ul_frame(fp,frame,subframe), pdcch_alloc2ul_subframe(fp,subframe), dci_alloc->rnti, dci_alloc->dci_pdu[0], 1<L); - generate_eNB_ulsch_params_from_dci(&dci_alloc->dci_pdu[0], + generate_eNB_ulsch_params_from_dci(eNB, + &dci_alloc->dci_pdu[0], dci_alloc->rnti, - thread_id, format0, UE_id, - eNB, SI_RNTI, 0, P_RNTI, @@ -867,14 +873,14 @@ void generate_eNB_ulsch_params(const int frame,const int subframe,int thread_id, 0); // do_srs LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d\n", - eNB->Mod_id,proc->frame_tx,subframe,dci_alloc->rnti, + eNB->Mod_id,frame,subframe,dci_alloc->rnti, dci_alloc->firstCCE); #if defined(SMBV) // configure UE-spec DCI for UL Grant - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",proc->frame_tx,subframe,i); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",frame,subframe,i); smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); } @@ -883,11 +889,11 @@ void generate_eNB_ulsch_params(const int frame,const int subframe,int thread_id, // get the hard_pid for this subframe harq_pid = subframe2harq_pid(fp, - pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe), + pdcch_alloc2ul_frame(fp,frame,subframe), pdcch_alloc2ul_subframe(fp,subframe)); if (harq_pid==255) { // should not happen, log an error and exit, this is a fatal error - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,proc->frame_tx); + LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,frame); mac_xface->macphy_exit("FATAL\n"); } @@ -898,9 +904,11 @@ void generate_eNB_ulsch_params(const int frame,const int subframe,int thread_id, } -void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int subframe,int thread_id,int num_pdcch_symbols,int abstraction_flag) { +void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols,int abstraction_flag) { - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; int harq_pid = dlsch->current_harq_pid; LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid]; int input_buffer_length = dlsch_harq->TBS/8; @@ -913,13 +921,13 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t LOG_D(PHY, "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n", eNB->Mod_id, dlsch->rnti,harq_pid, - proc->frame_tx, subframe, input_buffer_length, + frame, subframe, input_buffer_length, get_G(fp, dlsch_harq->nb_rb, dlsch_harq->rb_alloc, get_Qm(dlsch_harq->mcs), dlsch_harq->Nl, - num_pdcch_symbols,proc->frame_tx,subframe), + num_pdcch_symbols,frame,subframe), dlsch_harq->nb_rb, dlsch_harq->mcs, pmi2hex_2Ar1(dlsch_harq->pmi_alloc), @@ -931,14 +939,14 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t MSC_PHY_ENB,MSC_PHY_UE, NULL,0, "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")", - proc->frame_tx, subframe, + frame, subframe, input_buffer_length, get_G(fp, dlsch_harq->nb_rb, dlsch_harq->rb_alloc, get_Qm(dlsch_harq->mcs), dlsch_harq->Nl, - num_pdcch_symbols,proc->frame_tx,subframe), + num_pdcch_symbols,frame,subframe), dlsch_harq->nb_rb, dlsch_harq->mcs, pmi2hex_2Ar1(dlsch_harq->pmi_alloc), @@ -957,14 +965,14 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t if (ra_flag == 0) { DLSCH_pdu = mac_xface->get_dlsch_sdu(eNB->Mod_id, eNB->CC_id, - proc->frame_tx, + frame, dlsch->rnti, 0); } else { int16_t crnti = mac_xface->fill_rar(eNB->Mod_id, eNB->CC_id, - proc->frame_tx, + frame, DLSCH_pdu_rar, fp->N_RB_UL, input_buffer_length); @@ -981,7 +989,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t LOG_W(PHY,"[eNB] Max user count reached.\n"); mac_xface->cancel_ra_proc(eNB->Mod_id, eNB->CC_id, - proc->frame_tx, + frame, crnti); } else { eNB->UE_stats[(uint32_t)UE_id].mode = RA_RESPONSE; @@ -989,7 +997,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t eNB->first_sr[(uint32_t)UE_id] = 1; generate_eNB_ulsch_params_from_rar(DLSCH_pdu, - proc->frame_tx, + frame, (subframe), eNB->ulsch[(uint32_t)UE_id], fp); @@ -998,11 +1006,11 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t get_Msg3_alloc(fp, subframe, - proc->frame_tx, + frame, &eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, &eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n", - proc->frame_tx, + frame, subframe, UE_id, eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, @@ -1021,8 +1029,8 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t #if defined(SMBV) // Configures the data source of allocation (allocation is configured by DCI) - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %"PRIu8"\n",proc->frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); // smbv_configure_datalist_for_user(smbv_fname, find_ue(dlsch->rnti,eNB)+1, DLSCH_pdu, input_buffer_length); } @@ -1057,7 +1065,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t fp, num_pdcch_symbols, dlsch, - proc->frame_tx,subframe, + frame,subframe, &eNB->dlsch_rate_matching_stats, &eNB->dlsch_turbo_encoding_stats, &eNB->dlsch_interleaving_stats); @@ -1072,7 +1080,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t dlsch_harq->rb_alloc, get_Qm(dlsch_harq->mcs), dlsch_harq->Nl, - num_pdcch_symbols,proc->frame_tx,subframe), + num_pdcch_symbols,frame,subframe), 0, subframe<<1); stop_meas(&eNB->dlsch_scrambling_stats); @@ -1103,14 +1111,15 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t dlsch->active = 0; } -void phy_procedures_eNB_TX(unsigned char thread_id, - PHY_VARS_eNB *eNB, +void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, uint8_t abstraction_flag, relaying_type_t r_type, PHY_VARS_RN *rn) { UNUSED(rn); - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; // uint16_t input_buffer_length; uint32_t i,aa; uint8_t harq_pid; @@ -1128,8 +1137,6 @@ void phy_procedures_eNB_TX(unsigned char thread_id, // there is at least one allocation for PDCCH uint8_t smbv_alloc_cnt = 1; #endif - int frame = proc->frame_tx; - int subframe = proc->subframe_tx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,1); start_meas(&eNB->phy_proc_tx); @@ -1157,7 +1164,7 @@ void phy_procedures_eNB_TX(unsigned char thread_id, // This is called only for the CC_id = 0 and triggers scheduling for all CC_id's if (eNB->mac_enabled==1) { if (eNB->CC_id == 0) { - mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,proc->frame_tx,subframe);//,1); + mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1); } } @@ -1169,18 +1176,18 @@ void phy_procedures_eNB_TX(unsigned char thread_id, } } - if (is_pmch_subframe(proc->frame_tx,subframe,fp)) { - pmch_procedures(eNB,rn,subframe,thread_id,abstraction_flag,r_type); + if (is_pmch_subframe(frame,subframe,fp)) { + pmch_procedures(eNB,rn,abstraction_flag,r_type); } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH - common_signal_procedures(subframe,thread_id,eNB,abstraction_flag); + common_signal_procedures(eNB,abstraction_flag); } #if defined(SMBV) // PBCH takes one allocation - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { if (subframe==0) smbv_alloc_cnt++; } @@ -1192,21 +1199,21 @@ void phy_procedures_eNB_TX(unsigned char thread_id, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1); DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id, eNB->CC_id, - proc->frame_tx, + frame, subframe); } else { DCI_pdu = &DCI_pdu_tmp; #ifdef EMOS_CHANNEL - fill_dci_emos(DCI_pdu,thread_id,eNB); + fill_dci_emos(DCI_pdu,eNB); #else - fill_dci(DCI_pdu,thread_id,eNB); + fill_dci(DCI_pdu,eNB); #endif } // clear existing ulsch dci allocations before applying info from MAC (this is table ul_subframe = pdcch_alloc2ul_subframe(fp,subframe); - ul_frame = pdcch_alloc2ul_frame(fp,proc->frame_tx,subframe); + ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe); if ((subframe_select(fp,ul_subframe)==SF_UL) || (fp->frame_type == FDD)) { @@ -1232,8 +1239,8 @@ void phy_procedures_eNB_TX(unsigned char thread_id, #if defined(SMBV) // Sets up PDCCH and DCI table - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) { - LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",proc->frame_tx,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) { + LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",frame,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); dump_dci(fp,&DCI_pdu->dci_alloc[0]); smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci); } @@ -1258,7 +1265,7 @@ void phy_procedures_eNB_TX(unsigned char thread_id, } else UE_id=0; - generate_eNB_dlsch_params(frame,subframe,thread_id,eNB,dci_alloc,UE_id); + generate_eNB_dlsch_params(eNB,dci_alloc,UE_id); } @@ -1277,10 +1284,10 @@ void phy_procedures_eNB_TX(unsigned char thread_id, UE_id = i; if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,proc->frame_tx,dci_alloc->rnti); + LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti); mac_xface->macphy_exit("FATAL\n"); } - generate_eNB_ulsch_params(frame,subframe,thread_id,eNB,dci_alloc,UE_id); + generate_eNB_ulsch_params(eNB,dci_alloc,UE_id); } } @@ -1300,7 +1307,7 @@ void phy_procedures_eNB_TX(unsigned char thread_id, if (abstraction_flag == 0) { if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,proc->frame_tx, subframe, + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,frame, subframe, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci, @@ -1316,7 +1323,7 @@ void phy_procedures_eNB_TX(unsigned char thread_id, #ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious else { - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,proc->frame_tx, subframe); + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe); num_pdcch_symbols = generate_dci_top_emul(eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,subframe); } @@ -1328,13 +1335,13 @@ void phy_procedures_eNB_TX(unsigned char thread_id, if (eNB->dlsch_SI->active == 1) { - pdsch_procedures(eNB,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,subframe,thread_id,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols,abstraction_flag); #if defined(SMBV) // Configures the data source of allocation (allocation is configured by DCI) - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",proc->frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length); } @@ -1347,8 +1354,8 @@ void phy_procedures_eNB_TX(unsigned char thread_id, #if defined(SMBV) // Configures the data source of allocation (allocation is configured by DCI) - if (smbv_is_config_frame(proc->frame_tx) && (smbv_frame_cnt < 4)) { - LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",proc->frame_tx,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); + if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) { + LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt); smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length); } @@ -1357,11 +1364,11 @@ void phy_procedures_eNB_TX(unsigned char thread_id, LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n", eNB->Mod_id, - proc->frame_tx, subframe, + frame, subframe, eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); - pdsch_procedures(eNB,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,subframe,thread_id,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols,abstraction_flag); eNB->dlsch_ra->active = 0; @@ -1374,7 +1381,7 @@ void phy_procedures_eNB_TX(unsigned char thread_id, (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&& (eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) { - pdsch_procedures(eNB,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,subframe,thread_id,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols,abstraction_flag); } @@ -1395,7 +1402,6 @@ void phy_procedures_eNB_TX(unsigned char thread_id, if (is_phich_subframe(fp,subframe)) { generate_phich_top(eNB, - thread_id, AMP, 0, abstraction_flag); @@ -1414,11 +1420,11 @@ void phy_procedures_eNB_TX(unsigned char thread_id, start_meas(&eNB->ofdm_mod_stats); do_OFDM_mod(eNB->common_vars.txdataF[0], eNB->common_vars.txdata[0], - proc->frame_tx,subframe<<1, + frame,subframe<<1, fp); do_OFDM_mod(eNB->common_vars.txdataF[0], eNB->common_vars.txdata[0], - proc->frame_tx,1+(subframe<<1), + frame,1+(subframe<<1), fp); stop_meas(&eNB->ofdm_mod_stats); } @@ -1431,10 +1437,10 @@ void phy_procedures_eNB_TX(unsigned char thread_id, } -void process_Msg3(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t UE_id, uint8_t harq_pid) +void process_Msg3(PHY_VARS_eNB *eNB,uint8_t UE_id, uint8_t harq_pid) { // this prepares the demodulation of the first PUSCH of a new user, containing Msg3 - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; @@ -1468,7 +1474,6 @@ void process_Msg3(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t UE_id, uint8_t har // rate-adaptation based on the error statistics derived from the ACK/NAK process void process_HARQ_feedback(uint8_t UE_id, - uint8_t thread_id, PHY_VARS_eNB *eNB, uint8_t pusch_flag, uint8_t *pucch_payload, @@ -1476,7 +1481,7 @@ void process_HARQ_feedback(uint8_t UE_id, uint8_t SR_payload) { - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe; LTE_eNB_DLSCH_t *dlsch = eNB->dlsch[(uint32_t)UE_id][0]; @@ -1741,14 +1746,13 @@ void process_HARQ_feedback(uint8_t UE_id, void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, uint8_t UE_id, - uint8_t thread_id, int16_t *n1_pucch0, int16_t *n1_pucch1, int16_t *n1_pucch2, int16_t *n1_pucch3) { - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms; uint8_t nCCE0,nCCE1; int sf; @@ -1880,7 +1884,7 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, } } -void prach_procedures(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t abstraction_flag) +void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -1888,7 +1892,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t abstraction_fl uint16_t preamble_max,preamble_energy_max; uint16_t i; int8_t UE_id; - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; uint8_t CC_id = eNB->CC_id; @@ -1902,7 +1906,6 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t abstraction_fl rx_prach(eNB, - subframe, preamble_energy_list, preamble_delay_list, frame, @@ -1999,17 +2002,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t thread_id,uint8_t abstraction_fl } } -void ulsch_decoding_procedures(unsigned char subframe, unsigned int i, PHY_VARS_eNB *eNB, unsigned char abstraction_flag) -{ - UNUSED(subframe); - UNUSED(i); - UNUSED(eNB); - UNUSED(abstraction_flag); - LOG_D(PHY,"ulsch_decoding_procedures not yet implemented. should not be called"); -} - - -void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void pucch_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0}; @@ -2019,7 +2012,7 @@ void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id, int32_t metric0=0,metric1=0,metric0_SR=0; ANFBmode_t bundling_flag; PUCCH_FMT_t format; - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; @@ -2028,14 +2021,13 @@ void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id, (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { // check SR availability - do_SR = is_SR_subframe(eNB,UE_id,thread_id); + do_SR = is_SR_subframe(eNB,UE_id); // do_SR = 0; // Now ACK/NAK // First check subframe_tx flag for earlier subframes get_n1_pucch_eNB(eNB, UE_id, - thread_id, &n1_pucch0, &n1_pucch1, &n1_pucch2, @@ -2098,8 +2090,7 @@ void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id, UE_id, pucch_format1, 0, - &SR_payload, - thread_id); + &SR_payload); LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",eNB->Mod_id, eNB->ulsch[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); } @@ -2182,7 +2173,7 @@ void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id, pucch_payload0[0],metric0); #endif - process_HARQ_feedback(UE_id,thread_id,eNB, + process_HARQ_feedback(UE_id,eNB, 0,// pusch_flag pucch_payload0, 2, @@ -2313,7 +2304,7 @@ void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id, frame,subframe, metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]); #endif - process_HARQ_feedback(UE_id,thread_id,eNB, + process_HARQ_feedback(UE_id,eNB, 0,// pusch_flag pucch_payload, pucch_sel, @@ -2324,9 +2315,9 @@ void pucch_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id, } } -void cba_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void cba_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; uint8_t access_mode; int num_active_cba_groups; const int subframe = proc->subframe_rx; @@ -2352,7 +2343,6 @@ void cba_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,in if (abstraction_flag==0) { rx_ulsch(eNB, - thread_id, eNB->UE_stats[UE_id].sector, // this is the effective sector id UE_id, eNB->ulsch, @@ -2372,7 +2362,6 @@ void cba_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,in if (abstraction_flag == 0) { ret = ulsch_decoding(eNB, UE_id, - thread_id, 0, // control_only_flag eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI, eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); @@ -2381,7 +2370,6 @@ void cba_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,in #ifdef PHY_ABSTRACTION else { ret = ulsch_decoding_emul(eNB, - thread_id, UE_id, &rnti); } @@ -2489,20 +2477,26 @@ void cba_procedures(const unsigned char thread_id,PHY_VARS_eNB *eNB,int UE_id,in -void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { +void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; int i,l; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; void *rxp[fp->nb_antennas_rx]; unsigned int rxs; - - AssertFatal(thread_id < NUM_ENB_THREADS, "Bad thread_id %d", thread_id); + int subframe = proc->subframe_rx; + int frame = proc->frame_rx; + + if (subframe==9) { + subframe=0; + frame++; + } + else subframe++; // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_COMMON_RX,1); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,proc->frame_rx, proc->subframe_rx); + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); #endif if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) @@ -2511,7 +2505,7 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN if ((eNB->node_function == NGFI_RRU_IF4) || (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF and front-end processing for (i=0; inb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][proc->subframe*fp->samples_per_tti]; + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); rxs = openair0.trx_read_func(&openair0, @@ -2521,9 +2515,11 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN fp->nb_antennas_rx); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is"); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, frame ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, subframe ); if (frame > 20){ if (rxs != fp->samples_per_tti>>1) @@ -2583,15 +2579,18 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // check if we have to detect PRACH first - if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) { + if (is_prach_subframe(fp,frame,subframe)>0) { // wake up thread for PRACH RX if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", thread_id, proc->instance_cnt_prach ); + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); exit_fun( "error locking mutex_prach" ); return; } int cnt_prach = ++proc->instance_cnt_prach; + // set timing for prach thread + proc->frame_prach = frame; + proc->subframe_prach = subframe; pthread_mutex_unlock( &proc->mutex_prach ); @@ -2603,7 +2602,7 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN return; } } else { - LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", proc->frame_tx); + LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame); exit_fun( "PRACH thread busy" ); return; } @@ -2614,7 +2613,7 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // wake up TX thread // lock the TX mutex and make sure the thread is ready if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", thread_id, proc->instance_cnt_tx ); + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc->instance_cnt_tx ); exit_fun( "error locking mutex_tx" ); return; } @@ -2627,20 +2626,20 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // we want to generate subframe (n+3), so TS_tx = TX_rx+2.5*samples_per_tti, // and proc->subframe_tx = proc->subframe_rx+3 proc->timestamp_tx = proc->timestamp_rx + (fp->samples_per_tti<<1) + (fp->samples_per_tti>>1); - proc->frame_tx = (proc->subframe_rx > 6) ? (proc->frame_rx+1) : proc->frame_rx; - proc->subframe_tx = (proc->subframe_rx + 3)%10; + proc->frame_tx = (subframe > 6) ? (frame+1) : frame; + proc->subframe_tx = (subframe + 3)%10; pthread_mutex_unlock( &proc->mutex_tx ); if (cnt_tx == 0){ // the thread was presumably waiting where it should and can now be woken up if (pthread_cond_signal(&proc->cond_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n", thread_id); + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread\n"); exit_fun( "ERROR pthread_cond_signal" ); return; } } else { - LOG_W( PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (cnt_tx %i)\n", proc->frame_tx, thread_id, cnt_tx ); + LOG_W( PHY,"[eNB] Frame %d, eNB TX thread busy!! (cnt_tx %i)\n", frame, cnt_tx ); exit_fun( "TX thread busy" ); return; } @@ -2652,11 +2651,11 @@ void phy_procedures_eNB_common_RX(const unsigned char thread_id,PHY_VARS_eNB *eN } } -void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eNB,const uint8_t abstraction_flag,const relaying_type_t r_type) +void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag,const relaying_type_t r_type) { //RX processing for ue-specific resources (i UNUSED(r_type); - eNB_proc_t *proc = &eNB->proc[thread_id]; + eNB_proc_t *proc = &eNB->proc; uint32_t l, ret=0,i,j,k; uint32_t harq_pid, harq_idx, round; uint8_t nPRS; @@ -2668,8 +2667,6 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; - AssertFatal(thread_id < NUM_ENB_THREADS, "Bad thread_id %d", thread_id); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC @@ -2720,7 +2717,7 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // Do PUCCH processing first for (i=0; imac_enabled==1) { if (eNB->UE_stats[i].mode == RA_RESPONSE) { - process_Msg3(eNB,thread_id,i,harq_pid); + process_Msg3(eNB,i,harq_pid); } } @@ -2810,7 +2807,6 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN if (abstraction_flag==0) { rx_ulsch(eNB, - thread_id, eNB->UE_stats[i].sector, // this is the effective sector id i, eNB->ulsch, @@ -2834,7 +2830,6 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN if (abstraction_flag == 0) { ret = ulsch_decoding(eNB, i, - thread_id, 0, // control_only_flag eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI, eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0); @@ -2843,7 +2838,6 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN #ifdef PHY_ABSTRACTION else { ret = ulsch_decoding_emul(eNB, - thread_id, i, &rnti); } @@ -2869,8 +2863,6 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN eNB->ulsch[(uint32_t)i]->harq_processes[harq_pid]->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered - //dump_ulsch(eNB, thread_id, i); - eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++; #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d Clearing subframe_scheduling_flag\n", @@ -2880,7 +2872,7 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) { #ifdef DEBUG_PHY_PROC - //if (((proc->frame_tx%10) == 0) || (proc->frame_tx < 50)) + //if (((frame%10) == 0) || (frame < 50)) print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL); #endif extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o, @@ -3139,7 +3131,7 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN // estimate timing advance for MAC if (abstraction_flag == 0) { - sync_pos = lte_est_timing_advance_pusch(eNB,i,thread_id); + sync_pos = lte_est_timing_advance_pusch(eNB,i); eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check } @@ -3162,7 +3154,6 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN i); #endif process_HARQ_feedback(i, - thread_id, eNB, 1, // pusch_flag 0, @@ -3226,7 +3217,7 @@ void phy_procedures_eNB_uespec_RX(const unsigned char thread_id,PHY_VARS_eNB *eN } // CBA (non-LTE) - cba_procedures(thread_id,eNB,i,harq_pid,abstraction_flag); + cba_procedures(eNB,i,harq_pid,abstraction_flag); } // loop i=0 ... NUMBER_OF_UE_MAX-1 if (abstraction_flag == 0) { diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index b055544449..d757a7573c 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -57,13 +57,13 @@ #include "UTIL/LOG/log.h" #include "UTIL/LISTS/list.h" -extern unsigned int dlsch_tbs25[27][25],TBStable[27][110]; -extern unsigned char offset_mumimo_llr_drange_fix; +#include "unitary_defs.h" + #include "PHY/TOOLS/lte_phy_scope.h" -PHY_VARS_eNB *PHY_vars_eNB; -PHY_VARS_UE *PHY_vars_UE; +PHY_VARS_eNB *eNB; +PHY_VARS_UE *UE; int otg_enabled=0; /*the following parameters are used to control the processing times calculations*/ @@ -96,7 +96,7 @@ DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_1E[2]; uint64_t DLSCH_alloc_pdu_1[2]; #define UL_RB_ALLOC 0x1ff; -#define CCCH_RB_ALLOC computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,0,2) +#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2) //#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 //#define DLSCH_RB_ALLOC 0x0001 void do_OFDM_mod_l(int32_t **txdataF, int32_t **txdata, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms) @@ -485,7 +485,7 @@ int main(int argc, char **argv) case 'u': dual_stream_UE=1; - openair_daq_vars.use_ia_receiver = 1; + UE->use_ia_receiver = 1; if ((n_tx!=2) || (transmission_mode!=5)) { msg("IA receiver only supported for TM5!"); @@ -627,7 +627,7 @@ int main(int argc, char **argv) fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); if (!dual_stream_UE==0) { - openair_daq_vars.use_ia_receiver = 1; + UE->use_ia_receiver = 1; fl_set_button(form_ue->button_0,1); fl_set_object_label(form_ue->button_0, "IA Receiver ON"); fl_set_object_color(form_ue->button_0, FL_GREEN, FL_GREEN); @@ -653,7 +653,7 @@ int main(int argc, char **argv) - eNB_id_i = PHY_vars_UE->n_connected_eNB; + eNB_id_i = UE->n_connected_eNB; printf("Setting mcs1 = %d\n",mcs1); printf("Setting mcs2 = %d\n",mcs2); @@ -674,7 +674,7 @@ int main(int argc, char **argv) txdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); */ - frame_parms = &PHY_vars_eNB->lte_frame_parms; + frame_parms = &eNB->frame_parms; s_re = malloc(2*sizeof(double*)); s_im = malloc(2*sizeof(double*)); @@ -683,7 +683,7 @@ int main(int argc, char **argv) // r_re0 = malloc(2*sizeof(double*)); // r_im0 = malloc(2*sizeof(double*)); - nsymb = (PHY_vars_eNB->lte_frame_parms.Ncp == 0) ? 14 : 12; + nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; printf("Channel Model= (%s,%d)\n",channel_model_input, channel_model); printf("SCM-A=%d, SCM-B=%d, SCM-C=%d, SCM-D=%d, EPA=%d, EVA=%d, ETU=%d, Rayleigh8=%d, Rayleigh1=%d, Rayleigh1_corr=%d, Rayleigh1_anticorr=%d, Rice1=%d, Rice8=%d\n", @@ -838,7 +838,7 @@ int main(int argc, char **argv) } - PHY_vars_UE->lte_ue_pdcch_vars[0]->crnti = n_rnti; + UE->pdcch_vars[0]->crnti = n_rnti; // Fill in UL_alloc UL_alloc_pdu.type = 0; @@ -882,22 +882,22 @@ int main(int argc, char **argv) DLSCH_alloc_pdu2_1E[1].tpmi = (transmission_mode>=5 ? 5 : 0) ; // precoding DLSCH_alloc_pdu2_1E[1].dl_power_off = (transmission_mode==5 ? 0 : 1); - eNB2UE[0] = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + eNB2UE[0] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, 0); if(num_rounds>1) { for(n=1; n<4; n++) - eNB2UE[n] = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + eNB2UE[n] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, 0); @@ -933,42 +933,42 @@ int main(int argc, char **argv) for (k=0; kdlsch_eNB[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); + eNB->dlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); - if (!PHY_vars_eNB->dlsch_eNB[k][i]) { + if (!eNB->dlsch[k][i]) { printf("Can't get eNB dlsch structures\n"); exit(-1); } - PHY_vars_eNB->dlsch_eNB[k][i]->rnti = n_rnti+k; + eNB->dlsch[k][i]->rnti = n_rnti+k; } } for (i=0; i<2; i++) { - PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->dlsch[0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); - if (!PHY_vars_UE->dlsch_ue[0][i]) { + if (!UE->dlsch[0][i]) { printf("Can't get ue dlsch structures\n"); exit(-1); } - PHY_vars_UE->dlsch_ue[0][i]->rnti = n_rnti; + UE->dlsch[0][i]->rnti = n_rnti; } // structure for SIC at UE - PHY_vars_UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); + UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single = (unsigned short)(taus()&0xffff); + eNB->UE_stats[0].DL_pmi_single = (unsigned short)(taus()&0xffff); if (n_users>1) - PHY_vars_eNB->eNB_UE_stats[1].DL_pmi_single = (PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single ^ 0x1555); //opposite PMI + eNB->UE_stats[1].DL_pmi_single = (eNB->UE_stats[0].DL_pmi_single ^ 0x1555); //opposite PMI } else { - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single = 0; + eNB->UE_stats[0].DL_pmi_single = 0; if (n_users>1) - PHY_vars_eNB->eNB_UE_stats[1].DL_pmi_single = 0; + eNB->UE_stats[1].DL_pmi_single = 0; } @@ -992,9 +992,9 @@ int main(int argc, char **argv) case 2: if (common_flag == 0) { - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1_1_5MHz_TDD_t; dci_length_bytes = sizeof(DCI1_1_5MHz_TDD_t); @@ -1048,7 +1048,7 @@ int main(int argc, char **argv) break; } } else { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1_1_5MHz_FDD_t; dci_length_bytes = sizeof(DCI1_1_5MHz_FDD_t); @@ -1104,7 +1104,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].L = 1; dci_alloc[num_dci].rnti = n_rnti+k; dci_alloc[num_dci].format = format1; - dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); generate_eNB_dlsch_params_from_dci(0, @@ -1112,26 +1112,26 @@ int main(int argc, char **argv) &DLSCH_alloc_pdu_1[0], n_rnti+k, format1, - PHY_vars_eNB->dlsch_eNB[0], - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->pdsch_config_dedicated, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); num_dci++; num_ue_spec_dci++; } else { - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t; dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; - ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1145,7 +1145,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; - ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1159,7 +1159,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1171,7 +1171,7 @@ int main(int argc, char **argv) case 100: ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1183,13 +1183,13 @@ int main(int argc, char **argv) break; } } else { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1A_1_5MHz_FDD_t; dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t); ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1202,7 +1202,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t); ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1215,7 +1215,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t); ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1228,7 +1228,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t); ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1244,7 +1244,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].rnti = SI_RNTI; dci_alloc[num_dci].format = format1A; dci_alloc[num_dci].firstCCE = 0; - dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); generate_eNB_dlsch_params_from_dci(0, @@ -1252,13 +1252,13 @@ int main(int argc, char **argv) &DLSCH_alloc_pdu_1[0], SI_RNTI, format1A, - PHY_vars_eNB->dlsch_eNB[0], - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->pdsch_config_dedicated, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); num_common_dci++; num_dci++; @@ -1270,11 +1270,11 @@ int main(int argc, char **argv) case 3: if (common_flag == 0) { - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx == 2) { + if (eNB->frame_parms.nb_antennas_tx == 2) { - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI2A_1_5MHz_2A_TDD_t; dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t); @@ -1341,7 +1341,7 @@ int main(int argc, char **argv) } else { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI2A_1_5MHz_2A_FDD_t; dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t); @@ -1402,7 +1402,7 @@ int main(int argc, char **argv) break; } } - } else if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx == 4) { + } else if (eNB->frame_parms.nb_antennas_tx == 4) { } @@ -1411,7 +1411,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].L = 1; dci_alloc[num_dci].rnti = n_rnti+k; dci_alloc[num_dci].format = format2A; - dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d / format 2A (%d)\n",k,format2A); generate_eNB_dlsch_params_from_dci(0, @@ -1419,26 +1419,26 @@ int main(int argc, char **argv) &DLSCH_alloc_pdu_1[0], n_rnti+k, format2A, - PHY_vars_eNB->dlsch_eNB[0], - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->pdsch_config_dedicated, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); num_dci++; num_ue_spec_dci++; } else { - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t; dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; - ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1452,7 +1452,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; - ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1466,7 +1466,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1478,7 +1478,7 @@ int main(int argc, char **argv) case 100: ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1490,13 +1490,13 @@ int main(int argc, char **argv) break; } } else { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1A_1_5MHz_FDD_t; dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t); ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1509,7 +1509,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t); ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1522,7 +1522,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t); ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1535,7 +1535,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t); ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1551,7 +1551,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].rnti = SI_RNTI; dci_alloc[num_dci].format = format1A; dci_alloc[num_dci].firstCCE = 0; - dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); generate_eNB_dlsch_params_from_dci(0, @@ -1559,13 +1559,13 @@ int main(int argc, char **argv) &DLSCH_alloc_pdu_1[0], SI_RNTI, format1A, - PHY_vars_eNB->dlsch_eNB[0], - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->pdsch_config_dedicated, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); num_common_dci++; num_dci++; @@ -1578,11 +1578,11 @@ int main(int argc, char **argv) case 4: if (common_flag == 0) { - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx == 2) { + if (eNB->frame_parms.nb_antennas_tx == 2) { - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI2_1_5MHz_2A_TDD_t; dci_length_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t); @@ -1649,7 +1649,7 @@ int main(int argc, char **argv) } else { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI2_1_5MHz_2A_FDD_t; dci_length_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t); @@ -1710,7 +1710,7 @@ int main(int argc, char **argv) break; } } - } else if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx == 4) { + } else if (eNB->frame_parms.nb_antennas_tx == 4) { } @@ -1719,7 +1719,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].L = 1; dci_alloc[num_dci].rnti = n_rnti+k; dci_alloc[num_dci].format = format2; - dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); generate_eNB_dlsch_params_from_dci(0, @@ -1727,26 +1727,26 @@ int main(int argc, char **argv) &DLSCH_alloc_pdu_1[0], n_rnti+k, format2, - PHY_vars_eNB->dlsch_eNB[0], - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->pdsch_config_dedicated, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); num_dci++; num_ue_spec_dci++; } else { - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t; dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; - ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1760,7 +1760,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 0; - ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1774,7 +1774,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1786,7 +1786,7 @@ int main(int argc, char **argv) case 100: ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai = 0; ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; @@ -1798,13 +1798,13 @@ int main(int argc, char **argv) break; } } else { - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: dci_length = sizeof_DCI1A_1_5MHz_FDD_t; dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t); ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1817,7 +1817,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t); ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1830,7 +1830,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t); ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1843,7 +1843,7 @@ int main(int argc, char **argv) dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t); ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type = 1; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type = 1; - ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_DL,0,9); + ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc = computeRIV(eNB->frame_parms.N_RB_DL,0,9); ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC = TPC; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid = 0; ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs = mcs1; @@ -1859,7 +1859,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].rnti = SI_RNTI; dci_alloc[num_dci].format = format1A; dci_alloc[num_dci].firstCCE = 0; - dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); generate_eNB_dlsch_params_from_dci(0, @@ -1867,13 +1867,13 @@ int main(int argc, char **argv) &DLSCH_alloc_pdu_1[0], SI_RNTI, format1A, - PHY_vars_eNB->dlsch_eNB[0], - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->pdsch_config_dedicated, + eNB->dlsch[0], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single); + eNB->UE_stats[0].DL_pmi_single); num_common_dci++; num_dci++; @@ -1896,15 +1896,15 @@ int main(int argc, char **argv) &DLSCH_alloc_pdu2_1E[k], n_rnti+k, format1E_2A_M10PRB, - PHY_vars_eNB->dlsch_eNB[k], - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->pdsch_config_dedicated, + eNB->dlsch[k], + &eNB->frame_parms, + eNB->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI, - PHY_vars_eNB->eNB_UE_stats[k].DL_pmi_single); + eNB->UE_stats[k].DL_pmi_single); - dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); + dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]); num_ue_spec_dci++; num_dci++; @@ -1929,7 +1929,7 @@ int main(int argc, char **argv) if (n_frames==1) printf("num_pdcch_symbols %d, numCCE %d => ",num_pdcch_symbols,numCCE); - numCCE = get_nCCE(num_pdcch_symbols,&PHY_vars_eNB->lte_frame_parms,get_mi(&PHY_vars_eNB->lte_frame_parms,subframe)); + numCCE = get_nCCE(num_pdcch_symbols,&eNB->frame_parms,get_mi(&eNB->frame_parms,subframe)); if (n_frames==1) printf("%d\n",numCCE); @@ -1952,10 +1952,10 @@ int main(int argc, char **argv) for (k=0; kdlsch_eNB[k][0]->harq_processes[0]->TBS/8; + input_buffer_length0 = eNB->dlsch[k][0]->harq_processes[0]->TBS/8; input_buffer0[k] = (unsigned char *)malloc(input_buffer_length0+4); memset(input_buffer0[k],0,input_buffer_length0+4); - input_buffer_length1 = PHY_vars_eNB->dlsch_eNB[k][1]->harq_processes[0]->TBS/8; + input_buffer_length1 = eNB->dlsch[k][1]->harq_processes[0]->TBS/8; input_buffer1[k] = (unsigned char *)malloc(input_buffer_length1+4); memset(input_buffer1[k],0,input_buffer_length1+4); @@ -1994,11 +1994,11 @@ int main(int argc, char **argv) } // this is for user 0 only - coded_bits_per_codeword = get_G(&PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->nb_rb, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->rb_alloc, - get_Qm(PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->mcs), - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->Nl, + coded_bits_per_codeword = get_G(&eNB->frame_parms, + eNB->dlsch[0][0]->harq_processes[0]->nb_rb, + eNB->dlsch[0][0]->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs), + eNB->dlsch[0][0]->harq_processes[0]->Nl, num_pdcch_symbols, 0,subframe); @@ -2006,8 +2006,8 @@ int main(int argc, char **argv) printf("uncoded_ber_bit=%p\n",uncoded_ber_bit); snr_step = input_snr_step; - PHY_vars_UE->high_speed_flag = 1; - PHY_vars_UE->ch_est_alpha=0; + UE->high_speed_flag = 1; + UE->ch_est_alpha=0; for (ch_realization=0; ch_realizationframe_rx=0; + UE->frame_rx=0; errs[0]=0; errs[1]=0; errs[2]=0; @@ -2035,32 +2035,32 @@ int main(int argc, char **argv) round=0; avg_iter = 0; iter_trials=0; - reset_meas(&PHY_vars_eNB->phy_proc_tx); // total eNB tx - reset_meas(&PHY_vars_eNB->dlsch_scrambling_stats); - reset_meas(&PHY_vars_UE->dlsch_unscrambling_stats); - reset_meas(&PHY_vars_eNB->ofdm_mod_stats); - reset_meas(&PHY_vars_eNB->dlsch_modulation_stats); - reset_meas(&PHY_vars_eNB->dlsch_encoding_stats); - reset_meas(&PHY_vars_eNB->dlsch_interleaving_stats); - reset_meas(&PHY_vars_eNB->dlsch_rate_matching_stats); - reset_meas(&PHY_vars_eNB->dlsch_turbo_encoding_stats); + reset_meas(&eNB->phy_proc_tx); // total eNB tx + reset_meas(&eNB->dlsch_scrambling_stats); + reset_meas(&UE->dlsch_unscrambling_stats); + reset_meas(&eNB->ofdm_mod_stats); + reset_meas(&eNB->dlsch_modulation_stats); + reset_meas(&eNB->dlsch_encoding_stats); + reset_meas(&eNB->dlsch_interleaving_stats); + reset_meas(&eNB->dlsch_rate_matching_stats); + reset_meas(&eNB->dlsch_turbo_encoding_stats); - reset_meas(&PHY_vars_UE->phy_proc_rx); // total UE rx - reset_meas(&PHY_vars_UE->ofdm_demod_stats); - reset_meas(&PHY_vars_UE->dlsch_channel_estimation_stats); - reset_meas(&PHY_vars_UE->dlsch_freq_offset_estimation_stats); - reset_meas(&PHY_vars_UE->rx_dft_stats); - reset_meas(&PHY_vars_UE->dlsch_decoding_stats); - reset_meas(&PHY_vars_UE->dlsch_turbo_decoding_stats); - reset_meas(&PHY_vars_UE->dlsch_deinterleaving_stats); - reset_meas(&PHY_vars_UE->dlsch_rate_unmatching_stats); - reset_meas(&PHY_vars_UE->dlsch_tc_init_stats); - reset_meas(&PHY_vars_UE->dlsch_tc_alpha_stats); - reset_meas(&PHY_vars_UE->dlsch_tc_beta_stats); - reset_meas(&PHY_vars_UE->dlsch_tc_gamma_stats); - reset_meas(&PHY_vars_UE->dlsch_tc_ext_stats); - reset_meas(&PHY_vars_UE->dlsch_tc_intl1_stats); - reset_meas(&PHY_vars_UE->dlsch_tc_intl2_stats); + reset_meas(&UE->phy_proc_rx); // total UE rx + reset_meas(&UE->ofdm_demod_stats); + reset_meas(&UE->dlsch_channel_estimation_stats); + reset_meas(&UE->dlsch_freq_offset_estimation_stats); + reset_meas(&UE->rx_dft_stats); + reset_meas(&UE->dlsch_decoding_stats); + reset_meas(&UE->dlsch_turbo_decoding_stats); + reset_meas(&UE->dlsch_deinterleaving_stats); + reset_meas(&UE->dlsch_rate_unmatching_stats); + reset_meas(&UE->dlsch_tc_init_stats); + reset_meas(&UE->dlsch_tc_alpha_stats); + reset_meas(&UE->dlsch_tc_beta_stats); + reset_meas(&UE->dlsch_tc_gamma_stats); + reset_meas(&UE->dlsch_tc_ext_stats); + reset_meas(&UE->dlsch_tc_intl1_stats); + reset_meas(&UE->dlsch_tc_intl2_stats); // initialization struct list time_vector_tx; initialize(&time_vector_tx); @@ -2088,9 +2088,9 @@ int main(int argc, char **argv) //if (trials%100==0) eNB2UE[0]->first_run = 1; - ret = PHY_vars_UE->dlsch_ue[0][0]->max_turbo_iterations+1; + ret = UE->dlsch[0][0]->max_turbo_iterations+1; - while ((round < num_rounds) && (ret > PHY_vars_UE->dlsch_ue[0][0]->max_turbo_iterations)) { + while ((round < num_rounds) && (ret > UE->dlsch[0][0]->max_turbo_iterations)) { // printf("Trial %d, round %d\n",trials,round); round_trials[round]++; @@ -2110,13 +2110,13 @@ int main(int argc, char **argv) PMI_FEEDBACK: // printf("Trial %d : Round %d, pmi_feedback %d \n",trials,round,pmi_feedback); - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { - memset(&PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + memset(&eNB->common_vars.txdataF[eNB_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); } if (input_fd==NULL) { - start_meas(&PHY_vars_eNB->phy_proc_tx); + start_meas(&eNB->phy_proc_tx); // Simulate HARQ procedures!!! if (common_flag == 0) { @@ -2124,14 +2124,14 @@ PMI_FEEDBACK: if (round == 0) { // First round TB0_active = 1; - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->rvidx = round&3; + eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3; - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { switch (transmission_mode) { case 1: case 2: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; @@ -2160,7 +2160,7 @@ PMI_FEEDBACK: break; case 3: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; @@ -2206,7 +2206,7 @@ PMI_FEEDBACK: switch (transmission_mode) { case 1: case 2: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = 0; @@ -2235,7 +2235,7 @@ PMI_FEEDBACK: break; case 3: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1 = 0; @@ -2280,15 +2280,15 @@ PMI_FEEDBACK: } } else { - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->rvidx = round&3; + eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3; - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { switch (transmission_mode) { case 1: case 2: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;; @@ -2317,7 +2317,7 @@ PMI_FEEDBACK: break; case 3: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: if (TB0_active==1) { ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; @@ -2395,7 +2395,7 @@ PMI_FEEDBACK: switch (transmission_mode) { case 1: case 2: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi = trials&1; ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv = round&3;; @@ -2424,7 +2424,7 @@ PMI_FEEDBACK: break; case 3: - switch (PHY_vars_eNB->lte_frame_parms.N_RB_DL) { + switch (eNB->frame_parms.N_RB_DL) { case 6: if (TB0_active==1) { ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1 = trials&1; @@ -2507,8 +2507,8 @@ PMI_FEEDBACK: dci_alloc, 0, AMP, - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], + &eNB->frame_parms, + eNB->common_vars.txdataF[eNB_id], subframe); if (num_pdcch_symbols_2 > num_pdcch_symbols) { @@ -2518,115 +2518,115 @@ PMI_FEEDBACK: for (k=0; klte_frame_parms, - PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->nb_rb, - PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->rb_alloc, - get_Qm(PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->mcs), - PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->Nl, + coded_bits_per_codeword = get_G(&eNB->frame_parms, + eNB->dlsch[k][cw]->harq_processes[0]->nb_rb, + eNB->dlsch[k][cw]->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch[k][cw]->harq_processes[0]->mcs), + eNB->dlsch[k][cw]->harq_processes[0]->Nl, num_pdcch_symbols, 0,subframe); #ifdef TBS_FIX // This is for MESH operation!!! - tbs = (double)3*TBStable[get_I_TBS(PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->mcs)][PHY_vars_eNB->dlsch_eNB[k][cw]->nb_rb-1]/4; + tbs = (double)3*TBStable[get_I_TBS(eNB->dlsch[k][cw]->harq_processes[0]->mcs)][eNB->dlsch[k][cw]->nb_rb-1]/4; #else - tbs = PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->TBS; + tbs = eNB->dlsch[k][cw]->harq_processes[0]->TBS; #endif rate = (double)tbs/(double)coded_bits_per_codeword; if ((SNR==snr0) && (trials==0) && (round==0)) printf("User %d, cw %d: Rate = %f (%f bits/dim) (G %d, TBS %d, mod %d, pdcch_sym %d, ndi %d)\n", - k,cw,rate,rate*get_Qm(PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->mcs), + k,cw,rate,rate*get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs), coded_bits_per_codeword, tbs, - get_Qm(PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->mcs), + get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs), num_pdcch_symbols, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->round); + eNB->dlsch[0][0]->harq_processes[0]->round); // use the PMI from previous trial if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&PHY_vars_UE->PHY_measurements,0,PHY_vars_eNB->lte_frame_parms.N_RB_DL); - PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&PHY_vars_UE->PHY_measurements,0,PHY_vars_UE->lte_frame_parms.N_RB_DL); + eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL); + UE->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); if (n_users>1) - PHY_vars_eNB->dlsch_eNB[1][0]->harq_processes[0]->pmi_alloc = (PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->pmi_alloc ^ 0x1555); + eNB->dlsch[1][0]->harq_processes[0]->pmi_alloc = (eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc ^ 0x1555); /* if ((trials<10) && (round==0)) { - printf("tx PMI UE0 %x (pmi_feedback %d)\n",pmi2hex_2Ar1(PHY_vars_eNB->dlsch_eNB[0][0]->pmi_alloc),pmi_feedback); + printf("tx PMI UE0 %x (pmi_feedback %d)\n",pmi2hex_2Ar1(eNB->dlsch[0][0]->pmi_alloc),pmi_feedback); if (transmission_mode ==5) - printf("tx PMI UE1 %x\n",pmi2hex_2Ar1(PHY_vars_eNB->dlsch_eNB[1][0]->pmi_alloc)); + printf("tx PMI UE1 %x\n",pmi2hex_2Ar1(eNB->dlsch[1][0]->pmi_alloc)); } */ } - start_meas(&PHY_vars_eNB->dlsch_encoding_stats); + start_meas(&eNB->dlsch_encoding_stats); if (dlsch_encoding(((cw==0) ? input_buffer0[k] : input_buffer1[k]), - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, num_pdcch_symbols, - PHY_vars_eNB->dlsch_eNB[k][cw], + eNB->dlsch[k][cw], 0,subframe, - &PHY_vars_eNB->dlsch_rate_matching_stats, - &PHY_vars_eNB->dlsch_turbo_encoding_stats, - &PHY_vars_eNB->dlsch_interleaving_stats + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_interleaving_stats )<0) exit(-1); /* if (transmission_mode == 3) { if (dlsch_encoding(input_buffer1[k], - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, num_pdcch_symbols, - PHY_vars_eNB->dlsch_eNB[k][1], + eNB->dlsch[k][1], 0,subframe, - &PHY_vars_eNB->dlsch_rate_matching_stats, - &PHY_vars_eNB->dlsch_turbo_encoding_stats, - &PHY_vars_eNB->dlsch_interleaving_stats + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_interleaving_stats )<0) exit(-1); } */ - stop_meas(&PHY_vars_eNB->dlsch_encoding_stats); + stop_meas(&eNB->dlsch_encoding_stats); - PHY_vars_eNB->dlsch_eNB[k][cw]->rnti = (common_flag==0) ? n_rnti+k : SI_RNTI; - start_meas(&PHY_vars_eNB->dlsch_scrambling_stats); - dlsch_scrambling(&PHY_vars_eNB->lte_frame_parms, + eNB->dlsch[k][cw]->rnti = (common_flag==0) ? n_rnti+k : SI_RNTI; + start_meas(&eNB->dlsch_scrambling_stats); + dlsch_scrambling(&eNB->frame_parms, 0, - PHY_vars_eNB->dlsch_eNB[k][cw], + eNB->dlsch[k][cw], coded_bits_per_codeword, 0, subframe<<1); - stop_meas(&PHY_vars_eNB->dlsch_scrambling_stats); + stop_meas(&eNB->dlsch_scrambling_stats); if (n_frames==1) { - for (s=0; sdlsch_eNB[k][cw]->harq_processes[0]->C; s++) { - if (sdlsch_eNB[k][cw]->harq_processes[0]->Cminus) - Kr = PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->Kminus; + for (s=0; sdlsch[k][cw]->harq_processes[0]->C; s++) { + if (sdlsch[k][cw]->harq_processes[0]->Cminus) + Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kminus; else - Kr = PHY_vars_eNB->dlsch_eNB[k][cw]->harq_processes[0]->Kplus; + Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kplus; Kr_bytes = Kr>>3; for (i=0; idlsch_eNB[k][cw]->harq_processes[0]->c[s][i]); + printf("%d : (%x)\n",i,eNB->dlsch[k][cw]->harq_processes[0]->c[s][i]); } } } - start_meas(&PHY_vars_eNB->dlsch_modulation_stats); + start_meas(&eNB->dlsch_modulation_stats); - re_allocated = dlsch_modulation(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], + re_allocated = dlsch_modulation(eNB->common_vars.txdataF[eNB_id], AMP, subframe, - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, num_pdcch_symbols, - PHY_vars_eNB->dlsch_eNB[k][0], - (transmission_mode==3)||(transmission_mode==4) ? PHY_vars_eNB->dlsch_eNB[k][1] : NULL); + eNB->dlsch[k][0], + (transmission_mode==3)||(transmission_mode==4) ? eNB->dlsch[k][1] : NULL); /* avoid gcc warnings */ (void)re_allocated; - stop_meas(&PHY_vars_eNB->dlsch_modulation_stats); + stop_meas(&eNB->dlsch_modulation_stats); /* if (trials==0 && round==0) printf("RE count %d\n",re_allocated); @@ -2634,54 +2634,54 @@ PMI_FEEDBACK: } //n_users - generate_pilots(PHY_vars_eNB, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], + generate_pilots(eNB, + eNB->common_vars.txdataF[eNB_id], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); - start_meas(&PHY_vars_eNB->ofdm_mod_stats); + start_meas(&eNB->ofdm_mod_stats); - do_OFDM_mod_l(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], - PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id], + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], + eNB->common_vars.txdata[eNB_id], (subframe*2), - &PHY_vars_eNB->lte_frame_parms); + &eNB->frame_parms); - do_OFDM_mod_l(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], - PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id], + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], + eNB->common_vars.txdata[eNB_id], (subframe*2)+1, - &PHY_vars_eNB->lte_frame_parms); + &eNB->frame_parms); - stop_meas(&PHY_vars_eNB->ofdm_mod_stats); - stop_meas(&PHY_vars_eNB->phy_proc_tx); + stop_meas(&eNB->ofdm_mod_stats); + stop_meas(&eNB->phy_proc_tx); - do_OFDM_mod_l(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], - PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id], + do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], + eNB->common_vars.txdata[eNB_id], (subframe*2)+2, - &PHY_vars_eNB->lte_frame_parms); + &eNB->frame_parms); if (n_frames==1) { - write_output("txsigF0.m","txsF0", &PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id][0][subframe*nsymb*PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size], - nsymb*PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size,1,1); + write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], + nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1.m","txsF1", &PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id][1][subframe*nsymb*PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size], - nsymb*PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size,1,1); + if (eNB->frame_parms.nb_antennas_tx>1) + write_output("txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], + nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); } tx_lev = 0; - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { - tx_lev += signal_energy(&PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][aa] - [subframe*PHY_vars_eNB->lte_frame_parms.samples_per_tti], - PHY_vars_eNB->lte_frame_parms.samples_per_tti); + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa] + [subframe*eNB->frame_parms.samples_per_tti], + eNB->frame_parms.samples_per_tti); } tx_lev_dB = (unsigned int) dB_fixed(tx_lev); if (n_frames==1) { printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB); - write_output("txsig0.m","txs0", &PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][0][subframe* PHY_vars_eNB->lte_frame_parms.samples_per_tti], + write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe* eNB->frame_parms.samples_per_tti], - PHY_vars_eNB->lte_frame_parms.samples_per_tti,1,1); + eNB->frame_parms.samples_per_tti,1,1); } } @@ -2710,20 +2710,20 @@ PMI_FEEDBACK: } */ - // printf("Copying tx ..., nsymb %d (n_tx %d), awgn %d\n",nsymb,PHY_vars_eNB->lte_frame_parms.nb_antennas_tx,awgn_flag); + // printf("Copying tx ..., nsymb %d (n_tx %d), awgn %d\n",nsymb,eNB->frame_parms.nb_antennas_tx,awgn_flag); for (i=0; i<2*frame_parms->samples_per_tti; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (awgn_flag == 0) { - s_re[aa][i] = ((double)(((short *)PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + (i<<1)]); - s_im[aa][i] = ((double)(((short *)PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) +(i<<1)+1]); + s_re[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]); + s_im[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); } else { - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { if (aa==0) { - r_re[aarx][i] = ((double)(((short *)PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) +(i<<1)]); - r_im[aarx][i] = ((double)(((short *)PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) +(i<<1)+1]); + r_re[aarx][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[aarx][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); } else { - r_re[aarx][i] += ((double)(((short *)PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) +(i<<1)]); - r_im[aarx][i] += ((double)(((short *)PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id][aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) +(i<<1)+1]); + r_re[aarx][i] += ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[aarx][i] += ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); } } @@ -2744,12 +2744,12 @@ PMI_FEEDBACK: random_channel(eNB2UE[3],0); } - if (PHY_vars_UE->perfect_ce==1) { + if (UE->perfect_ce==1) { // fill in perfect channel estimates - freq_channel(eNB2UE[round],PHY_vars_UE->lte_frame_parms.N_RB_DL,12*PHY_vars_UE->lte_frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); /* write_output("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8); - write_output("channelF.m","chF",eNB2UE[round]->chF[0],12*PHY_vars_UE->lte_frame_parms.N_RB_DL + 1,1,8); + write_output("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8); */ } } @@ -2813,24 +2813,24 @@ PMI_FEEDBACK: //AWGN // This is the SNR on the PDSCH for OFDM symbols without pilots -> rho_A - sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(double)(NB_RB*12)) - SNR - get_pa_dB(PHY_vars_eNB->pdsch_config_dedicated); + sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(NB_RB*12)) - SNR - get_pa_dB(eNB->pdsch_config_dedicated); sigma2 = pow(10,sigma2_dB/10); if (n_frames==1) - printf("Sigma2 %f (sigma2_dB %f,%f,%f )\n",sigma2,sigma2_dB,10*log10((double)PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(double)(NB_RB*12)),get_pa_dB(PHY_vars_eNB->pdsch_config_dedicated)); + printf("Sigma2 %f (sigma2_dB %f,%f,%f )\n",sigma2,sigma2_dB,10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(NB_RB*12)),get_pa_dB(eNB->pdsch_config_dedicated)); for (i=0; i<2*frame_parms->samples_per_tti; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { //printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]); - ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti)+2*i] = + ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] = (short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); - ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti)+2*i+1] = + ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] = (short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); } } - // lte_sync_time_init(PHY_vars_eNB->lte_frame_parms,lte_ue_common_vars); - // lte_sync_time(lte_ue_common_vars->rxdata, PHY_vars_eNB->lte_frame_parms); + // lte_sync_time_init(eNB->frame_parms,common_vars); + // lte_sync_time(common_vars->rxdata, eNB->frame_parms); // lte_sync_time_free(); /* @@ -2850,13 +2850,13 @@ PMI_FEEDBACK: */ if (n_frames==1) { - printf("RX level in null symbol %d\n",dB_fixed(signal_energy(&PHY_vars_UE->lte_ue_common_vars.rxdata[0][160+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); - printf("RX level in data symbol %d\n",dB_fixed(signal_energy(&PHY_vars_UE->lte_ue_common_vars.rxdata[0][160+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); + printf("RX level in null symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); + printf("RX level in data symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); printf("rx_level Null symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)))); printf("rx_level data symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)))); } - if (PHY_vars_eNB->lte_frame_parms.Ncp == 0) { // normal prefix + if (eNB->frame_parms.Ncp == 0) { // normal prefix pilot1 = 4; pilot2 = 7; pilot3 = 11; @@ -2866,7 +2866,7 @@ PMI_FEEDBACK: pilot3 = 9; } - start_meas(&PHY_vars_UE->phy_proc_rx); + start_meas(&UE->phy_proc_rx); // Inner receiver scheduling for 3 slots for (Ns=(2*subframe); Ns<((2*subframe)+3); Ns++) { @@ -2887,24 +2887,24 @@ PMI_FEEDBACK: */ - start_meas(&PHY_vars_UE->ofdm_demod_stats); - slot_fep(PHY_vars_UE, + start_meas(&UE->ofdm_demod_stats); + slot_fep(UE, l, Ns%20, 0, 0, 0); - stop_meas(&PHY_vars_UE->ofdm_demod_stats); + stop_meas(&UE->ofdm_demod_stats); - if (PHY_vars_UE->perfect_ce==1) { + if (UE->perfect_ce==1) { if (awgn_flag==0) { for(k=0; knb_antennas_tx; aa++) { for (aarx=0; aarxnb_antennas_rx; aarx++) { for (i=0; iN_RB_DL*12; i++) { - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( + ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP); - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( + ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP); } } @@ -2914,8 +2914,8 @@ PMI_FEEDBACK: for(aa=0; aanb_antennas_tx; aa++) { for (aarx=0; aarxnb_antennas_rx; aarx++) { for (i=0; iN_RB_DL*12; i++) { - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2; + ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); + ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2; } } } @@ -2924,31 +2924,31 @@ PMI_FEEDBACK: if ((Ns==((2*subframe))) && (l==0)) { - lte_ue_measurements(PHY_vars_UE, - subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti, + lte_ue_measurements(UE, + subframe*UE->frame_parms.samples_per_tti, 1, 0); /* debug_msg("RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), avg rx power %d dB (%d lin), RX gain %d dB\n", - PHY_vars_UE->PHY_measurements.rx_rssi_dBm[0] - ((PHY_vars_UE->lte_frame_parms.nb_antennas_rx==2) ? 3 : 0), - PHY_vars_UE->PHY_measurements.wideband_cqi_dB[0][0], - PHY_vars_UE->PHY_measurements.wideband_cqi_dB[0][1], - PHY_vars_UE->PHY_measurements.wideband_cqi[0][0], - PHY_vars_UE->PHY_measurements.wideband_cqi[0][1], - PHY_vars_UE->PHY_measurements.rx_power_avg_dB[0], - PHY_vars_UE->PHY_measurements.rx_power_avg[0], - PHY_vars_UE->rx_total_gain_dB); + UE->measurements.rx_rssi_dBm[0] - ((UE->frame_parms.nb_antennas_rx==2) ? 3 : 0), + UE->measurements.wideband_cqi_dB[0][0], + UE->measurements.wideband_cqi_dB[0][1], + UE->measurements.wideband_cqi[0][0], + UE->measurements.wideband_cqi[0][1], + UE->measurements.rx_power_avg_dB[0], + UE->measurements.rx_power_avg[0], + UE->rx_total_gain_dB); debug_msg("N0 %d dBm digital (%d, %d) dB, linear (%d, %d), avg noise power %d dB (%d lin)\n", - PHY_vars_UE->PHY_measurements.n0_power_tot_dBm, - PHY_vars_UE->PHY_measurements.n0_power_dB[0], - PHY_vars_UE->PHY_measurements.n0_power_dB[1], - PHY_vars_UE->PHY_measurements.n0_power[0], - PHY_vars_UE->PHY_measurements.n0_power[1], - PHY_vars_UE->PHY_measurements.n0_power_avg_dB, - PHY_vars_UE->PHY_measurements.n0_power_avg); + UE->measurements.n0_power_tot_dBm, + UE->measurements.n0_power_dB[0], + UE->measurements.n0_power_dB[1], + UE->measurements.n0_power[0], + UE->measurements.n0_power[1], + UE->measurements.n0_power_avg_dB, + UE->measurements.n0_power_avg); debug_msg("Wideband CQI tot %d dB, wideband cqi avg %d dB\n", - PHY_vars_UE->PHY_measurements.wideband_cqi_tot[0], - PHY_vars_UE->PHY_measurements.wideband_cqi_avg[0]); + UE->measurements.wideband_cqi_tot[0], + UE->measurements.wideband_cqi_avg[0]); */ if (transmission_mode==5 || transmission_mode==6) { @@ -2965,21 +2965,21 @@ PMI_FEEDBACK: if ((Ns==(2*subframe)) && (l==pilot1)) {// process symbols 0,1,2 if (dci_flag == 1) { - PHY_vars_UE->UE_mode[0] = PUSCH; - start_meas(&PHY_vars_UE->dlsch_rx_pdcch_stats); - rx_pdcch(&PHY_vars_UE->lte_ue_common_vars, - PHY_vars_UE->lte_ue_pdcch_vars, - &PHY_vars_UE->lte_frame_parms, + UE->UE_mode[0] = PUSCH; + start_meas(&UE->dlsch_rx_pdcch_stats); + rx_pdcch(&UE->common_vars, + UE->pdcch_vars, + &UE->frame_parms, subframe, 0, - (PHY_vars_UE->lte_frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, - PHY_vars_UE->high_speed_flag, + (UE->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, + UE->high_speed_flag, 0); - stop_meas(&PHY_vars_UE->dlsch_rx_pdcch_stats); + stop_meas(&UE->dlsch_rx_pdcch_stats); // overwrite number of pdcch symbols - PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols; + UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols; - dci_cnt = dci_decoding_procedure(PHY_vars_UE, + dci_cnt = dci_decoding_procedure(UE, dci_alloc_rx,1, eNB_id, subframe); @@ -3005,7 +3005,7 @@ PMI_FEEDBACK: for (i=0; idlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->first_tx=1; + if (round == 0) UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->first_tx=1; if ((dci_alloc_rx[i].rnti == n_rnti) && (generate_ue_dlsch_params_from_dci(0, @@ -3013,26 +3013,26 @@ PMI_FEEDBACK: dci_alloc_rx[i].dci_pdu, dci_alloc_rx[i].rnti, dci_alloc_rx[i].format, - PHY_vars_UE->dlsch_ue[0], - &PHY_vars_UE->lte_frame_parms, - PHY_vars_UE->pdsch_config_dedicated, + UE->dlsch[0], + &UE->frame_parms, + UE->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI)==0)) { - //dump_dci(&PHY_vars_UE->lte_frame_parms,&dci_alloc_rx[i]); - coded_bits_per_codeword = get_G(&PHY_vars_eNB->lte_frame_parms, - PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->nb_rb, - PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->rb_alloc_even, - get_Qm(PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->mcs), - PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->Nl, - PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols, + //dump_dci(&UE->frame_parms,&dci_alloc_rx[i]); + coded_bits_per_codeword = get_G(&eNB->frame_parms, + UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->nb_rb, + UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->rb_alloc_even, + get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs), + UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->Nl, + UE->pdcch_vars[0]->num_pdcch_symbols, 0,subframe); /* - rate = (double)dlsch_tbs25[get_I_TBS(PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->mcs)][PHY_vars_UE->dlsch_ue[0][0]->nb_rb-1]/(coded_bits_per_codeword); - rate*=get_Qm(PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->mcs); + rate = (double)dlsch_tbs25[get_I_TBS(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs)][UE->dlsch[0][0]->nb_rb-1]/(coded_bits_per_codeword); + rate*=get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs); */ - printf("num_pdcch_symbols %d, G %d, TBS %d\n",PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols,coded_bits_per_codeword, - PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->TBS); + printf("num_pdcch_symbols %d, G %d, TBS %d\n",UE->pdcch_vars[0]->num_pdcch_symbols,coded_bits_per_codeword, + UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->TBS); dlsch_active = 1; } else { @@ -3057,10 +3057,10 @@ PMI_FEEDBACK: } // if dci_flag==1 else { //dci_flag == 0 - PHY_vars_UE->lte_ue_pdcch_vars[0]->crnti = n_rnti; - PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols; + UE->pdcch_vars[0]->crnti = n_rnti; + UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols; - if (round == 0) PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->first_tx=1; + if (round == 0) UE->dlsch[0][0]->harq_processes[0]->first_tx=1; switch (transmission_mode) { case 1: @@ -3070,28 +3070,28 @@ PMI_FEEDBACK: &DLSCH_alloc_pdu_1[0], (common_flag==0)? C_RNTI : SI_RNTI, (common_flag==0)? format1 : format1A, - PHY_vars_UE->dlsch_ue[0], - &PHY_vars_UE->lte_frame_parms, - PHY_vars_UE->pdsch_config_dedicated, + UE->dlsch[0], + &UE->frame_parms, + UE->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI); break; case 3: - // printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->round,PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->first_tx); + // printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx); generate_ue_dlsch_params_from_dci(0, subframe, &DLSCH_alloc_pdu_1[0], (common_flag==0)? C_RNTI : SI_RNTI, (common_flag==0)? format2A : format1A, - PHY_vars_UE->dlsch_ue[0], - &PHY_vars_UE->lte_frame_parms, - PHY_vars_UE->pdsch_config_dedicated, + UE->dlsch[0], + &UE->frame_parms, + UE->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI); - // printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->round,PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->first_tx); + // printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx); break; case 4: @@ -3100,9 +3100,9 @@ PMI_FEEDBACK: &DLSCH_alloc_pdu_1[0], (common_flag==0)? C_RNTI : SI_RNTI, (common_flag==0)? format2 : format1A, - PHY_vars_UE->dlsch_ue[0], - &PHY_vars_UE->lte_frame_parms, - PHY_vars_UE->pdsch_config_dedicated, + UE->dlsch[0], + &UE->frame_parms, + UE->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI); @@ -3115,9 +3115,9 @@ PMI_FEEDBACK: &DLSCH_alloc_pdu2_1E[0], C_RNTI, format1E_2A_M10PRB, - PHY_vars_UE->dlsch_ue[0], - &PHY_vars_UE->lte_frame_parms, - PHY_vars_UE->pdsch_config_dedicated, + UE->dlsch[0], + &UE->frame_parms, + UE->pdsch_config_dedicated, SI_RNTI, 0, P_RNTI); @@ -3133,45 +3133,45 @@ PMI_FEEDBACK: if ((Ns==(1+(2*subframe))) && (l==0)) {// process PDSCH symbols 1,2,3,4,5,(6 Normal Prefix) if ((transmission_mode == 5) && - (PHY_vars_UE->dlsch_ue[eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->dl_power_off==0) && - (openair_daq_vars.use_ia_receiver ==1)) { + (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->dl_power_off==0) && + (UE->use_ia_receiver ==1)) { dual_stream_UE = 1; } else { dual_stream_UE = 0; } - start_meas(&PHY_vars_UE->dlsch_llr_stats); + start_meas(&UE->dlsch_llr_stats); - for (m=PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols; + for (m=UE->pdcch_vars[0]->num_pdcch_symbols; mlte_ue_pdcch_vars[0]->num_pdcch_symbols)?1:0, + (m==UE->pdcch_vars[0]->num_pdcch_symbols)?1:0, dual_stream_UE, i_mod, - PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid)==-1) { + UE->dlsch[0][0]->current_harq_pid)==-1) { dlsch_active = 0; break; } } - stop_meas(&PHY_vars_UE->dlsch_llr_stats); + stop_meas(&UE->dlsch_llr_stats); } if ((Ns==(1+(2*subframe))) && (l==pilot1)) { // process symbols (6 Extended Prefix),7,8,9 - start_meas(&PHY_vars_UE->dlsch_llr_stats); + start_meas(&UE->dlsch_llr_stats); for (m=pilot2; mdlsch_ue[0][0]->current_harq_pid)==-1) { + UE->dlsch[0][0]->current_harq_pid)==-1) { dlsch_active=0; break; } } - stop_meas(&PHY_vars_UE->dlsch_llr_stats); + stop_meas(&UE->dlsch_llr_stats); } if ((Ns==(2+(2*subframe))) && (l==0)) { // process symbols 10,11,(12,13 Normal Prefix) do deinterleaving for TTI - start_meas(&PHY_vars_UE->dlsch_llr_stats); + start_meas(&UE->dlsch_llr_stats); for (m=pilot3; - mlte_frame_parms.symbols_per_tti; + mframe_parms.symbols_per_tti; m++) { - if (rx_pdsch(PHY_vars_UE, + if (rx_pdsch(UE, PDSCH, eNB_id, eNB_id_i, @@ -3204,61 +3204,61 @@ PMI_FEEDBACK: 0, dual_stream_UE, i_mod, - PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid)==-1) { + UE->dlsch[0][0]->current_harq_pid)==-1) { dlsch_active=0; break; } } - stop_meas(&PHY_vars_UE->dlsch_llr_stats); + stop_meas(&UE->dlsch_llr_stats); } if (test_perf ==0 ) { if ((n_frames==1) && (Ns==(2+(2*subframe))) && (l==0)) { write_output("ch0.m","ch0",eNB2UE[0]->ch[0],eNB2UE[0]->channel_length,1,8); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1) - write_output("ch1.m","ch1",eNB2UE[0]->ch[PHY_vars_eNB->lte_frame_parms.nb_antennas_rx],eNB2UE[0]->channel_length,1,8); + if (eNB->frame_parms.nb_antennas_tx>1) + write_output("ch1.m","ch1",eNB2UE[0]->ch[eNB->frame_parms.nb_antennas_rx],eNB2UE[0]->channel_length,1,8); //common vars - write_output("rxsig0.m","rxs0", &PHY_vars_UE->lte_ue_common_vars.rxdata[0][0],10*PHY_vars_UE->lte_frame_parms.samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", &PHY_vars_UE->lte_ue_common_vars.rxdataF[0][0],PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + write_output("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); + write_output("rxsigF0.m","rxsF0", &UE->common_vars.rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - if (PHY_vars_UE->lte_frame_parms.nb_antennas_rx>1) { - write_output("rxsig1.m","rxs1", PHY_vars_UE->lte_ue_common_vars.rxdata[1],PHY_vars_UE->lte_frame_parms.samples_per_tti,1,1); - write_output("rxsigF1.m","rxsF1", PHY_vars_UE->lte_ue_common_vars.rxdataF[1],PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + if (UE->frame_parms.nb_antennas_rx>1) { + write_output("rxsig1.m","rxs1", UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1); + write_output("rxsigF1.m","rxsF1", UE->common_vars.rxdataF[1],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); } write_output("dlsch00_r0.m","dl00_r0", - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][0][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][0][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - if (PHY_vars_UE->lte_frame_parms.nb_antennas_rx>1) + if (UE->frame_parms.nb_antennas_rx>1) write_output("dlsch01_r0.m","dl01_r0", - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][1][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][1][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1) + if (eNB->frame_parms.nb_antennas_tx>1) write_output("dlsch10_r0.m","dl10_r0", - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][2][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][2][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - if ((PHY_vars_UE->lte_frame_parms.nb_antennas_rx>1) && (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1)) + if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) write_output("dlsch11_r0.m","dl11_r0", - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][3][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb/2,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][3][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); //pdsch_vars - dump_dlsch2(PHY_vars_UE,eNB_id,coded_bits_per_codeword,round); - //dump_dlsch2(PHY_vars_UE,eNB_id_i,coded_bits_per_codeword); - write_output("dlsch_e.m","e",PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + dump_dlsch2(UE,eNB_id,coded_bits_per_codeword,round); + //dump_dlsch2(UE,eNB_id_i,coded_bits_per_codeword); + write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); //pdcch_vars - write_output("pdcchF0_ext.m","pdcchF_ext", PHY_vars_UE->lte_ue_pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*PHY_vars_UE->lte_frame_parms.ofdm_symbol_size,1,1); - write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",PHY_vars_UE->lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); + write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); + write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",PHY_vars_UE->lte_ue_pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",PHY_vars_UE->lte_ue_pdcch_vars[eNB_id]->llr,2400,1,4); + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1); + write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNB_id]->llr,2400,1,4); } } @@ -3271,30 +3271,30 @@ PMI_FEEDBACK: if(abstx) { if (trials==0 && round==0 && transmission_mode>=5) { for (iii=0; iiilte_ue_pdsch_vars[eNB_id]->pmi_ext[iii]),(PHY_vars_UE->lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[iii])); - fprintf(csv_fd,"%x,%x,",(PHY_vars_UE->lte_ue_pdsch_vars[eNB_id]->pmi_ext[iii]),(PHY_vars_UE->lte_ue_pdsch_vars[eNB_id]->pmi_ext[iii])); - printf("%x ",(PHY_vars_UE->lte_ue_pdsch_vars[eNB_id]->pmi_ext[iii])); + //fprintf(csv_fd, "%d, %d", (UE->lte_ue_pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[iii])); + fprintf(csv_fd,"%x,%x,",(UE->pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->pdsch_vars[eNB_id]->pmi_ext[iii])); + printf("%x ",(UE->pdsch_vars[eNB_id]->pmi_ext[iii])); } } } for (int cw=Kmimo-1; cw>=0; cw--) { - PHY_vars_UE->dlsch_ue[0][cw]->rnti = (common_flag==0) ? n_rnti: SI_RNTI; - coded_bits_per_codeword = get_G(&PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->dlsch_eNB[0][cw]->harq_processes[0]->nb_rb, - PHY_vars_eNB->dlsch_eNB[0][cw]->harq_processes[0]->rb_alloc, - get_Qm(PHY_vars_eNB->dlsch_eNB[0][cw]->harq_processes[0]->mcs), - PHY_vars_eNB->dlsch_eNB[0][cw]->harq_processes[0]->Nl, + UE->dlsch[0][cw]->rnti = (common_flag==0) ? n_rnti: SI_RNTI; + coded_bits_per_codeword = get_G(&eNB->frame_parms, + eNB->dlsch[0][cw]->harq_processes[0]->nb_rb, + eNB->dlsch[0][cw]->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch[0][cw]->harq_processes[0]->mcs), + eNB->dlsch[0][cw]->harq_processes[0]->Nl, num_pdcch_symbols, 0,subframe); - PHY_vars_UE->dlsch_ue[0][cw]->harq_processes[PHY_vars_UE->dlsch_ue[0][cw]->current_harq_pid]->G = coded_bits_per_codeword; + UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid]->G = coded_bits_per_codeword; // calculate uncoded BLER uncoded_ber=0; for (i=0;idlsch_eNB[0][0]->harq_processes[0]->e[i] != (PHY_vars_UE->lte_ue_pdsch_vars[0]->llr[0][i]<0)) { + if (eNB->dlsch[0][0]->harq_processes[0]->e[i] != (UE->pdsch_vars[0]->llr[0][i]<0)) { uncoded_ber_bit[i] = 1; uncoded_ber++; } @@ -3308,29 +3308,29 @@ PMI_FEEDBACK: write_output("uncoded_ber_bit.m","uncoded_ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); - start_meas(&PHY_vars_UE->dlsch_unscrambling_stats); - dlsch_unscrambling(&PHY_vars_UE->lte_frame_parms, + start_meas(&UE->dlsch_unscrambling_stats); + dlsch_unscrambling(&UE->frame_parms, 0, - PHY_vars_UE->dlsch_ue[0][cw], + UE->dlsch[0][cw], coded_bits_per_codeword, - PHY_vars_UE->lte_ue_pdsch_vars[eNB_id]->llr[cw], + UE->pdsch_vars[eNB_id]->llr[cw], 0, subframe<<1); - stop_meas(&PHY_vars_UE->dlsch_unscrambling_stats); + stop_meas(&UE->dlsch_unscrambling_stats); - start_meas(&PHY_vars_UE->dlsch_decoding_stats); - ret = dlsch_decoding(PHY_vars_UE, - PHY_vars_UE->lte_ue_pdsch_vars[eNB_id]->llr[cw], - &PHY_vars_UE->lte_frame_parms, - PHY_vars_UE->dlsch_ue[0][cw], - PHY_vars_UE->dlsch_ue[0][cw]->harq_processes[PHY_vars_UE->dlsch_ue[0][cw]->current_harq_pid], + start_meas(&UE->dlsch_decoding_stats); + ret = dlsch_decoding(UE, + UE->pdsch_vars[eNB_id]->llr[cw], + &UE->frame_parms, + UE->dlsch[0][cw], + UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid], subframe, - PHY_vars_UE->dlsch_ue[0][cw]->current_harq_pid, + UE->dlsch[0][cw]->current_harq_pid, 1,llr8_flag); - stop_meas(&PHY_vars_UE->dlsch_decoding_stats); + stop_meas(&UE->dlsch_decoding_stats); if (cw==1) { - if (ret <= PHY_vars_UE->dlsch_ue[0][cw]->max_turbo_iterations) { + if (ret <= UE->dlsch[0][cw]->max_turbo_iterations) { } else { errs2[round]++; } @@ -3338,10 +3338,10 @@ PMI_FEEDBACK: } - stop_meas(&PHY_vars_UE->phy_proc_rx); + stop_meas(&UE->phy_proc_rx); - if (ret <= PHY_vars_UE->dlsch_ue[0][0]->max_turbo_iterations) { + if (ret <= UE->dlsch[0][0]->max_turbo_iterations) { avg_iter += ret; iter_trials++; @@ -3349,15 +3349,15 @@ PMI_FEEDBACK: if (n_frames==1) printf("No DLSCH errors found (round %d),uncoded ber %f\n",round,uncoded_ber); - PHY_vars_UE->total_TBS[eNB_id] = PHY_vars_UE->total_TBS[eNB_id] + PHY_vars_UE->dlsch_ue[eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]->TBS; + UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->TBS; TB0_active = 0; - if (PHY_vars_UE->dlsch_ue[eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) { //try to decode second stream using SIC + if (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) { //try to decode second stream using SIC /* - for (round = 0 ; round < PHY_vars_UE->dlsch_ue[eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]->round ; round++) { + for (round = 0 ; round < UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->round ; round++) { // re-encoding of first stream - dlsch0_ue_harq = PHY_vars_UE->dlsch_ue[eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]; - dlsch0_eNB_harq = PHY_vars_UE->dlsch_eNB[eNB_id]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]; + dlsch0_ue_harq = UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]; + dlsch0_eNB_harq = UE->dlsch[eNB_id]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]; dlsch0_eNB_harq->mimo_mode = LARGE_CDD; dlsch0_eNB_harq->rb_alloc[0] = dlsch0_ue_harq->rb_alloc_even[0]; dlsch0_eNB_harq->nb_rb = dlsch0_ue_harq->nb_rb; @@ -3369,17 +3369,17 @@ PMI_FEEDBACK: dlsch0_eNB_harq->dl_power_off = dlsch0_ue_harq->dl_power_off; dlsch0_eNB_harq->status = dlsch0_ue_harq->status; - PHY_vars_UE->dlsch_eNB[eNB_id]->active = PHY_vars_UE->dlsch_ue[eNB_id][0]->active; - PHY_vars_UE->dlsch_eNB[eNB_id]->rnti = PHY_vars_UE->dlsch_ue[eNB_id][0]->rnti; + UE->dlsch[eNB_id]->active = UE->dlsch[eNB_id][0]->active; + UE->dlsch[eNB_id]->rnti = UE->dlsch[eNB_id][0]->rnti; - dlsch_encoding(PHY_vars_UE->dlsch_ue[eNB_id][0]->harq_processes[PHY_vars_UE->dlsch_ue[eNB_id][0]->current_harq_pid]->b, - &PHY_vars_UE->lte_frame_parms, + dlsch_encoding(UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->b, + &UE->frame_parms, num_pdcch_symbols, - PHY_vars_UE->dlsch_eNB[0], + UE->dlsch[0], 0,subframe, - &PHY_vars_UE->dlsch_rate_matching_stats, - &PHY_vars_UE->dlsch_turbo_encoding_stats, - &PHY_vars_UE->dlsch_interleaving_stats + &UE->dlsch_rate_matching_stats, + &UE->dlsch_turbo_encoding_stats, + &UE->dlsch_interleaving_stats ); //scrambling @@ -3402,73 +3402,73 @@ PMI_FEEDBACK: //if ((n_frames==1) || (SNR>=30)) { printf("DLSCH errors found (round %d), uncoded ber %f\n",round,uncoded_ber); - for (s=0; sdlsch_ue[0][0]->harq_processes[0]->C; s++) { - if (sdlsch_ue[0][0]->harq_processes[0]->Cminus) - Kr = PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->Kminus; + for (s=0; sdlsch[0][0]->harq_processes[0]->C; s++) { + if (sdlsch[0][0]->harq_processes[0]->Cminus) + Kr = UE->dlsch[0][0]->harq_processes[0]->Kminus; else - Kr = PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->Kplus; + Kr = UE->dlsch[0][0]->harq_processes[0]->Kplus; Kr_bytes = Kr>>3; printf("Decoded_output (Segment %d):\n",s); for (i=0; idlsch_ue[0][0]->harq_processes[0]->c[s][i],PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->c[s][i]^PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->c[s][i]); + printf("%d : %x (%x)\n",i,UE->dlsch[0][0]->harq_processes[0]->c[s][i],UE->dlsch[0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]); } sprintf(fname,"rxsig0_r%d.m",round); sprintf(vname,"rxs0_r%d",round); - write_output(fname,vname, &PHY_vars_UE->lte_ue_common_vars.rxdata[0][0],10*PHY_vars_UE->lte_frame_parms.samples_per_tti,1,1); + write_output(fname,vname, &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); sprintf(fname,"rxsigF0_r%d.m",round); sprintf(vname,"rxs0F_r%d",round); - write_output(fname,vname, &PHY_vars_UE->lte_ue_common_vars.rxdataF[0][0],2*PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,2,1); + write_output(fname,vname, &UE->common_vars.rxdataF[0][0],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1); - if (PHY_vars_UE->lte_frame_parms.nb_antennas_rx>1) { + if (UE->frame_parms.nb_antennas_rx>1) { sprintf(fname,"rxsig1_r%d.m",round); sprintf(vname,"rxs1_r%d.m",round); - write_output(fname,vname, PHY_vars_UE->lte_ue_common_vars.rxdata[1],PHY_vars_UE->lte_frame_parms.samples_per_tti,1,1); + write_output(fname,vname, UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1); sprintf(fname,"rxsig1F_r%d.m",round); sprintf(vname,"rxs1F_r%d.m",round); - write_output(fname,vname, PHY_vars_UE->lte_ue_common_vars.rxdataF[1],2*PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,2,1); + write_output(fname,vname, UE->common_vars.rxdataF[1],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1); } sprintf(fname,"dlsch00_r%d.m",round); sprintf(vname,"dl00_r%d",round); write_output(fname,vname, - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][0][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][0][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - if (PHY_vars_UE->lte_frame_parms.nb_antennas_rx>1) { + if (UE->frame_parms.nb_antennas_rx>1) { sprintf(fname,"dlsch01_r%d.m",round); sprintf(vname,"dl01_r%d",round); write_output(fname,vname, - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][1][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb/2,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][1][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); } - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1) { + if (eNB->frame_parms.nb_antennas_tx>1) { sprintf(fname,"dlsch10_r%d.m",round); sprintf(vname,"dl10_r%d",round); write_output(fname,vname, - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][2][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb/2,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][2][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); } - if ((PHY_vars_UE->lte_frame_parms.nb_antennas_rx>1) && (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1)) { + if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) { sprintf(fname,"dlsch11_r%d.m",round); sprintf(vname,"dl11_r%d",round); write_output(fname,vname, - &(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[eNB_id][3][0]), - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size*nsymb/2,1,1); + &(UE->common_vars.dl_ch_estimates[eNB_id][3][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); } //pdsch_vars - dump_dlsch2(PHY_vars_UE,eNB_id,coded_bits_per_codeword,round); + dump_dlsch2(UE,eNB_id,coded_bits_per_codeword,round); /* - write_output("dlsch_e.m","e",PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); write_output("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); - write_output("dlsch_eNB_w.m","w",PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4); - write_output("dlsch_UE_w.m","w",PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); + write_output("dlsch_w.m","w",eNB->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4); + write_output("dlsch_w.m","w",UE->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); */ if (round == 3) exit(-1); @@ -3477,12 +3477,12 @@ PMI_FEEDBACK: // printf("round %d errors %d/%d\n",round,errs[round],trials); round++; - // PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->round++; + // UE->dlsch[0][0]->harq_processes[0]->round++; } if (xforms==1) { phy_scope_UE(form_ue, - PHY_vars_UE, + UE, eNB_id, 0,// UE_id subframe); @@ -3498,29 +3498,29 @@ PMI_FEEDBACK: //len = chbch_stats_read(stats_buffer,NULL,0,4096); //printf("%s\n\n",stats_buffer); - if (PHY_vars_UE->frame_rx % 10 == 0) { - PHY_vars_UE->bitrate[eNB_id] = (PHY_vars_UE->total_TBS[eNB_id] - PHY_vars_UE->total_TBS_last[eNB_id])*10; - LOG_D(PHY,"[UE %d] Calculating bitrate: total_TBS = %d, total_TBS_last = %d, bitrate = %d kbits/s\n",PHY_vars_UE->Mod_id,PHY_vars_UE->total_TBS[eNB_id],PHY_vars_UE->total_TBS_last[eNB_id], - PHY_vars_UE->bitrate[eNB_id]/1000); - PHY_vars_UE->total_TBS_last[eNB_id] = PHY_vars_UE->total_TBS[eNB_id]; + if (UE->frame_rx % 10 == 0) { + UE->bitrate[eNB_id] = (UE->total_TBS[eNB_id] - UE->total_TBS_last[eNB_id])*10; + LOG_D(PHY,"[UE %d] Calculating bitrate: total_TBS = %d, total_TBS_last = %d, bitrate = %d kbits/s\n",UE->Mod_id,UE->total_TBS[eNB_id],UE->total_TBS_last[eNB_id], + UE->bitrate[eNB_id]/1000); + UE->total_TBS_last[eNB_id] = UE->total_TBS[eNB_id]; } - PHY_vars_UE->frame_rx++; + UE->frame_rx++; /* calculate the total processing time for each packet, * get the max, min, and number of packets that exceed t>2000us */ - double t_tx = (double)PHY_vars_eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0; - double t_tx_ifft = (double)PHY_vars_eNB->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0; - double t_tx_mod = (double)PHY_vars_eNB->dlsch_modulation_stats.p_time/cpu_freq_GHz/1000.0; - double t_tx_enc = (double)PHY_vars_eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx = (double)eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0; + double t_tx_ifft = (double)eNB->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx_mod = (double)eNB->dlsch_modulation_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx_enc = (double)eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx = (double)PHY_vars_UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; - double t_rx_fft = (double)PHY_vars_UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx_demod = (double)PHY_vars_UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx_dec = (double)PHY_vars_UE->dlsch_decoding_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx = (double)UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; + double t_rx_fft = (double)UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx_demod = (double)UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx_dec = (double)UE->dlsch_decoding_stats.p_time/cpu_freq_GHz/1000.0; if (t_tx > t_tx_max) t_tx_max = t_tx; @@ -3644,7 +3644,7 @@ PMI_FEEDBACK: printf("\n**********************SNR = %f dB (tx_lev %f, sigma2_dB %f)**************************\n", SNR, - (double)tx_lev_dB+10*log10(PHY_vars_UE->lte_frame_parms.ofdm_symbol_size/(NB_RB*12)), + (double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12)), sigma2_dB); printf("Errors (%d(%d)/%d %d/%d %d/%d %d/%d), Pe = (%e,%e,%e,%e), dci_errors %d/%d, Pe = %e => effective rate %f (%2.1f%%,%f, %f), normalized delay %f (%f)\n", @@ -3667,119 +3667,119 @@ PMI_FEEDBACK: rate*effective_rate, 100*effective_rate, rate, - rate*get_Qm(PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid]->mcs), + rate*get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ - (double)PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, + (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); if (print_perf==1) { printf("eNB TX function statistics (per 1ms subframe)\n\n"); - std_phy_proc_tx = sqrt((double)PHY_vars_eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->phy_proc_tx.trials - pow((double)PHY_vars_eNB->phy_proc_tx.diff/PHY_vars_eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); - printf("Total PHY proc tx :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_tx.diff/PHY_vars_eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_tx.trials); + std_phy_proc_tx = sqrt((double)eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->phy_proc_tx.trials - pow((double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc tx :%f us (%d trials)\n",(double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_tx.trials); printf("|__ Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped); - std_phy_proc_tx_ifft = sqrt((double)PHY_vars_eNB->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->ofdm_mod_stats.trials - pow((double)PHY_vars_eNB->ofdm_mod_stats.diff/PHY_vars_eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2)); - printf("OFDM_mod time :%f us (%d trials)\n",(double)PHY_vars_eNB->ofdm_mod_stats.diff/PHY_vars_eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ofdm_mod_stats.trials); + std_phy_proc_tx_ifft = sqrt((double)eNB->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->ofdm_mod_stats.trials - pow((double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2)); + printf("OFDM_mod time :%f us (%d trials)\n",(double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,eNB->ofdm_mod_stats.trials); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3); - std_phy_proc_tx_mod = sqrt((double)PHY_vars_eNB->dlsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->dlsch_modulation_stats.trials - pow((double)PHY_vars_eNB->dlsch_modulation_stats.diff/PHY_vars_eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000,2)); - printf("DLSCH modulation time :%f us (%d trials)\n",(double)PHY_vars_eNB->dlsch_modulation_stats.diff/PHY_vars_eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_eNB->dlsch_modulation_stats.trials); + std_phy_proc_tx_mod = sqrt((double)eNB->dlsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->dlsch_modulation_stats.trials - pow((double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH modulation time :%f us (%d trials)\n",(double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0, + eNB->dlsch_modulation_stats.trials); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3); - printf("DLSCH scrambling time :%f us (%d trials)\n",(double)PHY_vars_eNB->dlsch_scrambling_stats.diff/PHY_vars_eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_eNB->dlsch_scrambling_stats.trials); - std_phy_proc_tx_enc = sqrt((double)PHY_vars_eNB->dlsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->dlsch_encoding_stats.trials - pow((double)PHY_vars_eNB->dlsch_encoding_stats.diff/PHY_vars_eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000,2)); - printf("DLSCH encoding time :%f us (%d trials)\n",(double)PHY_vars_eNB->dlsch_encoding_stats.diff/PHY_vars_eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_eNB->dlsch_modulation_stats.trials); + printf("DLSCH scrambling time :%f us (%d trials)\n",(double)eNB->dlsch_scrambling_stats.diff/eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0, + eNB->dlsch_scrambling_stats.trials); + std_phy_proc_tx_enc = sqrt((double)eNB->dlsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->dlsch_encoding_stats.trials - pow((double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH encoding time :%f us (%d trials)\n",(double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000.0, + eNB->dlsch_modulation_stats.trials); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3); printf("|__ DLSCH turbo encoding time :%f us (%d trials)\n", - ((double)PHY_vars_eNB->dlsch_turbo_encoding_stats.trials/PHY_vars_eNB->dlsch_encoding_stats.trials)*(double) - PHY_vars_eNB->dlsch_turbo_encoding_stats.diff/PHY_vars_eNB->dlsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_turbo_encoding_stats.trials); + ((double)eNB->dlsch_turbo_encoding_stats.trials/eNB->dlsch_encoding_stats.trials)*(double) + eNB->dlsch_turbo_encoding_stats.diff/eNB->dlsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_turbo_encoding_stats.trials); printf("|__ DLSCH rate-matching time :%f us (%d trials)\n", - ((double)PHY_vars_eNB->dlsch_rate_matching_stats.trials/PHY_vars_eNB->dlsch_encoding_stats.trials)*(double) - PHY_vars_eNB->dlsch_rate_matching_stats.diff/PHY_vars_eNB->dlsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_rate_matching_stats.trials); + ((double)eNB->dlsch_rate_matching_stats.trials/eNB->dlsch_encoding_stats.trials)*(double) + eNB->dlsch_rate_matching_stats.diff/eNB->dlsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_rate_matching_stats.trials); printf("|__ DLSCH sub-block interleaving time :%f us (%d trials)\n", - ((double)PHY_vars_eNB->dlsch_interleaving_stats.trials/PHY_vars_eNB->dlsch_encoding_stats.trials)*(double) - PHY_vars_eNB->dlsch_interleaving_stats.diff/PHY_vars_eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_interleaving_stats.trials); + ((double)eNB->dlsch_interleaving_stats.trials/eNB->dlsch_encoding_stats.trials)*(double) + eNB->dlsch_interleaving_stats.diff/eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_interleaving_stats.trials); printf("\n\nUE RX function statistics (per 1ms subframe)\n\n"); - std_phy_proc_rx = sqrt((double)PHY_vars_UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->phy_proc_rx.trials - pow((double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); - printf("Total PHY proc rx :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->phy_proc_rx.trials*2/3); + std_phy_proc_rx = sqrt((double)UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->phy_proc_rx.trials - pow((double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc rx :%f us (%d trials)\n",(double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0, + UE->phy_proc_rx.trials*2/3); printf("|__Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped); - std_phy_proc_rx_fft = sqrt((double)PHY_vars_UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->ofdm_demod_stats.trials - pow((double)PHY_vars_UE->ofdm_demod_stats.diff/PHY_vars_UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2)); - printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)PHY_vars_UE->ofdm_demod_stats.diff/PHY_vars_UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->ofdm_demod_stats.trials*2/3); + std_phy_proc_rx_fft = sqrt((double)UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->ofdm_demod_stats.trials - pow((double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0, + UE->ofdm_demod_stats.trials*2/3); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3); printf("|__ DLSCH rx dft :%f us (%d trials)\n", - (nsymb*PHY_vars_UE->lte_frame_parms.nb_antennas_rx)*(double)PHY_vars_UE->rx_dft_stats.diff/PHY_vars_UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->rx_dft_stats.trials*2/3); + (nsymb*UE->frame_parms.nb_antennas_rx)*(double)UE->rx_dft_stats.diff/UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,UE->rx_dft_stats.trials*2/3); printf("|__ DLSCH channel estimation time :%f us (%d trials)\n", - (4.0)*(double)PHY_vars_UE->dlsch_channel_estimation_stats.diff/PHY_vars_UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->dlsch_channel_estimation_stats.trials*2/3); + (4.0)*(double)UE->dlsch_channel_estimation_stats.diff/UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_channel_estimation_stats.trials*2/3); printf("|__ DLSCH frequency offset estimation time :%f us (%d trials)\n", - (4.0)*(double)PHY_vars_UE->dlsch_freq_offset_estimation_stats.diff/PHY_vars_UE->dlsch_freq_offset_estimation_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->dlsch_freq_offset_estimation_stats.trials*2/3); - printf("DLSCH rx pdcch :%f us (%d trials)\n",(double)PHY_vars_UE->dlsch_rx_pdcch_stats.diff/PHY_vars_UE->dlsch_rx_pdcch_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->dlsch_rx_pdcch_stats.trials); - std_phy_proc_rx_demod = sqrt((double)PHY_vars_UE->dlsch_llr_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->dlsch_llr_stats.trials - pow((double)PHY_vars_UE->dlsch_llr_stats.diff/PHY_vars_UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000,2)); - printf("DLSCH Channel Compensation and LLR generation time :%f us (%d trials)\n",(3)*(double)PHY_vars_UE->dlsch_llr_stats.diff/PHY_vars_UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->dlsch_llr_stats.trials/3); + (4.0)*(double)UE->dlsch_freq_offset_estimation_stats.diff/UE->dlsch_freq_offset_estimation_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_freq_offset_estimation_stats.trials*2/3); + printf("DLSCH rx pdcch :%f us (%d trials)\n",(double)UE->dlsch_rx_pdcch_stats.diff/UE->dlsch_rx_pdcch_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_rx_pdcch_stats.trials); + std_phy_proc_rx_demod = sqrt((double)UE->dlsch_llr_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->dlsch_llr_stats.trials - pow((double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH Channel Compensation and LLR generation time :%f us (%d trials)\n",(3)*(double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_llr_stats.trials/3); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_demod, rx_demod_median, rx_demod_q1, rx_demod_q3); - printf("DLSCH unscrambling time :%f us (%d trials)\n",(double)PHY_vars_UE->dlsch_unscrambling_stats.diff/PHY_vars_UE->dlsch_unscrambling_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->dlsch_unscrambling_stats.trials); - std_phy_proc_rx_dec = sqrt((double)PHY_vars_UE->dlsch_decoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->dlsch_decoding_stats.trials - pow((double)PHY_vars_UE->dlsch_decoding_stats.diff/PHY_vars_UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000,2)); + printf("DLSCH unscrambling time :%f us (%d trials)\n",(double)UE->dlsch_unscrambling_stats.diff/UE->dlsch_unscrambling_stats.trials/cpu_freq_GHz/1000.0, + UE->dlsch_unscrambling_stats.trials); + std_phy_proc_rx_dec = sqrt((double)UE->dlsch_decoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->dlsch_decoding_stats.trials - pow((double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000,2)); printf("DLSCH Decoding time (%02.2f Mbit/s, avg iter %1.2f) :%f us (%d trials, max %f)\n", - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS/1000.0,(double)avg_iter/iter_trials, - (double)PHY_vars_UE->dlsch_decoding_stats.diff/PHY_vars_UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->dlsch_decoding_stats.trials, - (double)PHY_vars_UE->dlsch_decoding_stats.max/cpu_freq_GHz/1000.0); + eNB->dlsch[0][0]->harq_processes[0]->TBS/1000.0,(double)avg_iter/iter_trials, + (double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_decoding_stats.trials, + (double)UE->dlsch_decoding_stats.max/cpu_freq_GHz/1000.0); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3); printf("|__ DLSCH Rate Unmatching :%f us (%d trials)\n", - (double)PHY_vars_UE->dlsch_rate_unmatching_stats.diff/PHY_vars_UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->dlsch_rate_unmatching_stats.trials); + (double)UE->dlsch_rate_unmatching_stats.diff/UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_rate_unmatching_stats.trials); printf("|__ DLSCH Turbo Decoding(%d bits) :%f us (%d trials)\n", - PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->Cminus ? PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->Kminus : PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->Kplus, - (double)PHY_vars_UE->dlsch_turbo_decoding_stats.diff/PHY_vars_UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->dlsch_turbo_decoding_stats.trials); + UE->dlsch[0][0]->harq_processes[0]->Cminus ? UE->dlsch[0][0]->harq_processes[0]->Kminus : UE->dlsch[0][0]->harq_processes[0]->Kplus, + (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_turbo_decoding_stats.trials); printf(" |__ init %f us (cycles/iter %f, %d trials)\n", - (double)PHY_vars_UE->dlsch_tc_init_stats.diff/PHY_vars_UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_UE->dlsch_tc_init_stats.diff/PHY_vars_UE->dlsch_tc_init_stats.trials/((double)avg_iter/iter_trials), - PHY_vars_UE->dlsch_tc_init_stats.trials); + (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/((double)avg_iter/iter_trials), + UE->dlsch_tc_init_stats.trials); printf(" |__ alpha %f us (cycles/iter %f, %d trials)\n", - (double)PHY_vars_UE->dlsch_tc_alpha_stats.diff/PHY_vars_UE->dlsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_UE->dlsch_tc_alpha_stats.diff/PHY_vars_UE->dlsch_tc_alpha_stats.trials*2, - PHY_vars_UE->dlsch_tc_alpha_stats.trials); + (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials*2, + UE->dlsch_tc_alpha_stats.trials); printf(" |__ beta %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_UE->dlsch_tc_beta_stats.diff/PHY_vars_UE->dlsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_UE->dlsch_tc_beta_stats.diff/PHY_vars_UE->dlsch_tc_beta_stats.trials*2, - PHY_vars_UE->dlsch_tc_beta_stats.trials); + (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials*2, + UE->dlsch_tc_beta_stats.trials); printf(" |__ gamma %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_UE->dlsch_tc_gamma_stats.diff/PHY_vars_UE->dlsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_UE->dlsch_tc_gamma_stats.diff/PHY_vars_UE->dlsch_tc_gamma_stats.trials*2, - PHY_vars_UE->dlsch_tc_gamma_stats.trials); + (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials*2, + UE->dlsch_tc_gamma_stats.trials); printf(" |__ ext %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_UE->dlsch_tc_ext_stats.diff/PHY_vars_UE->dlsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_UE->dlsch_tc_ext_stats.diff/PHY_vars_UE->dlsch_tc_ext_stats.trials*2, - PHY_vars_UE->dlsch_tc_ext_stats.trials); + (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials*2, + UE->dlsch_tc_ext_stats.trials); printf(" |__ intl1 %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_UE->dlsch_tc_intl1_stats.diff/PHY_vars_UE->dlsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_UE->dlsch_tc_intl1_stats.diff/PHY_vars_UE->dlsch_tc_intl1_stats.trials, - PHY_vars_UE->dlsch_tc_intl1_stats.trials); + (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials, + UE->dlsch_tc_intl1_stats.trials); printf(" |__ intl2+HD+CRC %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_UE->dlsch_tc_intl2_stats.diff/PHY_vars_UE->dlsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_UE->dlsch_tc_intl2_stats.diff/PHY_vars_UE->dlsch_tc_intl2_stats.trials, - PHY_vars_UE->dlsch_tc_intl2_stats.trials); + (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0, + (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials, + UE->dlsch_tc_intl2_stats.trials); } if ((transmission_mode != 3) && (transmission_mode != 4)) { fprintf(bler_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n", SNR, mcs1, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][0]->harq_processes[0]->TBS, rate, errs[0], round_trials[0], @@ -3794,8 +3794,8 @@ PMI_FEEDBACK: fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n", SNR, mcs1,mcs2, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, - PHY_vars_eNB->dlsch_eNB[0][1]->harq_processes[0]->TBS, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, rate, errs[0], round_trials[0], @@ -3828,7 +3828,7 @@ PMI_FEEDBACK: fprintf(time_meas_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;", SNR, mcs1, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][0]->harq_processes[0]->TBS, rate, errs[0], round_trials[0], @@ -3844,7 +3844,7 @@ PMI_FEEDBACK: fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", SNR, mcs1, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][0]->harq_processes[0]->TBS, rate*effective_rate, 100*effective_rate, rate, @@ -3865,14 +3865,14 @@ PMI_FEEDBACK: round_trials[0], (double)dci_errors/(round_trials[0]), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ - (double)PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, + (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); } else { fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;", SNR, mcs1,mcs2, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, - PHY_vars_eNB->dlsch_eNB[0][1]->harq_processes[0]->TBS, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, rate, errs[0], round_trials[0], @@ -3888,8 +3888,8 @@ PMI_FEEDBACK: fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", SNR, mcs1,mcs2, - PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, - PHY_vars_eNB->dlsch_eNB[0][1]->harq_processes[0]->TBS, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, rate*effective_rate, 100*effective_rate, rate, @@ -3910,36 +3910,36 @@ PMI_FEEDBACK: round_trials[0], (double)dci_errors/(round_trials[0]), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ - (double)PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->TBS, + (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); } //fprintf(time_meas_fd,"eNB_PROC_TX(%d); OFDM_MOD(%d); DL_MOD(%d); DL_SCR(%d); DL_ENC(%d); UE_PROC_RX(%d); OFDM_DEMOD_CH_EST(%d); RX_PDCCH(%d); CH_COMP_LLR(%d); DL_USCR(%d); DL_DECOD(%d);\n", fprintf(time_meas_fd,"%d; %d; %d; %d; %d; %d; %d; %d; %d; %d; %d;", - PHY_vars_eNB->phy_proc_tx.trials, - PHY_vars_eNB->ofdm_mod_stats.trials, - PHY_vars_eNB->dlsch_modulation_stats.trials, - PHY_vars_eNB->dlsch_scrambling_stats.trials, - PHY_vars_eNB->dlsch_encoding_stats.trials, - PHY_vars_UE->phy_proc_rx.trials, - PHY_vars_UE->ofdm_demod_stats.trials, - PHY_vars_UE->dlsch_rx_pdcch_stats.trials, - PHY_vars_UE->dlsch_llr_stats.trials, - PHY_vars_UE->dlsch_unscrambling_stats.trials, - PHY_vars_UE->dlsch_decoding_stats.trials + eNB->phy_proc_tx.trials, + eNB->ofdm_mod_stats.trials, + eNB->dlsch_modulation_stats.trials, + eNB->dlsch_scrambling_stats.trials, + eNB->dlsch_encoding_stats.trials, + UE->phy_proc_rx.trials, + UE->ofdm_demod_stats.trials, + UE->dlsch_rx_pdcch_stats.trials, + UE->dlsch_llr_stats.trials, + UE->dlsch_unscrambling_stats.trials, + UE->dlsch_decoding_stats.trials ); fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;", - get_time_meas_us(&PHY_vars_eNB->phy_proc_tx), - get_time_meas_us(&PHY_vars_eNB->ofdm_mod_stats), - get_time_meas_us(&PHY_vars_eNB->dlsch_modulation_stats), - get_time_meas_us(&PHY_vars_eNB->dlsch_scrambling_stats), - get_time_meas_us(&PHY_vars_eNB->dlsch_encoding_stats), - get_time_meas_us(&PHY_vars_UE->phy_proc_rx), - nsymb*get_time_meas_us(&PHY_vars_UE->ofdm_demod_stats), - get_time_meas_us(&PHY_vars_UE->dlsch_rx_pdcch_stats), - 3*get_time_meas_us(&PHY_vars_UE->dlsch_llr_stats), - get_time_meas_us(&PHY_vars_UE->dlsch_unscrambling_stats), - get_time_meas_us(&PHY_vars_UE->dlsch_decoding_stats) + get_time_meas_us(&eNB->phy_proc_tx), + get_time_meas_us(&eNB->ofdm_mod_stats), + get_time_meas_us(&eNB->dlsch_modulation_stats), + get_time_meas_us(&eNB->dlsch_scrambling_stats), + get_time_meas_us(&eNB->dlsch_encoding_stats), + get_time_meas_us(&UE->phy_proc_rx), + nsymb*get_time_meas_us(&UE->ofdm_demod_stats), + get_time_meas_us(&UE->dlsch_rx_pdcch_stats), + 3*get_time_meas_us(&UE->dlsch_llr_stats), + get_time_meas_us(&UE->dlsch_unscrambling_stats), + get_time_meas_us(&UE->dlsch_decoding_stats) ); //fprintf(time_meas_fd,"eNB_PROC_TX_STD;eNB_PROC_TX_MAX;eNB_PROC_TX_MIN;eNB_PROC_TX_MED;eNB_PROC_TX_Q1;eNB_PROC_TX_Q3;eNB_PROC_TX_DROPPED;\n"); fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped); @@ -3969,17 +3969,17 @@ PMI_FEEDBACK: /* fprintf(time_meas_fd,"%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;", - PHY_vars_eNB->phy_proc_tx.trials, - PHY_vars_eNB->ofdm_mod_stats.trials, - PHY_vars_eNB->dlsch_modulation_stats.trials, - PHY_vars_eNB->dlsch_scrambling_stats.trials, - PHY_vars_eNB->dlsch_encoding_stats.trials, - PHY_vars_UE->phy_proc_rx.trials, - PHY_vars_UE->ofdm_demod_stats.trials, - PHY_vars_UE->dlsch_rx_pdcch_stats.trials, - PHY_vars_UE->dlsch_llr_stats.trials, - PHY_vars_UE->dlsch_unscrambling_stats.trials, - PHY_vars_UE->dlsch_decoding_stats.trials); + eNB->phy_proc_tx.trials, + eNB->ofdm_mod_stats.trials, + eNB->dlsch_modulation_stats.trials, + eNB->dlsch_scrambling_stats.trials, + eNB->dlsch_encoding_stats.trials, + UE->phy_proc_rx.trials, + UE->ofdm_demod_stats.trials, + UE->dlsch_rx_pdcch_stats.trials, + UE->dlsch_llr_stats.trials, + UE->dlsch_unscrambling_stats.trials, + UE->dlsch_decoding_stats.trials); */ printf("[passed] effective rate : %f (%2.1f%%,%f)): log and break \n",rate*effective_rate, 100*effective_rate, rate ); break; @@ -4030,9 +4030,9 @@ PMI_FEEDBACK: for (i=0; i<2; i++) { printf("eNB %d\n",i); - free_eNB_dlsch(PHY_vars_eNB->dlsch_eNB[0][i]); + free_eNB_dlsch(eNB->dlsch[0][i]); printf("UE %d\n",i); - free_ue_dlsch(PHY_vars_UE->dlsch_ue[0][i]); + free_ue_dlsch(UE->dlsch[0][i]); } diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c index 78bb09c552..73da52085f 100644 --- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c @@ -48,13 +48,14 @@ #include "PHY/TOOLS/lte_phy_scope.h" #endif +#include "unitary_defs.h" #define N_TRIALS 100 -PHY_VARS_eNB *PHY_vars_eNB,*PHY_vars_eNB1,*PHY_vars_eNB2; -PHY_VARS_UE *PHY_vars_UE; +PHY_VARS_eNB *eNB,*eNB1,*eNB2; +PHY_VARS_UE *UE; #define UL_RB_ALLOC 0x1ff; -#define CCCH_RB_ALLOC computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,0,2) +#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2) #define DLSCH_RB_ALLOC ((uint16_t)0x1fbf) // igore DC component,RB13 DCI_PDU DCI_pdu; @@ -459,17 +460,7 @@ int main(int argc, char **argv) int CCE_table[800]; number_of_cards = 1; - openair_daq_vars.rx_rf_mode = 1; - /* - rxdataF = (int **)malloc16(2*sizeof(int*)); - rxdataF[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdataF[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - - rxdata = (int **)malloc16(2*sizeof(int*)); - rxdata[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - */ while ((c = getopt (argc, argv, "hapFg:R:c:n:s:x:y:z:L:M:N:I:f:i:S:P:Y")) != -1) { switch (c) { case 'a': @@ -719,7 +710,7 @@ int main(int argc, char **argv) mac_xface->computeRIV = computeRIV; - mac_xface->lte_frame_parms = &PHY_vars_eNB->lte_frame_parms; + mac_xface->frame_parms = &eNB->frame_parms; // init_transport_channels(transmission_mode); if (n_frames==1) @@ -729,27 +720,27 @@ int main(int argc, char **argv) printf("SNR0 %f, SNR1 %f\n",snr0,snr1); - frame_parms = &PHY_vars_eNB->lte_frame_parms; + frame_parms = &eNB->frame_parms; get_dci(frame_parms, log2L, log2Lcommon, format_selector, n_rnti); - txdata = PHY_vars_eNB->lte_eNB_common_vars.txdata[eNb_id]; + txdata = eNB->common_vars.txdata[eNb_id]; s_re = malloc(2*sizeof(double*)); s_im = malloc(2*sizeof(double*)); r_re = malloc(2*sizeof(double*)); r_im = malloc(2*sizeof(double*)); - nsymb = (PHY_vars_eNB->lte_frame_parms.Ncp == 0) ? 14 : 12; + nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; printf("Subframe %d, FFT Size %d, Extended Prefix %d, Samples per subframe %d, Symbols per subframe %d\n", subframe,NUMBER_OF_OFDM_CARRIERS, - PHY_vars_eNB->lte_frame_parms.Ncp,PHY_vars_eNB->lte_frame_parms.samples_per_tti,nsymb); + eNB->frame_parms.Ncp,eNB->frame_parms.samples_per_tti,nsymb); - eNB2UE = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx_eNB, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx_eNB, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 0, 0); @@ -769,12 +760,12 @@ int main(int argc, char **argv) - PHY_vars_eNB->ulsch_eNB[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,N_RB_DL,0); - PHY_vars_UE->ulsch_ue[0] = new_ue_ulsch(N_RB_DL,0); + eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); - PHY_vars_eNB->proc[subframe].frame_tx = 0; - PHY_vars_eNB->proc[subframe].subframe_tx = subframe; + eNB->proc.frame_tx = 0; + eNB->proc.subframe_tx = subframe; if (input_fd==NULL) { msg("No input file, so starting TX\n"); @@ -812,9 +803,9 @@ int main(int argc, char **argv) } - PHY_vars_UE->UE_mode[0] = PUSCH; + UE->UE_mode[0] = PUSCH; - // nCCE_max = get_nCCE(3,&PHY_vars_eNB->lte_frame_parms,get_mi(&PHY_vars_eNB->lte_frame_parms,0)); + // nCCE_max = get_nCCE(3,&eNB->frame_parms,get_mi(&eNB->frame_parms,0)); //printf("nCCE_max %d\n",nCCE_max); //printf("num_phich interferers %d\n",num_phich_interf); @@ -832,31 +823,31 @@ int main(int argc, char **argv) for (trial=0; triallte_eNB_common_vars.txdataF[eNb_id][aa][512*14*subframe],&PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][aa][0]); - for (aa=0; aalte_frame_parms.nb_antennas_tx_eNB; aa++) { - memset(&PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + // printf("DCI (SF %d): txdataF %p (0 %p)\n",subframe,&eNB->common_vars.txdataF[eNb_id][aa][512*14*subframe],&eNB->common_vars.txdataF[eNb_id][aa][0]); + for (aa=0; aaframe_parms.nb_antennas_tx_eNB; aa++) { + memset(&eNB->common_vars.txdataF[eNb_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); /* - re_offset = PHY_vars_eNB->lte_frame_parms.first_carrier_offset; - txptr = (uint32_t*)&PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][aa][subframe*PHY_vars_eNB->lte_frame_parms.samples_per_tti]; - for (i=0;ilte_frame_parms.N_RB_DL*6;i++) { - txptr[re_offset++] = PHY_vars_eNB->lte_frame_parms.mode1_flag==1 ? QPSK[taus()&3] : QPSK2[taus()&3]; + re_offset = eNB->frame_parms.first_carrier_offset; + txptr = (uint32_t*)&eNB->common_vars.txdataF[eNb_id][aa][subframe*eNB->frame_parms.samples_per_tti]; + for (i=0;iframe_parms.N_RB_DL*6;i++) { + txptr[re_offset++] = eNB->frame_parms.mode1_flag==1 ? QPSK[taus()&3] : QPSK2[taus()&3]; //printf("%i => %d,%d\n",re_offset-1,*(int16_t*)&txptr[re_offset-1],*(1+(int16_t*)&txptr[re_offset-1])); } re_offset=1; //skip DC - for (i=0;ilte_frame_parms.N_RB_DL*6;i++) - txptr[re_offset++] = PHY_vars_eNB->lte_frame_parms.mode1_flag==1 ? QPSK[taus()&3] : QPSK2[taus()&3]; + for (i=0;iframe_parms.N_RB_DL*6;i++) + txptr[re_offset++] = eNB->frame_parms.mode1_flag==1 ? QPSK[taus()&3] : QPSK2[taus()&3]; */ } - generate_pilots_slot(PHY_vars_eNB, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id], + generate_pilots_slot(eNB, + eNB->common_vars.txdataF[eNb_id], AMP, //1024, (subframe*2), 0); - generate_pilots_slot(PHY_vars_eNB, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id], + generate_pilots_slot(eNB, + eNB->common_vars.txdataF[eNb_id], AMP, //1024, (subframe*2)+1, 0); @@ -866,18 +857,18 @@ int main(int argc, char **argv) numCCE=0; n_trials_common++; common_active = 1; - if (PHY_vars_eNB->lte_frame_parms.N_RB_DL >= 50) { + if (eNB->frame_parms.N_RB_DL >= 50) { n_trials_ul++; ul_active = 1; } - if (PHY_vars_eNB->lte_frame_parms.N_RB_DL >= 25) { + if (eNB->frame_parms.N_RB_DL >= 25) { n_trials_dl++; dl_active = 1; } num_pdcch_symbols = get_num_pdcch_symbols(DCI_pdu.Num_common_dci+DCI_pdu.Num_ue_spec_dci, DCI_pdu.dci_alloc, frame_parms, subframe); - numCCE = get_nCCE(num_pdcch_symbols,&PHY_vars_eNB->lte_frame_parms,get_mi(&PHY_vars_eNB->lte_frame_parms,subframe)); + numCCE = get_nCCE(num_pdcch_symbols,&eNB->frame_parms,get_mi(&eNB->frame_parms,subframe)); if (n_frames==1) { printf("num_dci %d, num_pddch_symbols %d, nCCE %d\n", @@ -930,91 +921,83 @@ int main(int argc, char **argv) DCI_pdu.dci_alloc, 0, AMP, - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id], + &eNB->frame_parms, + eNB->common_vars.txdataF[eNb_id], subframe); if (n_frames==1) printf("num_pdcch_symbols at TX %d\n",num_pdcch_symbols); - if (is_phich_subframe(&PHY_vars_eNB->lte_frame_parms,subframe)) { + if (is_phich_subframe(&eNB->frame_parms,subframe)) { if (n_frames==1) printf("generating PHICH\n"); - harq_pid = phich_subframe_to_harq_pid(&PHY_vars_eNB->lte_frame_parms, PHY_vars_eNB->proc[subframe].frame_tx, subframe); + harq_pid = phich_subframe_to_harq_pid(&eNB->frame_parms, eNB->proc.frame_tx, subframe); phich_ACK = taus()&1; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->phich_active = 1; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->first_rb = 0; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->n_DMRS = 0; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->phich_ACK = phich_ACK; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->dci_alloc = 1; + eNB->ulsch[0]->harq_processes[harq_pid]->phich_active = 1; + eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 0; + eNB->ulsch[0]->harq_processes[harq_pid]->n_DMRS = 0; + eNB->ulsch[0]->harq_processes[harq_pid]->phich_ACK = phich_ACK; + eNB->ulsch[0]->harq_processes[harq_pid]->dci_alloc = 1; - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->first_rb = 0; - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->n_DMRS = 0; + UE->ulsch[0]->harq_processes[harq_pid]->first_rb = 0; + UE->ulsch[0]->harq_processes[harq_pid]->n_DMRS = 0; - generate_phich_top(PHY_vars_eNB, - subframe,AMP,0,0); + generate_phich_top(eNB,AMP,0,0); // generate 3 interfering PHICH if (num_phich_interf>0) { - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->first_rb = 4; - generate_phich_top(PHY_vars_eNB, - subframe, - 1024, - 0,0); + eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 4; + generate_phich_top(eNB,1024,0,0); } if (num_phich_interf>1) { - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->first_rb = 8; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->n_DMRS = 1; - generate_phich_top(PHY_vars_eNB, - subframe, - 1024,0,0); + eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 8; + eNB->ulsch[0]->harq_processes[harq_pid]->n_DMRS = 1; + generate_phich_top(eNB,1024,0,0); } if (num_phich_interf>2) { - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->first_rb = 12; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->n_DMRS = 1; - generate_phich_top(PHY_vars_eNB, - subframe, - 1024,0,0); + eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 12; + eNB->ulsch[0]->harq_processes[harq_pid]->n_DMRS = 1; + generate_phich_top(eNB,1024,0,0); } - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->first_rb = 0; + eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 0; } - // write_output("pilotsF.m","rsF",txdataF[0],lte_PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size,1,1); + // write_output("pilotsF.m","rsF",txdataF[0],lte_eNB->frame_parms.ofdm_symbol_size,1,1); if (n_frames==1) { - write_output("txsigF0.m","txsF0", PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][0],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0.m","txsF0", eNB->common_vars.txdataF[eNb_id][0],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx_eNB > 1) - write_output("txsigF1.m","txsF1", PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][1],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (eNB->frame_parms.nb_antennas_tx_eNB > 1) + write_output("txsigF1.m","txsF1", eNB->common_vars.txdataF[eNb_id][1],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1); } tx_lev = 0; - for (aa=0; aalte_frame_parms.nb_antennas_tx_eNB; aa++) { - if (PHY_vars_eNB->lte_frame_parms.Ncp == 1) - PHY_ofdm_mod(&PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][aa][subframe*nsymb*PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size], // input, - &txdata[aa][subframe*PHY_vars_eNB->lte_frame_parms.samples_per_tti], // output - PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size, + for (aa=0; aaframe_parms.nb_antennas_tx_eNB; aa++) { + if (eNB->frame_parms.Ncp == 1) + PHY_ofdm_mod(&eNB->common_vars.txdataF[eNb_id][aa][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], // input, + &txdata[aa][subframe*eNB->frame_parms.samples_per_tti], // output + eNB->frame_parms.ofdm_symbol_size, 2*nsymb, // number of symbols - PHY_vars_eNB->lte_frame_parms.nb_prefix_samples, // number of prefix samples + eNB->frame_parms.nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(&PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][aa][subframe*nsymb*PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size], - &txdata[aa][subframe*PHY_vars_eNB->lte_frame_parms.samples_per_tti], + normal_prefix_mod(&eNB->common_vars.txdataF[eNb_id][aa][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], + &txdata[aa][subframe*eNB->frame_parms.samples_per_tti], 2*nsymb, frame_parms); } - tx_lev += signal_energy(&txdata[aa][subframe*PHY_vars_eNB->lte_frame_parms.samples_per_tti], - PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size); + tx_lev += signal_energy(&txdata[aa][subframe*eNB->frame_parms.samples_per_tti], + eNB->frame_parms.ofdm_symbol_size); } tx_lev_dB = (unsigned int) dB_fixed(tx_lev); @@ -1023,18 +1006,18 @@ int main(int argc, char **argv) for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_tx_eNB; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx_eNB; aa++) { if (awgn_flag == 0) { - s_re[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + (i<<1)]); - s_im[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + (i<<1)+1]); + s_re[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]); + s_im[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)+1]); } else { - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { if (aa==0) { - r_re[aarx][i] = ((double)(((short *)txdata[aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + (i<<1)]); - r_im[aarx][i] = ((double)(((short *)txdata[aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + (i<<1)+1]); + r_re[aarx][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]); + r_im[aarx][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)+1]); } else { - r_re[aarx][i] += ((double)(((short *)txdata[aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + (i<<1)]); - r_im[aarx][i] += ((double)(((short *)txdata[aa]))[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + (i<<1)+1]); + r_re[aarx][i] += ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]); + r_im[aarx][i] += ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)+1]); } } } @@ -1054,7 +1037,7 @@ int main(int argc, char **argv) // scale by path_loss = NOW - P_noise //sigma2 = pow(10,sigma2_dB/10); //N0W = -95.87; - sigma2_dB = (double)tx_lev_dB +10*log10((double)PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(double)(12*PHY_vars_eNB->lte_frame_parms.N_RB_DL)) - SNR; + sigma2_dB = (double)tx_lev_dB +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(12*eNB->frame_parms.N_RB_DL)) - SNR; if (n_frames==1) printf("sigma2_dB %f (SNR %f dB) tx_lev_dB %d\n",sigma2_dB,SNR,tx_lev_dB); @@ -1064,37 +1047,37 @@ int main(int argc, char **argv) // printf("Sigma2 %f (sigma2_dB %f)\n",sigma2,sigma2_dB); for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { - ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + 2*i] = (short) (.667*(r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + 2*i+1] = (short) (.667*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble( + ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti) + 2*i] = (short) (.667*(r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti) + 2*i+1] = (short) (.667*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble( 0.0,1.0))); /* - ((short*)PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + 2*i] = - ((short*)txdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + 2*i]; - ((short*)PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + 2*i+1] = - ((short*)txdata[aa])[(2*subframe*PHY_vars_UE->lte_frame_parms.samples_per_tti) + 2*i+1]; + ((short*)UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti) + 2*i] = + ((short*)txdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti) + 2*i]; + ((short*)UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti) + 2*i+1] = + ((short*)txdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti) + 2*i+1]; */ } } // UE receiver - for (l=0; llte_frame_parms.symbols_per_tti; l++) { + for (l=0; lframe_parms.symbols_per_tti; l++) { - // subframe_offset = (l/PHY_vars_eNB->lte_frame_parms.symbols_per_tti)*PHY_vars_eNB->lte_frame_parms.samples_per_tti; + // subframe_offset = (l/eNB->frame_parms.symbols_per_tti)*eNB->frame_parms.samples_per_tti; // printf("subframe_offset = %d\n",subframe_offset); - slot_fep(PHY_vars_UE, - l%(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2), - (2*subframe)+(l/(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2)), + slot_fep(UE, + l%(eNB->frame_parms.symbols_per_tti/2), + (2*subframe)+(l/(eNB->frame_parms.symbols_per_tti/2)), 0, 0, 0); - if (PHY_vars_UE->perfect_ce == 1) { + if (UE->perfect_ce == 1) { if (awgn_flag==0) { // fill in perfect channel estimates - freq_channel(eNB2UE,PHY_vars_UE->lte_frame_parms.N_RB_DL,12*PHY_vars_UE->lte_frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE,UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); //write_output("channel.m","ch",desc1->ch[0],desc1->channel_length,1,8); //write_output("channelF.m","chF",desc1->chF[0],nb_samples,1,8); @@ -1102,9 +1085,9 @@ int main(int argc, char **argv) for(aa=0; aanb_antennas_tx; aa++) { for (aarx=0; aarxnb_antennas_rx; aarx++) { for (i=0; iN_RB_DL*12; i++) { - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( + ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( eNB2UE->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP); - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( + ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( eNB2UE->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP); } } @@ -1114,42 +1097,42 @@ int main(int argc, char **argv) for(aa=0; aanb_antennas_tx_eNB; aa++) { for (aarx=0; aarxnb_antennas_rx; aarx++) { for (i=0; iN_RB_DL*12; i++) { - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); - ((int16_t *) PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2; + ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); + ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2; } } } } } - if (l==((PHY_vars_eNB->lte_frame_parms.Ncp==0)?4:3)) { + if (l==((eNB->frame_parms.Ncp==0)?4:3)) { - // write_output("H00.m","h00",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size),1,1); + // write_output("H00.m","h00",&(UE->common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(eNB->frame_parms.ofdm_symbol_size),1,1); // do PDCCH procedures here - PHY_vars_UE->lte_ue_pdcch_vars[0]->crnti = n_rnti; + UE->pdcch_vars[0]->crnti = n_rnti; // printf("Doing RX : num_pdcch_symbols at TX %d\n",num_pdcch_symbols); - rx_pdcch(&PHY_vars_UE->lte_ue_common_vars, - PHY_vars_UE->lte_ue_pdcch_vars, - &PHY_vars_UE->lte_frame_parms, + rx_pdcch(&UE->common_vars, + UE->pdcch_vars, + &UE->frame_parms, subframe, 0, - (PHY_vars_UE->lte_frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, - PHY_vars_UE->high_speed_flag, - PHY_vars_UE->is_secondary_ue); + (UE->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, + UE->high_speed_flag, + UE->is_secondary_ue); - if (is_phich_subframe(&PHY_vars_UE->lte_frame_parms,subframe)) { - PHY_vars_UE->ulsch_ue[0]->harq_processes[phich_subframe_to_harq_pid(&PHY_vars_UE->lte_frame_parms,0,subframe)]->status = ACTIVE; - //PHY_vars_UE->ulsch_ue[0]->harq_processes[phich_subframe_to_harq_pid(&PHY_vars_UE->lte_frame_parms,0,subframe)]->Ndi = 1; - rx_phich(PHY_vars_UE, + if (is_phich_subframe(&UE->frame_parms,subframe)) { + UE->ulsch[0]->harq_processes[phich_subframe_to_harq_pid(&UE->frame_parms,0,subframe)]->status = ACTIVE; + //UE->ulsch[0]->harq_processes[phich_subframe_to_harq_pid(&UE->frame_parms,0,subframe)]->Ndi = 1; + rx_phich(UE, subframe, 0); } - // if (PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols != num_pdcch_symbols) + // if (UE->pdcch_vars[0]->num_pdcch_symbols != num_pdcch_symbols) // break; - dci_cnt = dci_decoding_procedure(PHY_vars_UE, + dci_cnt = dci_decoding_procedure(UE, dci_alloc_rx,1, 0,subframe); @@ -1158,7 +1141,7 @@ int main(int argc, char **argv) dl_rx=0; if (n_frames==1) { - numCCE = get_nCCE(PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols, &PHY_vars_UE->lte_frame_parms, get_mi(&PHY_vars_UE->lte_frame_parms,subframe)); + numCCE = get_nCCE(UE->pdcch_vars[0]->num_pdcch_symbols, &UE->frame_parms, get_mi(&UE->frame_parms,subframe)); for (i = 0; i < dci_cnt; i++) printf("dci %d: rnti 0x%x, format %d, L %d, nCCE %d/%d dci_length %d\n",i, dci_alloc_rx[i].rnti, dci_alloc_rx[i].format, @@ -1168,21 +1151,21 @@ int main(int argc, char **argv) for (i=0; ilte_frame_parms, &dci_alloc_rx[i]); + dump_dci(&UE->frame_parms, &dci_alloc_rx[i]); common_rx=1; } if ((dci_alloc_rx[i].rnti == n_rnti) && (dci_alloc_rx[i].format == format0)) { if (n_frames==1) - dump_dci(&PHY_vars_UE->lte_frame_parms, &dci_alloc_rx[i]); + dump_dci(&UE->frame_parms, &dci_alloc_rx[i]); ul_rx=1; } if ((dci_alloc_rx[i].rnti == n_rnti) && ((dci_alloc_rx[i].format == format1))) { if (n_frames==1) - dump_dci(&PHY_vars_UE->lte_frame_parms, &dci_alloc_rx[i]); + dump_dci(&UE->frame_parms, &dci_alloc_rx[i]); dl_rx=1; } @@ -1207,12 +1190,12 @@ int main(int argc, char **argv) // exit(-1); } - if (PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols != num_pdcch_symbols) + if (UE->pdcch_vars[0]->num_pdcch_symbols != num_pdcch_symbols) n_errors_cfi++; /* - if (is_phich_subframe(&PHY_vars_UE->lte_frame_parms,subframe)) - if (PHY_vars_UE->ulsch_ue[0]->harq_processes[phich_subframe_to_harq_pid(&PHY_vars_UE->lte_frame_parms, PHY_vars_UE->frame, subframe)]->Ndi != phich_ACK) + if (is_phich_subframe(&UE->frame_parms,subframe)) + if (UE->ulsch[0]->harq_processes[phich_subframe_to_harq_pid(&UE->frame_parms, UE->frame, subframe)]->Ndi != phich_ACK) n_errors_hi++; */ @@ -1230,7 +1213,7 @@ int main(int argc, char **argv) #ifdef XFORMS phy_scope_UE(form_ue, - PHY_vars_UE, + UE, eNb_id,0,subframe); #endif @@ -1250,22 +1233,22 @@ int main(int argc, char **argv) if (n_tx>1) write_output("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); - write_output("rxsig0.m","rxs0", PHY_vars_UE->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", PHY_vars_UE->lte_ue_common_vars.rxdataF[0],NUMBER_OF_OFDM_CARRIERS*2*((frame_parms->Ncp==0)?14:12),2,1); + write_output("rxsig0.m","rxs0", UE->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + write_output("rxsigF0.m","rxsF0", UE->common_vars.rxdataF[0],NUMBER_OF_OFDM_CARRIERS*2*((frame_parms->Ncp==0)?14:12),2,1); if (n_rx>1) { - write_output("rxsig1.m","rxs1", PHY_vars_UE->lte_ue_common_vars.rxdata[1],10*frame_parms->samples_per_tti,1,1); - write_output("rxsigF1.m","rxsF1", PHY_vars_UE->lte_ue_common_vars.rxdataF[1],NUMBER_OF_OFDM_CARRIERS*2*((frame_parms->Ncp==0)?14:12),2,1); + write_output("rxsig1.m","rxs1", UE->common_vars.rxdata[1],10*frame_parms->samples_per_tti,1,1); + write_output("rxsigF1.m","rxsF1", UE->common_vars.rxdataF[1],NUMBER_OF_OFDM_CARRIERS*2*((frame_parms->Ncp==0)?14:12),2,1); } - write_output("H00.m","h00",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size),1,1); + write_output("H00.m","h00",&(UE->common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(eNB->frame_parms.ofdm_symbol_size),1,1); if (n_tx==2) - write_output("H10.m","h10",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][2][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size),1,1); + write_output("H10.m","h10",&(UE->common_vars.dl_ch_estimates[0][2][0]),((frame_parms->Ncp==0)?7:6)*(eNB->frame_parms.ofdm_symbol_size),1,1); - write_output("pdcch_rxF_ext0.m","pdcch_rxF_ext0",PHY_vars_UE->lte_ue_pdcch_vars[eNb_id]->rxdataF_ext[0],3*12*PHY_vars_UE->lte_frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",PHY_vars_UE->lte_ue_pdcch_vars[eNb_id]->rxdataF_comp[0],4*12*PHY_vars_UE->lte_frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",PHY_vars_UE->lte_ue_pdcch_vars[eNb_id]->llr,2400,1,4); + write_output("pdcch_rxF_ext0.m","pdcch_rxF_ext0",UE->pdcch_vars[eNb_id]->rxdataF_ext[0],3*12*UE->frame_parms.N_RB_DL,1,1); + write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNb_id]->rxdataF_comp[0],4*12*UE->frame_parms.N_RB_DL,1,1); + write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNb_id]->llr,2400,1,4); } for (i=0; i<2; i++) { diff --git a/openair1/SIMULATION/LTE_PHY/prachsim.c b/openair1/SIMULATION/LTE_PHY/prachsim.c index 37fc3a6a10..58e5428e82 100644 --- a/openair1/SIMULATION/LTE_PHY/prachsim.c +++ b/openair1/SIMULATION/LTE_PHY/prachsim.c @@ -43,10 +43,12 @@ #include "OCG_vars.h" +#include "unitary_defs.h" + int current_dlsch_cqi; //FIXME! -PHY_VARS_eNB *PHY_vars_eNB; -PHY_VARS_UE *PHY_vars_UE; +PHY_VARS_eNB *eNB; +PHY_VARS_UE *UE; #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 @@ -105,17 +107,9 @@ int main(int argc, char **argv) logInit(); number_of_cards = 1; - openair_daq_vars.rx_rf_mode = 1; - /* - rxdataF = (int **)malloc16(2*sizeof(int*)); - rxdataF[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdataF[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdata = (int **)malloc16(2*sizeof(int*)); - rxdata[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - */ + while ((c = getopt (argc, argv, "hHaA:Cr:p:g:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:")) != -1) { switch (c) { case 'a': @@ -343,10 +337,10 @@ int main(int argc, char **argv) printf("SNR0 %f, SNR1 %f\n",snr0,snr1); - frame_parms = &PHY_vars_eNB->lte_frame_parms; + frame_parms = &eNB->frame_parms; - txdata = PHY_vars_UE->lte_ue_common_vars.txdata; + txdata = UE->common_vars.txdata; printf("txdata %p\n",&txdata[0][subframe*frame_parms->samples_per_tti]); s_re = malloc(2*sizeof(double*)); @@ -361,11 +355,11 @@ int main(int argc, char **argv) msg("[SIM] Using SCM/101\n"); - UE2eNB = new_channel_desc_scm(PHY_vars_UE->lte_frame_parms.nb_antennas_tx, - PHY_vars_eNB->lte_frame_parms.nb_antennas_rx, + UE2eNB = new_channel_desc_scm(UE->frame_parms.nb_antennas_tx, + eNB->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_UL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_UL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_UL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL), 0.0, delay, 0); @@ -388,32 +382,35 @@ int main(int argc, char **argv) bzero(r_im[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); } - PHY_vars_UE->lte_frame_parms.prach_config_common.rootSequenceIndex=rootSequenceIndex; - PHY_vars_UE->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; - PHY_vars_UE->lte_frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=NCS_config; - PHY_vars_UE->lte_frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag=hs_flag; - PHY_vars_UE->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + UE->frame_parms.prach_config_common.rootSequenceIndex=rootSequenceIndex; + UE->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + UE->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=NCS_config; + UE->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag=hs_flag; + UE->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; - PHY_vars_eNB->lte_frame_parms.prach_config_common.rootSequenceIndex=rootSequenceIndex; - PHY_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; - PHY_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=NCS_config; - PHY_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag=hs_flag; - PHY_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + eNB->frame_parms.prach_config_common.rootSequenceIndex=rootSequenceIndex; + eNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + eNB->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=NCS_config; + eNB->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag=hs_flag; + eNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + + eNB->node_function = eNodeB_3GPP; + eNB->proc.subframe_rx = subframe; /* N_ZC not used later, so prach_fmt is also useless, don't set */ - //prach_fmt = get_prach_fmt(PHY_vars_eNB->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - // PHY_vars_eNB->lte_frame_parms.frame_type); + //prach_fmt = get_prach_fmt(eNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, + // eNB->frame_parms.frame_type); /* N_ZC not used later, no need to set */ //N_ZC = (prach_fmt <4)?839:139; - compute_prach_seq(&PHY_vars_eNB->lte_frame_parms.prach_config_common,PHY_vars_eNB->lte_frame_parms.frame_type,PHY_vars_eNB->X_u); + compute_prach_seq(&eNB->frame_parms.prach_config_common,eNB->frame_parms.frame_type,eNB->X_u); - compute_prach_seq(&PHY_vars_UE->lte_frame_parms.prach_config_common,PHY_vars_UE->lte_frame_parms.frame_type,PHY_vars_UE->X_u); + compute_prach_seq(&UE->frame_parms.prach_config_common,UE->frame_parms.frame_type,UE->X_u); - PHY_vars_UE->lte_ue_prach_vars[0]->amp = AMP; + UE->prach_vars[0]->amp = AMP; - PHY_vars_UE->prach_resources[0] = &prach_resources; + UE->prach_resources[0] = &prach_resources; if (preamble_tx == 99) preamble_tx = (uint16_t)(taus()&0x3f); @@ -421,10 +418,10 @@ int main(int argc, char **argv) if (n_frames == 1) printf("raPreamble %d\n",preamble_tx); - PHY_vars_UE->prach_resources[0]->ra_PreambleIndex = preamble_tx; - PHY_vars_UE->prach_resources[0]->ra_TDD_map_index = 0; + UE->prach_resources[0]->ra_PreambleIndex = preamble_tx; + UE->prach_resources[0]->ra_TDD_map_index = 0; - tx_lev = generate_prach(PHY_vars_UE, + tx_lev = generate_prach(UE, 0, //eNB_id, subframe, 0); //Nf @@ -436,7 +433,7 @@ int main(int argc, char **argv) //write_output("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); // multipath channel - dump_prach_config(&PHY_vars_eNB->lte_frame_parms,subframe); + dump_prach_config(&eNB->frame_parms,subframe); for (i=0; i<2*frame_parms->samples_per_tti; i++) { for (aa=0; aa<1; aa++) { @@ -444,7 +441,7 @@ int main(int argc, char **argv) s_re[aa][i] = ((double)(((short *)&txdata[aa][subframe*frame_parms->samples_per_tti]))[(i<<1)]); s_im[aa][i] = ((double)(((short *)&txdata[aa][subframe*frame_parms->samples_per_tti]))[(i<<1)+1]); } else { - for (aarx=0; aarxlte_frame_parms.nb_antennas_rx; aarx++) { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { if (aa==0) { r_re[aarx][i] = ((double)(((short *)&txdata[aa][subframe*frame_parms->samples_per_tti]))[(i<<1)]); r_im[aarx][i] = ((double)(((short *)&txdata[aa][subframe*frame_parms->samples_per_tti]))[(i<<1)+1]); @@ -491,15 +488,14 @@ int main(int argc, char **argv) } for (i=0; isamples_per_tti; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) (.167*(r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) (.167*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) (.167*(r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) (.167*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } } - rx_prach(PHY_vars_eNB, - subframe, + rx_prach(eNB, preamble_energy_list, preamble_delay_list, 0, //Nf @@ -530,12 +526,12 @@ int main(int argc, char **argv) printf("preamble %d : energy %d, delay %d\n",i,preamble_energy_list[i],preamble_delay_list[i]); write_output("prach0.m","prach0", &txdata[0][subframe*frame_parms->samples_per_tti],frame_parms->samples_per_tti,1,1); - write_output("prachF0.m","prachF0", &PHY_vars_eNB->lte_eNB_prach_vars.prachF[0],24576,1,1); + write_output("prachF0.m","prachF0", &eNB->prach_vars.prachF[0],24576,1,1); write_output("rxsig0.m","rxs0", - &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][subframe*frame_parms->samples_per_tti], + &eNB->common_vars.rxdata[0][0][subframe*frame_parms->samples_per_tti], frame_parms->samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", &PHY_vars_eNB->lte_eNB_common_vars.rxdataF[0][0][0],512*nsymb*2,2,1); - write_output("prach_preamble.m","prachp",&PHY_vars_eNB->X_u[0],839,1,1); + write_output("rxsigF0.m","rxsF0", &eNB->common_vars.rxdataF[0][0][0],512*nsymb*2,2,1); + write_output("prach_preamble.m","prachp",&eNB->X_u[0],839,1,1); } } diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c index fa96ac5843..d3c3df0754 100644 --- a/openair1/SIMULATION/LTE_PHY/pucchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c @@ -45,10 +45,12 @@ #include "OCG_vars.h" #include "UTIL/LOG/log_extern.h" +#include "unitary_defs.h" + int current_dlsch_cqi; //FIXME! -PHY_VARS_eNB *PHY_vars_eNB; -PHY_VARS_UE *PHY_vars_UE; +PHY_VARS_eNB *eNB; +PHY_VARS_UE *UE; #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 @@ -101,17 +103,6 @@ int main(int argc, char **argv) uint16_t n2_pucch = 0; number_of_cards = 1; - openair_daq_vars.rx_rf_mode = 1; - - /* - rxdataF = (int **)malloc16(2*sizeof(int*)); - rxdataF[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdataF[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - - rxdata = (int **)malloc16(2*sizeof(int*)); - rxdata[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - */ while ((c = getopt (argc, argv, "har:pf:g:n:s:S:x:y:z:N:F:T:R:")) != -1) { switch (c) { @@ -311,10 +302,11 @@ int main(int argc, char **argv) n_rx, transmission_mode, extended_prefix_flag, - Nid_cell, FDD, + Nid_cell, 3, N_RB_DL, + 0, osf, 0); @@ -328,10 +320,10 @@ int main(int argc, char **argv) printf("SNR0 %f, SNR1 %f\n",snr0,snr1); - frame_parms = &PHY_vars_eNB->lte_frame_parms; + frame_parms = &eNB->frame_parms; - txdata = PHY_vars_eNB->lte_eNB_common_vars.txdata[eNB_id]; + txdata = eNB->common_vars.txdata[eNB_id]; s_re = malloc(2*sizeof(double*)); s_im = malloc(2*sizeof(double*)); @@ -345,11 +337,11 @@ int main(int argc, char **argv) printf("[SIM] Using SCM/101\n"); - UE2eNB = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + UE2eNB = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_UL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_UL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_UL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL), 0.0, 0, 0); @@ -373,22 +365,22 @@ int main(int argc, char **argv) bzero(r_im[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); } - init_ncs_cell(&PHY_vars_eNB->lte_frame_parms,PHY_vars_eNB->ncs_cell); + init_ncs_cell(&eNB->frame_parms,eNB->ncs_cell); - init_ncs_cell(&PHY_vars_UE->lte_frame_parms,PHY_vars_UE->ncs_cell); + init_ncs_cell(&UE->frame_parms,UE->ncs_cell); - PHY_vars_eNB->lte_frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; - PHY_vars_eNB->lte_frame_parms.pucch_config_common.nRB_CQI = 0; - PHY_vars_eNB->lte_frame_parms.pucch_config_common.nCS_AN = 0; - PHY_vars_UE->lte_frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; - PHY_vars_UE->lte_frame_parms.pucch_config_common.nRB_CQI = 0; - PHY_vars_UE->lte_frame_parms.pucch_config_common.nCS_AN = 0; + eNB->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; + eNB->frame_parms.pucch_config_common.nRB_CQI = 0; + eNB->frame_parms.pucch_config_common.nCS_AN = 0; + UE->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; + UE->frame_parms.pucch_config_common.nRB_CQI = 0; + UE->frame_parms.pucch_config_common.nCS_AN = 0; pucch_payload = 0; - generate_pucch(PHY_vars_UE->lte_ue_common_vars.txdataF, + generate_pucch(UE->common_vars.txdataF, frame_parms, - PHY_vars_UE->ncs_cell, + UE->ncs_cell, pucch_format, &pucch_config_dedicated, n1_pucch, @@ -397,34 +389,34 @@ int main(int argc, char **argv) &pucch_payload, AMP, //amp, subframe); //subframe - write_output("txsigF0.m","txsF0", &PHY_vars_UE->lte_ue_common_vars.txdataF[0][2*subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*nsymb,1,1); + write_output("txsigF0.m","txsF0", &UE->common_vars.txdataF[0][2*subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*nsymb,1,1); tx_lev = 0; - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(&PHY_vars_UE->lte_ue_common_vars.txdataF[aa][2*subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], // input, - &txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe], // output + PHY_ofdm_mod(&UE->common_vars.txdataF[aa][2*subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], // input, + &txdata[aa][eNB->frame_parms.samples_per_tti*subframe], // output frame_parms->ofdm_symbol_size, nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(&PHY_vars_UE->lte_ue_common_vars.txdataF[eNB_id][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], - &txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe], + normal_prefix_mod(&UE->common_vars.txdataF[eNB_id][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], + &txdata[aa][eNB->frame_parms.samples_per_tti*subframe], nsymb, frame_parms); - //apply_7_5_kHz(PHY_vars_UE,PHY_vars_UE->lte_ue_common_vars.txdata[aa],subframe<<1); - //apply_7_5_kHz(PHY_vars_UE,PHY_vars_UE->lte_ue_common_vars.txdata[aa],1+(subframe<<1)); - apply_7_5_kHz(PHY_vars_UE,&txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],0); - apply_7_5_kHz(PHY_vars_UE,&txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],1); + //apply_7_5_kHz(UE,UE->common_vars.txdata[aa],subframe<<1); + //apply_7_5_kHz(UE,UE->common_vars.txdata[aa],1+(subframe<<1)); + apply_7_5_kHz(UE,&txdata[aa][eNB->frame_parms.samples_per_tti*subframe],0); + apply_7_5_kHz(UE,&txdata[aa][eNB->frame_parms.samples_per_tti*subframe],1); } - tx_lev += signal_energy(&txdata[aa][subframe*PHY_vars_eNB->lte_frame_parms.samples_per_tti], + tx_lev += signal_energy(&txdata[aa][subframe*eNB->frame_parms.samples_per_tti], OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES); } @@ -436,7 +428,7 @@ int main(int argc, char **argv) // multipath channel for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { s_re[aa][i] = ((double)(((short *)&txdata[aa][subframe*frame_parms->samples_per_tti]))[(i<<1)]); s_im[aa][i] = ((double)(((short *)&txdata[aa][subframe*frame_parms->samples_per_tti]))[(i<<1)+1]); } @@ -498,17 +490,17 @@ int main(int argc, char **argv) //printf("n_trial %d\n",n_trials); // fill measurement symbol (19) with noise for (i=0; ilte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i+1] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i+1] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } } for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { if (n_trials==0) { // r_re[aa][i] += (pow(10.0,.05*interf1)*r_re1[aa][i] + pow(10.0,.05*interf2)*r_re2[aa][i]); // r_im[aa][i] += (pow(10.0,.05*interf1)*r_im1[aa][i] + pow(10.0,.05*interf2)*r_im2[aa][i]); @@ -516,31 +508,31 @@ int main(int argc, char **argv) if (sig==1) { - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) (((tx_gain*r_re[aa][i]) +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) (((tx_gain*r_im[aa][i]) + (iqim*r_re[aa][i]*tx_gain) + sqrt(sigma2/2)*gaussdouble( + ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) (((tx_gain*r_re[aa][i]) +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) (((tx_gain*r_im[aa][i]) + (iqim*r_re[aa][i]*tx_gain) + sqrt(sigma2/2)*gaussdouble( 0.0,1.0))); } else { - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } } } - remove_7_5_kHz(PHY_vars_eNB,subframe<<1); - remove_7_5_kHz(PHY_vars_eNB,1+(subframe<<1)); + remove_7_5_kHz(eNB,subframe<<1); + remove_7_5_kHz(eNB,1+(subframe<<1)); - for (l=0; llte_frame_parms.symbols_per_tti/2; l++) { + for (l=0; lframe_parms.symbols_per_tti/2; l++) { - slot_fep_ul(&PHY_vars_eNB->lte_frame_parms, - &PHY_vars_eNB->lte_eNB_common_vars, + slot_fep_ul(&eNB->frame_parms, + &eNB->common_vars, l, subframe*2,// slot 0, 0 ); - slot_fep_ul(&PHY_vars_eNB->lte_frame_parms, - &PHY_vars_eNB->lte_eNB_common_vars, + slot_fep_ul(&eNB->frame_parms, + &eNB->common_vars, l, 1+(subframe*2),//slot 0, @@ -553,12 +545,12 @@ int main(int argc, char **argv) // if (sig == 1) // printf("*"); - lte_eNB_I0_measurements(PHY_vars_eNB, + lte_eNB_I0_measurements(eNB, subframe, 0, 1); - PHY_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dB = N0;//(int8_t)(sigma2_dB-10*log10(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(12*NB_RB))); - stat = rx_pucch(PHY_vars_eNB, + eNB->measurements[0].n0_power_tot_dB = N0;//(int8_t)(sigma2_dB-10*log10(eNB->frame_parms.ofdm_symbol_size/(12*NB_RB))); + stat = rx_pucch(eNB, pucch_format, 0, n1_pucch, @@ -593,7 +585,7 @@ int main(int argc, char **argv) } if (pucch_format==pucch_format1) - printf("pucch_trials %d : pucch1_false %d,pucch1_missed %d, N0 %d dB, stat_no_sig %f dB, stat_sig %f dB\n",pucch_tx,pucch1_false,pucch1_missed,PHY_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dB, + printf("pucch_trials %d : pucch1_false %d,pucch1_missed %d, N0 %d dB, stat_no_sig %f dB, stat_sig %f dB\n",pucch_tx,pucch1_false,pucch1_missed,eNB->measurements[0].n0_power_tot_dB, 10*log10(stat_no_sig),10*log10(stat_sig)); else if (pucch_format==pucch_format1a) printf("pucch_trials %d : pucch1a_errors %d\n",pucch_tx,pucch1_false); @@ -605,8 +597,8 @@ int main(int argc, char **argv) if (n_frames==1) { //write_output("txsig0.m","txs0", &txdata[0][subframe*frame_parms->samples_per_tti],frame_parms->samples_per_tti,1,1); write_output("txsig0pucch.m", "txs0", &txdata[0][0], FRAME_LENGTH_COMPLEX_SAMPLES,1,1); - write_output("rxsig0.m","rxs0", &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][subframe*frame_parms->samples_per_tti],frame_parms->samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", &PHY_vars_eNB->lte_eNB_common_vars.rxdataF[0][0][0],512*nsymb*2,2,1); + write_output("rxsig0.m","rxs0", &eNB->common_vars.rxdata[0][0][subframe*frame_parms->samples_per_tti],frame_parms->samples_per_tti,1,1); + write_output("rxsigF0.m","rxsF0", &eNB->common_vars.rxdataF[0][0][0],512*nsymb*2,2,1); } diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 56f8eb146a..96c0083f94 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -51,13 +51,15 @@ #include "LAYER2/MAC/vars.h" #include "OCG_vars.h" +#include "unitary_defs.h" + #include "PHY/TOOLS/lte_phy_scope.h" -extern unsigned short dftsizes[33]; -extern short *ul_ref_sigs[30][2][33]; +PHY_VARS_eNB *eNB; +PHY_VARS_UE *UE; + + -PHY_VARS_eNB *PHY_vars_eNB; -PHY_VARS_UE *PHY_vars_UE; //#define MCS_COUNT 23//added for PHY abstraction @@ -186,7 +188,6 @@ int main(int argc, char **argv) uint8_t max_turbo_iterations=4; uint8_t llr8_flag=0; int nb_rb_set = 0; - int sf; int threequarter_fs=0; opp_enabled=1; // to enable the time meas @@ -478,9 +479,9 @@ int main(int argc, char **argv) 0); if (nb_rb_set == 0) - nb_rb = PHY_vars_eNB->lte_frame_parms.N_RB_UL; + nb_rb = eNB->frame_parms.N_RB_UL; - printf("1 . rxdataF_comp[0] %p\n",PHY_vars_eNB->lte_eNB_pusch_vars[0]->rxdataF_comp[0][0]); + printf("1 . rxdataF_comp[0] %p\n",eNB->pusch_vars[0]->rxdataF_comp[0][0]); printf("Setting mcs = %d\n",mcs); printf("n_frames = %d\n", n_frames); @@ -497,9 +498,9 @@ int main(int argc, char **argv) txdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); */ - frame_parms = &PHY_vars_eNB->lte_frame_parms; + frame_parms = &eNB->frame_parms; - txdata = PHY_vars_UE->lte_ue_common_vars.txdata; + txdata = UE->common_vars.txdata; s_re = malloc(2*sizeof(double*)); @@ -509,7 +510,7 @@ int main(int argc, char **argv) // r_re0 = malloc(2*sizeof(double*)); // r_im0 = malloc(2*sizeof(double*)); - nsymb = (PHY_vars_eNB->lte_frame_parms.Ncp == NORMAL) ? 14 : 12; + nsymb = (eNB->frame_parms.Ncp == NORMAL) ? 14 : 12; sprintf(bler_fname,"ULbler_mcs%d_nrb%d_ChannelModel%d_nsim%d.csv",mcs,nb_rb,chMod,n_frames); @@ -594,40 +595,40 @@ int main(int argc, char **argv) fl_show_form (form_enb->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); } - PHY_vars_UE->lte_ue_pdcch_vars[0]->crnti = 14; + UE->pdcch_vars[0]->crnti = 14; - PHY_vars_UE->lte_frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig = 2; - PHY_vars_UE->lte_frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 7; - PHY_vars_UE->soundingrs_ul_config_dedicated[eNB_id].srs_Bandwidth = 0; - PHY_vars_UE->soundingrs_ul_config_dedicated[eNB_id].transmissionComb = 0; - PHY_vars_UE->soundingrs_ul_config_dedicated[eNB_id].freqDomainPosition = 0; + UE->frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig = 2; + UE->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 7; + UE->soundingrs_ul_config_dedicated[eNB_id].srs_Bandwidth = 0; + UE->soundingrs_ul_config_dedicated[eNB_id].transmissionComb = 0; + UE->soundingrs_ul_config_dedicated[eNB_id].freqDomainPosition = 0; - PHY_vars_eNB->lte_frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig = 2; - PHY_vars_eNB->lte_frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 7; + eNB->frame_parms.soundingrs_ul_config_common.srs_BandwidthConfig = 2; + eNB->frame_parms.soundingrs_ul_config_common.srs_SubframeConfig = 7; - PHY_vars_eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex = 1; - PHY_vars_eNB->soundingrs_ul_config_dedicated[UE_id].srs_Bandwidth = 0; - PHY_vars_eNB->soundingrs_ul_config_dedicated[UE_id].transmissionComb = 0; - PHY_vars_eNB->soundingrs_ul_config_dedicated[UE_id].freqDomainPosition = 0; - PHY_vars_eNB->cooperation_flag = cooperation_flag; - // PHY_vars_eNB->eNB_UE_stats[0].SRS_parameters = PHY_vars_UE->SRS_parameters; + eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex = 1; + eNB->soundingrs_ul_config_dedicated[UE_id].srs_Bandwidth = 0; + eNB->soundingrs_ul_config_dedicated[UE_id].transmissionComb = 0; + eNB->soundingrs_ul_config_dedicated[UE_id].freqDomainPosition = 0; + eNB->cooperation_flag = cooperation_flag; + // eNB->eNB_UE_stats[0].SRS_parameters = UE->SRS_parameters; - PHY_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = beta_ACK; - PHY_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index = beta_RI; - PHY_vars_eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = beta_CQI; - PHY_vars_UE->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index = beta_ACK; - PHY_vars_UE->pusch_config_dedicated[eNB_id].betaOffset_RI_Index = beta_RI; - PHY_vars_UE->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index = beta_CQI; + eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = beta_ACK; + eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index = beta_RI; + eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = beta_CQI; + UE->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index = beta_ACK; + UE->pusch_config_dedicated[eNB_id].betaOffset_RI_Index = beta_RI; + UE->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index = beta_CQI; - PHY_vars_UE->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled = 1; + UE->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled = 1; printf("PUSCH Beta : ACK %f, RI %f, CQI %f\n",(double)beta_ack[beta_ACK]/8,(double)beta_ri[beta_RI]/8,(double)beta_cqi[beta_CQI]/8); - UE2eNB = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + UE2eNB = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_UL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_UL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_UL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL), forgetting_factor, delay, 0); @@ -635,39 +636,39 @@ int main(int argc, char **argv) UE2eNB->max_Doppler = maxDoppler; // NN: N_RB_UL has to be defined in ulsim - PHY_vars_eNB->ulsch_eNB[0] = new_eNB_ulsch(max_turbo_iterations,N_RB_DL,0); - PHY_vars_UE->ulsch_ue[0] = new_ue_ulsch(N_RB_DL,0); + eNB->ulsch[0] = new_eNB_ulsch(max_turbo_iterations,N_RB_DL,0); + UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); // Create transport channel structures for 2 transport blocks (MIMO) for (i=0; i<2; i++) { - PHY_vars_eNB->dlsch_eNB[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0); - PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(1,8,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0); + eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0); + UE->dlsch[0][i] = new_ue_dlsch(1,8,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0); - if (!PHY_vars_eNB->dlsch_eNB[0][i]) { + if (!eNB->dlsch[0][i]) { printf("Can't get eNB dlsch structures\n"); exit(-1); } - if (!PHY_vars_UE->dlsch_ue[0][i]) { + if (!UE->dlsch[0][i]) { printf("Can't get ue dlsch structures\n"); exit(-1); } - PHY_vars_eNB->dlsch_eNB[0][i]->rnti = 14; - PHY_vars_UE->dlsch_ue[0][i]->rnti = 14; + eNB->dlsch[0][i]->rnti = 14; + UE->dlsch[0][i]->rnti = 14; } - switch (PHY_vars_eNB->lte_frame_parms.N_RB_UL) { + switch (eNB->frame_parms.N_RB_UL) { case 6: break; case 25: - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,PHY_vars_eNB->lte_frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; @@ -676,8 +677,8 @@ int main(int argc, char **argv) ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai = 1; } else { ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,PHY_vars_eNB->lte_frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; @@ -688,10 +689,10 @@ int main(int argc, char **argv) break; case 50: - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,PHY_vars_eNB->lte_frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; @@ -700,8 +701,8 @@ int main(int argc, char **argv) ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai = 1; } else { ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,PHY_vars_eNB->lte_frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; @@ -712,10 +713,10 @@ int main(int argc, char **argv) break; case 100: - if (PHY_vars_eNB->lte_frame_parms.frame_type == TDD) { + if (eNB->frame_parms.frame_type == TDD) { ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,PHY_vars_eNB->lte_frame_parms.N_RB_UL,((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; @@ -724,8 +725,8 @@ int main(int argc, char **argv) ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai = 1; } else { ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,PHY_vars_eNB->lte_frame_parms.N_RB_UL,((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; @@ -740,47 +741,45 @@ int main(int argc, char **argv) } - PHY_vars_UE->PHY_measurements.rank[0] = 0; - PHY_vars_UE->transmission_mode[0] = 2; - PHY_vars_UE->pucch_config_dedicated[0].tdd_AckNackFeedbackMode = bundling_flag == 1 ? bundling : multiplexing; - PHY_vars_eNB->transmission_mode[0] = 2; - PHY_vars_eNB->pucch_config_dedicated[0].tdd_AckNackFeedbackMode = bundling_flag == 1 ? bundling : multiplexing; - PHY_vars_UE->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1; - PHY_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1; - PHY_vars_UE->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; - PHY_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; - PHY_vars_UE->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; - PHY_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; - PHY_vars_UE->frame_tx=1; + UE->measurements.rank[0] = 0; + UE->transmission_mode[0] = 2; + UE->pucch_config_dedicated[0].tdd_AckNackFeedbackMode = bundling_flag == 1 ? bundling : multiplexing; + eNB->transmission_mode[0] = 2; + eNB->pucch_config_dedicated[0].tdd_AckNackFeedbackMode = bundling_flag == 1 ? bundling : multiplexing; + UE->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1; + eNB->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1; + UE->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + eNB->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + UE->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + eNB->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; - for (sf=0; sf<10; sf++) { - PHY_vars_eNB->proc[sf].frame_tx=1; - PHY_vars_eNB->proc[sf].subframe_tx=sf; - PHY_vars_eNB->proc[sf].frame_rx=1; - PHY_vars_eNB->proc[sf].subframe_rx=sf; - } + + + + eNB->proc.frame_rx=1; + eNB->proc.subframe_rx=subframe; + + eNB->proc.frame_tx=pdcch_alloc2ul_frame(&eNB->frame_parms,1,subframe); + eNB->proc.subframe_tx=pdcch_alloc2ul_subframe(&eNB->frame_parms,subframe); + + UE->frame_tx = eNB->proc.frame_rx; + UE->frame_rx = eNB->proc.frame_tx; printf("Init UL hopping UE\n"); - init_ul_hopping(&PHY_vars_UE->lte_frame_parms); + init_ul_hopping(&UE->frame_parms); printf("Init UL hopping eNB\n"); - init_ul_hopping(&PHY_vars_eNB->lte_frame_parms); + init_ul_hopping(&eNB->frame_parms); - PHY_vars_eNB->proc[subframe].frame_rx = PHY_vars_UE->frame_tx; - if (ul_subframe2pdcch_alloc_subframe(&PHY_vars_eNB->lte_frame_parms,subframe) > subframe) // allocation was in previous frame - PHY_vars_eNB->proc[ul_subframe2pdcch_alloc_subframe(&PHY_vars_eNB->lte_frame_parms,subframe)].frame_tx = (PHY_vars_UE->frame_tx-1)&1023; - - PHY_vars_UE->dlsch_ue[0][0]->harq_ack[ul_subframe2pdcch_alloc_subframe(&PHY_vars_eNB->lte_frame_parms,subframe)].send_harq_status = 1; + UE->dlsch[0][0]->harq_ack[ul_subframe2pdcch_alloc_subframe(&eNB->frame_parms,subframe)].send_harq_status = 1; - // printf("UE frame %d, eNB frame %d (eNB frame_tx %d)\n",PHY_vars_UE->frame,PHY_vars_eNB->proc[subframe].frame_rx,PHY_vars_eNB->proc[ul_subframe2pdcch_alloc_subframe(&PHY_vars_eNB->lte_frame_parms,subframe)].frame_tx); - PHY_vars_UE->frame_tx = (PHY_vars_UE->frame_tx-1)&1023; generate_ue_ulsch_params_from_dci((void *)&UL_alloc_pdu, 14, - ul_subframe2pdcch_alloc_subframe(&PHY_vars_UE->lte_frame_parms,subframe), + eNB->proc.subframe_tx, format0, - PHY_vars_UE, + UE, SI_RNTI, 0, P_RNTI, @@ -790,13 +789,12 @@ int main(int argc, char **argv) // printf("RIV %d\n",UL_alloc_pdu.rballoc); - generate_eNB_ulsch_params_from_dci((void *)&UL_alloc_pdu, + generate_eNB_ulsch_params_from_dci(eNB, + (void *)&UL_alloc_pdu, 14, - ul_subframe2pdcch_alloc_subframe(&PHY_vars_eNB->lte_frame_parms,subframe), format0, 0, - PHY_vars_eNB, - SI_RNTI, + SI_RNTI, 0, P_RNTI, CBA_RNTI, @@ -804,15 +802,13 @@ int main(int argc, char **argv) coded_bits_per_codeword = nb_rb * (12 * get_Qm_ul(mcs)) * nsymb; - if (cqi_flag == 1) coded_bits_per_codeword-=PHY_vars_UE->ulsch_ue[0]->O; + if (cqi_flag == 1) coded_bits_per_codeword-=UE->ulsch[0]->O; rate = (double)dlsch_tbs25[get_I_TBS(mcs)][nb_rb-1]/(coded_bits_per_codeword); printf("Rate = %f (mod %d), coded bits %d\n",rate,get_Qm_ul(mcs),coded_bits_per_codeword); - PHY_vars_UE->frame_tx = (PHY_vars_UE->frame_tx+1)&1023; - for (ch_realization=0; ch_realization5) || (subframe < 4)) - // PHY_vars_UE->frame++; + // UE->frame++; for (SNR=snr0; SNRlte_frame_parms,PHY_vars_UE->frame_tx,subframe); - input_buffer_length = PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->TBS/8; + harq_pid = subframe2harq_pid(&UE->frame_parms,UE->frame_tx,subframe); + input_buffer_length = UE->ulsch[0]->harq_processes[harq_pid]->TBS/8; input_buffer = (unsigned char *)malloc(input_buffer_length+4); - // printf("UL frame %d/subframe %d, harq_pid %d\n",PHY_vars_UE->frame,subframe,harq_pid); + // printf("UL frame %d/subframe %d, harq_pid %d\n",UE->frame,subframe,harq_pid); if (input_fdUL == NULL) { @@ -904,33 +900,33 @@ int main(int argc, char **argv) avg_iter = 0; iter_trials=0; - reset_meas(&PHY_vars_UE->phy_proc_tx); - reset_meas(&PHY_vars_UE->ofdm_mod_stats); - reset_meas(&PHY_vars_UE->ulsch_modulation_stats); - reset_meas(&PHY_vars_UE->ulsch_encoding_stats); - reset_meas(&PHY_vars_UE->ulsch_interleaving_stats); - reset_meas(&PHY_vars_UE->ulsch_rate_matching_stats); - reset_meas(&PHY_vars_UE->ulsch_turbo_encoding_stats); - reset_meas(&PHY_vars_UE->ulsch_segmentation_stats); - reset_meas(&PHY_vars_UE->ulsch_multiplexing_stats); + reset_meas(&UE->phy_proc_tx); + reset_meas(&UE->ofdm_mod_stats); + reset_meas(&UE->ulsch_modulation_stats); + reset_meas(&UE->ulsch_encoding_stats); + reset_meas(&UE->ulsch_interleaving_stats); + reset_meas(&UE->ulsch_rate_matching_stats); + reset_meas(&UE->ulsch_turbo_encoding_stats); + reset_meas(&UE->ulsch_segmentation_stats); + reset_meas(&UE->ulsch_multiplexing_stats); - reset_meas(&PHY_vars_eNB->phy_proc_rx); - reset_meas(&PHY_vars_eNB->ofdm_demod_stats); - reset_meas(&PHY_vars_eNB->ulsch_channel_estimation_stats); - reset_meas(&PHY_vars_eNB->ulsch_freq_offset_estimation_stats); - reset_meas(&PHY_vars_eNB->rx_dft_stats); - reset_meas(&PHY_vars_eNB->ulsch_decoding_stats); - reset_meas(&PHY_vars_eNB->ulsch_turbo_decoding_stats); - reset_meas(&PHY_vars_eNB->ulsch_deinterleaving_stats); - reset_meas(&PHY_vars_eNB->ulsch_demultiplexing_stats); - reset_meas(&PHY_vars_eNB->ulsch_rate_unmatching_stats); - reset_meas(&PHY_vars_eNB->ulsch_tc_init_stats); - reset_meas(&PHY_vars_eNB->ulsch_tc_alpha_stats); - reset_meas(&PHY_vars_eNB->ulsch_tc_beta_stats); - reset_meas(&PHY_vars_eNB->ulsch_tc_gamma_stats); - reset_meas(&PHY_vars_eNB->ulsch_tc_ext_stats); - reset_meas(&PHY_vars_eNB->ulsch_tc_intl1_stats); - reset_meas(&PHY_vars_eNB->ulsch_tc_intl2_stats); + reset_meas(&eNB->phy_proc_rx); + reset_meas(&eNB->ofdm_demod_stats); + reset_meas(&eNB->ulsch_channel_estimation_stats); + reset_meas(&eNB->ulsch_freq_offset_estimation_stats); + reset_meas(&eNB->rx_dft_stats); + reset_meas(&eNB->ulsch_decoding_stats); + reset_meas(&eNB->ulsch_turbo_decoding_stats); + reset_meas(&eNB->ulsch_deinterleaving_stats); + reset_meas(&eNB->ulsch_demultiplexing_stats); + reset_meas(&eNB->ulsch_rate_unmatching_stats); + reset_meas(&eNB->ulsch_tc_init_stats); + reset_meas(&eNB->ulsch_tc_alpha_stats); + reset_meas(&eNB->ulsch_tc_beta_stats); + reset_meas(&eNB->ulsch_tc_gamma_stats); + reset_meas(&eNB->ulsch_tc_ext_stats); + reset_meas(&eNB->ulsch_tc_intl1_stats); + reset_meas(&eNB->ulsch_tc_intl2_stats); // initialization struct list time_vector_tx; @@ -953,28 +949,28 @@ int main(int argc, char **argv) for (trials = 0; trialsframe++; - // PHY_vars_eNB->frame++; + // UE->frame++; + // eNB->frame++; fflush(stdout); round=0; while (round < 4) { - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->round=round; - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->round=round; + eNB->ulsch[0]->harq_processes[harq_pid]->round=round; + UE->ulsch[0]->harq_processes[harq_pid]->round=round; // printf("Trial %d : Round %d ",trials,round); round_trials[round]++; if (round == 0) { - //PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Ndi = 1; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->rvidx = round>>1; - //PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->Ndi = 1; - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->rvidx = round>>1; + //eNB->ulsch[0]->harq_processes[harq_pid]->Ndi = 1; + eNB->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; + //UE->ulsch[0]->harq_processes[harq_pid]->Ndi = 1; + UE->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; } else { - //PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Ndi = 0; - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->rvidx = round>>1; - //PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->Ndi = 0; - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->rvidx = round>>1; + //eNB->ulsch[0]->harq_processes[harq_pid]->Ndi = 0; + eNB->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; + //UE->ulsch[0]->harq_processes[harq_pid]->Ndi = 0; + UE->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; } @@ -996,39 +992,39 @@ int main(int argc, char **argv) if (input_fdUL == NULL) { - start_meas(&PHY_vars_UE->phy_proc_tx); + start_meas(&UE->phy_proc_tx); #ifdef OFDMA_ULSCH if (srs_flag) - generate_srs_tx(PHY_vars_UE,0,AMP,subframe); + generate_srs_tx(UE,0,AMP,subframe); - generate_drs_pusch(PHY_vars_UE,0,AMP,subframe,first_rb,nb_rb,0); + generate_drs_pusch(UE,0,AMP,subframe,first_rb,nb_rb,0); #else if (srs_flag) - generate_srs_tx(PHY_vars_UE,0,AMP,subframe); + generate_srs_tx(UE,0,AMP,subframe); - generate_drs_pusch(PHY_vars_UE,0, + generate_drs_pusch(UE,0, AMP,subframe, - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->first_rb, - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->nb_rb, + UE->ulsch[0]->harq_processes[harq_pid]->first_rb, + UE->ulsch[0]->harq_processes[harq_pid]->nb_rb, 0); #endif if ((cqi_flag == 1) && (n_frames == 1) ) { - printf("CQI information (O %d) %d %d\n",PHY_vars_UE->ulsch_ue[0]->O, - PHY_vars_UE->ulsch_ue[0]->o[0],PHY_vars_UE->ulsch_ue[0]->o[1]); - print_CQI(PHY_vars_UE->ulsch_ue[0]->o,PHY_vars_UE->ulsch_ue[0]->uci_format,PHY_vars_UE->lte_frame_parms.N_RB_DL,0); + printf("CQI information (O %d) %d %d\n",UE->ulsch[0]->O, + UE->ulsch[0]->o[0],UE->ulsch[0]->o[1]); + print_CQI(UE->ulsch[0]->o,UE->ulsch[0]->uci_format,UE->frame_parms.N_RB_DL,0); } - PHY_vars_UE->ulsch_ue[0]->o_ACK[0] = taus()&1; + UE->ulsch[0]->o_ACK[0] = taus()&1; - start_meas(&PHY_vars_UE->ulsch_encoding_stats); + start_meas(&UE->ulsch_encoding_stats); if (ulsch_encoding(input_buffer, - PHY_vars_UE, + UE, harq_pid, eNB_id, 2, // transmission mode @@ -1039,52 +1035,52 @@ int main(int argc, char **argv) exit(-1); } - stop_meas(&PHY_vars_UE->ulsch_encoding_stats); + stop_meas(&UE->ulsch_encoding_stats); - start_meas(&PHY_vars_UE->ulsch_modulation_stats); + start_meas(&UE->ulsch_modulation_stats); #ifdef OFDMA_ULSCH - ulsch_modulation(PHY_vars_UE->lte_ue_common_vars.txdataF,AMP, - PHY_vars_UE->frame_tx,subframe,&PHY_vars_UE->lte_frame_parms,PHY_vars_UE->ulsch_ue[0]); + ulsch_modulation(UE->common_vars.txdataF,AMP, + UE->frame_tx,subframe,&UE->frame_parms,UE->ulsch[0]); #else // printf("Generating PUSCH in subframe %d with amp %d, nb_rb %d\n",subframe,AMP,nb_rb); - ulsch_modulation(PHY_vars_UE->lte_ue_common_vars.txdataF,AMP, - PHY_vars_UE->frame_tx,subframe,&PHY_vars_UE->lte_frame_parms, - PHY_vars_UE->ulsch_ue[0]); + ulsch_modulation(UE->common_vars.txdataF,AMP, + UE->frame_tx,subframe,&UE->frame_parms, + UE->ulsch[0]); #endif - stop_meas(&PHY_vars_UE->ulsch_modulation_stats); + stop_meas(&UE->ulsch_modulation_stats); if (n_frames==1) { - write_output("txsigF0UL.m","txsF0", &PHY_vars_UE->lte_ue_common_vars.txdataF[0][PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size*nsymb*subframe],PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size*nsymb,1, + write_output("txsigF0UL.m","txsF0", &UE->common_vars.txdataF[0][eNB->frame_parms.ofdm_symbol_size*nsymb*subframe],eNB->frame_parms.ofdm_symbol_size*nsymb,1, 1); - //write_output("txsigF1.m","txsF1", PHY_vars_UE->lte_ue_common_vars.txdataF[0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + //write_output("txsigF1.m","txsF1", UE->common_vars.txdataF[0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); } tx_lev=0; - start_meas(&PHY_vars_UE->ofdm_mod_stats); + start_meas(&UE->ofdm_mod_stats); for (aa=0; aa<1; aa++) { if (frame_parms->Ncp == EXTENDED) - PHY_ofdm_mod(&PHY_vars_UE->lte_ue_common_vars.txdataF[aa][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], // input - &txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe], // output - PHY_vars_UE->lte_frame_parms.ofdm_symbol_size, + PHY_ofdm_mod(&UE->common_vars.txdataF[aa][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], // input + &txdata[aa][eNB->frame_parms.samples_per_tti*subframe], // output + UE->frame_parms.ofdm_symbol_size, nsymb, // number of symbols - PHY_vars_UE->lte_frame_parms.nb_prefix_samples, // number of prefix samples + UE->frame_parms.nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else - normal_prefix_mod(&PHY_vars_UE->lte_ue_common_vars.txdataF[aa][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], - &txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe], + normal_prefix_mod(&UE->common_vars.txdataF[aa][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], + &txdata[aa][eNB->frame_parms.samples_per_tti*subframe], nsymb, frame_parms); #ifndef OFDMA_ULSCH - apply_7_5_kHz(PHY_vars_UE,PHY_vars_UE->lte_ue_common_vars.txdata[aa],subframe<<1); - apply_7_5_kHz(PHY_vars_UE,PHY_vars_UE->lte_ue_common_vars.txdata[aa],1+(subframe<<1)); + apply_7_5_kHz(UE,UE->common_vars.txdata[aa],subframe<<1); + apply_7_5_kHz(UE,UE->common_vars.txdata[aa],1+(subframe<<1)); #endif - stop_meas(&PHY_vars_UE->ofdm_mod_stats); - stop_meas(&PHY_vars_UE->phy_proc_tx); - tx_lev += signal_energy(&txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe], - PHY_vars_eNB->lte_frame_parms.samples_per_tti); + stop_meas(&UE->ofdm_mod_stats); + stop_meas(&UE->phy_proc_tx); + tx_lev += signal_energy(&txdata[aa][eNB->frame_parms.samples_per_tti*subframe], + eNB->frame_parms.samples_per_tti); } } // input_fd == NULL @@ -1093,17 +1089,17 @@ int main(int argc, char **argv) tx_lev_dB = (unsigned int) dB_fixed_times10(tx_lev); if (n_frames==1) { - write_output("txsig0UL.m","txs0", &txdata[0][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],2*frame_parms->samples_per_tti,1,1); - // write_output("txsig1UL.m","txs1", &txdata[1][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],2*frame_parms->samples_per_tti,1,1); + write_output("txsig0UL.m","txs0", &txdata[0][eNB->frame_parms.samples_per_tti*subframe],2*frame_parms->samples_per_tti,1,1); + // write_output("txsig1UL.m","txs1", &txdata[1][eNB->frame_parms.samples_per_tti*subframe],2*frame_parms->samples_per_tti,1,1); } //AWGN //Set target wideband RX noise level to N0 - sigma2_dB = N0;//10*log10((double)tx_lev) +10*log10(PHY_vars_UE->lte_frame_parms.ofdm_symbol_size/(PHY_vars_UE->lte_frame_parms.N_RB_DL*12)) - SNR; + sigma2_dB = N0;//10*log10((double)tx_lev) +10*log10(UE->frame_parms.ofdm_symbol_size/(UE->frame_parms.N_RB_DL*12)) - SNR; sigma2 = pow(10,sigma2_dB/10); // compute tx_gain to achieve target SNR (per resource element!) - tx_gain = sqrt(pow(10.0,.1*(N0+SNR))*(nb_rb*12/(double)PHY_vars_UE->lte_frame_parms.ofdm_symbol_size)/(double)tx_lev); + tx_gain = sqrt(pow(10.0,.1*(N0+SNR))*(nb_rb*12/(double)UE->frame_parms.ofdm_symbol_size)/(double)tx_lev); if (n_frames==1) printf("tx_lev = %d (%d.%d dB,%f), gain %f\n",tx_lev,tx_lev_dB/10,tx_lev_dB,10*log10((double)tx_lev),10*log10(tx_gain)); @@ -1111,29 +1107,29 @@ int main(int argc, char **argv) // fill measurement symbol (19) with noise for (i=0; ilte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i+1] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size])[2*i+1] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } } // multipath channel - for (i=0; ilte_frame_parms.samples_per_tti; i++) { + for (i=0; iframe_parms.samples_per_tti; i++) { for (aa=0; aa<1; aa++) { - s_re[aa][i] = ((double)(((short *)&txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe]))[(i<<1)]); - s_im[aa][i] = ((double)(((short *)&txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe]))[(i<<1)+1]); + s_re[aa][i] = ((double)(((short *)&txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)]); + s_im[aa][i] = ((double)(((short *)&txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)+1]); } } if (awgn_flag == 0) { if (UE2eNB->max_Doppler == 0) { multipath_channel(UE2eNB,s_re,s_im,r_re,r_im, - PHY_vars_eNB->lte_frame_parms.samples_per_tti,hold_channel); + eNB->frame_parms.samples_per_tti,hold_channel); } else { multipath_tv_channel(UE2eNB,s_re,s_im,r_re,r_im, - 2*PHY_vars_eNB->lte_frame_parms.samples_per_tti,hold_channel); + 2*eNB->frame_parms.samples_per_tti,hold_channel); } } @@ -1169,61 +1165,61 @@ int main(int argc, char **argv) if (n_frames==1) printf("Sigma2 %f (sigma2_dB %f), tx_gain %f (%f dB)\n",sigma2,sigma2_dB,tx_gain,20*log10(tx_gain)); - for (i=0; ilte_frame_parms.samples_per_tti; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe])[2*i] = (short) ((tx_gain*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); - ((short*) &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe])[2*i+1] = (short) ((tx_gain*r_im[aa][i]) + (iqim*tx_gain*r_re[aa][i]) + sqrt( + for (i=0; iframe_parms.samples_per_tti; i++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { + ((short*) &eNB->common_vars.rxdata[0][aa][eNB->frame_parms.samples_per_tti*subframe])[2*i] = (short) ((tx_gain*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + ((short*) &eNB->common_vars.rxdata[0][aa][eNB->frame_parms.samples_per_tti*subframe])[2*i+1] = (short) ((tx_gain*r_im[aa][i]) + (iqim*tx_gain*r_re[aa][i]) + sqrt( sigma2/2)*gaussdouble(0.0,1.0)); } } if (n_frames==1) { printf("rx_level Null symbol %f\n",10*log10((double)signal_energy((int*) - &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][(PHY_vars_eNB->lte_frame_parms.samples_per_tti<<1) -PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); - printf("rx_level data symbol %f\n",10*log10(signal_energy((int*)&PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][160+(PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe)], + &eNB->common_vars.rxdata[0][0][(eNB->frame_parms.samples_per_tti<<1) -eNB->frame_parms.ofdm_symbol_size],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); + printf("rx_level data symbol %f\n",10*log10(signal_energy((int*)&eNB->common_vars.rxdata[0][0][160+(eNB->frame_parms.samples_per_tti*subframe)], OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); } - SNRmeas = 10*log10(((double)signal_energy((int*)&PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][160+(PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe)], + SNRmeas = 10*log10(((double)signal_energy((int*)&eNB->common_vars.rxdata[0][0][160+(eNB->frame_parms.samples_per_tti*subframe)], OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))/((double)signal_energy((int*) - &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][(PHY_vars_eNB->lte_frame_parms.samples_per_tti<<1) -PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size], - OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2)) - 1)+10*log10(PHY_vars_eNB->lte_frame_parms.N_RB_UL/nb_rb); + &eNB->common_vars.rxdata[0][0][(eNB->frame_parms.samples_per_tti<<1) -eNB->frame_parms.ofdm_symbol_size], + OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2)) - 1)+10*log10(eNB->frame_parms.N_RB_UL/nb_rb); if (n_frames==1) { printf("SNRmeas %f\n",SNRmeas); - // write_output("rxsig0UL.m","rxs0", &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],PHY_vars_eNB->lte_frame_parms.samples_per_tti,1,1); - //write_output("rxsig1UL.m","rxs1", &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],PHY_vars_eNB->lte_frame_parms.samples_per_tti,1,1); + // write_output("rxsig0UL.m","rxs0", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1); + //write_output("rxsig1UL.m","rxs1", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1); } #ifndef OFDMA_ULSCH - remove_7_5_kHz(PHY_vars_eNB,subframe<<1); - remove_7_5_kHz(PHY_vars_eNB,1+(subframe<<1)); - // write_output("rxsig0_75.m","rxs0_75", &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],PHY_vars_eNB->lte_frame_parms.samples_per_tti,1,1); - // write_output("rxsig1_75.m","rxs1_75", &PHY_vars_eNB->lte_eNB_common_vars.rxdata[0][0][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe],PHY_vars_eNB->lte_frame_parms.samples_per_tti,1,1); + remove_7_5_kHz(eNB,subframe<<1); + remove_7_5_kHz(eNB,1+(subframe<<1)); + // write_output("rxsig0_75.m","rxs0_75", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1); + // write_output("rxsig1_75.m","rxs1_75", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1); #endif - start_meas(&PHY_vars_eNB->phy_proc_rx); - start_meas(&PHY_vars_eNB->ofdm_demod_stats); - lte_eNB_I0_measurements(PHY_vars_eNB, + start_meas(&eNB->phy_proc_rx); + start_meas(&eNB->ofdm_demod_stats); + lte_eNB_I0_measurements(eNB, subframe, 0, 1); - for (l=subframe*PHY_vars_UE->lte_frame_parms.symbols_per_tti; l<((1+subframe)*PHY_vars_UE->lte_frame_parms.symbols_per_tti); l++) { + for (l=subframe*UE->frame_parms.symbols_per_tti; l<((1+subframe)*UE->frame_parms.symbols_per_tti); l++) { - slot_fep_ul(&PHY_vars_eNB->lte_frame_parms, - &PHY_vars_eNB->lte_eNB_common_vars, - l%(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2), - l/(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2), + slot_fep_ul(&eNB->frame_parms, + &eNB->common_vars, + l%(eNB->frame_parms.symbols_per_tti/2), + l/(eNB->frame_parms.symbols_per_tti/2), 0, 0); } - stop_meas(&PHY_vars_eNB->ofdm_demod_stats); + stop_meas(&eNB->ofdm_demod_stats); - PHY_vars_eNB->ulsch_eNB[0]->cyclicShift = cyclic_shift;// cyclic shift for DMRS + eNB->ulsch[0]->cyclicShift = cyclic_shift;// cyclic shift for DMRS /* if(abstx) { @@ -1233,14 +1229,13 @@ int main(int argc, char **argv) } */ - start_meas(&PHY_vars_eNB->ulsch_demodulation_stats); - rx_ulsch(PHY_vars_eNB, - subframe, + start_meas(&eNB->ulsch_demodulation_stats); + rx_ulsch(eNB, 0, // this is the effective sector id 0, // this is the UE_id - PHY_vars_eNB->ulsch_eNB, + eNB->ulsch, cooperation_flag); - stop_meas(&PHY_vars_eNB->ulsch_demodulation_stats); + stop_meas(&eNB->ulsch_demodulation_stats); /* if(abstx) { @@ -1249,31 +1244,30 @@ int main(int argc, char **argv) if(trials==0 && round==0 && SNR==snr0) { char* namepointer ; namepointer = &fperen_name; - write_output(namepointer, "xxx" ,PHY_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][0],300,1,10); + write_output(namepointer, "xxx" ,eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][0],300,1,10); namepointer = NULL ; // flagMag = 1; } } */ - start_meas(&PHY_vars_eNB->ulsch_decoding_stats); + start_meas(&eNB->ulsch_decoding_stats); - ret= ulsch_decoding(PHY_vars_eNB, + ret= ulsch_decoding(eNB, 0, // UE_id - subframe, control_only_flag, 1, // Nbundled llr8_flag); - stop_meas(&PHY_vars_eNB->ulsch_decoding_stats); - stop_meas(&PHY_vars_eNB->phy_proc_rx); + stop_meas(&eNB->ulsch_decoding_stats); + stop_meas(&eNB->phy_proc_rx); if (cqi_flag > 0) { cqi_error = 0; - if (PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Or1 < 32) { + if (eNB->ulsch[0]->harq_processes[harq_pid]->Or1 < 32) { for (i=2; i<4; i++) { - // printf("cqi %d : %d (%d)\n",i,PHY_vars_eNB->ulsch_eNB[0]->o[i],PHY_vars_UE->ulsch_ue[0]->o[i]); - if (PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->o[i] != PHY_vars_UE->ulsch_ue[0]->o[i]) + // printf("cqi %d : %d (%d)\n",i,eNB->ulsch[0]->o[i],UE->ulsch[0]->o[i]); + if (eNB->ulsch[0]->harq_processes[harq_pid]->o[i] != UE->ulsch[0]->o[i]) cqi_error = 1; } } else { @@ -1283,33 +1277,33 @@ int main(int argc, char **argv) if (cqi_error == 1) { cqi_errors++; - if (PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->cqi_crc_status == 1) + if (eNB->ulsch[0]->harq_processes[harq_pid]->cqi_crc_status == 1) cqi_crc_falsepositives++; } else { - if (PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->cqi_crc_status == 0) + if (eNB->ulsch[0]->harq_processes[harq_pid]->cqi_crc_status == 0) cqi_crc_falsenegatives++; } } - if (PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->o_ACK[0] != PHY_vars_UE->ulsch_ue[0]->o_ACK[0]) + if (eNB->ulsch[0]->harq_processes[harq_pid]->o_ACK[0] != UE->ulsch[0]->o_ACK[0]) ack_errors++; // printf("ulsch_coding: O[%d] %d\n",i,o_flip[i]); - if (ret <= PHY_vars_eNB->ulsch_eNB[0]->max_turbo_iterations) { + if (ret <= eNB->ulsch[0]->max_turbo_iterations) { avg_iter += ret; iter_trials++; if (n_frames==1) { - printf("No ULSCH errors found, o_ACK[0]= %d, cqi_crc_status=%d\n",PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->o_ACK[0],PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->cqi_crc_status); + printf("No ULSCH errors found, o_ACK[0]= %d, cqi_crc_status=%d\n",eNB->ulsch[0]->harq_processes[harq_pid]->o_ACK[0],eNB->ulsch[0]->harq_processes[harq_pid]->cqi_crc_status); - if (PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->cqi_crc_status==1) - print_CQI(PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->o, - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->uci_format,0,PHY_vars_eNB->lte_frame_parms.N_RB_DL); + if (eNB->ulsch[0]->harq_processes[harq_pid]->cqi_crc_status==1) + print_CQI(eNB->ulsch[0]->harq_processes[harq_pid]->o, + eNB->ulsch[0]->harq_processes[harq_pid]->uci_format,0,eNB->frame_parms.N_RB_DL); - dump_ulsch(PHY_vars_eNB,subframe,0); + dump_ulsch(eNB,0); exit(-1); } @@ -1321,24 +1315,24 @@ int main(int argc, char **argv) errs[round]++; if (n_frames==1) { - printf("ULSCH errors found o_ACK[0]= %d\n",PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->o_ACK[0]); + printf("ULSCH errors found o_ACK[0]= %d\n",eNB->ulsch[0]->harq_processes[harq_pid]->o_ACK[0]); - for (s=0; sulsch_eNB[0]->harq_processes[harq_pid]->C; s++) { - if (sulsch_eNB[0]->harq_processes[harq_pid]->Cminus) - Kr = PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Kminus; + for (s=0; sulsch[0]->harq_processes[harq_pid]->C; s++) { + if (sulsch[0]->harq_processes[harq_pid]->Cminus) + Kr = eNB->ulsch[0]->harq_processes[harq_pid]->Kminus; else - Kr = PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Kplus; + Kr = eNB->ulsch[0]->harq_processes[harq_pid]->Kplus; Kr_bytes = Kr>>3; printf("Decoded_output (Segment %d):\n",s); for (i=0; iulsch_eNB[0]->harq_processes[harq_pid]->c[s][i], - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->c[s][i]^PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->c[s][i]); + printf("%d : %x (%x)\n",i,eNB->ulsch[0]->harq_processes[harq_pid]->c[s][i], + eNB->ulsch[0]->harq_processes[harq_pid]->c[s][i]^UE->ulsch[0]->harq_processes[harq_pid]->c[s][i]); } - dump_ulsch(PHY_vars_eNB,subframe,0); + dump_ulsch(eNB,0); exit(-1); } @@ -1356,20 +1350,20 @@ int main(int argc, char **argv) break; if (xforms==1) - phy_scope_eNB(form_enb,PHY_vars_eNB,0); + phy_scope_eNB(form_enb,eNB,0); /*calculate the total processing time for each packet, get the max, min, and number of packets that exceed t>3000us*/ - double t_tx = (double)PHY_vars_UE->phy_proc_tx.p_time/cpu_freq_GHz/1000.0; - double t_tx_ifft = (double)PHY_vars_UE->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0; - double t_tx_mod = (double)PHY_vars_UE->ulsch_modulation_stats.p_time/cpu_freq_GHz/1000.0; - double t_tx_enc = (double)PHY_vars_UE->ulsch_encoding_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx = (double)UE->phy_proc_tx.p_time/cpu_freq_GHz/1000.0; + double t_tx_ifft = (double)UE->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx_mod = (double)UE->ulsch_modulation_stats.p_time/cpu_freq_GHz/1000.0; + double t_tx_enc = (double)UE->ulsch_encoding_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx = (double)PHY_vars_eNB->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; - double t_rx_fft = (double)PHY_vars_eNB->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx_demod = (double)PHY_vars_eNB->ulsch_demodulation_stats.p_time/cpu_freq_GHz/1000.0; - double t_rx_dec = (double)PHY_vars_eNB->ulsch_decoding_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx = (double)eNB->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; + double t_rx_fft = (double)eNB->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx_demod = (double)eNB->ulsch_demodulation_stats.p_time/cpu_freq_GHz/1000.0; + double t_rx_dec = (double)eNB->ulsch_decoding_stats.p_time/cpu_freq_GHz/1000.0; if (t_tx > t_tx_max) t_tx_max = t_tx; @@ -1492,12 +1486,12 @@ int main(int argc, char **argv) tx_lev_dB, 20*log10(tx_gain), (double)N0, - PHY_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dB, - get_hundred_times_delta_IF(PHY_vars_UE,eNB_id,harq_pid) , - dB_fixed(PHY_vars_eNB->lte_eNB_pusch_vars[0]->ulsch_power[0]), - dB_fixed(PHY_vars_eNB->lte_eNB_pusch_vars[0]->ulsch_power[1]), - PHY_vars_eNB->PHY_measurements_eNB->n0_power_dB[0], - PHY_vars_eNB->PHY_measurements_eNB->n0_power_dB[1]); + eNB->measurements[0].n0_power_tot_dB, + get_hundred_times_delta_IF(UE,eNB_id,harq_pid) , + dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]), + dB_fixed(eNB->pusch_vars[0]->ulsch_power[1]), + eNB->measurements->n0_power_dB[0], + eNB->measurements->n0_power_dB[1]); effective_rate = ((double)(round_trials[0])/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3])); @@ -1519,7 +1513,7 @@ int main(int argc, char **argv) rate, rate*get_Qm_ul(mcs), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ - (double)PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->TBS, + (double)eNB->ulsch[0]->harq_processes[harq_pid]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); if (cqi_flag >0) { @@ -1529,7 +1523,7 @@ int main(int argc, char **argv) cqi_crc_falsenegatives,round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3]); } - if (PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->o_ACK[0] > 0) + if (eNB->ulsch[0]->harq_processes[harq_pid]->o_ACK[0] > 0) printf("ACK/NAK errors %d/%d\n",ack_errors,round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3]); @@ -1537,7 +1531,7 @@ int main(int argc, char **argv) SNR, mcs, nb_rb, - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->TBS, + eNB->ulsch[0]->harq_processes[harq_pid]->TBS, rate, errs[0], round_trials[0], @@ -1551,101 +1545,101 @@ int main(int argc, char **argv) if (dump_perf==1) { printf("UE TX function statistics (per 1ms subframe)\n\n"); - std_phy_proc_tx = sqrt((double)PHY_vars_UE->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->phy_proc_tx.trials - pow((double)PHY_vars_UE->phy_proc_tx.diff/PHY_vars_UE->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); - printf("Total PHY proc tx :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_tx.diff/PHY_vars_UE->phy_proc_tx.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->phy_proc_tx.trials); + std_phy_proc_tx = sqrt((double)UE->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->phy_proc_tx.trials - pow((double)UE->phy_proc_tx.diff/UE->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc tx :%f us (%d trials)\n",(double)UE->phy_proc_tx.diff/UE->phy_proc_tx.trials/cpu_freq_GHz/1000.0,UE->phy_proc_tx.trials); printf("|__ Statistics std: %f us max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped); - std_phy_proc_tx_ifft = sqrt((double)PHY_vars_UE->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->ofdm_mod_stats.trials - pow((double)PHY_vars_UE->ofdm_mod_stats.diff/PHY_vars_UE->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2)); - printf("OFDM_mod time :%f us (%d trials)\n",(double)PHY_vars_UE->ofdm_mod_stats.diff/PHY_vars_UE->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ofdm_mod_stats.trials); + std_phy_proc_tx_ifft = sqrt((double)UE->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->ofdm_mod_stats.trials - pow((double)UE->ofdm_mod_stats.diff/UE->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2)); + printf("OFDM_mod time :%f us (%d trials)\n",(double)UE->ofdm_mod_stats.diff/UE->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,UE->ofdm_mod_stats.trials); printf("|__ Statistics std: %f us median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3); - std_phy_proc_tx_mod = sqrt((double)PHY_vars_UE->ulsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->ulsch_modulation_stats.trials - pow((double)PHY_vars_UE->ulsch_modulation_stats.diff/PHY_vars_UE->ulsch_modulation_stats.trials/cpu_freq_GHz/1000,2)); - printf("ULSCH modulation time :%f us (%d trials)\n",(double)PHY_vars_UE->ulsch_modulation_stats.diff/PHY_vars_UE->ulsch_modulation_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->ulsch_modulation_stats.trials); + std_phy_proc_tx_mod = sqrt((double)UE->ulsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->ulsch_modulation_stats.trials - pow((double)UE->ulsch_modulation_stats.diff/UE->ulsch_modulation_stats.trials/cpu_freq_GHz/1000,2)); + printf("ULSCH modulation time :%f us (%d trials)\n",(double)UE->ulsch_modulation_stats.diff/UE->ulsch_modulation_stats.trials/cpu_freq_GHz/1000.0, + UE->ulsch_modulation_stats.trials); printf("|__ Statistics std: %f us median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3); - std_phy_proc_tx_enc = sqrt((double)PHY_vars_UE->ulsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_UE->ulsch_encoding_stats.trials - pow((double)PHY_vars_UE->ulsch_encoding_stats.diff/PHY_vars_UE->ulsch_encoding_stats.trials/cpu_freq_GHz/1000,2)); - printf("ULSCH encoding time :%f us (%d trials)\n",(double)PHY_vars_UE->ulsch_encoding_stats.diff/PHY_vars_UE->ulsch_encoding_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->ulsch_encoding_stats.trials); + std_phy_proc_tx_enc = sqrt((double)UE->ulsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/UE->ulsch_encoding_stats.trials - pow((double)UE->ulsch_encoding_stats.diff/UE->ulsch_encoding_stats.trials/cpu_freq_GHz/1000,2)); + printf("ULSCH encoding time :%f us (%d trials)\n",(double)UE->ulsch_encoding_stats.diff/UE->ulsch_encoding_stats.trials/cpu_freq_GHz/1000.0, + UE->ulsch_encoding_stats.trials); printf("|__ Statistics std: %f us median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3); - printf("|__ ULSCH segmentation time :%f us (%d trials)\n",(double)PHY_vars_UE->ulsch_segmentation_stats.diff/PHY_vars_UE->ulsch_segmentation_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_UE->ulsch_segmentation_stats.trials); + printf("|__ ULSCH segmentation time :%f us (%d trials)\n",(double)UE->ulsch_segmentation_stats.diff/UE->ulsch_segmentation_stats.trials/cpu_freq_GHz/1000.0, + UE->ulsch_segmentation_stats.trials); printf("|__ ULSCH turbo encoding time :%f us (%d trials)\n", - ((double)PHY_vars_UE->ulsch_turbo_encoding_stats.trials/PHY_vars_UE->ulsch_encoding_stats.trials)*(double) - PHY_vars_UE->ulsch_turbo_encoding_stats.diff/PHY_vars_UE->ulsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_turbo_encoding_stats.trials); + ((double)UE->ulsch_turbo_encoding_stats.trials/UE->ulsch_encoding_stats.trials)*(double) + UE->ulsch_turbo_encoding_stats.diff/UE->ulsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,UE->ulsch_turbo_encoding_stats.trials); printf("|__ ULSCH rate-matching time :%f us (%d trials)\n", - ((double)PHY_vars_UE->ulsch_rate_matching_stats.trials/PHY_vars_UE->ulsch_encoding_stats.trials)*(double) - PHY_vars_UE->ulsch_rate_matching_stats.diff/PHY_vars_UE->ulsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_rate_matching_stats.trials); + ((double)UE->ulsch_rate_matching_stats.trials/UE->ulsch_encoding_stats.trials)*(double) + UE->ulsch_rate_matching_stats.diff/UE->ulsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,UE->ulsch_rate_matching_stats.trials); printf("|__ ULSCH sub-block interleaving time :%f us (%d trials)\n", - ((double)PHY_vars_UE->ulsch_interleaving_stats.trials/PHY_vars_UE->ulsch_encoding_stats.trials)*(double) - PHY_vars_UE->ulsch_interleaving_stats.diff/PHY_vars_UE->ulsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_interleaving_stats.trials); + ((double)UE->ulsch_interleaving_stats.trials/UE->ulsch_encoding_stats.trials)*(double) + UE->ulsch_interleaving_stats.diff/UE->ulsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,UE->ulsch_interleaving_stats.trials); printf("|__ ULSCH multiplexing time :%f us (%d trials)\n", - ((double)PHY_vars_UE->ulsch_multiplexing_stats.trials/PHY_vars_UE->ulsch_encoding_stats.trials)*(double) - PHY_vars_UE->ulsch_multiplexing_stats.diff/PHY_vars_UE->ulsch_multiplexing_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_multiplexing_stats.trials); + ((double)UE->ulsch_multiplexing_stats.trials/UE->ulsch_encoding_stats.trials)*(double) + UE->ulsch_multiplexing_stats.diff/UE->ulsch_multiplexing_stats.trials/cpu_freq_GHz/1000.0,UE->ulsch_multiplexing_stats.trials); printf("\n\neNB RX function statistics (per 1ms subframe)\n\n"); - std_phy_proc_rx = sqrt((double)PHY_vars_eNB->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->phy_proc_rx.trials - pow((double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); - printf("Total PHY proc rx :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_rx.trials); + std_phy_proc_rx = sqrt((double)eNB->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->phy_proc_rx.trials - pow((double)eNB->phy_proc_rx.diff/eNB->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc rx :%f us (%d trials)\n",(double)eNB->phy_proc_rx.diff/eNB->phy_proc_rx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_rx.trials); printf("|__ Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped); - std_phy_proc_rx_fft = sqrt((double)PHY_vars_eNB->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->ofdm_demod_stats.trials - pow((double)PHY_vars_eNB->ofdm_demod_stats.diff/PHY_vars_eNB->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2)); - printf("OFDM_demod time :%f us (%d trials)\n",(double)PHY_vars_eNB->ofdm_demod_stats.diff/PHY_vars_eNB->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_eNB->ofdm_demod_stats.trials); + std_phy_proc_rx_fft = sqrt((double)eNB->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->ofdm_demod_stats.trials - pow((double)eNB->ofdm_demod_stats.diff/eNB->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2)); + printf("OFDM_demod time :%f us (%d trials)\n",(double)eNB->ofdm_demod_stats.diff/eNB->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0, + eNB->ofdm_demod_stats.trials); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n", std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3); - std_phy_proc_rx_demod = sqrt((double)PHY_vars_eNB->ulsch_demodulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->ulsch_demodulation_stats.trials - pow((double)PHY_vars_eNB->ulsch_demodulation_stats.diff/PHY_vars_eNB->ulsch_demodulation_stats.trials/cpu_freq_GHz/1000,2)); - printf("ULSCH demodulation time :%f us (%d trials)\n",(double)PHY_vars_eNB->ulsch_demodulation_stats.diff/PHY_vars_eNB->ulsch_demodulation_stats.trials/cpu_freq_GHz/1000.0, - PHY_vars_eNB->ulsch_demodulation_stats.trials); + std_phy_proc_rx_demod = sqrt((double)eNB->ulsch_demodulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->ulsch_demodulation_stats.trials - pow((double)eNB->ulsch_demodulation_stats.diff/eNB->ulsch_demodulation_stats.trials/cpu_freq_GHz/1000,2)); + printf("ULSCH demodulation time :%f us (%d trials)\n",(double)eNB->ulsch_demodulation_stats.diff/eNB->ulsch_demodulation_stats.trials/cpu_freq_GHz/1000.0, + eNB->ulsch_demodulation_stats.trials); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n", std_phy_proc_rx_demod, rx_demod_median, rx_demod_q1, rx_demod_q3); - std_phy_proc_rx_dec = sqrt((double)PHY_vars_eNB->ulsch_decoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, - 2)/PHY_vars_eNB->ulsch_decoding_stats.trials - pow((double)PHY_vars_eNB->ulsch_decoding_stats.diff/PHY_vars_eNB->ulsch_decoding_stats.trials/cpu_freq_GHz/1000,2)); + std_phy_proc_rx_dec = sqrt((double)eNB->ulsch_decoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, + 2)/eNB->ulsch_decoding_stats.trials - pow((double)eNB->ulsch_decoding_stats.diff/eNB->ulsch_decoding_stats.trials/cpu_freq_GHz/1000,2)); printf("ULSCH Decoding time (%.2f Mbit/s, avg iter %f) :%f us (%d trials, max %f)\n", - PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->TBS/1000.0,(double)avg_iter/iter_trials, - (double)PHY_vars_eNB->ulsch_decoding_stats.diff/PHY_vars_eNB->ulsch_decoding_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ulsch_decoding_stats.trials, - (double)PHY_vars_eNB->ulsch_decoding_stats.max/cpu_freq_GHz/1000.0); + UE->ulsch[0]->harq_processes[harq_pid]->TBS/1000.0,(double)avg_iter/iter_trials, + (double)eNB->ulsch_decoding_stats.diff/eNB->ulsch_decoding_stats.trials/cpu_freq_GHz/1000.0,eNB->ulsch_decoding_stats.trials, + (double)eNB->ulsch_decoding_stats.max/cpu_freq_GHz/1000.0); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n", std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3); printf("|__ sub-block interleaving %f us (%d trials)\n", - (double)PHY_vars_eNB->ulsch_deinterleaving_stats.diff/PHY_vars_eNB->ulsch_deinterleaving_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ulsch_deinterleaving_stats.trials); + (double)eNB->ulsch_deinterleaving_stats.diff/eNB->ulsch_deinterleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->ulsch_deinterleaving_stats.trials); printf("|__ demultiplexing %f us (%d trials)\n", - (double)PHY_vars_eNB->ulsch_demultiplexing_stats.diff/PHY_vars_eNB->ulsch_demultiplexing_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ulsch_demultiplexing_stats.trials); + (double)eNB->ulsch_demultiplexing_stats.diff/eNB->ulsch_demultiplexing_stats.trials/cpu_freq_GHz/1000.0,eNB->ulsch_demultiplexing_stats.trials); printf("|__ rate-matching %f us (%d trials)\n", - (double)PHY_vars_eNB->ulsch_rate_unmatching_stats.diff/PHY_vars_eNB->ulsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ulsch_rate_unmatching_stats.trials); + (double)eNB->ulsch_rate_unmatching_stats.diff/eNB->ulsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,eNB->ulsch_rate_unmatching_stats.trials); printf("|__ turbo_decoder(%d bits) %f us (%d cycles, %d trials)\n", - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Cminus ? PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Kminus : PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->Kplus, - (double)PHY_vars_eNB->ulsch_turbo_decoding_stats.diff/PHY_vars_eNB->ulsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0, - (int)((double)PHY_vars_eNB->ulsch_turbo_decoding_stats.diff/PHY_vars_eNB->ulsch_turbo_decoding_stats.trials),PHY_vars_eNB->ulsch_turbo_decoding_stats.trials); + eNB->ulsch[0]->harq_processes[harq_pid]->Cminus ? eNB->ulsch[0]->harq_processes[harq_pid]->Kminus : eNB->ulsch[0]->harq_processes[harq_pid]->Kplus, + (double)eNB->ulsch_turbo_decoding_stats.diff/eNB->ulsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0, + (int)((double)eNB->ulsch_turbo_decoding_stats.diff/eNB->ulsch_turbo_decoding_stats.trials),eNB->ulsch_turbo_decoding_stats.trials); printf(" |__ init %f us (cycles/iter %f, %d trials)\n", - (double)PHY_vars_eNB->ulsch_tc_init_stats.diff/PHY_vars_eNB->ulsch_tc_init_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_eNB->ulsch_tc_init_stats.diff/PHY_vars_eNB->ulsch_tc_init_stats.trials/((double)avg_iter/iter_trials), - PHY_vars_eNB->ulsch_tc_init_stats.trials); + (double)eNB->ulsch_tc_init_stats.diff/eNB->ulsch_tc_init_stats.trials/cpu_freq_GHz/1000.0, + (double)eNB->ulsch_tc_init_stats.diff/eNB->ulsch_tc_init_stats.trials/((double)avg_iter/iter_trials), + eNB->ulsch_tc_init_stats.trials); printf(" |__ alpha %f us (cycles/iter %f, %d trials)\n", - (double)PHY_vars_eNB->ulsch_tc_alpha_stats.diff/PHY_vars_eNB->ulsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_eNB->ulsch_tc_alpha_stats.diff/PHY_vars_eNB->ulsch_tc_alpha_stats.trials*2, - PHY_vars_eNB->ulsch_tc_alpha_stats.trials); + (double)eNB->ulsch_tc_alpha_stats.diff/eNB->ulsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0, + (double)eNB->ulsch_tc_alpha_stats.diff/eNB->ulsch_tc_alpha_stats.trials*2, + eNB->ulsch_tc_alpha_stats.trials); printf(" |__ beta %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_eNB->ulsch_tc_beta_stats.diff/PHY_vars_eNB->ulsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_eNB->ulsch_tc_beta_stats.diff/PHY_vars_eNB->ulsch_tc_beta_stats.trials*2, - PHY_vars_eNB->ulsch_tc_beta_stats.trials); + (double)eNB->ulsch_tc_beta_stats.diff/eNB->ulsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0, + (double)eNB->ulsch_tc_beta_stats.diff/eNB->ulsch_tc_beta_stats.trials*2, + eNB->ulsch_tc_beta_stats.trials); printf(" |__ gamma %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_eNB->ulsch_tc_gamma_stats.diff/PHY_vars_eNB->ulsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_eNB->ulsch_tc_gamma_stats.diff/PHY_vars_eNB->ulsch_tc_gamma_stats.trials*2, - PHY_vars_eNB->ulsch_tc_gamma_stats.trials); + (double)eNB->ulsch_tc_gamma_stats.diff/eNB->ulsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0, + (double)eNB->ulsch_tc_gamma_stats.diff/eNB->ulsch_tc_gamma_stats.trials*2, + eNB->ulsch_tc_gamma_stats.trials); printf(" |__ ext %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_eNB->ulsch_tc_ext_stats.diff/PHY_vars_eNB->ulsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_eNB->ulsch_tc_ext_stats.diff/PHY_vars_eNB->ulsch_tc_ext_stats.trials*2, - PHY_vars_eNB->ulsch_tc_ext_stats.trials); + (double)eNB->ulsch_tc_ext_stats.diff/eNB->ulsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0, + (double)eNB->ulsch_tc_ext_stats.diff/eNB->ulsch_tc_ext_stats.trials*2, + eNB->ulsch_tc_ext_stats.trials); printf(" |__ intl1 %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_eNB->ulsch_tc_intl1_stats.diff/PHY_vars_eNB->ulsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_eNB->ulsch_tc_intl1_stats.diff/PHY_vars_eNB->ulsch_tc_intl1_stats.trials, - PHY_vars_eNB->ulsch_tc_intl1_stats.trials); + (double)eNB->ulsch_tc_intl1_stats.diff/eNB->ulsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0, + (double)eNB->ulsch_tc_intl1_stats.diff/eNB->ulsch_tc_intl1_stats.trials, + eNB->ulsch_tc_intl1_stats.trials); printf(" |__ intl2+HD+CRC %f us (cycles/iter %f,%d trials)\n", - (double)PHY_vars_eNB->ulsch_tc_intl2_stats.diff/PHY_vars_eNB->ulsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0, - (double)PHY_vars_eNB->ulsch_tc_intl2_stats.diff/PHY_vars_eNB->ulsch_tc_intl2_stats.trials, - PHY_vars_eNB->ulsch_tc_intl2_stats.trials); + (double)eNB->ulsch_tc_intl2_stats.diff/eNB->ulsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0, + (double)eNB->ulsch_tc_intl2_stats.diff/eNB->ulsch_tc_intl2_stats.trials, + eNB->ulsch_tc_intl2_stats.trials); } if(abstx) { //ABSTRACTION @@ -1673,7 +1667,7 @@ int main(int argc, char **argv) fprintf(time_meas_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;", SNR, mcs, - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->TBS, + eNB->ulsch[0]->harq_processes[harq_pid]->TBS, rate, errs[0], round_trials[0], @@ -1688,7 +1682,7 @@ int main(int argc, char **argv) fprintf(time_meas_fd,"%f;%d;%d;%f;%2.1f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%f;%f;", SNR, mcs, - PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->TBS, + eNB->ulsch[0]->harq_processes[harq_pid]->TBS, rate*effective_rate, 100*effective_rate, rate, @@ -1705,29 +1699,29 @@ int main(int argc, char **argv) (double)errs[2]/(round_trials[0]), (double)errs[3]/(round_trials[0]), (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ - (double)PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->TBS, + (double)eNB->ulsch[0]->harq_processes[harq_pid]->TBS, (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); //fprintf(time_meas_fd,"UE_PROC_TX(%d); OFDM_MOD(%d); UL_MOD(%d); UL_ENC(%d); eNB_PROC_RX(%d); OFDM_DEMOD(%d); UL_DEMOD(%d); UL_DECOD(%d);\n", fprintf(time_meas_fd,"%d; %d; %d; %d; %d; %d; %d; %d;", - PHY_vars_UE->phy_proc_tx.trials, - PHY_vars_UE->ofdm_mod_stats.trials, - PHY_vars_UE->ulsch_modulation_stats.trials, - PHY_vars_UE->ulsch_encoding_stats.trials, - PHY_vars_eNB->phy_proc_rx.trials, - PHY_vars_eNB->ofdm_demod_stats.trials, - PHY_vars_eNB->ulsch_demodulation_stats.trials, - PHY_vars_eNB->ulsch_decoding_stats.trials + UE->phy_proc_tx.trials, + UE->ofdm_mod_stats.trials, + UE->ulsch_modulation_stats.trials, + UE->ulsch_encoding_stats.trials, + eNB->phy_proc_rx.trials, + eNB->ofdm_demod_stats.trials, + eNB->ulsch_demodulation_stats.trials, + eNB->ulsch_decoding_stats.trials ); fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%f;%f;", - get_time_meas_us(&PHY_vars_UE->phy_proc_tx), - get_time_meas_us(&PHY_vars_UE->ofdm_mod_stats), - get_time_meas_us(&PHY_vars_UE->ulsch_modulation_stats), - get_time_meas_us(&PHY_vars_UE->ulsch_encoding_stats), - get_time_meas_us(&PHY_vars_eNB->phy_proc_rx), - get_time_meas_us(&PHY_vars_eNB->ofdm_demod_stats), - get_time_meas_us(&PHY_vars_eNB->ulsch_demodulation_stats), - get_time_meas_us(&PHY_vars_eNB->ulsch_decoding_stats) + get_time_meas_us(&UE->phy_proc_tx), + get_time_meas_us(&UE->ofdm_mod_stats), + get_time_meas_us(&UE->ulsch_modulation_stats), + get_time_meas_us(&UE->ulsch_encoding_stats), + get_time_meas_us(&eNB->phy_proc_rx), + get_time_meas_us(&eNB->ofdm_demod_stats), + get_time_meas_us(&eNB->ulsch_demodulation_stats), + get_time_meas_us(&eNB->ulsch_decoding_stats) ); //fprintf(time_meas_fd,"UE_PROC_TX_STD;UE_PROC_TX_MAX;UE_PROC_TX_MIN;UE_PROC_TX_MED;UE_PROC_TX_Q1;UE_PROC_TX_Q3;UE_PROC_TX_DROPPED;\n"); @@ -1769,8 +1763,8 @@ int main(int argc, char **argv) // - //write_output("chestim_f.m","chestf",PHY_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][0],300*12,2,1); - // write_output("chestim_t.m","chestt",PHY_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates_time[0][0], (frame_parms->ofdm_symbol_size)*2,2,1); + //write_output("chestim_f.m","chestf",eNB->pusch_vars[0]->drs_ch_estimates[0][0],300*12,2,1); + // write_output("chestim_t.m","chestt",eNB->pusch_vars[0]->drs_ch_estimates_time[0][0], (frame_parms->ofdm_symbol_size)*2,2,1); }//ch realization diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index 9a0f60167d..7a2a747741 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -786,7 +786,7 @@ rrc_get_estimated_ue_distance( const int CC_idP, const uint8_t loc_typeP); -void fill_dci(DCI_PDU *DCI_pdu, uint8_t sched_subframe, PHY_VARS_eNB *phy_vars_eNB); +void fill_dci(DCI_PDU *DCI_pdu, PHY_VARS_eNB *phy_vars_eNB); #endif /** @}*/ diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 1f7d08c13d..a8444edfc9 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -139,8 +139,8 @@ extern int sync_var; time_stats_t softmodem_stats_mt; // main thread time_stats_t softmodem_stats_hw; // hw acquisition -time_stats_t softmodem_stats_tx_sf[10]; // total tx time -time_stats_t softmodem_stats_rx_sf[10]; // total rx time +time_stats_t softmodem_stats_tx_sf; // total tx time +time_stats_t softmodem_stats_rx_sf; // total rx time int32_t **rxdata; int32_t **txdata; @@ -154,7 +154,7 @@ static struct { pthread_mutex_t mutex_phy_proc_tx; pthread_cond_t cond_phy_proc_tx; volatile uint8_t phy_proc_CC_id; -} sync_phy_proc[NUM_ENB_THREADS]; +} sync_phy_proc; void exit_fun(const char* s); @@ -271,7 +271,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) */ static void* eNB_thread_tx( void* param ) { - static int eNB_thread_tx_status[NUM_ENB_THREADS]; + static int eNB_thread_tx_status; eNB_proc_t *proc = (eNB_proc_t*)param; FILE *tx_time_file = NULL; @@ -279,11 +279,11 @@ static void* eNB_thread_tx( void* param ) void *txp[PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx]; if (opp_enabled == 1) { - snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->thread_index); + snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf", "eNB"); tx_time_file = fopen(tx_time_name,"w"); } // set default return value - eNB_thread_tx_status[proc->thread_index] = 0; + eNB_thread_tx_status = 0; MSC_START_USE(); @@ -306,10 +306,10 @@ static void* eNB_thread_tx( void* param ) if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB tx thread: sched_setattr failed\n"); - return &eNB_thread_tx_status[proc->thread_index]; + return &eNB_thread_tx_status; } - LOG_I( HW, "[SCHED] eNB TX deadline thread %d(TID %ld) started on CPU %d\n", proc->thread_index, gettid(), sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB TX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); #else //LOW_LATENCY int policy, s, j; @@ -372,7 +372,7 @@ static void* eNB_thread_tx( void* param ) } - LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n", proc->thread_index, sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -388,10 +388,10 @@ static void* eNB_thread_tx( void* param ) while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->thread_index), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0, 0 ); if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->thread_index ); + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX\n"); exit_fun("nothing to add"); break; } @@ -403,13 +403,13 @@ static void* eNB_thread_tx( void* param ) } if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->thread_index); + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX\n"); exit_fun("nothing to add"); break; } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->thread_index), 1 ); - start_meas( &softmodem_stats_tx_sf[proc->thread_index] ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0, 1 ); + start_meas( &softmodem_stats_tx_sf ); if (oai_exit) break; @@ -420,19 +420,19 @@ static void* eNB_thread_tx( void* param ) /* run PHY TX procedures the one after the other for all CCs to avoid race conditions * (may be relaxed in the future for performance reasons) */ - if (pthread_mutex_lock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); + if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n"); exit_fun("nothing to add"); break; } /* wait for our turn or oai_exit */ - while (sync_phy_proc[proc->thread_index].phy_proc_CC_id != proc->CC_id && !oai_exit) { - pthread_cond_wait(&sync_phy_proc[proc->thread_index].cond_phy_proc_tx, - &sync_phy_proc[proc->thread_index].mutex_phy_proc_tx); + while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) { + pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx, + &sync_phy_proc.mutex_phy_proc_tx); } - if (pthread_mutex_unlock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); + if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX\n"); exit_fun("nothing to add"); } @@ -442,19 +442,19 @@ static void* eNB_thread_tx( void* param ) if (oai_exit) break; if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { - phy_procedures_eNB_TX( proc->thread_index, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); + phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); /* we're done, let the next one proceed */ - if (pthread_mutex_lock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); + if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n"); exit_fun("nothing to add"); break; } - sync_phy_proc[proc->thread_index].phy_proc_CC_id++; - sync_phy_proc[proc->thread_index].phy_proc_CC_id %= MAX_NUM_CCs; - pthread_cond_broadcast(&sync_phy_proc[proc->thread_index].cond_phy_proc_tx); - if (pthread_mutex_unlock(&sync_phy_proc[proc->thread_index].mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc %d\n", proc->thread_index); + sync_phy_proc.phy_proc_CC_id++; + sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs; + pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); + if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n"); exit_fun("nothing to add"); break; } @@ -503,7 +503,7 @@ static void* eNB_thread_tx( void* param ) } if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->thread_index ); + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n"); exit_fun("nothing to add"); break; } @@ -511,55 +511,55 @@ static void* eNB_thread_tx( void* param ) proc->instance_cnt_tx--; if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->thread_index ); + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc\n"); exit_fun("nothing to add"); break; } - stop_meas( &softmodem_stats_tx_sf[proc->thread_index] ); + stop_meas( &softmodem_stats_tx_sf ); #ifdef LOWLATENCY if (opp_enabled){ - if(softmodem_stats_tx_sf[proc->thread_index].diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf[proc->thread_index].diff_now/cpuf - attr.sched_runtime)/1000000.0); + if(softmodem_stats_tx_sf.diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); } } #endif - print_meas_now(&softmodem_stats_tx_sf[proc->thread_index],"eNB_TX_SF",proc->thread_index, tx_time_file); + print_meas_now(&softmodem_stats_tx_sf,"eNB_TX_SF",tx_time_file); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->thread_index), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0, 0 ); #ifdef DEBUG_THREADS - printf( "Exiting eNB thread TX %d\n", proc->thread_index ); + printf( "Exiting eNB thread TX\n"); #endif - eNB_thread_tx_status[proc->thread_index] = 0; - return &eNB_thread_tx_status[proc->thread_index]; + eNB_thread_tx_status = 0; + return &eNB_thread_tx_status; } #if defined(ENABLE_ITTI) static void wait_system_ready (char *message, volatile int *start_flag) -{ + /* Wait for eNB application initialization to be complete (eNB registration to MME) */ - { - static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", - " ....", " ...", " ..", " .", " " - }; - int i = 0; - - while ((!oai_exit) && (*start_flag == 0)) { - LOG_N(EMU, message, indicator[i]); - fflush(stdout); - i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); - usleep(200000); - } - - LOG_D(EMU,"\n"); +{ + static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", + " ....", " ...", " ..", " .", " " + }; + int i = 0; + + while ((!oai_exit) && (*start_flag == 0)) { + LOG_N(EMU, message, indicator[i]); + fflush(stdout); + i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); + usleep(200000); } + + LOG_D(EMU,"\n"); } + #endif /*! @@ -570,7 +570,7 @@ static void wait_system_ready (char *message, volatile int *start_flag) */ static void* eNB_thread_rx( void* param ) { - static int eNB_thread_rx_status[NUM_ENB_THREADS]; + static int eNB_thread_rx_status; eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; @@ -581,11 +581,11 @@ static void* eNB_thread_rx( void* param ) //int i; if (opp_enabled == 1){ - snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf_%d", "eNB", proc->thread_index); + snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB"); rx_time_file = fopen(rx_time_name,"w"); } // set default return value - eNB_thread_rx_status[proc->thread_index] = 0; + eNB_thread_rx_status = 0; MSC_START_USE(); @@ -608,10 +608,10 @@ static void* eNB_thread_rx( void* param ) if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB RX sched_setattr failed\n"); - return &eNB_thread_rx_status[proc->thread_index]; + return &eNB_thread_rx_status; } - LOG_I( HW, "[SCHED] eNB RX deadline thread %d(TID %ld) started on CPU %d\n", proc->thread_index, gettid(), sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); #else // LOW_LATENCY int policy, s, j; struct sched_param sparam; @@ -678,7 +678,7 @@ static void* eNB_thread_rx( void* param ) } - LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", proc->thread_index, sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -692,7 +692,7 @@ static void* eNB_thread_rx( void* param ) // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe of TX and RX threads - printf( "waiting for sync (eNB_thread_rx %d)\n",proc->thread_index); + printf( "waiting for sync (eNB_thread_rx)\n"); pthread_mutex_lock( &sync_mutex ); while (sync_var<0) @@ -710,9 +710,9 @@ static void* eNB_thread_rx( void* param ) while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); - start_meas( &softmodem_stats_rx_sf[proc->thread_index] ); + start_meas( &softmodem_stats_rx_sf ); if (oai_exit) break; @@ -720,44 +720,44 @@ static void* eNB_thread_rx( void* param ) (fp->frame_type == FDD))) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); // this spawns the prach and TX threads inside and updates the frame and subframe counters - phy_procedures_eNB_common_RX(proc->thread_index, eNB, 0); + phy_procedures_eNB_common_RX(eNB, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); if (eNB->node_function != NGFI_RRU_IF4) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); // this is the ue-specific processing for the subframe and can be multi-threaded later - phy_procedures_eNB_uespec_RX(proc->thread_index, eNB, 0, no_relay ); + phy_procedures_eNB_uespec_RX(eNB, 0, no_relay ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); } } if ((subframe_select(fp,proc->subframe_rx) == SF_S)) { - phy_procedures_eNB_S_RX(proc->thread_index, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay ); + phy_procedures_eNB_S_RX(eNB, 0, no_relay ); } - stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); + stop_meas( &softmodem_stats_rx_sf ); #ifdef LOWLATENCY if (opp_enabled){ - if(softmodem_stats_rx_sf[proc->thread_index].diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf[proc->thread_index].diff_now/cpuf - attr.sched_runtime)/1000000.0); + if(softmodem_stats_rx_sf.diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); } } #endif // LOWLATENCY - print_meas_now(&softmodem_stats_rx_sf[proc->thread_index],"eNB_RX_SF",proc->thread_index, rx_time_file); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 0 ); + print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); } //stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->thread_index), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); #ifdef DEBUG_THREADS - printf( "Exiting eNB thread RX %d\n", proc->thread_index ); + printf( "Exiting eNB thread RX\n"); #endif - eNB_thread_rx_status[proc->thread_index] = 0; - return &eNB_thread_rx_status[proc->thread_index]; + eNB_thread_rx_status = 0; + return &eNB_thread_rx_status; } @@ -778,7 +778,6 @@ static void* eNB_thread_prach( void* param ) MSC_START_USE(); - AssertFatal(proc->thread_index==0,"Invalid thread index %d for PRACH thread\n",proc->thread_index); #ifdef LOWLATENCY struct sched_attr attr; @@ -869,7 +868,7 @@ static void* eNB_thread_prach( void* param ) } - LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", proc->thread_index, sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -888,7 +887,7 @@ static void* eNB_thread_prach( void* param ) if (oai_exit) break; if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n", proc->thread_index ); + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n"); exit_fun( "error locking mutex" ); break; } @@ -900,17 +899,17 @@ static void* eNB_thread_prach( void* param ) } if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH proc %d\n", proc->thread_index ); + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH\n"); exit_fun( "error unlocking mutex" ); break; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); - prach_procedures(eNB,proc->thread_index,0); + prach_procedures(eNB,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n", proc->thread_index ); + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); exit_fun( "error locking mutex" ); break; } @@ -918,7 +917,7 @@ static void* eNB_thread_prach( void* param ) proc->instance_cnt_prach--; if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->thread_index ); + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n"); exit_fun( "error unlocking mutex" ); break; } @@ -945,67 +944,64 @@ void init_eNB_proc(void) for (CC_id=0; CC_idproc[i]; - // set the stack size - + + proc = &eNB->proc; #ifndef LOWLATENCY - /* - pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) + /* + pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); + if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) perror("[ENB_PROC_TX] setting thread stack size failed\n"); - - pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) + + pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); + if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) perror("[ENB_PROC_RX] setting thread stack size failed\n"); - */ - // set the kernel scheduling policy and priority - proc->sched_param_tx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_tx, &proc->sched_param_tx); - pthread_attr_setschedpolicy (&proc->attr_tx, SCHED_FIFO); - - proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_rx, &proc->sched_param_rx); - pthread_attr_setschedpolicy (&proc->attr_rx, SCHED_FIFO); - - proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); - pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); - - printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); + */ + // set the kernel scheduling policy and priority + proc->sched_param_tx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_tx, &proc->sched_param_tx); + pthread_attr_setschedpolicy (&proc->attr_tx, SCHED_FIFO); + + proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_rx, &proc->sched_param_rx); + pthread_attr_setschedpolicy (&proc->attr_rx, SCHED_FIFO); + + proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); + pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); + + printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); #endif - proc->instance_cnt_tx = -1; - proc->instance_cnt_prach = -1; - proc->CC_id = CC_id; - pthread_mutex_init( &proc->mutex_tx, NULL); - pthread_cond_init( &proc->cond_tx, NULL); - pthread_cond_init( &proc->cond_prach, NULL); + proc->instance_cnt_tx = -1; + proc->instance_cnt_prach = -1; + proc->CC_id = CC_id; + pthread_mutex_init( &proc->mutex_tx, NULL); + pthread_cond_init( &proc->cond_tx, NULL); + pthread_cond_init( &proc->cond_prach, NULL); #ifndef LOWLATENCY - pthread_create( &proc->pthread_tx, &proc->attr_tx, eNB_thread_tx, &eNB->proc[i] ); - pthread_create( &proc->pthread_rx, &proc->attr_rx, eNB_thread_rx, &eNB->proc[i] ); - pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc[i] ); + pthread_create( &proc->pthread_tx, &proc->attr_tx, eNB_thread_tx, &eNB->proc ); + pthread_create( &proc->pthread_rx, &proc->attr_rx, eNB_thread_rx, &eNB->proc ); + pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); #else - pthread_create( &proc->pthread_tx, NULL, eNB_thread_tx, &eNB->proc[i] ); - pthread_create( &proc->pthread_rx, NULL, eNB_thread_rx, &eNB->proc[i] ); - pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc[i] ); + pthread_create( &proc->pthread_tx, NULL, eNB_thread_tx, &eNB->proc ); + pthread_create( &proc->pthread_rx, NULL, eNB_thread_rx, &eNB->proc ); + pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); #endif - char name[16]; - snprintf( name, sizeof(name), "TX %d", i ); - pthread_setname_np( proc->pthread_tx, name ); - snprintf( name, sizeof(name), "RX %d", i ); - pthread_setname_np( proc->pthread_rx, name ); - } + char name[16]; + snprintf( name, sizeof(name), "TX %d", i ); + pthread_setname_np( proc->pthread_tx, name ); + snprintf( name, sizeof(name), "RX %d", i ); + pthread_setname_np( proc->pthread_rx, name ); } - + + /* setup PHY proc TX sync mechanism */ - for (i=0; iproc[i]; - + + proc = &eNB->proc; + #ifdef DEBUG_THREADS - printf( "Killing TX CC_id %d thread %d\n", CC_id, i ); + printf( "Killing TX CC_id %d thread %d\n", CC_id, i ); #endif - - proc->instance_cnt_tx = 0; // FIXME data race! - pthread_cond_signal( &proc->cond_tx ); - pthread_cond_broadcast(&sync_phy_proc[i].cond_phy_proc_tx); - + + proc->instance_cnt_tx = 0; // FIXME data race! + pthread_cond_signal( &proc->cond_tx ); + pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); + #ifdef DEBUG_THREADS - printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i ); + printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i ); #endif - int result = pthread_join( proc->pthread_tx, (void**)&status ); - + int result = pthread_join( proc->pthread_tx, (void**)&status ); + #ifdef DEBUG_THREADS - - if (result != 0) { - printf( "Error joining thread.\n" ); + + if (result != 0) { + printf( "Error joining thread.\n" ); + } else { + if (status) { + printf( "status %d\n", *status ); } else { - if (status) { - printf( "status %d\n", *status ); - } else { - printf( "The thread was killed. No status available.\n" ); - } + printf( "The thread was killed. No status available.\n" ); } - + } + #else - UNUSED(result) + UNUSED(result) #endif - + #ifdef DEBUG_THREADS printf( "Killing RX CC_id %d thread %d\n", CC_id, i ); #endif - + #ifdef DEBUG_THREADS - printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i ); + printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i ); #endif - result = pthread_join( proc->pthread_rx, (void**)&status ); - + result = pthread_join( proc->pthread_rx, (void**)&status ); + #ifdef DEBUG_THREADS - - if (result != 0) { - printf( "Error joining thread.\n" ); + + if (result != 0) { + printf( "Error joining thread.\n" ); + } else { + if (status) { + printf( "status %d\n", *status ); } else { - if (status) { - printf( "status %d\n", *status ); - } else { - printf( "The thread was killed. No status available.\n" ); - } + printf( "The thread was killed. No status available.\n" ); } - -#else - UNUSED(result) -#endif - - pthread_mutex_destroy( &proc->mutex_tx ); - pthread_cond_destroy( &proc->cond_tx ); } + +#else + UNUSED(result); +#endif + + pthread_mutex_destroy( &proc->mutex_tx ); + pthread_cond_destroy( &proc->cond_tx ); } } + /* this function maps the phy_vars_eNB tx and rx buffers to the available rf chains. Each rf chain is is addressed by the card number and the chain on the card. The rf_map specifies for each CC, on which rf chain the mapping should start. Multiple @@ -1197,381 +1193,14 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c -/*! - * \brief This is the main eNB thread. - * \param arg unused - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -/* -static void* eNB_thread( void* arg ) -{ - UNUSED(arg); - static int eNB_thread_status; - - unsigned char slot; - // the USRP implementation operates on subframes, not slots - // one subframe consists of one even and one odd slot - - slot = 1; - int spp; - int tx_launched = 0; - int card=0; - - void *rxp[2]; // FIXME hard coded array size; indexed by frame_parms.nb_antennas_rx - void *txp[2]; // FIXME hard coded array size; indexed by frame_parms.nb_antennas_tx - - int hw_subframe = 0; // 0..NUM_ENB_THREADS-1 => 0..9 - - unsigned int rx_pos = 0; - unsigned int tx_pos = 0; - - int CC_id=0; - struct timespec trx_time0, trx_time1, trx_time2; - - //avoid gcc warnings - (void)trx_time0; - (void)trx_time1; - (void)trx_time2; - -#ifdef LOWLATENCY - struct sched_attr attr; - unsigned int flags = 0; - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - //This creates a .2 ms reservation - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = (0.3 * 100) * 10000; - attr.sched_deadline = (0.9 * 100) * 10000; - attr.sched_period = 1 * 1000000; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] main eNB thread: sched_setattr failed\n"); - exit_fun("Nothing to add"); - } else { - LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n", - gettid(),sched_getcpu()); - } - -#else - - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - //Set affinity mask to include CPUs 1 to MAX_CPUS - //CPU 0 is reserved for UHD threads - CPU_ZERO(&cpuset); -#ifdef CPU_AFFINITY - if (get_nprocs() >2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } -#endif // CPU_AFFINITY - - //Check the actual affinity mask assigned to the thread - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity, 0 , sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf(temp, " CPU_%d ", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - - } - - - LOG_I( HW, "[SCHED][eNB] Started eNB main thread on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - (int) sparam.sched_priority, cpu_affinity); - - -#endif //LOWLATENCY - - - // stop early, if an exit is requested - // FIXME really neccessary? - if (oai_exit) - goto eNB_thread_cleanup; - - printf("eNB_thread: mlockall in ...\n"); - mlockall(MCL_CURRENT | MCL_FUTURE); - printf("eNB_thread: mlockall out ...\n"); - - timing_info.time_min = 100000000ULL; - timing_info.time_max = 0; - timing_info.time_avg = 0; - timing_info.n_samples = 0; - - printf( "waiting for sync (eNB_thread)\n" ); - pthread_mutex_lock( &sync_mutex ); - - while (sync_var<0) - pthread_cond_wait( &sync_cond, &sync_mutex ); - - pthread_mutex_unlock(&sync_mutex); - - printf( "got sync (eNB_thread)\n" ); - - int frame = 0; - - - spp = openair0_cfg[0].samples_per_packet; - tx_pos = openair0_cfg[0].tx_scheduling_advance; - -#if defined(ENABLE_ITTI) - wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); -#endif - - while (!oai_exit) { - start_meas( &softmodem_stats_mt ); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame ); - tx_launched = 0; - - while (rx_pos < ((1+hw_subframe)*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti)) { - - unsigned int rxs; -#ifndef USRP_DEBUG - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos ); - - clock_gettime( CLOCK_MONOTONIC, &trx_time0 ); - - start_meas( &softmodem_stats_hw ); - - openair0_timestamp timestamp; - int i=0; - // prepare rx buffer pointers - for (i=0; iframe_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&rxdata[i][rx_pos]; - // check if nsymb_read == spp - // map antenna port i to the cc_id. Now use the 1:1 mapping - rxs = openair0.trx_read_func(&openair0, - ×tamp, - rxp, - spp, - PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx); - - stop_meas( &softmodem_stats_hw ); - if (frame > 50) { - clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); - } - - if (frame > 20){ - if (rxs != spp) - exit_fun( "problem receiving samples" ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - - // Transmit TX buffer based on timestamp from RX - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - for (i=0; iframe_parms.nb_antennas_tx; i++) - txp[i] = (void*)&txdata[i][tx_pos]; - // if symb_written < spp ==> error - if (frame > 50) { - openair0.trx_write_func(&openair0, - (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance), - txp, - spp, - PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, - 1); - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, timestamp&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance)&0xffffffff ); - - stop_meas( &softmodem_stats_mt ); - if (frame > 50) { - clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); - //update_difftimes(trx_time1, trx_time2); - } - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0); -#else - // USRP_DEBUG is active - rt_sleep_ns(1000000); -#endif - - if ( (frame>50) && (tx_launched == 0) && - ((openair0_cfg[card].txlaunch_wait == 0) || - ((openair0_cfg[card].txlaunch_wait == 1) && - (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti>>1))))) { - - tx_launched = 1; - - for (CC_id=0; CC_idproc[hw_subframe].mutex_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", hw_subframe, PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx ); - exit_fun( "error locking mutex_tx" ); - break; - } - - int cnt_tx = ++PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx; - - pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].mutex_tx ); - - if (cnt_tx == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].cond_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n", hw_subframe ); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (rx_cnt %u, cnt_tx %i)\n", PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].frame_tx, hw_subframe, rx_pos, cnt_tx ); - exit_fun( "TX thread busy" ); - break; - } - } - } - - rx_pos += spp; - tx_pos += spp; - - if (tx_pos >= openair0_cfg[card].samples_per_frame) - tx_pos -= openair0_cfg[card].samples_per_frame; - } - - if (rx_pos >= openair0_cfg[card].samples_per_frame) - rx_pos -= openair0_cfg[card].samples_per_frame; - - - - if (oai_exit) break; - - timing_info.time_last = timing_info.time_now; - timing_info.time_now = rt_get_time_ns(); - - if (timing_info.n_samples>0) { - RTIME time_diff = timing_info.time_now - timing_info.time_last; - - if (time_diff < timing_info.time_min) - timing_info.time_min = time_diff; - - if (time_diff > timing_info.time_max) - timing_info.time_max = time_diff; - - timing_info.time_avg += time_diff; - } - - timing_info.n_samples++; - - if ((slot&1) == 1) { - // odd slot - int sf = hw_subframe; - if (frame>50) { - for (int CC_id=0; CC_idproc[sf].mutex_rx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n", sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx ); - exit_fun( "error locking mutex_rx" ); - break; - } - - int cnt_rx = ++PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx; - - pthread_mutex_unlock( &PHY_vars_eNB_g[0][CC_id]->proc[sf].mutex_rx ); - - if (cnt_rx == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[sf].cond_rx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RX thread %d\n", sf ); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - } else { - LOG_W( PHY, "[eNB] Frame %d, eNB RX thread %d busy!! instance_cnt %d CC_id %d\n", PHY_vars_eNB_g[0][CC_id]->proc[sf].frame_rx, sf, PHY_vars_eNB_g[0][CC_id]->proc[sf].instance_cnt_rx, CC_id ); - exit_fun( "RX thread busy" ); - break; - } - } - } - } - - hw_subframe++; - slot += 2; - - if (hw_subframe == NUM_ENB_THREADS) { - // the radio frame is complete, start over - hw_subframe = 0; - frame++; - slot = 1; - } - -#if defined(ENABLE_ITTI) - itti_update_lte_time( frame, slot ); -#endif - } - -eNB_thread_cleanup: -#ifdef DEBUG_THREADS - printf( "eNB_thread: finished, ran %d times.\n", frame ); -#endif - -#ifdef DEBUG_THREADS - printf( "Exiting eNB_thread ..." ); -#endif - - eNB_thread_status = 0; - - // print_difftimes(); - - return &eNB_thread_status; -} -*/ - void reset_opp_meas(void) { int sfn; reset_meas(&softmodem_stats_mt); reset_meas(&softmodem_stats_hw); for (sfn=0; sfn < 10; sfn++) { - reset_meas(&softmodem_stats_tx_sf[sfn]); - reset_meas(&softmodem_stats_rx_sf[sfn]); + reset_meas(&softmodem_stats_tx_sf); + reset_meas(&softmodem_stats_rx_sf); } } @@ -1582,8 +1211,8 @@ void print_opp_meas(void) { print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL); for (sfn=0; sfn < 10; sfn++) { - print_meas(&softmodem_stats_tx_sf[sfn],"[eNB][total_phy_proc_tx]",NULL, NULL); - print_meas(&softmodem_stats_rx_sf[sfn],"[eNB][total_phy_proc_rx]",NULL,NULL); + print_meas(&softmodem_stats_tx_sf,"[eNB][total_phy_proc_tx]",NULL, NULL); + print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL); } } From cbc4160ba4ade33ceeb4d3f7cc28e9ccade501a4 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 29 May 2016 15:42:51 -0700 Subject: [PATCH 014/206] added targets/DOCS/oai_L1_L2_procedures.pdf --- targets/DOCS/oai_L1_L2_procedures.pdf | Bin 0 -> 1696869 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 targets/DOCS/oai_L1_L2_procedures.pdf diff --git a/targets/DOCS/oai_L1_L2_procedures.pdf b/targets/DOCS/oai_L1_L2_procedures.pdf new file mode 100755 index 0000000000000000000000000000000000000000..e14948f5af9195b59e06b4b4aefafa065756d09f GIT binary patch literal 1696869 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

6iO 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%0D-Kd%-JT|s@W=@?eq@|k^nn{s`<$ULj-F%V7 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

mx?Q46WZ@}}7`U#Z(EU$VYh|hA_wyI8~#A3Vh zcWLpAbZH=u1(=>NqHXoZ>nIQ+C{Pc!63FtyTUsjn3FAyrl)>$AAEE~o#Gk<)%6goHLv3qJN5i^9XT{}Vc?4F z>tw#{yxU86p5s`xY2T5&c+HWt>+7a^3k-ZI;ZN;I+t+g+L``nG^v2;aP%qkM7@f4p>YJ9~+^TyQ*}&p`hH5-q!xnFsz^^?J!OAiIxuz$Y z`(;J129g_3+$4|if}A4kaK;1{X&v0&p-IB%wCDSL!XQ7gR&{?7=N5-B4@|xXZ*x4H zqc$nX?4R}v%`R?o#!0Z9Z#eK9mtMaTRZpxE2|S{~wB?hP9*vvpFqMA;7s}%N82}mT ze(hMPhehiYU#rp*Joc+-@N7BN)h>Zkhwd?71ZPL40qgP-UrFh!zKX0_`+RlkpXJwg z&n<`MD>8t{;MjSDagfY74$@z^OG&i-NthZ@CgmlMDm)2~vdM=|I*f=U@=5 zt-peC|4eA=<$hx#v3B6l1|s^q=!MdhVPI;PTeo3xPS|`-D5;m-PbImM-Kx0k`EHtD6 zgh?A&*>T0UNoBsa@R3qg8EYTN>q}A*lbN~EN7LrQM`WbhS4k_KnRuNShLqkz2+eRU zv7=V&&Oe{nsz{7?&yGT%Kzr92l5qjPDLS5!XlnylrREexJ*Ds8?>&FIWamKAXdYo5 zLPo$eeP?>EIe1uV{&`{GA>1n{kzx zH~|CNAAFs_N69F>@q1K?^(@0lVINTj^K(ys+W@b7A5-bGt!pKB74NuK<+!p@ue+fJ zMO?p!gjF2Prg1e$pa)nCoQff-e!n|MNd^PTYLkiZ{osqvJ{oZkdkGkhmi^>YS*#c8 zK`&+6HF4|t5lV70)<@b_qOVW$v?>BQYk>#3*eVGLHPuq@+ZbHI!Cba}Fu~4?fV+#L z6_I=n)jc`HP9dsUGR4tE;cu72@+sJIi^FgAJBW5t6hh;iwyqO2v)Ko2o(iK>Up-#C z_EnUo`e}BAcbdNQO@8r8Gbqy^!>%gLFD9bG5N@`f9=tRwuDKw~`N7g}1Re0TF=Jho zmk2&`f25#I23sJ5Wj~Xef98czT1quoS0Vlmi@HOdR=}+&%>iTLF|@N}ro9D%&7~+v zrp$0%XY%z;Bv8z7#{WapvZ8sj+Vfjitm8nOe-&-~hWR2c!j)U2=Pdx%o@MRI36yvt zjZ!#N=Gn69^Sw;4C_{uk=cNZ>JbmKVsUR!au}C(Sz?M}ASz2iweWmy4>2#q;asH1 zd;ro!ilOXdA&9AzipYC4e^1#yk+Ztpc`~ej1zUF1ONj3_Eq|VU+$)@$vT(R8!m0ky z@T;vP_}M~E)`LBXLSJSsl6Y%Ef?qaJI_SUsQHWCCf^!99@^{qg(D=X5=_pYvpP=+<5 zn0d22d+*@o9CtK3&b{z=WCn8F{oB5HmU; zbe;tYbifXPDZP6S66{{Dy`8d610BAior%vL9ab!7()%CZwi)DpI~jXNGxzW&#W0yZ zczy)=u$ScIi7V+brpR)qESoV#Ct4TU(avmZ(`a?$a=M`> zaDwiA(}(6Yyp_q{^Xlu=yrHnQIDCZ1ywxerv{?Ck|vN!6_G4Rm(Ri zYUxijBSJrvO?@`U_G4xC^&4~x(DCp{MfmfL3`Z!8F19mv9rX1um{ViJvn-BgRmgrc zxKx5fZYr$f*@&E}54%RY#RHt-kdeHw*zHHU2Wxlzbx}xLTtQcw@dBbYe@4t_X+9B( ze5zOrxfaqUu_Mh&!hK^!p?W4BpE=U%%5sg(YbLypWGwa}x*;l0*ZTP;THIXtI;(|K z{qBKR9vSFrwD4Pbn`HT+-m9rLPnAp#>utBuqnL}KCwc!Rk-Z9}I_h(}SiC$pkp>xw zUsk{`QyET!@j-49tJaO3Aay953V!@~f#C|d?6OOF4n-g4+!u}n3NP05Uww&B5RnIx zK1?3r=MRT8hl|71nr7;a2&*J~U0-5_om=*+lM=+Lh(l0Z4Z{z)#x`r$%>`mUG8P<(%P zOE0jF-|3GS<2T0kUc9L+f?Lsa>u_FBR>~2KR4aOm&qT2rY|?(*n>u~;hj12LRa_Pe zj35*5M6ocST=@>a%^*_iUG0+GCfsdOd6k(XmM~ zXpB&NCwqf&`$64FtMF%zm}Iv5O{djovtz7+RA(}a6;dS6u#R6uD=ho6mZprp%9^sO zf=Fy|;cm^W+b&W#mkJ&Rk!wdP5h%@uq!CN_`Hs&Gye0OjpSz20BA9dtcmx7hRfACR zo$?r+xLTC;pME#}$NN?gV<)xPho-}kG)>d$=*A|Y=S;(_nHU1ZVtkkY`FX#{&-??DuHl;nz-B>C0T=X@bU3R{1g=S<+I4ubk!dmfGK{@d_=5`ixy;2-`N#FV1wK zbS~q-v|X099)}mpx)uAMb(3+H+7 z|Dg8qNBZV*iObtDdK)4q0a;C!QqcJ!NJ9s$1nsS$lBQNeoAZ-8`g*o{50oCh?3NRD zqnTF2R&?`|@*By;mztB_LN?Ru2zEhV$h;eJ|DEFymgSjbsStBEZroLDQw9@Qmr9lOL|b3T=d!@qch9q|@X zbKeHgo|Fi`tX0UU^>)S%73Yxr`!-#_Wu_`}y7F%P;VCsjN~5@3AybgD#3D+Y%>u4& zK^RnyWvlf9pOM*?;HPe^=_BiE`rgV)71f<(rYL&1bfhH4Gs0AlW`RM-Uz~QKIp0B@ zIzuS7slm6{zilx$+vk*#b~C?t0yER&PU;FQ8?&Z^+~{=cQ2#6LkZzjmLC|5paj6w$ z^?r`L8*C0-J2P~J8ei9^MoQ^=Yn^;S=bYG2zLB7s0UtacMJtS8GOuJIs_WV{F}2hu zfQZ}M^|iG~GS@d>Rd3N_IrKnFJn3eqBTCA`iv8Ajh51dGmIn(le45w`BUWgSY53^@?GFH}LgGJ{76@V9_HUq5mlLt%K8 zMV0o2P?U*>KKR2TmXKV|9c3d&UM#%wr7C{_n>`6u9+~K!Pl@F2UT>Y^>4|W<=iGt5 zM8Dx+Kvyhuy@((**13o*G{uBUI|oN;3M>W6(f|bs#;-ONalUvy851M0dEy#EpYO2C zz$CBgKak^}>kyM@TufO}kBDU6#5#f^L*-D`Zq}b9pecuda}x*h*tFahj;0081*Wm? zNh!*Sd)4Gruy<|ooN?+3zfiYoc8BE1cM!iIAM+Kq(|fGcZ*LFi)Ls0#)nE^&=oobS zPIRPz@wR`Qua9_YU2cdk6Y~L;ho<04NXV>=xSte$YM zb~WEi94OJ4^YuI1M>2Gb8C{hfXt4C!&inA#9Z-bf;R5LQudXe|^Pnta6cfnU$DrW1 zZSXveOX9VDq8Cv^jx2NtM?Yo-%nSseP0!`5`m-rPFct5d2PEh#{u;YU1rKyYg8DWw zTp6>zlSbk=S>J7)Va%m8(N&Ci$d3Gw(;7KBM_LY@v_|dws@9aCDf+szIrn`Ph)FTAHjIC63?CMEwn!A zm`Ii-dnU0lBG@vGer?Wv6VaG)aHrGZ#?z-Npp#@%{U|>{NCCVW9Y1>|8!zJe0%uEq zTWAMiOrp|b2g0)jqD(->PzeQDK&o)4C@v+&T?{HPV=j9Iwyr5Ef%kj+Te*IQoeW8N z%JE%t+&CgKmaQ7<9ur{`Mce0_^(Vf2BS0A5K=UP-9pyg9sXgc`O%M@C;cHqF8k9<&8(~WI=*5`j` z1L-AbU@j+3OQ#fmoWn3{i`F=Qb{~v>MG}Ot80fq(o+ogkrpEVpmVNZ-(HXBZg7Ycc zLd+lH);CM$o3PIfPtek-O-0t+>@BGnpxzdwSvRG@86F`WWqBZ9%emhZ$@}v9TOkNb zh9)<&ZpWO<;cd-(-*^m`#~W%?HV^IE8-)aI@bqOE1AqS8Mo0u!aofU(_g3&JD+IjJ zsmwE!Uv6WY-do3F*05)L)QH`~H(cG71wqaMv2pdfS^5>nWN}&(gy@w$VbNs4NEDPJ zwk9@ssyrwK6L{^uQ>A(62T-vxE76zp=6%ldxzE`EdNgc2^H=l$k%5qH1)rI#B3C-i zAR7AH&(oeauY9awpr;QBc<>_f?#;m7nrrqp>~C8J2#1H(OCIrW!=q00N$lGQ3Gbn7_F;SUq%vl@X4>sU@<~JzpGoS|494 zKFrEGn14OvErq%_B7jc?7q%*I8W6t=&$&%aL<|gHP%s>5E?R0_2cUfVySlW*wWufM zT!f_X{t}U)h)uhbw&3Ke>6*CFnSc&1Y-9hHE6Ee#z?z6W zf-}H(mhYj>@5+t!=Yy2plEJx%cGXIV#dVXz@?0$daQCB>)sU9#TojtEyV_QoQMyef z-^<~?yk%tS_ku+dpwxA-i*^M^A9gJ7#>XqcNs^!%FPt(zT>k}yzZ}FS+#}6s5h4b7 zvH`uJBkmxV!R5R!8fR?^3%*Qp)5iFXLm@*yc{ZRE!WhKGtx$GiKY^M>PPQx$VA{kCzQ zF8+a8caiMOqtm7?@XhYg7jTAwiNk+G9kKowyy5>w9f?Uw$tlbJEv5w^ME@Oi#KsJu zjsUhxfRPjc9kKlv=;;5Wm6iiwUHvzA!~%dW{ug&7KrcxDlU|5kgkB7wrj??X{##G0 z01(tF)2sg_sHHcgH?##XMt}Qg0UlbwpZR}^Xf5ggA5^q<#t!DTM)dy}X&tTpvfBRd zURu|`%(V0##tyds!7=@Xj{FBp!uH=T_Wy}v`rnrP-y9R;f4XS_pZ-lUasDNZ1t>%R zW@G+}8~|l0%fBKM3oD?^#QwKqmGS=+*#Q1pfSwe9838=903r&&{ID?n?W*Mjw7~lJ zz8oB^e{nVdJ_sOq{p;(0nrCKW{R^7z&G5Cv{yoBf`eFg}#Z355WCN6$2>+QnAOeJ`Y=9B4vjE^N zMs`3gR)7x{fOP#`i=FAOrD5U#EYjbqUv>cV1gOEr0B8Y#P5lL4{au5d^{@G|v9bf! z=U-)j^cMgw0Tj-EDQuYl@o!x0?*-@l+YS5g5&YE~(_d{d0b2Z@Yx*DMzgOy?S^aaE zSOFGV&VL=a|5|2d{GW&IpKt%;Q~-O6XfsNu>4*AJN`F()nC6i|8Y&Q|Cejx-+UD_6X3f4=M#XhVq#$Z z@A)cbX3qZ?Z|yU<-1^xg1k66&ckl?5jm?Pm_Mi69h_qsMG;|spo09gfuJov(dzYw` zGX7iVoztrqFTUFoor&qB({-km4^H(dbYH2=B3&!6J~ydoUneFz@<=Cm<|={Kg6OnbHS6{v?pX@SQofWT`=X3&B~kk9`dfYdel^P7LZq4C@H0`2S^ z9T|SE;}Kp0IRUGuae^dG60-3_QsxJz^YEis0fPv3d{TgQ#=(K@k@gH7?(X(l9PW(4 zxYVNS>p{5r5wZcn{ic~2#503_F4qIVS)kWBV`}ndKpJd>%f5dy^k~9D(_s;T&{hIz z{bH)*5ZFZ}f5QSvz|SP9f|UFK#`|Jac^&q{y3W}G;!xxKgnJ^m>IU)0{c>TeuL0uX zNaytM$E^fbA@n5VR~89J+k@7JNaNJ_G&VE2f(d!eY|ZpPpPa~r@HMr8h(l6^OcQ{8 zmvyf~|4v8|MpI5R@>z|%`UwMiQP+@PNV?Jsd<=4q zd`F-M?$FTiS`H=2PQhj^8dr}ar*q0jE{8N`o6d>|vZHTm>f1jB4D+ zN`V;4?);yF{N=t3_t)C|zkonpj?e9ZR=zww-X@`b=%nb0dRA{A`sUDQ7HnxsQ<)d} zQh%ya5CK1eJ=a{{0;zGhuK?qocVq$a>cIPLe}%j>1Aozd+LmTu9rKOWe#KB;nSn!G ze<^}CxPMjlfAAR!d;t(Epm+K}7|b8z{6HU9v+PDk`pte__V0foR@$F`Avp4%+ah0I z3SDzlD4c-Tz`;1pllb8{?OZ%k2MJ9Q!%( z`;6$)%=*g~N1%!cfSwg%LmBAbO@I4%LjApaArQmQT0?VOJr2>+*E{v;>ogNwUlXW9 zSv6DtstF!+Isc^~!KL9x_ocxtgRkS49vPXA0ds$x8wR=454rd#NXPzNY;z;*yKyJ7nn&QJQ3eGjrm{44T#1=xzI8;QbC z`jUMQq-OL>M2>fG8)~fh9tV)o!Iy+GXAHnzDSlvd`rnp*h~NUTJpi^=-QWnUvig$P z0A()Of=vp)u?O6qd;oU+@I~TdVXohXvM~PyRGHMCpgs4SDULw<)0}mt`@+X{T@8Z0 zwx>G)3TFb`6#DDSmuzFhR~#4D2j!C$(<;T6pOWkv0jhH46ak8?=@S%?8T%a`zH)VF zd=%pNITTz8;xAUK@eNcErQr)yu-^3qJVYobU)w1j8wKyd2W}? zjA_FD*L`&6KHuEe1va~rQr7P$@Ml+omfYYUtL?3yNCedOfIcK$UqA)V-mNDbu zw|w&j#$6iO9UEWzfyZ9BK#vawA!_Y`KdT_ylB^IBt_k30Fl~JK&CWKy{AOI--b1qF zY^V7MSvr;hXc_g@_NV}fJE-<&?rRQgPv0c?8qLVID$BjgGyUfq<2Nu55IVW8$v`@= zKr73@wX3qha2_?6;rJzXu71M@$UZm12G~|W_8a;+GDLNXcA%z8WNx`B+?{KW{ zZD}{`Ms)!FRI=36;u1ug0vzCCT-=@L^+&BDc!}^ zvmuo<=$B~6AVwU+(28Q&VzK}=3H~8{|7(zZ8y%w6`MEF7*&Fc2@S5a%%U;fGr5Dj& zKXD+dlN&wHMy2R#%E+^%67-O8S6ZyEIHzPru`WQ1h!e#60o)mxH^2S8zmc|xfac~1?&l(giDS{DX^4=d1^e~H zYR#a#le=VEKek<3hk6NYYDGCxcHd-ZZ}L{`Rm0ou#ry=Qq(V(Y`QmAPxx19ceeAqX z`rDg? z;p47JRNgtAv+c-Ug~J_Q)SC!fl=qdgA4Kuf)1`0KZsmv3d^T3 z9_waRyQLET{JxF$+B|4G;C0(UN*^xP~OTvNlFUi7K*|B~dtt{4J zZOKOIR;>Gjw@L}kDxjv(R}=6@K4dVn0K2j9d@r3OtWlcWME~gB12x%DaFsc69?@v`B>~Se9~p50?c#b zw4Fu0jI_W2&@!NG_0q~1f||>GeW}%GhJJ|q4d+kb{ONhy37eo>`y<2UQ>xlpZi4%k1(`H_*q#;+B~LUbyb~X zR@6<(OB*?2dEM>B*VM+x3>zYDCrUZ)iy1aMY2s^dAs`iWmUj{4(y57rS@v5iTZ*|q z*5Ql+sgn@+r*S`$ouwp;y+gl3X0&g5J*mXYalZltYTAO{hQvqyy{Al#8p)EpJvTqf-$mHT#qgGL(38KH~!MkC;(LK0uUUEx)Fce$nuq1#m z&o^Dj`!tQyx1toO6#A`9yO5JvPt604Vr4ePuUbjPYT6CP5H8pn-?vg# z(oKfuviz1<^W-*fQSZ!O3UTv=`$!s7F6WKtI1eQ#Z_LQj;;nM(18Va8aEs)&ZZX>) z1flnp=P`;_Gg}h-Flh?-toNR_OIjJd? z4`2sDifpcR?WrdA`aRU#Ec1JV>_dYO8Z)_QyP&~$?z3oyv zdVb$;$Da^xPlgetn%4@1#>!o5AD|)Tn3M~2%ms#)q1yMtjf-NmK+8}|W0tJIPxy|* zXlex`MwrSXs7x>%C{dnqJNe;$d{QfoNCvDpe_v3*wx88zL{b*&s3E!RxfCw)&EUg3 zKp^23b0d_CDeGgy0Gu?QhWSRdgE~?-yaycOQou|ry3vKr%hZGUlRK%%3>#|$5qJUv zQkKrOD!M?%o3l?A{g(>y?yeiQjhi(&jJ#oN4&0hJ9IsrVzMp+D#W<3YDbu`F1B&kS zZU!dG@28|;lmqD1XP=vO;m_+emX5;w0hMSLu}#(BFVoYJIM6;`Jw3)=%;l#nusU49 zIxh35X}nM57fB|g{QhhP36DYOpQfw*DA`plZHin?N8kq$Tqj8URNZyfRMK+YS<*9C z=M%+<4bLaVithV`j7+JWN8oF(I-&}LaN=#EiqipDi)O3N(BVR0oTO4{JWMD3thM_ud52RZ=odtV;CT|&m@7$0*O@fLVVy>gr3+vT z$j;k^U`Kx>U8-8Ut`R)D{Osg0IZ-);+-mR?C9pc^jz86ITQf$b^in5ym2hBqxKm}G zsFDHc;ylaE0GosQ1B+yXM}4;@H)Wefx>?kOSaue)YXL0W;RhkQ5^%7cxMoI=E zT2xHzWvv+sXGA-}B!Ay=(y8}6V)qkWk@>ZJ@bg8iyK|x3)r7p#B_x5t>odVXXf;dA zTJw(8injI-w-fI|PFzKpcS21>SGP~WR*dl1+$7&^M*G@>ggyh7lsc)%pO?jxRvhmJ z(?6|Op=PQmNZ+gKapjeNZeHGd z8=V8HtHxXn^L_u7#5y7g5zZ0>2976KVZR5NTf$TVziq@wZ>cYAa@I4^--%i2U@tG= zEtWy@5%|&0`KX_F4edlyJ25lElf}v{q!ab}TYIg!Ofk`XC7T2|;Pp;;%0#$KX2!;8tnOiau#)haJUNps;4&+nQVti!-{1wT97{ir@JrEAu*gdb#51)hXy~FM8 zBaJ;OM@^&fCJj}@Hvb3D0sj;L9uxIz;_z%?U@MSsIQgv`P4LPnZ z#0A7`oV0YexKL#;+yG`16sWUzhzM5hjnS7#gt zQ;I91UAk{r31%FVxVw!jmZZP@opy;3TuFHfABs&lRA9v7fvj?fNvPfJt1K}lk4nl2 z=|c%r*@xoW({BxWO>qyV{V*zbY$l2K^*Rz}Ix zn=&HlNXu;C+lI5c;-OJD;@6(&_acEZ>qaki@Pstgt0S+RpDcD%o;!Cjklb;B$qDRu ze|5!fI7ocii-8{tEyI&O4LIqjEx%xbUb`kZr(VXR2_fKkzt$Kf`Q&Ri+8RV`^K=rU zpC0=?I8k&-uaQ=<%M)nd@BBFMtXAW{|CJF%n6Fx2M`#e9)$Ln$>)H0=O`NKE3!Y}h zj@&NhMS0n-S9zFx{9ugAX zK7!kLUhPPmcJAj6`K@L?cE1YL9R?4lQ6nLWczr&Z(cl8Htl?da6ZLCl#OUts1R671%=4Scs&{2c&~1BceH%;R-B281rCb=P$9^773T z?rF7#6?!gsluflQBh;+k^luIztPo~=v;tLJI6x_uXqZ@(v_|^quRNb~ z)Rr%>-6*6wf8?3#lrIcfY^_TvX!N!|Va{Rq6MZZ71S+D}RX*j&^n>i$8uKzNtLi%e z-$9)GJPyZc+S_1RXPuAv+8#y|m|Q-TT)2w)qK5yd zP=KPY!YFD^IV6%8lJukHn8TggKpTY}*1b+wU|?khUpo*?pxo>DS|Ab%F8bST!sqgx zA)Tfc7xM{xV^UXp*!B|+dm}&SRPv053@!n<0osG9%0hAe70_~&H+*Jigy}3fM%pKN z-TE#n+*nLcVVku;5mkRwZR!cMOJJI@fw$T0#-l`eNdnHLW8Ns7DQi6`vbu$5^ zjp`!Tdrd+P!j%w1X4uy3T%JkpHW{nwkL6Zf<3HUAh$F?~AB{xM2KstlLgJmQ>ktQa z{%#KLzC1{wmO9JTWYwJ9AVMKMUN`WLXyDAdJhk}@xSfH8z40yQ!vEH?rI*s275nuPe+Oa7KM~_eS;{ zi`s}?)zHed)?X(6q798qvYQ|9$<0|n$opOCj0MXz7kdnD+cG5XSF36dOZea8EfJnO z`w0(!XM287RyKY`M-7M8Pcn!m2*M{EJzc~E1eukRr+a{FV2DX%?5!m5Wg zpbbOC_-YSePUZ++xVO`%JupK!BT^?fF4fVhjxXVGIePk+pD4`yAkdCo!SI|2XG*NY z1=--HzaKism*F`lvpcQb9eCHuw4PT`AIOkYMMxZaZgSCzKiTC*`moX{pgzLjK`{;t*>y(|^QGbidL|+9r z=hy6|BdJ4{anOmDLW_DgABrfHCFw3dGe3hNOCkE3+IoI;U%^~;ZHvZIqW9(hwxkR) zP7~KzTKsZimc44a%KxD`&SNRZd@R#My6^zpd0#-Xx9n}c)l!k8B?Rf!M!2O}0Y=vS z&2k=8YQT8Wh<1t~-&Xv^ij?S&{HKOzYoVG{NvB{x3NjOt(B7ifg^h6`NOCW z_ng2ar&_2(K74dxeu2o9*pw-H&{pwX(WVXuDJ;W%E%q4d#qESgZMK-#`MR7J8|y?* zjk?G>6El#>NOUWDO{86k@oAPeBfQdA#k|4lIuB=%D%}iiLc}K>=Z@CW4D2@a*5T(F zr>|qGQ8T%tLl0P8YO2|5z=vk$OVCb=yOA#{ONyJ51Ff2V&mhxW{hT!C&tmv?UN>k5 zK>(}K8yS+i2;mZ|KN?V90B^m3Z{ijXM$BpI%<*?Pf-)Vcj3Cex%_pL=Mj$^MmeSOO@g?tr4 z-5&z4(}e-a=vM5wir8o$h6H%zPlIdt2a!0FO3ebYjU0W*+GjS5m$M6~0x zqD@pl9_k9Sw{Eh?|8koOy1U6_IF3z6nR zI81etDtyNn<#}4Tw>s?>bGJqmC?}I3#0t?PPL>GKP{(qN3wIplo)z$8>)Dfiy*mz8 zc{Bm=cfA2m@mfMN^-M$9QqRMS6>uK3Q_b^{%>NJ#BjIni_Us=1@63pU-$Ihfy z>5F#c$Xl9SUnK=xut&$t-N9@iR1am{_HW0idg#LKQ0*w}pJ_zDtBUJsyP|kB!D$D5 zE444j(+9DGj7U~9(FA)2^UCyfbjomKi*VA~G<3HY7MVo3xo#!iLv*EKq;)la^L-Cr%EFCp+?+`uP);@4VyfCM z%GFzZw@@TXLKVqELEmdrp=!k(q7KvZZtYwotKR)N3;)9*#S6Pgy0Li5*z!u~vjs@Z z?G|;q!#R5O8|n$~MRi{vsa@o4eU(M{i5ic+P5@3!$f{bN%Qf7nMI6o(Z6mnvV4NyL zbC1yFDLQK2H!tiaprDulwOFk97d{fOTiFYozRH2~2*0$8G_DDG=qtAS@8cqv`)^e% z1N!6rJAVS&phL))rRU$Asvao2`TFy_gCa8*Df#fyxaFaI(R5}_CMHG_HAf3Yi9vKz zwD)QGm6By&#ne!p)=_x9?$v$Ic1OlY6DfcTQEx}{EoM34Wx?qUGjE@P+4%;EG{Sg9 zpI4&LHkuuzIkgqJ0^KP+wdNZ}5ttzyk69>L&BOIhbnGLZ=ICqdW&nv`p6XQZ;u1ci zX#>p-ToW@%6nNfm1gLZhSojY4MQOCkq&CoP>b^R`&e$Odcxg!TT(o29Ix%%SS7Z!X zx3h#ncT#D7xxGBb(4^w3#{ z*X+PPaU@bJ^Q3E$iRcCyOsZ8@uAR|kBJltR#S++Tsl#;LWzBS~SG`9abx{=3AKiwF zLs|zujT$|YD+J-|a;=LXKMF%hm+DE~v0EwZ#a$AqI7%cK;{6oOAbp1)cM)bZdfy<8 zNkHc>cc;garE81PLYJFU%WfN56{DB2<`x}4Gi2vAWRBE{v7VeBjSI7VOhF{;4Kr5! z1RWz#pm>Ra_pA-sh@#SUQOKtGg8r=-809Hqag)tYVZW}|y<4HnZA&@jNT3E&*3Eh~hl2D9lemi;|Dn~Np2UYw zS*L&u1p1}EVMV$w;G-_W2qTSq`En7YXMge;hYRXd$ii2!72E9$UFZ3(^M{Rf^iHeU zwp5|HwX}T?vE7J9Vr#rJZokEE=XBxfcNnrV7K>IE9Q5Dr)-NvRI*pbr^XpDUD%9ms z_`KssybQ6)cuE!PLJ*lUdDpo}auYb8ZW_%sVd8VwW1;r@2Uo09U#6$iw9ep>z3FeG zaqKe4(&WS6;N#>wbj|GZpi#j8q@!;)x@63))eyIGGvFN1>8Wax>?{;9IA|H}XcaB# zB(zbyKwoerAa70QAaCXrM8;8cQ(!sgc|G{g)KgSqlA&4$a${b7K6Kj6#5U#vZ7H!I zNaRUrm#0&N7iK+Q_b&I^z|q1TCZ#08xj6rhC!XT>1msXVXVwI7tIs)p~NiHNP9v;AjNeB7CZL{OTO$SN_eIOpEf)*Ol zQDFVZynVd;6nUJhxnQ4kB`EPdr>&d1Hq(~CYqCtu()^gctfGj&Z+v(Rd9JAC9Sqy* zA|Da!X3wORJu^U+)(lhvy80IXwo3kPQVzQKqwlcuRBY5co-P4?zS%+89<9(-;e5?# zc6}?y27NSjt24LwJh1rfMk92xJ61znImfLyv`^&hsQqv)gdhy?`C|L zerL<{T1DbpdacB|6J&-P>to#tH1h8kA-gRpfe*8tb3wqi{!@;SSe^0V_bC=yxOuU1 z-xtnOZL5pm8NWyTntLRj^slT|4vBUwmiVwY7}!M{>eqzap()#vdMb_Gs*RH-3)X-9 zFc@SJP^Xh|`(3C1Wuw9%)sFg^*np%Uyxxlj&t7Tv6mvChKI+$rDL5QtHZ$v#LZtB< z!&`2q(zPtcAc~i6OF;P^QBdO=!Et{hM1+2XM!TWMN8gQaGq57z8+!i-q?Z@W!W@R! z`V@#ZMavao#z%RihQu4H_2PbN1qmPJ z;1d4|P>}zXeRmDvsK|1zRYtlSu0BhQ+B_XAidZ7|6#?GNqcabm8DMyzgm`~EUkhKK zg_I-ok+ty23!({PXD#BrZZ+~NyS&gr+q3S+{Y{zJPf<)P(e5QF5oqZBuU_k`@SlvcFE zE^wOtkkmopiSNR;uTh=%+4^W8+N|Piv($%ae`q&_BrD-UscDTcTlnZ>f8C-M=(xQR zGBmW8wstMhzu&<8VtRkT^wYsl4eJ1xt$^{zQ?d6h9<&=KqqU(f)Yp+rk11m0G^U5? z{r!V&YKrweL7w8XN-&H{DP5aoJ;qx$u6f&k~d~3@20* z{M^?+NCbAWKD6lGtH)ky$#IZdK^L+$<53kM0LS5MHS@;1 zZOSvk$dcHCcOdt%^*R)-RY#QwDWpwov@gpz_#f=OQ+#DxyRRGDwr$%^#i-b>*tTuk zso1I*72CFL{ghcT=`;6vWtaVcqr33Mwkmk1_lq)D!7*5Pg0PGwASc%=R}A z=dLj8vJU36qzL}|)i4_y-gG1cm^C|xgEH8n-)gF={h=@RP7 znAYVHbV)yVGRca_hEx{X>_uQaUn*VmX|H^q}|{O4MhPM54x_H__M;TXIUBYL|m z1#B;m`}%`yPT9fdAXmL@*%A9)difT4fodsUE{SiE7e59?uY|K_6s?HgOLdkQwX8)= zCddxs>1b?kquHhrQFdj>}oI`&+YP}C!y+@6-Y&={GA zHAZvfL=@;CzR@^M<&<<697eg{TRK_iw!Sq2ha!O8mh zDhHBc4NYsK9fi_i=LV6phTkBb&{!&-95EB1;#j(U%u0WH48rp*NDQX%RHwiztl+W- zL4Y^%N#4C?O2Qzi2py{oZUY_47J828y>r~i$+@#X2xclJu?ngRu4E1kVkYhsTS3>5 z^U$C>0%&`Zg3BsdzbdKC zYA6p^${7_H5QC|HiY$I$A;sHu3x{*tePl!``d>QSL2B{)v`|74Pw*i40()4Yq{)(C zgf(?_Me1niKx4cjd_#Pe5uJw2@M=>n^(rhJ-o6j~J+SB!o75az1FRhXWaSZmuVv~* zEmxNDU0irE1wiK0Yhh8wR))A_Y36ByB zSfV3RsQCHRJQpiWQbIr7gNphK)ZUvtVtpUS*n0Ge1P*>-ai;d?vUR1^oBfWZS-)Wu}hT27xQ34cGe#^d&7;TG7 zrdd8(<(FRFwdI{w ziIWVIWr@PATH@l8zsVARLt~%+RxdRZ#PyndDM+@hI^eIHurwC!@4Gg%xRyU5<3J}2 zpQ*{ZbO-hDE%vr0ODKsN$*2S)%Rn}#IHbK!sv;fc?y?@Ekn|GEr(=uiRJ~jrREu)3 zXZ6}bB!fkI+MchO0|qOtZ93B#h0jL)&h2z!3ulN!w80ONsdeavK&da=N{77ywoRAY zK%{1y?A#GQb+;ld0xxw1W&ipTld*;brn?<=w(}~-MueBjj$^Jb)_4wR_F&iCM19 zM%JL5UV|_A9v^vtKLQ%a2FMj5Cu*R$0QBLOnSL$?^Ff%ca$*g9E~dTeyw%VOB9lFw zX6D!l7PT6o`HB^;Jov3yg;>ye{GcS8%*^;N4l5R;G zENga**ZDFVesoxaK+ina<{Vguy z15ksMR~7RNgzDq4xfmS?&2d`DD8@%4jhs|LGqeHoA`Is{2N!GOK{6(*BsnAYOr>0;Jo;SW}`x?2g^D(&~|AG54<^5-LqHn8vK zDgxy+1VXS;!QeDpU5p$mdOI2WJ;^3S75z{+Sc`0n_XJ6BOqH9S`$_BYQa+zzw~f=i zgM%k;_-Mor5O1J{jyE}+ge;?PiGHpxvUxC+@fP&y1OYfY*}_I<^$~9Cy#<1nozjgo zfEynu=E{&jp zx3S@2(Y8!a(1(7D)hTZ_36f60Hb$S;WMLH_yddvBRHGg>-Bdt7J}jBoJz@BIl+py( z!%L_9u^aA80Cjo@HVz7Nf(M)5=t^!rKN&7LkdEb6dWabi^MnL0HEjMeM_e&Fq3Q3T zl*#!QI(=VNcdzR0V&Fj+b98R4kO1%lHj}tsm~W`McrO@ZL()So+3W^#h;oXNeK{r{ zEj^-T3tV+bM(~^jD)BjQzDyE^(Gxc z8=O~jjM^evB1g|{GNRm4{tm|oQB5m%5A@`)5};Sjz-9NadFCQq&I8M($2<4Rys%{s zu)mB-Z9>Np|O3Pso6Zh2-voAK_l@Ek{OH}s#8Yk(EG0Oqe| zWRfFh7dhc^=WszD9vY)7B-%t^KvaWyp>->h$7 zvxy6QJyhpXKm2TRBpZJBwDDeL`8AZ@od>y8w2jKdap)Ef&`Ua#Yn6(7MRp%0Z>kSY zsrvH(81na|!NHsS1S_$Z?sj;}WXLBAJLf}#wci+?Q@!4%nLD&Z1p-CGTatz%q|U9b zawRxxv#}pEBAgy-Ha)(SQ7Bef_K`8Dtc&8G8m;4XJ$@$6>+*G7sfLP zsqez=*G}BMvKy0DDp>*-;uADO#^trW|IKiw!6 zT7{^le1y@(5aw5%2U+$$eoGu)z8WbQ%tu0c<2jx1Kxz>pe}d>;>g_>#VJsQJ^aID~SI0%PM0EcvN44^JB3_bG)C29|=mKynV1}}l;)(W0xyLDW`Scie;IXUj= z8S|NG0%I-HI^5&z3o)wb{Gf7P*zLhswvI{1j3ZDQWFK8E*_enGNRp@&tm0*b<|^Xi zn-l1feRHMyuqzXkOFLvPh6JO0J~@<2bx41c zWw@jZCY$xiNWK^S$X?1N38CG_-NqQwoL8~~ zi=jeBA-6HhYXG70+k`b>o?;IXFZMN-#~~j{1NqYr*#%WsuxyvskNy7lWrgqE*YF!J z&*gea0Tk>pZql7v%)g2miMrq3*bHd(X3sHDqX@7kUOcTn#cRTy@l5TecPb|mxxqur zis1BkwKj(++4DLbZ4Hj|#w=~Ym|E@clfte}!XR1gaDhVdv94d=O~aQ7S4@gI%&=EK4=ezFsccFz zw%##Bd{8;)?5<&Wp=Ei?CYe%(Q+B0Gu+umjZKA$%YsezE>DrP1bRw?A>!a1YBpI z{7I5_?|`Ek#g(@2s!@*uL<=H8yuMM`s33ET_U3UViLVpJG;S9>5ez82?t9F4q@#?0hiE0Ss)`(stzdHQ+895p< zyIPx}cV!G>id9Jcs|>ANYhHysIn}IY(lQN2SLUWzhK26vf-v*sTClgE`EO z_}y5@%yyb(%fnG-B1*WMZleHqiVmd`vFQND`)to@YHEJ{>P0_aDIyI!$U`qlG}5 zgxTMBv^`UcSG>zlhXT+SVpfl@n+!G0I|wkXOq_#SvK0-9GuW>YD@oT4MJz$;1^NAv zhNB7eg}R_h+~4WefQjxCv6t$Qw`AB4?~V^Ko3bT9ZP-H(YKi#n!R>C0_?bzGh8`Nx zx)@e7wDPUgzh6it^vT_ZZrmIc$HoR_jPmlIN3Ewdc4aQoO}=$<91yK;P;a(XI!eFP z=!mlNr@L)Y|C-E{`LSSpGZvH_Olo%0XeGWub{$t(wGcw4nAM6=bUtpvg30!~$JRKR zaQmd|6V!zrvmO5F7zH%%Hh##eE1ct6k!~nhHf&zdz@I`Zb9Xgv@&AD&KIwgp$@N!e#6#RU;TqV#~>!2nH z<}ty@G)KVS<^vz9o?GX?aVRJM%KeF2x{~Y}9v)jHR;{Fc~rRd)lrPSXZr5wFHy#oCo zms0u5rd0der!=tFH?%Nzv@|wxr2o7AE6(jN(bCe!`akKGru1g?W^T4-#@6&d=>MOH zmbR8o4*#|-f4I{BZ;i|U>RkTO$^MgH#`)hqod2D3`9D3P|8Oo@{uv&}$i(zNoJ*E3 zz40qI?yr%Rnej`XklzH~@V)<3e`S3()n-}S$a{(l+&HRs$n{NG56a|BgJw!ULSB8qZ^ zh_qfhiodWf#9Z|STn(KjT=$2Vp(UNEOw5HKBKYP~lAGA@B<}P6+3C=Ed6sE4*)iGi z*m3D~F*;FU(_alBy4G$S0L zhPoR9)UR*K`%|)qbT?3}O%f97<>{-T0b(`~1-!VrHJ>j$&N&D}pj$6byS{vPbu!>D zJ&?1>1(2&{zyVp?Nq!tL3h)N_C19`?#+F_}hQdRcP;?}yTYxoXaEu>jz;|nUL;OQ4 zJ_t_$K00s!Bmghm>p9b1NIh{~0X+y1P}^W)FFkS50N^duFu5gVw7w6bw}9OeNAyHX z^TV(@IinCwh>sm@eUxwcRmx|2VfkYfH%iBfiIwIKsJWpK>)sD;@&4; z#PsD+X67&PUoH`$&3_(K9a~&~EZ=O(ii#%E6Zqmg7ASZVDi8pGAfbVVM)&~;e#+cE zqQ1?4*p%~Od>mf;eiqINaODET`#9P;c=~u7YMLP76CkVC3f_Vox&GuDWO_J2b&KmAe8l?IIfmlL$M7a z)_)$^xzHU!jv_U^Jss7MZ289$9^r6j-{fPl^whj2u*M<2B ziv$YdYt4oVb^A_h>zfOJ6x0a`xWw>V*rDdY zGBDxCwm}B>kxtTN)2Ljey@N>um2%0Zzp_{FU@GfvtW zzT6v6D{C^6t$U2Ie<5nY6pc)rLfKdWx^NC*_8n_B&Rp$cXckFq{l~a+I6Sy$Ygvnl zQJeMQ>BDE`p$?tTE(VTs@ZtIBsAWe!ZJ(BIbwjSeH==0+v036S|i zmer%a23R*(><6}B&tBY~5y=EX2S?8xB^p-Vm5%j?T)ex`Z4X%Gl`-fCEUq}&yWfY3 z!xOj`u<416sp$hdk!vh%Fdd@?)ruFt^J{UM>sv#tR+#V67)vFgOY!Kk&Q;De~=oRTP__c*b!?I(vaC{-5>z+jEoeMM|NjyKd_ zf6s#IOsYyX0H@+n`o?qK#AU6}EH|_lt=REPbrk&d*PeLM#{zt1O%3)u zHU)Y+mmOmU$~YA$o}^mrC>(I-`3Vu8^mr5wkqlp5V-=k;Js|y~G~ZUJ*f55hG_};* z7-i57i*(8idZIJ+iah^hnkuNIbZS(`&R6@WzQA41Ee$4%*iL<($HZV-Ri)$^QZ_@h zmP*!uY_Tz2TC2jju_~*`MwD|88QT(GE7YpjopcYUM~y(yc$LDa4uE^oB|Uz#7S1HU?+;FkJ7Y50ds1?2pXOHB=9V-yOEj6RBC?dziYpVLGx{v zXXachlT(4ASw}K48o2EH+`C4i)gL6YZS$K_vkZ_Bhwh6ii19~1@#T-K3F8Mm3ogU5 zd7$m7q#jyGDsL)DMj!EetC|TWXG_{t8h{cW_w`qF@-4Pi(IP`F17A?M%iYKPnxznr zllszNrbv4|&7Aaf4%_-E4`wSU{2Djm!?Tqa`mcb&&VlS%z)o_?sR3%0;Q2MDeNz47 zeVG^bcwUgXV+7Y>kWe3AI=!qQ)dN>B{hqI~CoYY_vT(Je(C|&+nqHj{IA_f}3s|_r z;p1j77hx3kU^iBKcY4m+cH>*5`ql~0J>;s=d(b{#T?y~9WKVJx0!fh_`r|g_c%>%} zRXvLC-`rwe`4spG4+rX+thGdvv)AXJnhYg`{p!*nNtU?V4z=4#?5RSzYl~U*QKI5+ z=*O!h)=z)^+BAD@S&0*34xU6c!pvn8m z%mQM)^GZ@GX>emxq*s5-(19{dM0&jc$|MLnef}Jvs-`VKQukJZ|UDtp;u^=Jy5pCb1@q&mJv(b(#-oWcggEW5n z!c&(PTLsfls^vt#vPcju>6&7odT(&n=0=WqZEh*Ol4IkrV&H+z1V(2E4|mB&8>mgL zWS|`@6yGxZVm6SAzoqKfe`Xh-K4oSe?lA2(+-{Wd0WZ<xQBiMqB>V(ml*GYk*om)!aw)@ms&%B1f2K z3OhS_MUq|=j`)IyNRAK-8{;+CQl4${pitfgayU7f{FL5OWfYy56?uZ$-3>;r6*WS^ z3!3s^>&L7(rq3r_J-jg9h}$NS8_mwTWTzY%DAh_Jmz_d(W%LKm4%)KN&@&O8-=$;E z-#%t@#>4EIUin2c(-Nj>6a4FH!OVWp-`xc#a!cX%U?ODOmm4w?6X~;x(@a}SIF^KT z5;x^&O3?XPs$~7HSWAK2upaSTBkHt48tyve#j5IE?;a}NGZo=8lQc757=r%h^s44g z8@{oD`=a1*3gB|GH&cpS;FBS$6BuHoo{>&1rsJz=ed@;Z8Yr`uIy(4va(;CQ?eTKM z;et=6YNCoLyBn@yKnc;brb9ffE+f5hwi#OWixj)|MgJ>oQYF&uBk#M3D``yzt9;%` z<*Av?#oOv5$i^*6I>#MbjF5$LGz-Wj94OoK3?OeIY%&49PRDU_bAap+7})%*M|Kz_ zMR+}~P9R>I{ZKzl?|v0`mxW}kTG!Bqx~m|L|3DGmcDon59@&UB2r3n?WTV#>l17n- zUEBNEdK!J|)b#@s^9f5dDAj}yQ%F3(5&l4jQED*KcWUAnTlhug)r(n@N;uDA1PM4t zS@-*jJZ9Mg0Y5ms5lBvzzsDM zm&DmT#L~fnNC=|Hr^^7gBTM?KKhN<_tL_6>}b>;wJH^fM?ABk&W6*vwk$-Q!^65+SNf7=ay+m@i|dh)*+iwD<54snG9;=g;FV#V;_H)?jq*4Snoozq!wP4B<}fdeTCR_i72! z$v%+Vs8%peb7J<;%ZMHicVgYwyUkW+4(ATWv_zsR&|5R;Y+poMjyyPD`XYPAQq7>9u)bg(3t+x><$nc-0$ELe9A z_7&qRm@MF2Z1#eEp_8j$=IhIf)aENJvXa_L8pTC~?tdU+q)UVCTfDo8>XfL#UOE@t zSS)u=EuGr=Czzv|dyhpt-!hLDZ?}0=m5$mYU_*=I)}JaGz8J$BweQwuVbB{EqC#|L zyoZNQGzx}n%eaKRcuDThldD079C$FE(oOm*&ZPM3-IuKH&qZCV#au@VsSY|SDX>Mh zafB8E@kaJ){%|h`U3efkyXtIn5ZTry3sf2Fzd%fyJWeh#rD)6ByU+sGAOFG!z}wjz zPO1}{P^6XuAe1Fqpk0A$fSssnJsj;fG9190X-(JMJ4o#w4Ai34%5irCMm97@0s3Hb z49sH&94m<%>l`^9bzd5dN)?(GXAF>KjDLP|7`85#n4TDqjfO5`MRIkJmjq%zs!g(3 zUE3DrtUM{yKzHR&Ri57)OCi7ha$OJ ziB6L~=W$|{V#tDbPhl_rtlyRkq_gWd0f_S+6)HQ2%Uh-H+xwbI|2t&cKw@{~X@FJM zdA&C~w=XX#`T37XIV*EmZ1U16mB$nd#m^$4p{&^veIysoZ$R4lwmrx`@3u^NBLp0j zd$$znPbb?=wWDI+t@gbtnWqh)7_vKnV#)?0$`RgYAEa1k9G<)7NC~r8p77mea4(zd z_x6DW2ZnkU1yQQPG9U;yriF58>~~Vlsv*xQR$DVkxh{*#CwhkYP`^o=@rymy z?pMYr$xV`MiaYv@HwlEW@cjJJAFNj&^@P(tomi!gb7A!wydc9L8eXL%pFWkdLJ>^oCKva}X3d(c8Nj;%kMflgwCLEf|-o-meeS`zu50GD1 zyln17=f|GvYPD*E^QF?}uvO*+tmOy1f%D63f}-jg(Nve@?J25V;|ZE1|2p91XKK3C zG3t4g=NN@%kO74=beJs!3;_B&1$FmY+2YsyHAC7DEKojgAF%bjcGp zBXXuyeiIs9n6hQktnD4;_`aE&kBT*}HoDpV8KbSqQW6LK?1Gr2C|-B5EKsc8Sg#a{ zR&Ra56A_a$FICT}%gSp=NXqCHf^)Mj!xXd8?FkRu#He`{5`~cPItjJV@YbQ_Y0b2s z^m`S`TUO*oR=|h|r4}Wqw1wE=99c%P*)BJfRT%C|lYbgD; z;z#N^cd{p2QDG6%Wa%S)C&i`@A_Xbk$CBc7Pe$jdP%BFHf-Et;23G#J@AzmbtED-c zdv2ZN`Sr<}apvlZVs{&(*eRNtYLFc((@Jxx4b#^mtt(CSTG{-0C9OoE*bQ$Z!h9pB zmHA#XdXAZHyu0SfyDEqAhYqS{?10VBe*L%0$^Ed~4aEWrF_|dqin_i-KVnM7oj)=@q z7VD&KiXF?W3(o6k`YG{y>v$%<k+&Lq?8%fg92+#!w@5hhm2vj88 z#!W&GFB86-KR$lQWjGBBEG;TmP@PGuj0twaarI{A@f8qK?d_!W zz!RWNhl55SI#XE<8E!#bGTsu|IU7!wr)nMcz$Y8tbLfexCxAFeTT4VLS`zn%S}gJe zqVPirwO^dAAbyVQ$zM7Dc#%?!>lY$hG&q=8i*2LuV;#YyNe5Z(U#24Sk&mT! zBzSej$;ug8O%!JsvWwjjz~kmYWrc8@C0+ybEI1^MyIE^7Dkqm5Tw~tz!POCY0aG1% zcHjB=OC7}NrYgJ03CoX%`x*&9h4jQtP((+pd|atRoeokJtwC8be?cGfN|BL%V4>(c z8aF(P;w27EHkQe_Dg>(vLA85R%+(Ve^W(8RY2*agBaqR?cWsFw(@(OP0%N=eB#}Zf znXisA=MyOPU zl8umQ>PyGJ;DOFcEnQ80RF1dc6HrDP;cLQC;(72p(>Ho%HI_=n2e0sEnXZbf{K90J z1GVKf^`Axw3r&ljx=kqYCw-wbnD_FVd?&w!dv8hupg zlJOxX(maTHu<5MR)hmuYEGJ|vYSTYkd3SdlO2Vx4KBT#19VQ8G4#8Kv2(uDCO4t-6 zz;Qmcz`?rxbqGde&4C|j!aEy6?X~1a!XR^8J>v6HD|VDl9$%xTG0>M!Ty`30tu$h# zjU25bX%Mv=lzpEKFH4wbDKqiZA`grRJGk+xLVmY4IT0-j!7LjR9#FxZjH` z?qLCnNIdBi$x~i-6m8^Hf(N(nhabL7S>7@Bw(i~|Up%VX{~j80#O~PIA-J-t^L%eM zvKD)B!C$5>+RWZ?yv`l0I~uky|N7M_Y&&aw1ZXyaWDD7;pC}<&V82ArJQPvKo9||pk^da`il}0&gFSZjAHR~B2C{3 z%a~NG`KMD6fNpc`Q?F~!%mD_na@9>iv1EmL^1DJh_ara518=c++mCjq>ishPCkv=J z=Ld%QaX?631mx4q-+j4YcQYrUeGJ6G3Zrb|y{(R1dr6u(K5FN@I_AdJ)d@%!CeL_W zil<@BCZ!{5%|Db~`M_V;g`-nkX^s+xEX{Koc|#rL^E?Za+)>dq1%xh;E*~NfpGicn zeamG-TO>jP>;{^S4vnhLU6{Z#0LiIumX9qN{Ugru$Q3%zN5a)OQ^+WaPC(go((`1P z<54l}Nfc0j;I5aw#;td&0_YAz(&lJ$%<_u-kiS-@5Z~)Y+RU00oBND4jR`{(DW(!8 zpF4>4x*Hj7T$ame2-ScBdNBDUz^4G%zhYLf#t246k@bX zRP&s6pzKT5Qr+oGQxS8D{V|)5oiJf)5WE`D?(~em&ioY$obR^RfD4nL>*%e;>%J&4 zt9%)8_oJy@{IS@3T+~-9T#{9oNCE*?jb5di02RX>!?VAQLk{SDV~rfSwLw{dME8xB z0{eSg!nd55TSHMskrg^MJG)T4$6D+J4%X2{RAyoikrm2A?Qho=ufkQXIrf}8b{0~= z+Imp{sLvoOz?EkdoNY^_e$+5)b(i>pljw$c*g#D@pc+zQJT39B;kVhrVf46yfU@qS3*!8*qFJMbHkN)~l3>`3w-yuIpNI3E*M^rXp;r5vahh#kcl=#!P9^uv zZclz9ym&JGy-c~CNLuitOfu|Sc-MDB!F8dhecO!yDa#JyQJXBr7;A3hS~L@2m25dR zPZIYY!|#rveZ@N3KWiGCoV-{iW^qzU_N<=rxld_LyXMt>(v$nv(-0!ZT53vKb#E-Z zQd#`Zj8whGTOob;Mi+QFoUV^0TuH{{7(!_WL|q>XcKR7ybn#vvQ)jv>(k!i}KvgQX z6fEDjRzXds7BxP&UChNZ8qvUQ2BT+Sz>slQzde6z-^CC$rU%%mqinnBwohKPln9YmIv zT_w)mZwN-ul21{TQ!9MJe%@XP9&#IvvF2MFVx~ebQipNDYd3NQR5qa_i^a)3WQn*t zB3DEiys)BAyP|tkA)X1(ChLk05uLtB={=;{)fkLK)mBUcNs8wP({RXPCV+&hrwGm& zPAxe`k4#x^X}~7CiKOK)ML=i0HioXBBr{}F)O1e7*n~EB6}q6I9N~U)muoYwGf~x+ zY@=Z$tvkNGO|CAVir9Lg{ZPYc6OCwHg3T*_-v}jlFk~Lv7$efzgQczI!ELl^YD}IXbtY3OSgqC2^l>k&xO zNCS0#b8N4$E{B_(u}bYxU}H0mln+l5EOczeMUF;tY)afu1dOS&XtoKKsQEMUddVFG zP@vH;-Sx8J-zap~^&67qn7YY4Lktp48ugreDZ9^mz^@ zA^o`tJ${N|;Q~6IJqU;XUC?zEBI5GiJs*zRXt->%yB6(>eFMuKQv2)vD2ymkQA~le z%2MZPn?7LZGbg=;%m&y{Aa?WCvb44e9}SLF@RkpNpI!jVeVETE;IbNy*XJO698s`Tvso68`F!um1&Y8Gn&k zR`k~NHuSdi_Vf<)j{odl{};&epU4)b|8~*;JCf>uUiyEaRBT^JnzX)y*Z=>Z(if2QH?;H@kn~?brT+>c{q;Kjr$_aL6%p7Nm=o~u{2Mg-qM}$h{-cZf zS5tKcP7c<8AN(hU#K^?V$^3r9NSYKZ!Tqn%}Lh@&6-|cvGx&G*~seII~M`NC>GQISA-~%_eM|C1oVEzdy0R?4e zU|?vn4<1TwZgvHvrp}qFuD(3|vy`=4mMzz(-)v5U09>2_rS~($uLT(52qZxgAWP3V zTpmJTVi~M^08nrDz;t)p)EKm;zV7CI65*s9J{I7Y?>IpC7yu^)$X=)zEnK663xK8? zSC84pBeH<$H+a3>-Cg~+QCtFZXnTMRAVL7q+yv4gv;i}y2Ed=fGCc(3kDr0L$PJG6 zb-Skec1}*lU@Kfq!niaWQ_MhGJ+jFFtg*yHJ)lNlPudIukY>;?ZA>OC=DxwCOV>87 zTytx~s7C-m-5_jwN(lXk2iq`=z?=YjdjL-ApuTmu5I4=Wy_;Z>zCP~2dWI&i>}&iR zUBG^XKAgZZGI>qT0-@X(27nCUtG)muicn*+*0PZR1pQ~tgi`~EP`BW}0D9O2kW+hf z(|`dL^UDATD!P3}99WzHRyjGDxc#lXQ-*H1VJb%B5t!|MR?!Z4QXb4yV9Mc!|ZSOfCSVB)PA)W#Sv9-4abMyEpeWDjK zGz3odlgR=gBYFwvRuO-|K!p| zqXkvhcCriZqW8+^vRqFGz0BptIYVDKJ7q+e**^&|^uV&u&O;^ckYBQn&f(e*= z^+UI^0vVwRCm#Vi!)F!3IT5JMZ%nycwm8`*YV;Eh5N#a{2C!5Bx2MYn3ji6L`t)FF`6{1P{(>O6ORcPGX2A3P19pGpSz){>V2o{|i9lbjNwkg|$pt`(e(5txNs|9JO~8U9dA5;q!M*445#FBe^L z#X0>@dVW>@ea-9PEriPg7f9u_nObLf`wirFeq3%`h7F@*z&5Dr5f?Rcxp{weR-gsQlkz5J!!?-dlCh$_EExUf$R5Hen@oRqlO z#&RREoGv=D0fkw@x(Q>H%%2Esf3pcqC>-u+i!_EGCtwS%GX-W`tyS1I(fI)D>q1Jf zn5TtH%?cY3JRu}h))wH1{u)A2n1WOk8C&WTmAa|r9wM`C zr4XE)esX{Q4FTj)4a8oLr70w1S;drDLzHWK*NKI83WzcgN9MLHnzWuI^$HwS5)$@k z47mq$;|}8NTy7*3JP#Wd01^qyafL6Q7(-xQWUU9{AP7Po2rB6gUuQvs%W4+Z#4}pS zBB5*OiO+kZdMSGUIMHMLUg7-SsppKM4{@<`*6rD%$@ZiD)%`5lZOr@jeJWTuX*H?} zp9D!-jfO+TA=VOE^pYn47%@5_H%+)?glF3?5ITPxjY#vnC8+GAoQOlw}H_md}kfFEGqdwf?y_!ZQf7S;HuOwjUntz%4f zu566^%xleYYi%P3i1TCTK5xOHAImCAdgVPbm<)ew#2aS#PeRt@+)$*Qw<-4cF2M+}vuL>7m>QVs7jNLPg8$GPAr(%fgA7$gm zgiYnZy*tRASnqfmheuP_}w|i}`7V>@HT>8EK zAm#ITaO9D;HNk_r5TeS64|F8HSAT<)oJ8|mX}$bcXm*?>p9TGD{rqJ1shSi@iV|~s z(5@y*Z|uIx_5gOJt2tVo&;uPFT?CV9Z;r1jW{cXlZy_4)6u8dnqoWts_xkf|{bh76 zT9OT7y*plIiMbx(F)V!#``hWA-e5}16CURu2G}!G5-l;DHc(j(~ zJ7HUIaC095!&32*W^m^-*w-8F>h?LYo)EDsfTGEsb54nmJb`~uNI+1ZWDqnxD&^Mb zc2-jG)Yxg491pmP3&B=njp4#KNbm@=mxgKxYYdtu9g-?P-a8?bc|aa+#4mqkNFEcN z*_=2I4)WPqCMtqt`^%R%tb4w_BFeLgs8e5$;kR7#=$L5Y$IT~qj5 z`YHR?bUUFyR0I74V&g^-rpQ6GH$vNY(tJu?ITiL$$&Vh~Frn7u{P)vu=r;FMFfofx za}yxW;ggPmw7?q8kaLx|L1!^)Aw|t!Y|C|#Vxl>nPg-q*&b9}sK!p3p(bGTRXeeQN zwlq44z}RpMQGA}>#*@y5?fC_3CM~Jm)$3tzQ^T;$H6W*doHRY%J#rSo1EM!9)~Ybq zT8WV-Mze#YoFU?T8~AYEPHck-w4Ylh%1bwlRHG68pe)B*deFb4To67UP+`rRprc3b zgb9Zu)-Pn3keX5hgS_OM9K@OPeatcw8J_O8GSQ2MY@M~BL^IC;6HAVX1E{5ZT<6OL zvMi5WQ!Ta=nJD}&yW<-EBYlJ&*4Ng8wl9kmv=io+8+|YF)xe98%N>!ngqi}j*-@tW zZ7gS1=aQM2w-08U{*tMPBUNzcFN>9~0#$J>1kpf5h@7)y#S}*)eLTNvD-W*Wp&u4S z->kzHtOnyEKiYYY(FhS#{V^;U7-6$-T%q^#5F|7i;~hUe$zZHhp}*CM=ecOl(kM`k zc}xp?f25}YQU#pF_AI4#vDio2P1<;UcLKSOWI&o{qY$x6;$5y`(wtMOrrc?Fi{QSSz`^OmB;{Va}ZQH%u zwr%aUZQHhO+um*4wr$(CHT^s1-ZSS+{&SI;CpWoIDpjderBZ9Hs+E=R`}Lu(S!tjn z1-Yr46HXH@a)7Hc{_}OYa!Ooeiv32>yn_|mK46TvI!r&6SieMi8Su6FuhB7TS8V%! zTSRc+U0c7YQL$(@;?c20yqaDpnA(*daE#nr>`l2$e;X4oH`J?k@YXb&ZGFV<_hUjP zD*$_&jwra^N_NjH!6IycYS{=T3sVO@z(z+?jSy>>Ng~C3=4bSPU9F?2dX{nZKuR%} z^Xh1=I>wm}HZGM7QzEV&8RzlRyd&b^7?I8oHLtR)lp%Xnimje|X3xT>5DIh=}keE{LxXP@{L`4`NUQf-}J%0y*jJg12^XxC}1N*GVu^x+M|W3 zlH>av%};O~+OkXvmST`@o(tj}UKVgTb>+jw(lD_Qh=r?0fuA5FIdIRl)9i7szfGrb z2qkH4%DE7z!m;gQNT-j`eFed6M)jbTEH}B2I#h`2lo=-^1!zxDKB<>BuO3}fB+Tt3 z&*@|?Uq<=d9lBp$qIJ_@F#pBzmRPnw3}GSVW|V2*BCe&9Mux>o9IoNZ^km^)lV{}`NZvhH@k3sF2B(`m|;8a;w+mrXUCh|3n8`7*Zr%O3g>yAxwo)ol%)cJX;=i8{5yUNL&|_ z_>>EZ?AZJeN%hHQ?=;jq`ng6?V$~ z2!zW=)R@0Pi-nOmoqV$Q_HoL8j9;uu^KSW=AP7(^S&%oIRaM+t3^TN4W*QL!=6rJi z;ku`!AM@c$j9_0u7PJ1~cOJXiNy0MSykTXM*{~}(_r~Q})SEgPr^S>R|Kx?_I4Q$iORz(b)K9xRjVuRe~rm0l>l_kT~|=b5pON1&CpI0@li`M+>G zt{J6XE>dv+la#bHEkx3I)ahuS5;-tik0Od){yRv#@V*hYByVMi#WlrX0w8_S- znD54nR1W$qc|uB?yTz5?CVgt7OQ(VYMLHH}yJV%-*@N(S^N}=maXiRjcy^B^>;@$l zq#rL8I?^RyNFLHUF!CUVn=Ofoz8mM&>5uC_d%Bgc~;?>@WXEVjo=dDTOX^y@_ zpmw{!BN)OZN?(mxY;e!_{TbQqi|h1)%jlWUOir%M(j#-I`^AX{DK2U2hR563mdB}} zqQ?e?$#+{?=bhy~)kgYPB)1?{;zRW)NIBs*_5n6D5)5fbzKcf0LbD=<^!!irg&G(k z5MLt+YCAFKK1~Vmh8&lnoF4Xi4w+W!7zpcMXg2R2G(&Wctypd zxj*@s+_x;sO!sFWpS`opCUl_;c2M-alL#Ak0Ro$jM9G)gJFeKJ)jdb2MLrwFk3^eq zs(%6?4;SC09lh0F8xED#rJ;Vd_d;SLW}dYfh2T@v0|UD~lBm$`L=oBJ2vGti zt513S;XkQw68_q?mn%G_B;E%Dyo}zXwZy!TT>;qqnwhehVW!II9U#zuJw(*5vB*}e zn~xLLW#EnF3EOz;&3!uSl8+G;?h|V)u0n_ADg+S+G|~_bktEj+f_o`qvZ}0;f;1o; zn>3si^p>?0;uTPxGy1D#hHY71VCC&gDA1Pb0uSz!_&4&&0@a?-Y3n=uAFph5 z`}44YmjC6~rH4F@6DPb#>gkTfzgF85$JWI@QFMtdZIAVMu?VU$4_GA2TSr}IK}HZK zM3!!0#7&S!Yq$c7`51q|^9{fow8XbPD0Wg~V#YeXWRUrGYk;t%$~h2azZ%QQ;ooFD zQCKPJbkrrL9$v6N68hJnB!HRRL6K15EhM03Ocw~I8a=OwIj{VFlp08FTr&1 z8vR%p30&J%o$dVIKWR^`aafL2-2YHJ{z|IjPZJDjbgE0wU6X956=p=jJSt|tTE@!> z`m^_NKZt3euPm%E0#fQ;g%WG-vEU859mlNn%0u&WCjxBPcwjCBVuJH2#E|EB9wLQ8 ztQk#C_J!N9=COF*m2!JZ$MkKjg)zJFME$|74yj_|OrV?_t;QKF^wrnNkQJ+%ZR_oP zl3jfmP*XUr@+-gmEuCTSHK)uRUNks#^#wx*!F}D|v+9vbfmvE36@e9+q)@jHEQcF0 zbxsmr3LcZ&_ZIPnqlP|uU-M1xzMNT;n&xhD)-+~Nt{ENf7< zSE0(v{&?(&lksU4$!9tN#HrKTC9wsnQX0;x1k_28xd8LAQob&4ZMj>Y6w(q>>%I^j&Sys(2pCB5~AScX4xkzCh7YvF@>I|g$T(nocCmxikzGk zF3)y9k`}J4*|2g?ai3f$ok!UX?NVQl`+YXw%f=|+T2|3XoqOk108^#EP4o zF09QSv|H3L2c1=`3-gB%?kR?_;}4|`kNZY9E(!VL9VoD(jc=e_#)rY}>DmaQdY3Az z_W`^l=Jt&D?C0-kqR_4=!=Ej1#`eyGbuA@ZZ#!J-f=2ocq550&F>nY-I*Mvc2)#67 z3k>Q5T=yb3x+BG;`w+RcCk#kh%o^44jUJM#~d&X%8`2yXYce^a9@?4jjULr+l z=DP29XLmw2De>bm_qY}$O@8*j2O^yDD*A93XkUjx^$o1{$q^b%5Ia^TF+^w$$jjLk zpW%62Z2PkmznIQ_{ehMn-Mlv4EG;6;GRfn(H#s61HV_S=2@LY`l{jIf2 zUnpU3PoSac@P;J4l3DW6QGCtnDUi2mv2cCuq4dc7>f^xP7=(S{Vf(4${as`q6FZBw z)fI&(BhtR`4_-!O&Ord6ZXMvxZ5u~y?30z^M)WZxoqt`%A*Xa>1Cj~| z96WD&Qx@mmhlQ6-E2n?qPosG0r_JOfBzzv(;b!P4GX~aF;|VOacQL_nJzEpYtC8_v z+@q^fyYCaE-ot=h12l2MKiqvv&XoRiDX}_G)X-&arAv{I$AlC1XJbrTeS`ou{C*d3~!Ducqyxi$ML6olh zt2$0b8RL3g{hXoxSNJqy_xn7h9nUf$;OA+Ha1Ye9WSN?XJ6+lGIVka)pZBa$YaKjk zg<97@d zUcsmoI44SAdYloo%vo&MNve|XV?!Mm{s7UgguX?zszH0DW-BO@tw^VC!m**pobk3y z*^EXWeHk*QL&8%vUr1pNHCdx@whg&wO9XV0-XEJCc*gPhiqFpU5dS?a^?awgfWvk% z#rTEw`EmIZ#n#1*wy3oj;jYtB8RMZlQm7(?!s)^lwX zVX*AT&Sd=^xjLYsC+(e$DP9*^TPbY9>=Mj)%W$GWpvTNUq^De62Bo*-cH15W0bUBN z>-Um8{(1#!ps@R?1aD1m8>YfM4oR;!gQfc=?7ZmAItxeT@1bunJ}Q2R)YVqml;e7G z^>W@gVaKo0EQBDpU#w5YWY)K>X8FI6#P057wbOxnr8usWi+cF=7wC#mk!8Hk9h9oR zfWPtTkYLgUY1X-cSS1+}4R6kA)`nygU?ZGUfYYH>RUaEM%@($D%&HevA_@=-Sc#cA z3h_&?+lEWEniczc78a)Cd53fCq!c~=v*?iForN?9VehVe;XV|i{sr6hA9iIG4m5>l)0rDt)6(r`M?;Tpw}D3>1M z9jbi-)ECy(1m+|-HGV8t*7VTA%X!Ph&Y(VfJVKMg>(d(Nv|X$&Hn*F@UDbyi5T5>c)PGZjv$EOXVUW>UZx z>67y>&os~)Oo)QTBN^EAa@+PhSLW12?ywC@`@8nV;{vn5eVt-$&08j`U}v_qv}A+y9w5=f+9VQi_9%z;$3D((YeV(ixraV_!XYi(Ab-!KfO# zcYan$xzU7>Re6SErTEOtlOJE7L7I7NKMjLKQ+05v_v0_l>{irQ6it7(0}-OfsF#BW z;7S4M4jMEU0^ao&Trif;*-e(Y&}CD)8jcEm32ws=ic8Gwmer5FyZjw(fCv7921}*< zoYxgo-WscZBtr&cvX2Joi{Eaz^m|~bm7_VSYxvOJ=IOA+vZEr!JPYuDJ_TH@So-`_ zax-NvhyK~wQ0PfVO>M;ug?9~CYxjOVzfbRM7}yFvrWPU&cPgQ617B<*adP>)Lj+{b zXpA(YA-J&Gcr?AvD6abGwL8gP_Njq$7z^@3Dc+r$Rnb)nF|9hM!ag=>;`zSUM0yK* z6qnlpte14>-qF-v7HB0JVO&WTcp1enJml;S23;j=5O=RWQuA=a&TkFcBLNhu+IMob zSilMsHf$)nRx-&cx$0e~QV3I(965yWa+IV`Fi?yY|%z(CYf!ygR%-c2+@6Gbv^U)-{}jTRA!2udQFJMrZrbH#Iq zMpYn-dT;5 zXel!{c;gc9P!mKjCCS(`Wwq2WIu&ka%;BH~k@M?$l!AEzlUo+CSmT1A!WTx#*VbsD3e@`SkOPrjmTcXow-{Q>=R{1}Czt??|x+kU{Hf&VX znzqr_Jk57l_GpJ|1wOu8Q}lb+ELTD^aVJCn_;N$d!9jWkqa|8^R`j zhiWPOWOz<VHqla5=p_+ie*qnP*%DMs^IaQnnpciTQknNfG2k)BFJ$WE!xaqHARaNsFNGtasj z*ZKMw_Ves)VY`g;9C>JYt**bw-*Cf>aW>9Y6V4k|P@af`E(pY?nTb9sUKmc)oJDw7 zhDT6fR^)iH&fgk>E7{CYaE&4Toq=EC?C?#ma^;Qa2z;fK-k7^s3`-W;G_HnEgTl(6 z?;#w>Ip`>2mMcK0`Vr~;={DY0?7M0A;F+lD&6K`65lztuwi{tf;!2``A;I57_-G6U zO7)ng8M$`#IsUss*9pRGdL%6_w~=dw<&_PH(Z$DTduWR`e96RrWZX)n+&XaLtfWJu z|D?v}dqS)FTz>}}B7^(vQq}3G-oo@C8=_|9>os5sR+@VdI^?SQTd&U{)bU1biNoVO z4AaYgo*PQ6-Z){NHc5fPLs}d8s-F%boS-S$oPfr{Uudri?1&c9v)t$V1 zobwX3OZ}BT-PA04+yBXk))`Kotxeg4e*k!ZG&2~)y_=aq<#cgRiunycIM1@+&L3x2@{1IyqJ$$rnK)$xt z*DkZW9)8Xp)ra$zR)3I(h7%v`V2bzx4yWA-{6|!s3x~SDy`udjj+6;+djXMGc}6&0 zLAmBx%8?=e0_0f1k^4$A27D^*gTK5T+_swyK)Fx5BgPHwsLz>J*PLG)GD7+55)BLq z#I@BaM6k`W6U!}xxawk9mn-MbQ5>%{i1;U0X9U&}tmyU9y8dh`fq2zId-1nuij!VF z6x9LYsQ$ZVUk960Rgh|DWy5fMFl)XsumoYTW6N%ndayfI=|S&O+E`hqp=U=p#S8Wm zR$o(w!}~p_7V+O_m3CfH0_WeqwtFpCrQRRVv*s6pQ#<;OKrN|TtbM2zO@`a*`nG`g zQ3~3ecA@pO`o10<>9z%Uag@;2?4{>S!}h$Fmb{8MPTAShNylA57tov44%yD?jfUTs zhU)x$0<0Ga%V5hKU{7xCO@G`&j-+hSCG-IvZpttL`J!^R#enJ=J<@<|eU{^j;C!o} z0^?+K)tkQ3IZeFGp(`l;rY6U0-BA_&*6A7Ra_pG6CVF^^e2zgBm;RlBA#+(6-31sk zj)mKP#IotN(TlNvcS2JbbQ=)*Dd}AgxH9ntXQ;jcX}@*2jRzvX-gxsjSh1bd`oS5z zj|aQ!x$~im2pz^7p4zVg|0Y4M4RcH}RIsNKS10Zua>`LBv)*c4&IG1CJ0Iz-&<|4C z%eJI3pmb|mpswq@1(D#YvV~+3k(1xcB3S0Wk`G%pIV8wHuccqd3U{hAmdLqNXSCw4 zU}(yrV7NMhvTSEQgf2;{MI^XIrpaXt{_O(1Dfi4RGq z?|!0Du`j-}j=hNuZEMi(so^Ne1OW5O46=oUVGiR@GB>iCv5!0WtFx#wdht-W1ooWF zdF5z}(8SQ;^!jgd5rvX90n@_l__2E7;b9TM^)#vTx0JxV8+DM3hO$5D^IEULe~r%k z`Gi$eMIlb|{Um*N)<$DTNj9DRZ~`;-u1}gzp%5ZhxyP>-qY=Y<>O4e)m&vh77B1*x=zs|jg+F35{@&&{)x(wJ+k(|&& zu$5nf>J57sp~vH@G4Tj{%{Vce?fPwU^$t7bg7jHgkg7CJoh{b~GlZ7v*x{9a21A8W zwx<>|sBX`FX))cA_B(NMk-9;vXg9@3`w%o`^uX?4a0W?5x;-*MTJy1 z1x1;a5XliLa!0Z!?H^! zD1%S8YRYu)Z6%ouSgANE=K=Nujx||8Pz$Wp6ZIVwh^^gE?iIx%$qWq?lkpVdI{4pz z+V4(XiaoBg? z(DaxQWk2OlXJK2h>YcctCO-USeAL>LNNCndajnBQQtxM^*%BWU!2pTNSbiSj0t zDpo1$FJAI!S#vpz%6*0$#zvy{(g>AYttxko1B2K3W=LLi<)h$>+p`Twot_$_xGq_R zu@OV3lrp^U-rKV`gBzC+%Yc-`jC8l$I?tpC0AoCinHt9najuS=BWI}PbB-G(g0jpN zvSDy4mzU$Lj-~y>v~Lhh*v44+Mah_new)vtu|@WHnm=@ieV+rHZS=D zGO&1&Fj<*t4AuS|YP?I86U)ONTZWPS%4h5f9oSswNEou)qUi%kvh0k{{?@th6q}*0 zsuEa{y^3&9oJ9XBvy2>E8f8?->f zj0Dw_2zT6BCQ||Zn8sdQj=tV!dos;A@>zj=y45|A*D>Py%z@l}K<`N>=Uz-4rd$jaS_+N@Kf?$aI``;}lH&;B&G99@sYBIiXpg2R#21*W2`0P;iU|iWyDUDb zpucoVK74egQP6=2Jv}wKiF9Uk-zYnof`ZYPG$2mZEns>Cm-$RJ^|Y#X5OdkuMZ+OS zKwgY$Nii(Q5@YktMh%XQpAldT_~Y4my8D0AIABOHVT$Tr;i4B5wfQ23UH>kL;2H`k z7mwns+z&A7vc1y3epw(H_9dbV`bOZ7ms5(Q>Z~^{gO6j=4!hTYfyIL~=iS=BOkjETxL$a9uE$OjevCxu(4xeb4s`gf|2(f6Nj7uE)<(aRfs_PR(U z0o^_zf&H9DfuRLj_}njNFOWog`1)8pC5I6Hg_bDQFo4g+Ag9<>6qFzDlW@@4xX~!^ z#;oNiXdfV;>7q&|wM(UIL)c^v0eLNaa%vjn`8HXG65W3k+Z~EEr~K{H`f`nxy&_wi zy%5-YRY^BI|CPU$6j7LKxO;WGm`fNONou$UipwR(Ca_z4KOyxXQnnmJJF7~!8eexk z9pai?ny)NKWC_J&*^;3=oT(r~?b&i@R0D?nuHyT=66v0hbo}pV@{9fU-WOP)ZEDK@ z-vKzD{Nn4*I$p)QRjL5QolPS>x++nMJYoAaEw@hu!^x`4Jg&J{xinhUf^uWyKpt0P zvtzA?G@@Kwvrc7#(oek6o-<1}LZC>jrf!s|&kiK?S(R~kgeY*W^6BcySj8(;`r^z` zhZK~w_|rGxgjN1+zOd&3V*w;t?w_3RjEG9i-8^Kse(P$To5SQ>HiO=p$h(EOdcZ`S zr|5|>h080>P*^Yq{V{1{rot#~>`pUFb5XPh`en#HNp!&b6dUr+{+W;VKkHlN`;!yC zf+6QHAj?qZmnoVQga%dgj(1j0t)8a2NWbgvin;T|xfwo}HeM@FQIQ!0Zhrs+=3ImR zi}r^3e`*{4-?cX?QsU~0g1_yJlG6W4dh;J_nTheYxM2C^l{tRfivOpz%)s!!Sj+!; z_&=;=#{b~I|E0Ce_M5W&4{Mp}KX36{xF{Ms;gi$x(+SWC(h1T1$66Mp6Z>s&{%_Nk zjm=HXoal`0o%OBgOz2F^U5x2WY@HqGOzBJ=jP;$29sVne*~Z+)_&5Er{k^rLv(tAl zw)t>Co`GuVw|G)N`ng3I!{4c2r z%YV5!|6f%_|A&qGKcb@lbD#PDinsj#f9?MdegpqSBlVx3jsIoGWBs3Yy#F0)rvD#N z)GuSr!uA`{{rBho=R}H~g`M&LgF;FLR4GZjg|rZh7zG0%&LqU<%qH$yUoRxhKd%TY z2~Hf6pO3S!qp(mAGYM75Jg)sz_2uJ6`(m5La;kGC<|OOnvTKG*>M?^eOJNy;DvTTG zdK_{eC<4G}u@LqZkPn{@4Pi8JVz3a}(b@0QeAswC5MNslqIJ|4I*wm}TKmSTKBd~# z-U5Q1Z*2+?U?0>EM2IhdkPqJv9OBP66@vdCz)_9%fl5FNEdXN>?EQcV;y}B5fqtvJ zYS)R+CkQ>j1|Yuv{s8Qr1we%u1Y#H~Nbpkib^(GISE>LS8~{!TdYJw5CpsuphSG|P zL|HK^$rtTcDrY zZ6tg;63}|?WVf>Jw0gvoV@tskpvSk8gfDa%9f~P|niKfgI0Sa8Xq&npiNOQ}yB&rv z``-oi&vrrJn;)`zz=4_@pGf*w$Ae!maE>m4YfT!;v|X|RXa;42$L^Eg0u!tMNCT|XTMI}m6f zKxzZM)c{msG%ztA@E_S21`pufRDY3vvtO|7CtL`C&!@MKvB&DJN<=&G8sC23l~het zZT=y#)GzoU-;cr~#2f%ynZNjciJ^E90C$jgKp=0R0Np>uZyx~PNIx6p=8zwbj=jF< z$-Ar&ez$m-*KjvSFQD(f@Vz%lKUFur zb)ULbKe<>5u8wxES0-;)KX^8hqG^FExqz-!m&YD#s1{)zdwxHrrGF1&6R2>?VE!-2gTte2Mb73cuj@LG3O+1FzL!zD4?7 zsYQP9{{pa~hk$f&tg~-k9nmpCIGKumhx{OcxCj#79DlkFY?XaM|8y(iBgjIayV`&O zqQcfyz?pN@Bzf%iwJ{L>9c#?X9UnjA3AJ+m5D!b9)QHDu4B$?dz&$0@(MmMrh|enN zc;2@5ibdH@DqZqAb2P@S;pv`>;^Gpy(`WWoEiX<*Js~KmJ}jPTYKYbO$Kyd{(ZQ$~ z(~yafcZ^l<7>f%!ld-)Y9IMZSrICpOMCqnFgq$@ulP?7XU6STdr6a4zpx5p&Z_p6` zeM_9d$&pPwh1*r67-Kr}v=w>mePP`=j_kbRlKszw=Qhg8~= zHs3pttU{71NI=TEMy0-bD=^(uCJ5tZ8)&rPYF1t+m2*VULv1a=l22hBH<@de=uSE4|*z-o2Z7yR3nR zD+HTGd0^p&P1`ulh5G3&Sxadn;0S@HMecTXO%@^6kkhSd$Lhr3UNv9TY42H>BRuW+ z?&#;9@W$tw;6Xz%e2obKphsK5eW|*&CDij8ce$dR_3se)n%Y&7&llnv(j-WMTfD)} zC3q&oHNUISa@u$6xuL9OQ`6hsDA2I*v}WpG;$ims z#8w@rAiV!@3XgH;5@r6eAk!GvIN^*WxZXssB^f*yY6pbnI>>mih3l zZ~U(@)0QO0QAO}1z#id&MkWeWs`hTY;)b3YmQE% z;J9tb=fH-J4Y1G%8*dO>-DQM~$pxq>=wj!y@K!{mAx;`oR{Nbp1t@l%r zQ7hDwQA_%Eur2TveFeMAdEx87?dC9zEA=)}D=du{;C>u%mZ8goH8S1BtKH556l?N7 zzRY{h!;fZkN03j7S!k3H3R38eTui${5yP6ed*-EA6hSQs zceG^1gtCny4!p+%j~AY|w1NBN1%rb$IbHu6Lqm0R(saD$@5 zw5}CLVN%6C|E5x`;|lOGFY%FL%cYW7ldvm8hkr1I3LN~rvc2D_nhurvtcdX)# zgOp4t9r4fOzQO9;MaxcU>_-t|cBW?BqA(>NWpPE0#|EA7Q3fR0oci63Hy7ziyi1PW`~rRiyvPCm^!=nJ=&k4N`t!(&_*vI`DUdTzhPy1y9^K z$W2q{hW!C{!^pbF+CXSB?li}<2*Sh2w4pU zX@val05V4{vAN|Vobf6qZWVjr%jZk(tVDL-YF3+R=C}fD7g>>e! zbK1d@qAkgq!d#Bq{C^LuEhVJl?*bN$Yb_){^pj&pd+1#5+LR#{eUeB$O>at|K?-Rx zTnsJ0EZSWA)988d(9zJ-3sOI>bu}8>u;|?=ma}fupMTtEDrOz1+OJBdC9g5GtKXF! z;HN_?IcC#i0o8Qyp9}9%a%;ENXeht9_3k&5r+w#Dqidt5M|qiD*))f)6v?C&L3ONn z)ZZzAQL6h|$G;lGCZ+wULi0?_@3hMk(TW9bsS}xc=@ucic1Kw1(1{!wq3O0}V>oqA zGnjvmeg0AE``n70Qs68ddc?S3dE%5QHBVIwLa2Xo_HeIKB)6Xjm4e2#Fu2~de+iga zSS78fL}%;nEtROIHtcL#)QheJIjh2!>b!vX#;ASWT_)4^=RkQVg#jbIvosi^Y&PUY%L`UynVvuu z>`_@R4vbmu`&9-2j+~Q$p3i2S%|31ny%(+fY%2^f$MKP*U|Poi3Wh9aWO<%DpgdGc z{f`eFQCoF*6|6XMUN*$=l|3ZJe}E6lJUBGw5?`vo%2v>seKpgw;+q zSl$!%JREiA(0AuEyn(lJ1F={xkBaUA`FfaTw;Gb5Re{7*!K)B5HLEd4JTJ%TWpdQd zxp94|N=0GzQBR2fTQV{kI;>|0kzaSzI0#yMu}YA#e#yUIpecZD2la9|y=39F9f<0- zSf2UXg{Z!*c0uDO?&#f6Y+sx>V>4>iG7E@rqa}Bft0WWbf+7Z?TdlHy;1~O8M?Bf96LD1Rr0-jk&o^S`~J%oJTF6~ zl{x!IddKC-TJ#Qah%Gh`LL;|;%+@Y^zZ+j~!@f2^^2^(zXsY1K^||9NyAYi>qNZ&@ zsVg)(tfIoT`mDuptU8<(dolgNjy4iZT>-rJPAuw_cFPY z1!YUpo!0b02m+ih!{0@X6R3AKgi?}ewrpzB_w2sXhpQ7xveFBK?zeUuzkrudWNWKG zL7!P;=pqeOKz}Ms`FGAR1;xbSyDX{c2=p{7J%(E*&np(WP42%AgM-l81-Y1QBZ3)# ziojK9cqK5Bh5W1=V9r@8W&NkW@>=zj>Oo9DhRXj`BlH(ZGKMA*bJ|bfnX0-Slonz7 zq@iv(r+oPI^B}__ku}rW66;VHoRW*c#XuS8@&5PKhXs;rGK5ky?G}W@yo%ZM`*b!fH_Dsq| zlTN1t##qu~+ugxBlv8?n_7x{F65Y_0y*o4}8SyGQ#*|du8ijKT#%uXHKwNhG=QhjZ zSi;_waUu|v8vA^*UM=e`b;)=WF0St_GM)jxYmimr1`b;s%M$U60AUff1UHIR1mOgt zltzw_2}VI@dEs)KAz3xc zpin6Y$vy#08q=nBD52eT<&ZQFSNC!(CtZE$c%x2;?3mIzCS^UOb+$B|_cGlBmSmdd z3ZX@9n@HA{U<{l4Ftl93k+fES*c@eDt2Sn}ZT2bY{!>wWYBQP0wV-j^SBMZ&@JQ1L zWhr*bDs(N^@X2WFC48Lfu2Sk${Q0-K!BmC@qLfh#hg_u`=tL>Sxd=FytA`}_YtyyXbzE)z_3q{k2#Ydt~ zI(5jdM&~SJy|SbXSJy)?7%cT$JIi?4wrABcu?vIWe4tLSTw9%RTuA7-+Da01VqZPs zIQ7!x&`P*{Ot=Ef1#RL`kf5S9@OO|*I7V?V8m5vnJg(vu&yL53kc-O&m0nOm1MlaY z^-wI{k?xJ5;w@4uuQD`9Z(dT1MqgA@3h}WquraJIk~Mr(Yv=>IBW-1YTJFM%7r9NW z_VL5RE*J`m2{%3vUoQ|aD$lDxx($v#W-?pU3(ACvW|mImtQeKg-X4ba3D*vqTpwUK zacQjyXT^M#$t}Nmt~(xyrX}<-Qkr|i48@f+Y*0QV`ei&+l9E}~s6LV1=t*Pxd2n4W zL17RY`T2?o;h(B98*3)U>Qb~i)JC!mO6_#wPbnm+(*~p-(FAm@ke55(bfXw{JxG3tcu#1GWK%s{LmWMyjB2}D=QH(CBcbyCoVYvl7V0(5K@%*a z*P^mTL{KSs@r>tL)EVL1& zcE11e`!L}0G9WJ@KUSGvFLQNIHKvDU?4u52UcHld$Ld#BklQ?_BSz|$Zi-{_Cwqt-WJtVEuH^>youzV6R7T z)&`xZHL^E3gYcwulDG%Uh3v+FK+r+tZLI{4m$uLcmdXR>Ct`tKfNvKw%YJ2il+RO! z@Mow4lm6_^(;7sx|LSAY!Ppvuy}5wfW#Gm1w=DTRUQ#nLN30IatSfEn#yFSkc})x) zQZQlOwNp?Dcws%{aC{V{)a##!yGl%B(A6|YLf+}XBd*vD9F~}^Ky5rnbB;5Urns%M z#eFrzXTmkf*Cg1RsU;^>A|3+kGdpzR;7|P9X$(0??^uuN%MEy5aj!TT99@N^a(cl}Qr9*%HYUFo%qGv-y!MnXA6ocd(d|8P1Hnff79m3{sm*BRlf{iJJzdV^H*di-f}5q{x5%T}Y+u zA|qJTq*YR!49tMc5aTXrzL)_N^|={vm?|{)!g#t2L>VZPM9u@IjU|wc!mDv3Y6&yx zK5k$`&P(?pU#w81aqI2Tpk(Kr%{Q+8v(VAj476F_ggq5l2*@Vj85!er(5X+=sPdP? z#?l==C-ur4+C}pMpZoC95f-v57cr4VG`p%$lDvL%pG#4bRD(ECwWX;(t+r3hd)a>Vxm(Ei*7N<(MO0VQaK!fAbov@Vm^cKi7CbKv5<`-4L znt02+#O+KpuTGvsA^UQDrjVS8uU>*C++?QF z=6ofg09@N!E}GQQ2&i>UURfUOjDUZ_-zE)z64VF_Y|*HEy`e_gIhavcNk-njAnj!3 z=G^&~xvvoz;dM@f543OrcW#`r_U*YSDJNh2ATn}hjzhepKO%@)FA)K-SW#2A>m@*~ zbVC-!CV@;dSgW`2dgSjrTk*uoCP3ZeXmEJrjx*`@kPfVkTm{j|)EQ7>r+*S6Ym=Xb zX|KN(8T7l0gE(JcJvt3l8OpHu$LQL3)**PkKDmG4NDGfo>m~As`QAmGq@6Y1E{luU zBdd{-_4!RYqY^RFW4k2zE=!q0~cC2@PzD(RTK62E*CjqW7c?` zQug#=A`8MPeXMepj=X#UO10CC0T~UT_UOuFv8Of3jevz->vWu#nlycLA5q}=t%lh% zS3FL1yiWUj{2;dzkS=|zsk%*75JYNpeDA3bHI*ENsQ>zvZ8k!3+dn83EieDPf6O*Q zE9A2Ck4=NU_Moo7YYOeo%klL_$CnRuMHhwh|cbwPHv z8)t>%A1pCXpd0gU=ao0?Sx?}dS2nf|T45eu3o;Js(o&rQw;F*%!xHTb!!$qkg!FJ%+C7b{59|1LggOF#6EaMc0wl*kk}?igA;DZ2-4D94d@LShyx00G*B z$6Kj^V`1>zXf@ZaAMCJ)jx}h4$ySr6)J1ts$tp4`9`6~I?q*NZ4?w_xaWddnS(O{4ta6aLA|2cSgBIk0@zZUF49ukbiteu2TU+@r1(j zV45~Xv8Y)w5X|mAb$1`qMj|s7U|zy(l@5Z+w|=3%EyzhMrSCzPP%Fb4^iVqTfOVO@_a=$Rhr31ThNvCVhqS=?%__TT7KtGF#QK^e-Lu z1Y>qWrYt*C%EUn5L^kqOU5w|rh>l_eTgJngTK65h)U$m{A=OwwUn(57iNlsX3OLob zjNQ6d7_Ysv=Je)6Na-;6P{fdfa7$Tr*0o3mib(oeF#Dk#VK`|5}s#Rn5k+>#G zbO}2OXNN5u`QI3O$2d!ZMBBIQF59+kcG* zvNI!gL}bLy{ULw3R;)kV+jYo-(@J;$`CI`M8rBlzj$>L1|8#`K3!4caZewtf6=u%) zVLaHg`$oEYZ~s|6C-~s)#b>o}ACqy6H(pka{d+(*dI|Q1gwr_WbGM~uD(A>r^ydtd zar>x6a!Qi48~=x9;5o6E=Kjt!ZX#MK zwWNr*gJHNV+ynHcWU%XC+FlEIi@v7Ft@ON^kV^3k^c%L?iK#-CyGzV^(3B%?xi`HL z?X69a<_6;;|K*f}=m|ERE_M$c)Uc?RX}FfAl&sY>~NwJIR5*k zdzTej+qS`d@3*@M+1n0xOZo zyRK3Q&9(kG+#^7~p}zC=V9qTP$4XK>ZfW{*FuC4W2$i!)EXm*mv$ft-y4BWMLics6 z8Gu6hYg$=4G1WBNOaw!YwaG8@UtAZU@@*x!`Z7qb6py@BHH4ZoVq8FwDGzKiStYzx zOR^A>Zog?FKUZ@SKWIwtZ4~nfFDy^Twj1t56VnA0t?7Gjj^LV=@9!p=ou_SovFfk= z04X#Nz|1=6%)iVP4zWl3@smTIwsvI@Y(kCMP!ZyL$n4 zGK2OVkiSCSFV>`#gKrIwVgr1AdZXZg;683atu0?}H-Tr;devrmcn1 zLG{W>L^5cuDa5NTH$J7QU#oo-j2o`!n0vKZv9LdpP_35pNxC-^vQD9>cIzJ(gw6$G zE2*V6tm_jY28x?`*#?*IsFbxxCiewJ#fXU3`&aDlg2lk? zFPDAXiW<*lOWgx*343Avj+XmG1e z`%I08E_`tYhxdQ>E3H_`!5t55T`SX;ek%5#zdxOiy~##vMFq&rLKRBrf#yUqk%2(P zpSB;13C>7qLQOE$6ME1j>?bJZ1h~i_6Wbni6egT73V%ktqS{}~afq_ns1vjMTa^hI zNB1gO)Oo!!nn?EQSJsIdCgW>QB3=ZmmTbOmJD9uqDB2+P*}HvlMe?L9KaQwto{3Jv zl-UZ2&K@XIyz#n@+(2G%HpR^=aSc*i$*H_!W3t**#ZMe8p};4*H~@BqKcM6lj_>1s zMLqSZ7?Fpm24vllOoM|?uL0LBm9aWVG>A(cd;zf}7Ww}V_OZW!`2UK={r|F$DanXR zYAAi%#{|{BZ6P97`lgQf%-<)rHcoEG~X%7G>qSDbOvVjZv;9E>%SSuIKEp7 z>D!6@!<>cB%Kq&P`6;Y(F9#X(-!cB>Ap8049228cpi`t%qtl=> zGd{eNDIm4or`2yCq1pKSl= z_0RhM)%TzE9RFa{|6?=;#(&K1pN;;#1KU3uvHo4#|KLmd`+xk8yT$Quck5riBqol3 z^Chv;vwZsx|GO{g+rY^2|HGH01ge(!(NUtP(H`QLhghhnAP{$%QuhNr%G#<>C@wC+ zCJF2WS)hpcC%=Y(Fr+{`*Tdv<_m$U|WA#~<<;uh52hU4K?oqd{4=%8wzB0r-V1@rr zz2KprezyS5+J=%G0Py4lKp+u{*LRt{wRXpNOrSj&$kF};2)AD}{5U^A_3fKA@u_KL z(82-CJbM8R5CIs>-5D_4@!|1dLB>B&!hTKw+xThTMw)4ulEd7_|3E{!WiCOAZkE=m+-v;X2YIi)>&3009#P%Fdsy z2NB_0@n=$QWXE*#c8=cGj|F~&hXLUF=<1416T1sv3}o{t_geQ2g=J}_tE$xg58Gak zw}pk6tzT|!D>lEHj07q^DJjK|xcGQLkoS&n0{t`eJ6$Cp#N&}euP>zq0d_n<+YY+j zz#DYv5uOIbXZ$2fZx7cofxTA9cdT=M_YXNJh+&?=&mExWc@okd;IUFWgPb{NzVE3X`vgw9!<6QS=>tBZw(@# zBgG>CNPIW+(SM||AsYY;1Z4Xnozy7*_UP4zC<8J=N6eF&En2j(|p9t{NwBT8>gLhhA?Ayb4{d_(I2EFgp+Mok6k)rSFK zC!9m(TcIQcg?H|ah8S_r%HGp$>ccf-mT~VP_p^Loc}bnjm$M~L+xr88_zV720d3tu zt8o01X$fTNval4*O5X#e;ab-q5lv&YnQhN$lVT>`(4`q~o|>vrGu)xU-XeP5tPE$d2Y%@&iO)1@Jh5g$dzI zaKeXS9lMuj!UAHby7o1*U=L*uNAHPS&JZ;nBdJKQTqkyRt)ddlkp?!$sD2g}m-Lae1tUqgp;-=a3= zc2z}PA7>e+y{r~7bmSOlu-Jcjj#YiBB)hmOD)iIv41Eo!rgp*BzZ=lXdbJjPTsgw9 zhWuVxJXbNBPMX(N94;DUG8IR=w3TrVuk!EiPOrx@2#%V|XDv zzR?N)Q(B6$7`B3T(i641YNB{vXKO#z=%B+WM%AuK$-jSMgXsr(KdsZ=b{7KP3pqB54sI>Mpoa0qs+5g6kJuo&G9tay2` zbvu0St15$Ua8}@&SIbh{agxQI+Pw8t=!X(+OE72S+Xj}O6omw*T-p4=g=rl8DKQ`v zfyR?HTza`D**tDSS<&E}F?XQ+{1$CTzQIOYWn!LMysf*2y5+0=DIGtaI&o8E0*u97 z+XZDt%kP|l`K$3)V6 zFbd+%e;BckYe}~AH!sYO>|aPPNmCFZuaBLyqSq8HD9E&_AH(wvj)Caz7|&5vPgWz6 zcZFAgJCwI6gc23SStOSOPJbVhl|r6C+QRZgzuJ_Cx<@!tmhJs`$Y8et+W4(|AJH%(P*d0=7yhQ2hhcMX*Lu|948cj)nBM6H zBE-`LA;M)PdTCYxZxg>I>h^v=>{iQ+$I^C+vug0Z4=62%??rW5n5nHxK51)*>Xa+l z;?`g-7^VL7i24K@rt!3K$sbSUIO?8}ci^8xPY;MCZ4_EoCXyRNs(T~9iatU+0ZHl* z3{2)b)Mwk_nORpr1lJKW&+fqpP#&N6``7{S)&G4oo$S5EbFenLIri# zkjVv?ym*dUPdcBTe64XMTp+g6;zVtgDiXxIiVWMPJZ7WB5SgiZYi#OvXXdA8ay+<@ zyS}Fo4lJJ*izd;OO}wlU%jqOM3?sx^%0(N85mSU4{J~fZ^+s zHhp}b^h6{VeS^fvpGWv!52koLBQmc<5Q-BgLRJyNVC)T zG<4wmo8=y0(nE1&!_NSmMfi4y_}!+20cuuX37l64!BqD0KHj!<8)q6autmpZ$fuk0 zyHG6+rnB23Ua1iNI=1Up<7UH1K*b3JnU=|3Ow(-kJES1jYb!OUW=_h(!b+6vO_j?X zz1AE=_P_ncG$VVNWRnLRF5Htj-JSi&VZtbmGZ)KU6N^q3_cX{8Lp59*jjkajPR&xNL;*U;i;T`RNKIYA;WnWXb`~)i(lU4l zVzPg7JdCknVL52Qm9`fiQBnzw(TQii3=8`RK&qJuIwrVuc1W@z$E{&EsfsycD;*M{ z#}rf7<62|fBhV5#Jw_1Tp_4v(a1Wim>5v0)-7kuqgni|CwFdT4vrRd%4m&sfB!cFh z!|h}uQS+)9)2>?(BkX-r35iQUgA4tgPJUQk-WKE$SlX@}68nl0Cu-C__c94NG0a5T_5kYI3)+OT>n^ zE2@RZJH2Pm(KZDf$2>T9kGWxan387jVxRr}!y)`fyZdRNlX6)Amkz^{wRauOYi~b~k>Vu<2ZKYEqf@-eS9&k|p@Yd7p^7Ja zslLzMI>p+5HZ)#OTJE=NgoD{5j9!ZInMdcaO?D&gOWr`E5O59>`Ss%Nv3l!WUV|-b zVXJ)--Jv7)vOAcy()nPLune$~xjYDFvS>wXVYJ!C&b9k^xNs^A230RPo@91hNp}gN zkAnm8xR^t3^G0);wTE33@XKN5v-SrnMsxKAu!>6lOs+%~Q#2GYETf5GSb#hJWp=Fe zbT=(C276J5&t0brZiZ}l?1d_Z1_hi(Efbg3Mayq^bpQrSi)t0}!-AV9ijOiaZ)mdX-RaMiug)Ny92uCO*VsBEou^h!A@rGl8{rclR8luF9FIs$6F@F^2<(-sqqg)!K#*suBTFhosXmm3g`uKlSzo2fG zE;x?kXw?LVH4Yg$Wx9>VF8li`ZQx$dzGSNR?2dB?vd!Z}buJ@`VA@P};=6bb{>sE%&6%Tf5Q4{zpj+ zjl2UJ8)HOkK@_vGkh}VW)AY<3;>h({VEy2(npCx2{WtHhrn%E{rR=6a{!|XfNr%-^ zP%3!3bI7$KpG2jzk%KeI33EQ2p^^>583rDqPk`PtscH~gr!!N+0g3Z28e?GBq_yT}k2=os z+rvP~0#2HSvvIeogFt|s&bHh5c!Xz%kJ+_5L18#liW5s$1hbG&8_{bJf(8%p6G+ohaB5V+-fdGh}4 z{<$(#IP>%jFjM(~prp@>S`6cUS`;^JMJ07mOP6&ilCU~r3tM3^RhH^wPmQ|q?Kk?|PUd#0GZ3(k%kEllh zTM8k!%#IyN1RaxVQ*O_Lh+k6U!2@2b;EcfAcRm)FSzKmtPE<#2zmML@-?!;qZ)^H{ zvk32YC;m~oV`*pq`t9?}-h0Pu6h>%iQIy#0dZJo0rQx*(ql?&K$KYqmZ6{NPNzyeJ z?rNCl8#n{-0_C3+-4FXkZ0Loh0sPv>qV%*78yc>g7OwK6Cbq{D;IMv;BuJwi3e$bc z`uuJmJrl{4-5)=!jo$r*r*NQ@mg&T1Qe<5AVJjTu@Roy5yV8jqi#bkNSM(=!c0Jt9 zok#hH#KlFSVDYkE4vzGlNX8+?OT92$C5pfIIQ7%DYMa?_Rgkwf!^r;5VG<;7Y! zjD3irsmZ136&`BB)f`W&H!tY;BxF^VLMv6q_+lc0RC9$+uJ}}%PZCRdOj*Y@6WYzJ zU|JV`8rS>4XYJq+Z6lJthhzB)?$h9o?|lHVrOiv;mIK|xky0po@--2c_{mxAabA5E z&N_qrY(+|9+ap5JR7K~xlsGA+itOGHew=VcC+YT65Mi#vqhaIbL1(^0zKDHvoopwL z@2jyBQSXL**%HSFK+w$_CwJHB0)rVIF6NTFcc03nis$@la3^ksYCQTL&_Y<5-10FC zYF}~nqo5OqWmOaBEcRpv$x9~p%ll5YMOOI2n@eQT*#-fHSAW8F6kK*dtB`8sx*wz# z+ub)>DCSO&OE#0YSY{?f{ap^7ajD{kwo=aelFk_Dr&Z6x>r3E@Fhp8KRk(DHhESCf zu_JFR7rk%1o9GgL%{WA!COzCnUd)-cOmLQhm$51dOIM^Cc4GHFfLy{HBen)?w#_2? zQ#_ZYaj3AW?g`#?{~0Q*CxhxPYjsfhbXtE&UEWv1p3x7u>h7+p2WHCV}y2Q(%cCdV*;@#^g z?d}pKtryPn&DB8v4Bg6DOCnE~aeaTD+u#RSTA)(j4$*r7Pr)O%G%IC6%v zj0RI~qYXkQzlB)NZI{%wuT;YLX)j5@&o~%WdnR%R&8*^{$#Iaa{>d zu5l+6Dp*t>*N0+==tA0?*i1-w9n*kVsC!T1Raf z3R9|&8H|!lm86QprA_69GArG!$UpnEHaIEGrW)soT^VbWEbPe0xh<@P{AqvND2+pr z*`4G-hXCpv6XUpcWcvR;DK-3fgh`p4gzfOri(eA$TBfdg4BTK-e|y}sCB>AN(^@r% z6_0iMy(MW*{?LnurhNWH_44|P_(33=A}f_0kp?skqBg2+u9%KQkY)I09NF)Vi?#9Q z!*gpykIUHo<14${QR8%JkU+sq&@1|FP6XN&0nhQi6kdA;JQ_4NO&S#SP6FzC;~yd| zi0Q&nCB4ru<*-*IhZLCVa9LZ|wqw=6tj~IW>9rp1`HShib4+Ndw3WK~B!db3k=s z5T->VrP5<{=^>j*3Gr4KacoJaUQH-50@h1H!ZHdKUY2Lhh6_^+`K2v_`$`pP1-#S> z8NNzO;Jj~ZxSbNrXiMrSeb`AN{wfvK`D#c=WSEO&_&r$6b5LK}aUO#0@mr$8P(l;=roQf9*k8#+qs2swjh4x@zV0_t%C>fJwF z-GPqosPFl?PL~OY1NI%2=9g5Wu5>uWUNWZ|WVB4&$OLS6*;pewJ!})E?mGo#`-tr% z;(}Hl#R+$%Pg4#`_5fZgT|I{GmK!A+n#6xhC@mC2d0URJr4ML5?fvd}PusPW)tVII zoOyQMn4n%#AWfpf>fvE%vSk~L?EKltf}GjNI$g6ij9rZ5y6<2cd|=NG{IaGqYCjf3 zUz5`m8ohz9_OecpnnM(d4uPRU7uQ=qz`@*YrKDw@>XtLoEZ=Ue%gF0+f7|D4`V_X!fYWrc7(rLWS z8?IdprLy)=7~6p&AmAeu;&!%i(qn^I zhQ%+?vhbX$|1LCt%bov|>iSm#b}+YdvUT{Ujx3{ZZH!N+EGsQ6Bl4FKtp1%i@IML7 zj2!qh94zeLDkn4Rw~os8zlCNtmT#=}d@0uw)GyDG^&D8Zf%fWKvL2f>pnUPuSM|MKOJU;#j z05A-L5X=^k0?_=Ad3+p1M4$j>G07HYh54KOqpYW_yU#C;ofea-^zTQs^SAYtu4Vc; zb2CQ?&E6^eTRZfC#87Brs3hg3Wferg0Ddnme0Vxkq(oR`eejown4uzQdxwyI{erKs zIOhOAgs0|Gy+Q9hN^CGCmpb6vYe07pVfUb)0{HlJ5X85t_?zO$&&cOcO#l@RfXTb` zVN9rr)SG<+kQT<#tygy|L~%=5KSqfN2?uYuaLBFU>;p0a_4$?Q`!NlCcjmCIz!yU@ zg$N*GeUtT2T14=%f3~%4ZEm)H^I)~?$fzJ$Ve_z%^?xh|unT2r5uoy`aqosikLb~nXlvNc0DY^RfenP0c5cvT= zAMFCTx4L~Q{ta{p&a2%S({pre?E*$W1PoROq{(-I&uj05LhHxr0|XhM_5lsJ$l85+ z(Nm>ggtc>1z0YrviqM76Pn`<7wr ze7bfN%a8`&KR0<=zp$%mU@pP#UZK?m^-)uL%+y-h?f60kaJ2CyWWS=?*z`ZF8v^kC zfbikPo_(<4Mezr>HZ$H-fpOr#M{UVw=TU-Hw*ARyqA)c`<@4gl|gLqP`k@qSg`;KpKL8g+KA_eLZ{;>^~GSe)(4az`EYSS^WLv5dxt8mC}PC24Lj# zHFW2z6R<<^#dq;laoaQg)w3hEJv4pUlKT+r_ca379J=oQj$vP8iZ=LRQ`UdQ2J*O* z?-9p`s)1qv=v?<@TZ0JX)k8E-U+J0cczgY+AH+E!v_*i5DHqiCfG7BBiTL#6JdZvM zY!l=4Y`#qv(EoG7wa4|a`3WuZ?xWME1OLhL;i|-e-m!J4=Hm|vJV-!xRxhsF)1Mwu zAbz@>H{m9~)~{u@xJ+m;(alnTE67&>nq3*So)XG$YIDkm@oV(YON3{>up^zw&A1){ zy0{I*S2#MnxQ$ahIe^g**&6z|jZ526U?7KqPrxgxfiJ)p|4o@MzW{!lLB7{*w#WA$ zU&33PLt`hO7SA-ZZ;mhD0S}@0@UCGT%lE{aTGXQ@oMkVa3K`?kj^1L}7oxXqymUu$ zIgnrlk~WJ@94cHy-iK?RFDEj%?ns%k7K|}R>ClQJI+iSrO}Ou+S&g@uDvc(#WLGlr z!+$!b%TCB{umILP!Wmy% zqZU`jDMTJ$R+|xEPI)*jgUXDm*Q=Zt0;}$z2a}W+&+{SKcJ)R$SK_OkUY?~BofnzM zLddyzH~I8FV+xRyEem}l;dKeR(t=-cR?a$;C67)>`Kwus6jbhK3NAY9ORkHAD<&QO zD1NjS+v6Jlsi=p~;h3GxIhR<6vnuC#hkb7b#JogFy~Y+~#;Msf{|fhWBL{ zNe;l9AsKIA0H{c(R$t8UHoQB*t3uegmEclI*|TW7acDbrG3~5F0yB*FxDc+ z<;=U(i=tmZ$o9D?&(IGZ_3X2x`nQ?JKYs$2-+*`RX~fECyk2yeU>vz(W1i{O1(;%M zsK@p2{&7+RB|H)-0;@$tBj9su%DB!;NMdFZKfNxI=Jda>9Oze7kj`-{f(kzTvv^S0 zVBrdHC|gC9!AozLzT%2rSncl<(|Z`NPo{reI&0C*Jd3Pe#+N|hoj}WL28#r+LMs?;<JI-be&l}E zxR#<*;zdh%@AHe$I5WSyMe_5zAiT%5Aw;tEv!7KIuh_RQlAut0sB%g{z>1w4JY7 z4Lbps*oQl_;<7egxv4E~Dm>CFR<_f5rU4FWMUP4>11t3rIE|@tUEy3h zb9ACh>a?ukd@J<4(H~yWK^l~na=nUCTB?u}Nr`6Mi%~}Lz1^AK``MjFwT~z=SMV&` z*Yo3OLbK`USkfA-Sa&V77hq3yt>iy(JptR5eBy;K3NxwUTlO?4k!y`$Yy)Q11ZIOQ zh1Ig4pZxf?>*u=#MSTjM`pQEk582qC!{f+3DGxA3rjjf@8l!N zC~N>t4TAjZCaytkiqu*%4l>Su5=)5P){av}5eeJ0Bjw1Fw~XP+>VS54l;uD6^T-hu zIKsh=%!4kOSFq@JzQU)N{etRCslwEmRSlkTaIn4-y(6?}cv>oOC(bg2(yG+QupK!`0_PqA zVY{OgyzGtQ95Kxzy>P)5sYak;o-Y|Vku&O_sKntZ%M0ywmc@=*BFp6zm~H}tJsN0 z^)O>MWo=i5W6a{&E9{Gkgo#;fTw`Q|!Nl}io*d&wc7O94B;oM^YB@y9;c%Tu7K31+{MPCo_|S!!>;Dgo6r9!q(1w|DK7 zJ%hdNa)%{Vh;mFOIkWLj^{w1Vap-(}I-v}Q&U1{x$TDkWIf?P~WTbF0D;o>%`$=y9 z@N=ha?%TP)41?{{&#ybQrabspKsFMr4uTrzSH%lvA^o$#q|}HLW9VYF^dIjdmh=b* z{0*2KQG9y@z^(<)d)ek|g%Xdh$;IR7}&7tjn z?QA#&({3U#w@f~fZBV6`!N$!({^KJTyfMU7Vin2M8ZBs*)=SPy__8>VI(fOS0o$@c+LiR z;q#d|rw-+!V&@ZgBa*C#!i##~S~MayR-lnl{n8**Wd5B#6}#uNA~PZj?w5!AG~Vj*!)qXll=Eh}>vLgw`tB zqQ;lI?L>645^Qd{=ME2jIM6qklAIoy1()Cl?rq0V9ru}YNCL4s3~0NDNx+56{JSm0 z40c*vidg$+z3K_gA}M1coI(#-Y1~6swNI`=G^G~XHh7f~6`nph#QTw;-RazFw$moH zv^qQTzx3v0-r>DC`XJ+V^O@1Bme_Zd&_mmuRQ z?Iyoe%v4B@LNEXQ8brig2TUz^ca~PrC1cM0J2&`P{1LXrt{V)N z9`MvfvD0pV#RhnuOS%P%Y?jiohT@P=o04>+TSdocUt<(}!d(pzwIPxHbCQ)|+~ZeQ zBAoS)LhP8P;zMt*(jF#^@AXB4HU0VdO(uuVy2WN*#sL|3H&8g# zErWMyYFrEE_lw4ju~?*EL=g^wHRXkGAjM3pnpv$A5^s;vteazKqy%a$8WqD6C1=&d zG)|tB!!d!;YF9hX+%;qBk5wugREhgvZo6skQgtqi)8$*Dmtj;@GrqPhix2ce zq~_(K1tTNUDerMt^B#oHlc#qRs=teIfL32zM&nzfZ`hD0a8HkD7q(Z2?rW|fis~U> zXHNo>Fu05oOo%HB%nW;iIfv30FM^Wne%Z6umQ43>++1Bml8%jH-t!$Pm9p63cfzYz zQ(wpT@^*?V!kRW1OW-~(IhT#zJp0q50}Pj8$kBBps4j!K_t!WVUVRCt@W9q=nG%p=r_e zs+nb~v{5`E-=&%i+_Om<&{)5ijxZz%z)BBQEVeert#ijZT$mh(Bq46skyW#-6yLvi z44IbCHz#uIA2pamuU`PPgXv(7=OQbkc(LLEiHS}vO(jdh9%(}Cq1zhXGt1Dg^=-VmD+pL zW?6m-?ej)xj%{$^;^Wy1N6@mU^c^9^m_50V{ify@H%q#y{9e9D;{#{P^_QL-LJf=lk1luQvcE^%1(s`~lRqjSFKWRLZ`eg2d%9|!8iL`+7h z$@1aH;db9a604>bZ!t*Q&nmqL+J)IAkq!nzy;ZR2DW1^TC6p`7_vuM2(N_ucg%x{X zstEv@__2(>18GM}>X3JvQSZ(yl;ej=Rxo9O0?Y<>f;S>Nte(E8IU9M!)bY z(bf5S#q%=IB5Ep`R>^yAwZaI&tqD)EoK!N)qUL)7Zwu>5y~b(d^f1o^;SD8Wy1i-_ z)C*N_Cq1#F|9n^>o8D_HX1Ypm_Fo$My(o)?oC7k;TVoFs-O&G}ptisx*`6a*3CWk^ zYU5MlL+;@7CcZbtPBo)Ve~5MaB{RouU!!!W^eW1!fG4x8olHtxF%2+velQ_;LnnIw za^_cQ<`8&nW(QV5?k6obi$Q#}F9W!@f}|nf&j+k*;HrnP=SqTxP)f-K7!1DrYNw3J zQDQ$>j&RE2=%(R_P}JQ|M@{e@@xtPm!mfbeqI+Gm6sB1m?`}}Ut;4dEo1LT1g6b0n zz?%AcP=>cJ?lnaB+m#(BS?Q00Z%Uq%^488&l1R1dyyKc(=f}@>5^il~qOO)Gk5<@D zy1kb7sLeo{hxy+ZP4TQ|LiRAo<^iICjS0SM8a!H|XqE*Mb@cLOWNa*k9l1ar>Q^by zvxrjz+!JN!H90D&g6kwlKirWVL^Qvj8v9kR?{VzY`nDWYB~gUn-SE{G7XYpP>00?;mn8Q+kna6R`~Uj{C=1gL1sNu7j=$w z>bp6(4^L`YfJAi`-Jn(W$a}vJ+SGK(^ArW>-=HdXI(cotZe`@PZ&0_kA}|VEbS``E z7~XFL1=YpXdDXi_)iR`+kcAlM(X!Dc$YYipNPn}G($OM2319Ev2dNQ0|c5@W=baL#d{JFAV={xyTh$o7XvqXnGFm#Z4^~31d zN0RM=bubA%72s#Fos9d=S;A?+s+-g8t%M9z_+V5liN=6)I&h3jcr@4maD96|q)muVVj7X7k z2TY+Y`4*bwp*@TO1Xu&L3pD6W>p)P;#Ft)u1B#uH5p7nex%9s73RJp#B= zIQ`bCecFtX2KQYY;vD`NyvzrL4lZpGalD||ovpFpX!dF_6Kr*MGkt5mULyQ@()G$m ze)rac|O-sO}-2fNb#T`3*lGDU#@LTBCm@dOP>0Xq%N^YtEk=cPT;Ia z3m!GCDQd94#N9S$(q6>Ro!fRSkt_paWwwUyQ%pcnN1H*AV>=a9d2O6e>D!u0GrFo> zIf*k>wKz02pe13QQ^YRqt;DuV%ZrElG>!eY!?<|7m~LfIt+h3UONc-lME7dB@MpI6 z{mY^>-c2GjRx-(yX4Em|PD*&wF-y+@6LFJjk+g2Riy(O7&1w7I36w}@EX+roIk?6T zaTpi}ny-=B-rkB7g8&tZ;4HP|9>P|j1Ft-HC=MO$JAS}6UgI(%xJ3sacz4(53a`0m ziJZ!^tFp;!f;_$o*7MyL) zog!vx^x#5@FT(1u!>nLN{4-}A48odd+Z&&yf%Sr1H||o29QO?K!7Q-^l6z{bJbcv1 zbYZh~k+E2+ZG6UMl5Ts9Hc7Q=ogL(ojObp**eDkx=#U2$e#hb^T&4)tt!;tfk*~(2 zyIs?BL$93a3XQVB?6e@^no13GmQ{|>DO7x9C8gJv zR2|upQ7HHkTe^zjj&Q(2qrT;TZy&PlK(Np*qj#dEW81T6Cueq$6Ay ztz1(}5{GPX4CG@&8w=K3x1rVm*t>2h-;Bf!biR^&?5r({U&|^y?W6*C7f_P9J4@3V zYEakg@OuT&B#%PCt8)-M<+W-3LOA(q$)1Fk8$7EaPsVplZ0oFFdgVVm*`z2wX)WfV zP^m2clo`Wr|ACjlVbM=QQ-=VSQwA>3YVQp`YS&^Gb8(&W0Ibcm1ad%#JccOtzr4#d zt}E4D9>cE3#NwM-;u*n!^v!xxhvX8Bnc4w?1Ca!X%fLJ53&Ied0ik^QXIkbX#s}GIbFnCanTQXF%_lM8*NKU z(MhPNl+92MqfB;KzOb?z$2F_?Ykc}}rntl$=CGgJxW8_T|Zo-(77co=5GLGGLk3YnLjh7_`r*edh| z%yRf}Ha(};+0BMcMGUEPp)2btYHkYu^%0=AD{urJDPeAcB?9qk-KkA%KHg z{Ji%J;bB*?aahtBWh1<=5bWl($XZ+O$P#UNz+4|}bYfu-WM?4GM~0u7SNoH#mZ8`m z-h>sw7Ad1rVou=Du$XLS?<5I$^9NK?yuu%kjAysahYuKDV7k-Df=5i-*(pKU4HIxd z88O{?u1XdwXw+x=Gno_kPizW?BVA#R0K5bQWNkkrpMBp) z#F0}3^{EUj?%9MhYFADfd*jT=r}IzJlOj=7c}c1*|5THV_v6E`uEilMMmG=K2#A$r z8ug-T#my%%l5;0Ufqo%C&;1JX0{gDwFtP;>ee_9>o9hT4$x!Q*ZON7P6hFFEMyj*J zYPR*4TDNiPO?;{6fyzSDvD+2##5?4zjR-Pks5m#_n5yX@(QzU< zV2h(DRiOr#!~kks>Ttl2V~eh#qve1Xl;kDE4c@D0gh7u@OM z7HpLHVN(Og0+fI`)ar9OOBDrK#9lQ9#YK097&ws!FX>y8eS%Yh$ybYWU15FCre(Rv zi3J{Emxr|IsXW}k1uxGrc$3xiwCNagtLs?Q+)B4?AoVJ!;_gT#qL0!HT-l_PGg#pN zP-X>pmq}mh{&u97n0EtEktHd+p=%s#N|^Z^JQAzK$VsHl2oKwKDYvb;>Ep<(q-#v0ZOs(6F|tfj zQ5Uh-J_p+^qrh>rv#QhMndRUau6tSTaBfXqt0z8w1YTJ$Q8rAp0hzNxu@V>`X*SHE zHH;sVnQF@O@Vt5~$Qs0|MBnOrO7jpjnC8s<{NbOH-TiVrd~Ttefi~1QNFaU@{JD8j zHWaw>P?D*Yzj4)!tIDR4Ap7mGG)1L#3fn9RvgeSsn0sUWSy$xr z|4{dhftfX1y0Pt!ZQHhO+qT`YZKvZ-$5zMg*iMHX8-3sO_nmuZ&N(x8{?4DuO6}UU zs`f6tYuB@$b+CxqZNpcRwBFE{p>!%IoXAr5E zA3*Q;wR6>Xvi(HKRO$;xFE!Ml!$+IwXQnnDe((GFf^O@ zis_eZOIQcDDJ2rd5|}}83#DY09%)4_iC@1U{OLr?DvQ$eWuLP|qpPmF8@dN?tt|T+ z>)9rQMv(zL>~SMjuLR^G%8Q)y zy@dB_Mxm0^?_P9l?No;xKl?snwv*5cJ&%c`iU@}vCBOPJFsi(`vIf_tSyd0lRM^Bu z*wFoK46K|hq+_<#nav{}#7sIf4ZR_=ZDm>_q?Zrae}!)!KPgne<31V3y0k~OQ^bbx%+QWFdy+={*`;+-=kpU6xEg0|Da%0r2Y#S48XztFTMo;69B-kpYi{} zVA%hOZ{g$L{|*KN@Sy(-2Ez#`_+Jn%h%gv207B_l0Rrh*G1xNL1H$DvGq^H%|3|t7 zwh!#de*&ZY`v67%9WdsfJO2NWF&}>Z{}&na5q0SQLSxt%0n`ToQUyTD3E&@K{X1o5 zWdq2}93R98f8aC!WeSLH0$@#GWn%|0B(QR^eDEZ&G6T2~IJiF868^fElamdQ&&0?G z;BNSn{a5uY%xr*L|1JWkfbBoY92{JLYM24HvJtWX?&A16{j2=n_55`eppgCVlK*{U z|0h@f()hRDKP~)A7b`#)fb!u_$__}GKgc)$tpcQk?10t-@Kk`XMC?o)fKqInoPVx- zl;U9icr?tM9DsX2=ps0nKI&m(XZ)ax0B|}0a{iRyVEgDVJK%AC5Jmiv+1WlGKL?-$ zfV=`w6XQose`)37_{jOcE%?yJ{81P4AC`!}`uU&aKTqnfUj6l&*jPSZ`d=^ZKgujj z|9EYG<^HFk0B8r`o%|UboB+BEKtKM}^7nK7Oa7CxurUEz1K{N#Wa0Rb{?-5(P=EpQ zr#GyBKF?1U^IaJxTcI0;$)X#Xg~Mac4p4Fw=GGXgsG zcNsv1tp8BU3>X^!(96sQc-8+X1E4JVhh6~qj_ohK{QQJw_NIUZ4TkMs;|CG4aj^k3 zS=j<2ZUO$<0wQmTnwdD5ni2Bz!??HtLUGx_c&-krjmKp(qHWxu>nDMOfs)T0Ncvf( zh^-m1M$2P@*$3;`s>rg+^>jm+d?wGdl890j>&JN5ahc*H2W}U`@^kV3Vo~6a6{d9d zSt$aF=!+@k?HrS#`W>|(4~5_bo(eLdLn?}ZWPKDjM_YsMXXvq4T4>Z12en%0pQ$&4 zU8ryvBhf`rZ3H})l*OHz1&(3salyL2Vox!Tqdvqtx@uyU;qmQRi)L z;asE20feB!l;t%DP)Ro1K~YwPcb)j(NCC2Zw~8$^kK0c`;f*vt`KR zC+cNrP+_gPtWMLY4VegnTzX(r3;lv;jg72{j#YJfy_h3j%2t2OvRV*VJ>Y*Hr+(Q1 zaAuV)W2duNv3?p^D$w;6VyK0jZiL;w;6?(E-9Cjy?h=Pm_g#|CQR4PEqXZ(qOt#0) zHc?}yTH|B*94}^MN3<4xe{JSrEuvuV^8+@p3n%{~-Q(e2_;Sn^hbc8}c(1*vs2}ZD z6n>fe9OO^J-_d+~G|LUgeaXgaECcNz>^i^BI`>!NNibfV@0GKF%xyTFb?eGGFL24yoBK%h7iGZ#W$UKjw9P|?}JS{@e!mSIpB@Ld6v@!U_MH>VPZ}2U`bc6-OfzGeBj4 z`$bd;br=+lTmiGeo)EAXyIYx zyAC^G-DLc;%{#mPxxn z0ZT1l#{Ylk>A8-M2TlvJ|IfN*iMA%fb%yx*ALQ<5xH{_7Rti~=VkIU`#K#e?$vN*& z{vqSe9^kc-5{HJhue>`GGE1+3Q0|OI!X%+a z^6WPVK~yHTE_}0_jPz!yC^&iwo9qtntX>Pum`5;poLlR!oLp(LoEPZUJVUWU1azap zu?yI^p$QXh*rlvhx55)OmcjFhRD9NPQ7!nTagzoP$x4<(O$o90d7oG_TF`djZg|Iv zY3G{7scPC$*l~Z)NLadVPabq8%1UTIfk&DEbv{`uQ{Nme18ZU59{67G`#N81G(OO3 zR%PFCe9_U*SD@I!>w0}Ah|e-9Rdcy@t=Bf7rMIZ3%_ez2dO3VuDRI3_zsXa4MC|q% z{ob`aVwwe%S+X%ATGzo`5hN?kAz`da9vL~4#}Zw!D#AS2`oqLh$|Bj6q1$s_atk*% zFNZH6^iZN42~L25p@-K`%kgyQOY`n>Wj;zbQ*dJ)ubxK!bLG-%9&C(Dkduvh6UE+m zN{NZ7bvVsoXpN$Dm5w_w5->UUEJ6TiddUtm)KE<{7LFYDrgDnOjA4?7jd@D7l5}W~LxvBJ~B}S(rYbMH`Vus>0=_I|}QTnvP`#tX@;%nr< zsmTC{IQ~|5w=Yk2cTe6%%mm?(DZCJvo7^-Qn&=EOlAxzDKN8#zMo^Ch2BjKoKwv4P zl`q?j$oDP4#?_UeAQgStK!si_mY#%zaUu{|GhOuL76DtBaHTL%2j zPuO-z*T}v3vQLdjK883x04@%CP2t3oqy6{2xx0O~%J&p-85*&QUEBEvB+BO~GMQ7A zsKGoW#yW3UVn8rwuzeQ^PinkUYmN!=7UT>TP*zogunZW83hYjy1d^4U<#6jpt2oj;;^NCG{6oZ9_GU6#rI@8p^8|2 z_1}V@3`x`-Zv^GIzI1%kx%z=@UDhJ5k&VyMf3LXX-N3pAL+z!+@0S%Qcu8-hFdTfG zuytT)9Y{@%Tqs_?x`(kK0l$g6p-ZcNAxLuZO;-NUTDPqeiez2}D7KgtR9*I=5&r3&AxDq_8m6`H`^*DF+l zsQge&Rw z+4eM<>Lh6rirU<(Q*;7%HxM?)14m2oHZ$rgGDv<*aUwN7-c^!I^ngHvSn?_H-UuJ= z!Hio~Z7`Dc*A}Q;;t(;$41inz`g9R76Vz>BgrBNfP(Q>9b^2}9S7m)=kfl*-wJ0KoyD zO|2c-(L^CG2(?N7`-QpWB?}5OnXBw%Ps1BK?ypb8mfgho@|Z>8(%yF%c~#`sj&)uB?-Ih2=mx>+^YqJ<@s8bYDBJ;ksfK0oD9tP7FX zX4|Z|?`){XQdsyY4WJ6eoy^xN2y$s=c8Ks+1a6ZBN_7D!BMiDy&u(CCULd>_h=Q2Q zd%n%?ah-Aci{{3Ij8tckz_$(oaN28YCr7Ufr{CV+-AOl4PgdgQeGRG5qkej<#EJg6 zm#EKeWSRp6iIc5Q6SDfsEaO2!1B3RBJ-SkB<@q&=@>gvM2Qwl=J#7fetM6VKv3}H-KwC04?qT z(X@m5IR;*=(LYKgK7DN#(wU$frg?qR`VOnp*hAyi!`ND%|JiUil@3~}t1)0A8Z@<) z>enRAYUk)kp&^IisK3x9^3i%>;S1@{MzbYwsNN$o*Bp6S{tNQBec`wwVNkQH1O9+A z&4ES_s-(GzBW+7{wpmh1B&D+%Qe~V7`IW4Fvl>;=JARVfj@J*tN~(Q!S=V zLSbRpiLVo3DaIpr(EKWt5QJhbHYQRdI%4e(*<$f(6f6e!b8t)pVVn7jVv$`z2#MT^-m*j{Q-0vem0 zU9~d#$W@DgmO=t@y&EU=io8`np0}K4l45v$nHoOnU#>~Cu?Dy=vvDb&RYQ6h7E-ILZhLxu6 z0Qzrwdu+;$Y>68FQtc)b47d*xcI=iKsCF|caTl`Eortzo+5Yve(I zImhr)!$Rfao9q2A?)>m~Z14<^TgU(cOe^_x2K_RicPF`omFJ|vLd5d2s-t0)@p;0S z4TZV2hM_F%XxGdbhXSjr3jGqfHm%w_V=lQ=!#4prc7sNy=iMrY*mCOqCHx zu1sO#w5i~qm-$1 zuyZo~4-6Yz8y6goUmgB~{<8K{HYmPZEr$!Fb0zlGQ;l<{kP_}FTO;wB_C9Y9kcOk^ z9%527Ho5Nfc`+oH&?sO+K;M;B>u9vzEUw#<*i-{#Ny|jfbL;H+<*P4K6Pw!wN7TmD zZX(@?K=d6~e6K5>FXKlMwGfvTg-WXn!l9%tDuBza|T6k>UikdW@ZskfS^wuf+b@ICfXDaVE7HC7Z=G%gB|GrtR3NuJlL56ol<) zLRp`6jmtg<(%nX!r7AB^a z4YZP#QKnr(@2XNfh_XR}+?h<&`~V7wo%@kYP`uylYB@fNXsK9|lt@UK8?mI8Ftj8Z zu{?)ZlQXj#$Zw(nECVV6YfM$PjxPm^x(WVFGKAPlemuv&%kUjLIO|Rc;TQ9GGvyHs zfNFK|I#m~LK^NUN7eNZL^5p%!Zm-U+&kpzR&#vkgZtwP=T(8^Cp-p3Drx$=FqPyO% zX)tn(G3yeYsXdDf#jSaqZ(1%)M zL~vZ}*j_0s9qB^C6$pp>bn4oj;YU5Al9kmORLR|i$yX|-=$0^5D?iO3;7-;D+$`u# zkfFV6)w_U3Ulw{U3(vU`UIBf=;zqjwwnC-?8ub(_TNC;iEc>=`HJ4s$rYPCS2xG7p zC4I2S=>D)zgz#f8hZjs3vjXdDx?s7A?(^&VuQI`LH8TpPFxyOFj11vsSt6G*B%KV9 z?I5aOVN|BjrBxx#dj)V!k=~Q?zLdE#z9ZNsfMjI=}f-0<1o0<~KKU-!}X0NI3w^Sw+2Ta;Kge`>7K4J8|as%{85`_t+mVASru`KtA$ zwJwRKUo9aZA3({7_m(!jz|YP~iSrc#h|TqNbKlto+W30fWl8q9c^L&_+^2T|Msc7~ zAQgotDBnO!_mwyvf@{XEUs_&px*u{-sqm0#%ugZUhrN_04pvKlpNGk-#=ft{-E~5` zqWtWcqZj{KLFuPX=EbTiq=LTS!qE{rGGckoM$G4U)52XX1o}(pT4u?sRFNy%VQEU7 zdzB(dQUosPMQ2O@l%v`Bq=s?gboR}C9w#cWOeY2D19hdmEk;DJR3^kHJ9c{N{F{CY z7|_O(J``!TMM{`JTIu#X{3wtg$j#NYPd4gHwkl{@W39bIl|dq+O(O%GA}O}1cdTKX zO+qfzr`i--4}=@J5ANeSom1cl6E_uUW1I;pYn%zCA}%gcNLxWnCuCseHJZrRLe*#1 zgg^_nm}*6-UF*jis+Dc#TQYl3Q0pdJBrn=;9^}6Z{1AE0e4YmH-+-}UG$A>*cQ6ZA>WY7#kBS+wR>DahhoWj3hZ-dUhjWsI zESv&xjf_H7-x89zCnC!#;C&O5t9UOuZ2B6TxKczsH5qMv^i4IvSuVl!ZB3C>8WymC zD#aqxdXLQdKB$S+&iKbV2p5VSECX59MaQqonCeAK-g|^~{>9Coi_BR;uQMZ1r zRJ^jQ*ln>R-B`JAbx5dsiDl2n?-t;fX?Q{j*V8gl^8 zsMqt^+OaPX5rv`v(^4A*{Up;&1Pff{WHYoc5;9*IkgK3?HhTy6*etP?8A>S*pP*xQ z(?x7ArMNm)C(pRXNh#Sve)()3%xQM)1sPh9)TzA&nLR3F6iz@QR&Uj5!+7!yj+f`_Ex?6v`F*xw;8Y<1!<9bes;`$4GtpBp zLqBEiZgS!5?6xJlK@7O5p($$C_oZm)0FKzzX*$|NRTDJb0j;E@ENgS{bY<<~?#y7R z+y+hec)9u0fwxYPmem`#H)2#IX?IFL@8tog!F$(Z5q9DV5tR)WZr2;(tT6FAv2~4=8Q1wtJNGsd87sCzN_|s-1U)Z4Ih*+voNg zrfEtmwv2_fLbNG(Qt$&$hq|*}7?5R6{&; zy>a@msLpQ5mR{!up-={L4e5FKg88EBT%W2l7XyYxtE3tHOa(64uKQXnV&ELT(%_Tn zIJSN7xh)WQ!y7aCM8Y)xaKyM>_wxivkw7jc2iA}DZUJ22s_RB&y=onS7hQTHC$9!C zPiP+=nnNY31=v}yl@i-or%duMtS--QgIyvqX9TSiBWsNEk4-{d#As=4bpfH;JRUz= zJ;GLl>=m5eal0Jne?Do#;?^m)LhJD6t# zjcCM7rXp17Kc(d7j3{d9qA0ez5f@*UlPn**ok6fFl6C8sLpc-18{b>y>X2rRGGCrT zXIIP@N{4(cjnY&|EiPx!FVxb-qnxk9@ABzh=0~geWkt#0@d;X4`{@OHw4t0QCX}C1 zm~JOe+?m&qbX-FYY&-Js5n}nfO+&`sBP<9i?>Ogr)t9Oyw`gVcOm@C(toTayFp6?) zU!2l41Z8I90th(-uD+w$i1{GWVldTc;?jCCT+uNp6Is4n3#M$`y6UblAL7UC9U8=2 zBX}+w$07YQlA#&ht1&p{)z6gTFKg#D<|#(q{P_kOX)$zSJ0XlP`mvSHi02^n_g%5N zG!Lk7g=6oV!D-Z)E!*DpoVwdvcQ5FE#NoT=*aqqNH}ymTtHa-ZdaGCuy6#x`;q!tT zL|YiTyE!HDW1T)hfI#ZR?BW!hlgeTK-hJIW80|cg`p!ov(H<$nL=v*KL_>7+U4FFz z*}Z zc7tewZ<5wjX6F*#$uiPvr|-qOI2CkFSm(?N*6j{#ZxsSm`Ylmen@%`CGa)0jMI18A z1?*DnS;IlGW5mG2M6om*^-5RdKt4f+u?7e|1!R?X73r+?`hM)nu*l1;yiw~vyE zgSvR<6^_ID>iydbO!wmXzNeg`g@U13aWfNgYzy(ACA0I(fpp(h400A`;X*paaiRjZ z1_Qaguy2U17j79Ztr#dlb!1#4Ie0*or8bRf$dvP0d6FE<8m!~wbv=gYelxtIol6vO zt&BcLbD0Mp6_}o8i$P=brI993zgiHu)AXp)gghqOINZ*{=ecO+C5|Hh(2gr4GQaS< z-4oZj8*UP;`(v+MxZ}z5N)ld9EboO}XrXybvXcydgKj|x75@aD{rmmHy_NIb%Z=O1 zVUtCW{2m_Brlak%>$f4t28cEIo(|59M@Z=cQrATNsvZ?-Kbe2pAFuO*K!dTI)2t^GuVP^f zdC{&7=xU&fbAE@h0PXg6^}Y|4{bV{NA;Az}j#QIHRd=jF<>i`O>CxCbwf`Fu7b-mK zUk!Kmf2E4~C&T@ZG5f#rIFb%vq!ZG8*zN#e2jDak0RQ-JP9xbrjwk==G?IlG(EIw+RQ2}waFny+1b;uU_?YpOvl=@hLH&EwM#_ZqLF*{#vN+4ae zeV@jU^xkSHFPqdot*+ckyeLZ^G6;p&hZ*EhuQRzgSpY1E1&j)zOzAU4Gu$)AKvXhS zOnEG^;EM{LBpu|mgD1k{t!RSOn$Nu}5GCX1yjB6&9Q(X!f;QK$_Obsg=52< zw-HJUMq;WGY4!e~Z~@{*&No$U z6}a5{6{_7cx?YBg;292duh~48)LZWvF!V}L$L1niVE#h%B4A|ocVx|hmW3o8t%8ngS7>8 zcen3r+7+GVflnl&-bd8{)~?=$Vt`Kv#4<%%dS9yi(m~l2#7nJ5!*49MdgGI2J0yS)YP1)g_>4sx&>cDGZ&qKLg{?{xhJn52p zN$6z<4JfMO6=G-4A)_VmBNLgHwBpD?8Wh%*aN^$H4e_$yZ&k%nq;_JeU#E-+`9de! z*;k7#E~F5*1f~nrp{P@^!J2|m>HNfFpU+HV?}wpaSX-#xuaT{t+ptMm5JpBxFRuEs zaynZMV}aFjNFZc$z2@pzQ}1KFjD%nAEIGoAeo!e&)JA^N4&KH3+`1Ut-=l(Obw}+3 ze_HJ7n@Bv_@hz%F7mY=^*-4)M@Fw~uCxXy3d0;y%LUOk6W%vruosGx%*SV ze*QIx3X32a0^ygZ(IB6l-ksXVMscgKGC11sHLyW63FAcgkyG_m6-XZ7vQI`W;Tvwo z*#$aG(;}PKV9gE5vQZ_Hg2+oAc+i}1lJ%C(lO zk`5NoKk3)I!XMVcR0Ma?15_Aqg{xH=GsMiPJ`KURTirv!?ysD4;;8Jp!|AC zf;tR|>SWO--K6U_+aELr1e?s+tX1vxM6wHQX*eCVau}fnHOB>EIijj|D7J@~=m7Zz zTmha$p_h5DcIZPTH@=KK6u7MOOnBaI~r>(bsN-RX>QZ zI;Gx0C&AEu8WgLb&{3&mMOKke_lz3CpJU1^)-+Nsk~U|Ru1#gHReQJ%ep(qTSt~(a zHEUS$hy*=c+@3z3ogQsi3i2j&33BSs;6bEf*N`RBdNsVBPcQnqJEtwvn?2sXoxkrV z^%X=9279GY_XaJJ>fI!qy{SN|w5(+cFRsPn6VyUGwx&6Ekf&WsM1N)jiL zS6XxQy75+0$n^cH?PQj`s1fz%7`A)qm+P7TbG_P#8BPT)In8T}Dr&NP?{sa@m7lMt zja-Ak%p$}%RdlB0%d2!C6e%wXc5`To?U+2ZWx~jwWzH9|fEF-zk zdT%4E2qo#Y481Ds@$DLXj@A@i@0Je>ls1@L;$E6{74k}_BXqH3$Ndw6J#ypXSCFkcZ8>{-_KA5E*0h#HFlA?V-5H_Ca%!^lzBcbvQgcx zQ)XWS**g33pULY~ysxfUA2>m80#N(+$;q~B=&%j z)(+kL#y;7pQ*zzDxR~}IEEexjQuV7FIyL2P;}q&_%iKviT^GBCx`9eb6wICclCo{O z0bV03ZnqY^&a7U|0nP4%no((B9JpO~lDw?9av5Q>&*+L9r3m zpe~T0qsWql#9xWYnhaNNxnz^QH@~FCpGZ(x7U2z)xmOtuYf_OX+)-Dcg~3f1w;F~{ z%Gf{93)P|bB+Ied^sPq9U8JwbMT;fIkZnd?yR%u;ETYa4gSeS9#BoAdY{R1!5J6n0 z%om1i=>)h=qbZC?A{_d=1wz@p-4c{ovx%9JOlqu?Lcp5O&0~uJ!b5=9GrjcFd;4pK zvZ35L1hVv7Uls>ZF5T+Rou_qaXtZ7?qH!y|14Tgijy8MdJ-)sb=`v{Pi8y18oDX=- z9u2q;_|prpPnhNO_Z!vV-L?{@Z_uBz>1Mb!u2;8AY$DA`gXspR@)RL3jFI>S4WKFY z$_m-WD2>(fA-_|<2AVL64+0TWrCp`?rFqYPWga)`+#7?`Sj{-etaFD;KyODOB2Dtw zac};CimueLQM15#=eD}MR6%&AX=CjYOCcQf;witrc1kVe>l*>|805_(liYlr@kKwa z;GLjrvj0oYHv6@k#AlminyHuqtThd4iozeY8y@Sp<)@^ote}2kXY4`X&1v4nS5e~M z*M~9fhyceD!<3r-8O7g*s7}vIcuTZT15-nmdgV*yC!^s@GD)A~`NNF=k- zrK)HMyj4Z|h_mJRKC)q`&W4hnBu>v<aUzp^$5wON_eQCt+!MP znVc8*GvIA&;xB$AhYF;vYE}C#Q7v)#MTvN{?5uaoCeHKrWY8c-j;OtC-ibYwhUybuumi zPU>iZoI8(|_>=xUulD>^+!|*IV#D{bsm3Z&zV)b^J5;)SIfyX%=vQ_^a;DGP!o$2Z z8D3aDa#Xkm@efPEsY7~qWlK3umdC0csb0bum9CL*6Jma>IKX3N zCTqXSYN$Ll%XMU@wLBP5erXhPZ*}qG;_0Zsr)QY@I=O(UK)Dau6?u?PRvDdeB+ z!M|Xf{|n)%bO6dyz%lG!CLssQA3urzpHcW99Y+3flFP=<@;@*Nb#+{DTF^frs@*GY zk=y=}!-#Hp98TG?zN50{xaGwoDRhWrgGuY$Z+CA9?&)CaKy7Fmi7a=~@KJ;a2vg@g zkeHjiR-!ld_ua^{?7uUe$YU)zZ>HvY`q_Uvn7d5LCahNu-5ioWMbxFUluxt=A&jrA z9Ue_LlvgqBd1|xq6395_!(#-rW0S;1;SbK{DBU_lH0;T`V5ZoFmaWtX3>om4&85*# z)&1nenH;rcoorw-hSjT$f$*>H^AwuJt;mg|CYk$`=t^rnin5fE?<&WgFjhvPK}$}j zmV?hEO*_|!ZN&yZcc=H8y7^LX=b>2*{yaj8zQc(yI@!MScBvlS)@pWZA`~{3{kw#% z)N_z4v0Y|b*yjy}LXjNu3y{4WZfck>RnF3S7G_~eG^z@*P5GENTIzS^b#=PDU;U~&986x(U@*VX*wdU48upi; zlVmX1nXVH$feu&fo2z6i$qN1y-vlZ#-8ZEcoOea&988dg`Pm_0H~jadTF^H*EGL*T zX+|SI`R7Nrqo}kKT`=-io5L(CleLRfGiBGU2bt)VQs*p_D2(KRnQSpuq(}{CI+Wxn zQu#zx8u=Y9nYZX+qGOYc@a01gn;&jGJ!`$$>uo(}9cv{Wz0zJQq#Fe5;Q73)9{7Cz zO2mYPecZ}l`5OhEYFWP-jfJ`sSDw4Ox~{l~mhAMS%^9-#ixB@B9^p)zfJo9EmNepy zikw`B$-G6N71T)jCE!#Tor1Ub<35ET9c%s)TvQu!?%w&}sbU84#>@(9v}DN-aqeDm zLc}P!aH*XWNxYr^frzW3@6{_3!FMPsKQ+e7O7SR^==Wm0HkNGPk=&Mu?cR&O62=Oa zKwshD@tXMtyIu#Y#0VqVj9Y+u30Qc^95j{wE>-d)R33NI__d}`rj*9o=7@Fn;mKIM z!Fkb!&!OF~Kze^3tJv%GZ?3qVm1D8an9x#rUU)_*>`V4y`|QJ$W40Jue6--0H9Nhw zx2@Q4c5w{qr@YIL7qN76% zl=9go;MB%4NB%7+AsP{l`J53@&)Y!@B`1kdBC1gU=DGnH2{jor5{XaePe&C6R_mBN zlTva-PVsECLP7w`CmI^2C*-V?IE}rY^k^(joD)k&{JYzW;NZva*zT}9>ptNK;c^9- z%Rq|W2P^j5WX?{}?gCOWRKKbN`dpB&E$X4;K|Nm*12mJ;I$Tob)}&K`5c zR*AUh&v|NYaES0;)uR>16X<)3&cq`IMB+*y2+M;7q?inaJEj&1C00WPV$=67f66DT zNfHwdXXjUMaIOpvkE3V=Rk(q53&fGcnxYiaE$hwn7!6g=24DfdyZDEqm^?AD`PZ64 zsXvo{Vu7zxWAxSzpBQ@~<&MVx#P_8DfxvXD%jA(d8pq-y6GZuwto}&x-c9uQMLr*x zADN!ZPyI-Kq`(-WVoRyhn@z7S7g_2*zO00II z^csG(Qq0U32bwQ~u(p}#%Y(6c8F~jk`oB3kJvK)W0ugbCHgM?mBdMzu9O_kuu2+Cg zG2%N81uI5=0#$QCWimmVbMBS>>?%`|YuK+KvO=^jm8%jCxfN6Q0t6!)LfCEtv~c;W z3`J-*$xH3*Cjv&ZLEk>JI$#J!yFlw6l?}K&(Kq}U-IhvqdS>W72;kZ% z#oIgNu^B{Z^4P5|xcj4(n`_U@-piX5rkdAEYPqCgl*+Tti*L9}VQi$fJB!_Smn{Pa zS35T?!xCbfslv>p!(y74z!#q^wS1M+Q<}cYf7L^tbB1h3^ARN| z_5Ma3e!X9nVv6C$OnHSV%m5{PcWIKLyBF#Fh&&>nQ;;*)7kH-sE<>1Vr6L6x=BTra z2+88~(=ec)QJ=hN8d^c+M02NS>5Vgl5(XC89GgDjT@%%re$3`Gts0B~yjmFU*jUcV z?(X&D{I zmsHgU3l#O>4V`YR7=~toWLif}`Sm0b;rM|95UFJ_nSB;eE|ztOQUPPYmz25r3>;o8Z7={ZLEmW*EpqLZv_sHyIUDBeGrN0|tZ2exN)|`PP4b z81Ce`*}2I!0zC+W&PVA02htDqNfPp$t{uAgw`A?b&_?LN(skAnW&CRF!7SgBh{6%O z)oJ2I(lDo?;&~;yU@Ys>xhim{SxY3e8_%zN!1FsX-l*MOKhkci3X^gzz#`}IdDfU! z7{@w3JhfM_K`?0iNzg92ADsv#8#%;st}gMZgqEIgKg=||Cq@_$o_=euScP+I9b1aA2m4eRMk_Q|ZW$B1@-n;C_53(J>Jv zmxz?z3>^tapw&s73ZW7ohAIbg@`sCX;egr&yAp^`N*LNQsy0F;oM9qS@RqYT zZGzX}9>zX(ToOpy4qR{AOkpQ_+Nv=0mz$Mr&<*7tNY*@Ex`M3{s=)*~$L4NliCys0`g#;Ut)v8@AsM(Zr(sJ9=^z`<$go zW~F18nK+pz^CAA3YP`A4R6Upw@|rEFJm>x9iv0lE{xYtr#BD)8dX3l~MXU8Jx^i>$ z2K}=hI&+G3N( z#1Hc_lb@`0O#!9IiExHL0~^6C>Ntgm6)RH%X};*4&}uGiv**w;S4|39dB>A5o-}m zO^D`w-EVTFZ*Vcd7Yuq zVEa_m_>=29aa#l?46Xa8&A3UHUx{nQxR>bRwZNzaV5p&AZtJ$}ze@vslJ2moPkN6@ zeP^go%0rtJ?a`TIeF6dO4x=2WC6xuiYRBWcG_)m{nf&>}IEzK3zlgm>Q>^ znjHSL6ZZ%6D%AIs+~%xJ>r;GzU$w2%OaVD7?a-4LR-kiC?)hN2xVZv3_B42WvzR5bn8Ekm$Af6vC?DCxD23%>8Sd~Ahm-PFP%EW>+9p_-A;*I z_JZM$-S677KAPj`;kNg9=2~D7JjUPd_kAp8v9906o;pK+MYzt`)yR3Hk}5kq4rk@v z8__J8sXA7vxssrmM#BhuXKs|5L;EoboCDtID6w9oUyv($E;{w`BG?pV^e~7D-Q91J z#ET#S|HMj6p+2H+JE8cV8)t zo@r-M`p{zW&EN}S^xVK!)HF>!;TdT#q!51~!-W7YZTxQ?=dKwP3wO4T{S`$MpG(Oa z`;8D8Z8c~xTK30wu7;4P*|t_$k&pd+I@^yEjl5lt*ZmY^-H5iNa}U?j4{2zrNwh}xYj+t?z^YIMC{{$RXpCq8*bzhyg$7<7(5W* zH^sZr${S03jw48eJT*+C+x`tC|GPxs-`LO}o|ykQN&L59X!buI%l|vU&;Vb0CN5?| zI)JbIhj%^`JsTkO2^$B%|Ng%_T>Up5+03i}*Z%+i;i|Tb3(hcd_nw9=AdV7G-b1l2 zzo>J{cgR$_s|0Fkz;2?P@D&I;FlFB$|5s-23Zyx3QsAC+wJ|zV-T9Jhzy?c4<71oQ z;P5EjYx(6c%oN;g8oKoH?l*eQdVk{gek8hDipIxbQhuT6ADUv6yslabdHD+60i&ur z5p%kjKQ+Fx%jZv%V_Ga!Ei@GEH*;pIO&5}dQcn4My|q|?$8|lH6C@3;C@eI$uTN== zTU7BVEKrI&y-j zsvd~;SYNF);6^?qL&t zs<}FC3+2*)>X~8il0lDc^oDUM!h4o8h_BTQR{V)jMFS0+qMO>wDg-8P;rJUzauqt?oIueHMEp)16vlwgCw85I)a(x3OL=b|IBBH_( zf?#@`A(@{-;X?(mrj5T3Nb&(+q)@&ZUqckJ3(BYCB_k9yV%jcL{p2beL$+D4%CHtk z^YCltK;nVJb@YBB8s3!btxsm;fKhZTxOqcsRoU(yeGUXKkp{j@KkK$KUVVJ~mTAz_ z>A4iX2}Q2s3E?V2OJD!<%PhXzseC@po)XsU=LR7L!drTB7GEq35$+vbeuxzGf=y0x zks%i2z)|k_QFu!I+LLTsI1rLV;=|9hzch&*rDV>AY2C4*szt3>)kg9(PtW+Pwt3FK zwWN$9=cQ0&ygWcLk6U=5e?-~zj4}t(~%TmMi5-n$4G0H0j&DaVa z?+9T{DTJqY+SB>#=VTFTOKxsHN(rDTL2n>YNR9^l->34JIcRgh=EM4H z<&hiTd#|`8;b45nj)%!0fU%k=Sg^Y4=>kBCgqtJvJ&tu#x6G<9z=r`XxUN$_GR^rER7K&vU$pRGnJy zsyp@mw+v%#5DxAQQ(lg`g!&3b!o;nK3)oOBiR{hX*QP)%)rS@QUMGqOTT;HPF4$D3 z_&2NZm$xxTAp8~5Qj^r6P_VHt-OKqCVO53PR1|(V{Q`aS`Z|Gko1u@oShng3f$PBshZh(2Da3MM zk+=~}-Be#~%X)(`uJ9Qvx!tK}232dxX2pw~{aZ0BbD?WGbZH{A86G*(&C6?cvG@?m z6K8<;<$2#@;!5tXk%6U853cc&MJ~{bH8n1uD}Szf zo;-u!!VTvl?(*E)wN7x0i)HA}GuGw33crSb0y< zJ!0N0H0O1j2tVudrUlQV&ZliCH!gL$&OuTk{OF;h`d$ZthflX@nVwqz&@gb-#akam zUU#UJ@MW~Td0!oUgYed+CtV9l?-@|W26`&%CFd`Dwp@!rVt*RD`Qj#T&+UFCkkZqn5?#dvGEa^}82|1o~WlZ!WKxfP>*!sjzB z32LaPeQ9`y&}E6pHsfQNhg9WW-+G$zC4^0Ob%EgxiFG9#Np8@x2AHCBsuXsuO^;;z zyzNZtv2wmIz2R-b2@LLs_i2fyINd&UZXb=3fS=Qv+9y&QP3xbT;zuvz38Ewlu{~2k zmufD0oiuVzZ>;Ty#WA*vtM2mUSc~=&YHN2|XmY#KSZZ?DoQTXsa}xy?xH?omPVdQD zCUQSO_cnwA2jPqVs-;p!%82EBQ0~$?u$iIRvgNYBL-wan7fqh2 z7%jO@^_ohd7OyZ?Cood(H2&RluN&DYUl4bn+3y^~IRAkdVQL-o@yl`syc>Pau4RwX z_GB#d=NEb)Rz^tU$rksqQYoK+_I5ZKf4N`aizR|z0tmK0e}4Pcvj^swd%pAB^6~Kx zRpxFg-?}*>deK)Fxd<_C-Ez0*>dvwZO=rSvC|$ROeN0%va0IibV)gA5j85f=2tKDc z_rmacnbZDC!JS%RHv^Nh10qi9KFY~fTSDvam!$BOV&mrUXE~~E3N%-}^|jAB#?j}C zq!qH##+-~S6>t2^y5HU?D(UVgr5Dbn?7qTsVMWK1s?`IvS97mFx%kOpuDo)|v)fbE z?j9-IWF%g4GBBHK-=Y9gE2Zt8QGOa4+7cY=-Z%sv<#%59M#MY9ue9>>Cbv?@xkM5Y z?XQ-WIPn<@-CGyP)719#^?^pYO+`8J7d2etLV3@rnK{*5%vabf5>c`D#n}RXd&jbv zn_Y=5AqtUN8|->w70e{we!hmC;7M1QWAx$ zc(rm*d`tCLSs0Rd*@-B}HSu2SCpj{~<@2QuMWqy&8C%Dw)?F;{pBuMWp|sd;2S>9I z)p=*(oa{@v|FY=><=pbVBVEVV8OG*xo`6;NdX|%^ioF?!-oCnZPYN7@(aMaT;(8yQ zOuwN%hXm)1@I80brA&CH?NTNjT%3IC*CR_mAuCVyjT!NB^Kx<_-&aTdqC3KxCL4JF zWbL68$>YjPc;{cweOBhdAilA6jy!oxy*&YmTIjliVmlmi95U=Li1>N-_BfZnklJT= z@}0&4y5NLz6~4}tJ)A4vldfK-&1>|}PJte}Y@vlhk#;Ms?n>}KraMw(eVndbxj0iu zLnu_LXH`|lkyeep4uSJLJJ-COFTL9uZ^h$i(Y^P|!@0{E5}7Hk-$-Uzuhn3*++*RRfs}g{X^O-|U-E=VzLK{0 zPHwks-PE47gv6)r^Gk-*XQw$a+|f2)L$?Sn+qtFd%)ei|>Xpwu6#nMp`&cMNeZxAx z#Z))u9KmcLt!4*K)Rq1+zn5&FXH!vP(H$6pjy8Nd9O0$HP@`C6 zM{r_IE$5Yw@gF|kcuIfAwt0!d6$-_B7mirXI~$^A#MWrklNzIb+-^?7t)4R7%`$tf ziuAkBCfrH(%2*zhx0d~$180Jwv{|5s7t1B%#tl4X+FfiY2~GcZ3bp1J)|hg+mX$T| zpxu>sc@bWwF45gs$ilReg* z@8n7+o&Hc`ffXJ3l0Edzd=@X7*yFaQ8suCpI^NdU8&b`_P<{W+{VRIrAM_&?tlvoQ z)MgnN@Ipn^ZhvXe#!4dH(2a#Etk>N#bUyM>-e9|}Z@*VVb>nj7o-z$qspqaOabn)* zIMvalvZm)B(=6o;Un!+^;pqG@rv?63>=e#q#VhhC$3C;zb#<4dCgun-&BWjJOPg$1 zXDo|cmx0&3&xP&pINrVN4Q^N>z&yX|I75Cjvz>fs;y-r?OjYhu)k!WeC~z<*zqS5q zL*1#$5BS9L8&o{oi!mE&957K#W=@s`w9azReNRcKJ1$ieO8khacpF~JXk+}$qlrCG z)1G>jacYBtRqH!mny(zk<}7EWbq=3f>2+-0Gtu1op8LwDJxvXF1g$S$vuzi?`quY0 z2SikY-`nt^L!uw&f16tyn16)NS&M`(C^?q>c0+~SGskjs{Sd3eA!pSI7RKix^ZuS~ zFBhUXg#Xeca_K?e_Ar;!XI$L}H3I$H0uFrgt073OTNWJZ$9uiunq;J@&zFaOpKTZ7 z*Qe=ys_3e=r43n2sz>di`L#nzY^kqnkaJwiO+%_%1txyFABC9&%c{68g=iQa?sDd5 z{G{WQw`6rx=Zo!1Z_=0VwEn7Yf7j%mdLW~}w_&UXxAWY_h%IN5i9KRHrH*x$#jaY% z?ssI&kC8Q4>Dq{CfUgjztUFq%m8XUnj>L_?UGr`DJXZuhez= zhl~B5Y-HSeA~&Tg%wNi)=HMn*N{MDX=A~r;>zSVLEI%QpVb&h5u;%$%#pT;f_TBqn zC+{c7{beoLGpVabdg6H&r@q^_Nxx7cvt4UWt2Cdiz$Y%r8`{;r1`9P$M$jxWtgFN` zWs+!UtgJ|2-Ts;O#R9?e)J61$Zr$HvRgPMATD=UhM1E$E{iJXwckhkp2ww}~If?UC z4hFTWaX&~E32@qH;gS3@`)>Z8PXdvTPDE}$?@2eIddzgz11t{3T|E2uD0?V}%ct`7$2KBYeRabyWf6 zlX;r1m9}v`(*|S}0j|E^(E652`~B}{yd$hAu%Yjn!=wIw7I}Q&YengqsMq=WdpZRe z4Ic7T5aCI!v>~S!?sOCGNN-SCxmf%^*MfOIZpFFw0F(rc%^?GNEc(YTNX_ zVy*4T7s|#LLX0=v*RGY!y5zD-imzq`?XJx{YhP~I*eSF(+2mu_+Jzr4ISH(LnZ3;f z6H!^P^-$^Yx5nb^a-8Z9i(Xhr#F}=k>!dB}#Sl=&RVq`PKUE?}v(TolXI(0q8u&=X zDARv&+7@T6PG61lhZ!qaYeU;@5|~0Y?(E)Zl5_*TmPXe2$Q{$PrhD1ic3sIL?9X9qL3?bm-pCDF<+9;9;aW7pMGx7||7-wby%vgf_u)ALQo{Op`%DiS36 z?Gd4&$h4X=MIr&tP2sQgMTK_P%!yfl=hPwdL#rt@OAl=iY}AZ(YOJ`Zd-%pOhFRJYGJ2~zGQbr98%bm8JlO;EU&NVJje(CXWM^OZ6%_e+eD|+gze2S8VLS+2};^KFmHuhK_9IBJAYMIhwTA#0gClY^0+iIimi>1N) zg<7m@o*JF9KKAKtaM8i~6>|kz2%dEN&XZ&bHWswx4nJ)X`ohGyXkCs|`uS}KFDHo# zS?oJazpj=fP~W`i!YfBko=r=Su~aB%Y(MpsvSAfVi;Xz<$yaTy;%lp~`zz%C8}Pie z#oJHIApUXI7n3i`-I}+o^E!L&LG_LLhJWnMr3CCe>RuU%5|w*Cz7T(t-i_KWR_U2S zeA=Vj{2TbI-0;lr(1?@F5ja9eD#B~xTYhx=6}bewH2qIh%ZUvZpitF}A&Qp!=ShF@ zXK>cgL2YzX^;l_QB_8*ZYuimRit;8ay3Oz9#W(55F~_!bHW&JD*5;u682G+}`S?=Q z!ymvM{+_AYCX|7n4+i(5LJ0`NQ{9A5SZs<#^(F?W z-#faHSkoi+{FW20($VLSU%tcQw@vTS>r=;Mk5((_DdhzP?(B8XC`&NI$2)dXAR-|q z{%BEJbLge0| zy1EUVCfY~i%6G;QgfkmIS;%Jmg!Cp&{=(|wxuKpn&)z)D!6YV#f7xv}MtRQ1r?*OI zPm8)y;8_T6%?k1`y}S1=l`G9@<*%v6H_n@>NT{`b-s~GK=ivN+xn|YgeO6}K>c{LY zS{r>t&Jm}*A&H7BTTSNM5`FuVC(W%QzWma(&oyK+lV65qG_w>mZr=PVQ9H=y z0mDC=oDbj5WL4uiyX@(F_7?#=A6=SnB|RsLe`&#$NA4S$o-33W+!P9r4%*(e>&!`Q z>uX8X(v*2`v&r{Tpt+(%FfJL7-7h5|_bL7>_2p__$X3gC3!QMn4_9=)EmdicsHYte1i78m+r)J~ zl_Zj!!rLsoujGNOQAT~S<>^?4!&RL6A9^C#S(p8D(7MDswffEDq%3>&jD{`mGCrT- zEUi&hYInJ-oRkw2c|gYF;G1M&*Uj~tZk%6RFOaOwZ4<@6|C*iJg|mfutX`CU(v3Tt z&VF*2C|@P)MH0F5e!YhE{>2453+B(eKyYLE!iZ;%UL+Sg_dRban1%bhvGKxAR(SCOtFiZ0nlS-mIVVgDDz67ZRrFwRYB~ zM=TMbsXW)pDDD(i{JC1CP4(*6>wMdm&HLw#K|*YG;cBOrLTA^#b-BycxbE0qU;QvZ z>?=_wUn`IEhpm`nE6?uP<>f+o{mHf?477<&pO2D6vU;gr)!XddLy!8f<6jS9uye;dnSGi5wsp^nwHNuX1Qi6!| z(_Xy7Yoz#-((4pVq(j*w-=}-G7e8Wn!o$DnGqK6Guyw<~`5?P3 z&AA>~;k@s+6=XRjZsfMi^}M5h0~+D>%nh4({$#P(xyf=Bksa3>gNIXJfuT zQKC~#D3LHYQG2iK^wuwPcLg*bWpOUI+Q_|2?cg1b!bQ#Ov<7((Gdy2WUw8A;33}w8 zUoDZH^vHtr%Y0k&P;R1Sgq)VLwk&V+vW~mRQ8oEeHC+q(#vVv=r6r;&j_sDe%SrJw z+ilI|8Mm=sQ9W)`>$17^ReB7kceYb{X8U>7xKvAKp0NAbvda0f77eBr4c^ZGkaOyO zO|0i@b_$Vm-PKB-Crr3Z(bz$HPtjR7%!kuxWzC?A6(#wvzt&$6aLXhS-S521NB=lW zw?>I*sXfP=-uiGKX;7Q5Xf&&O)$ zzNKC!*qg+|M{2o$38&%3hvsg3kUt)t5DI5AG8{a$nyYzO4 zS$Dg}%-79NH@{##uXA7Hd`|~?wUgS#a`W;GI&Lmnd_Gwu;c2nu@t5e0?6u-_$@r~& z%P$)V6&ODtc)bt*Tl~tKq6`P{V}rO@nejiQ(TAJe%nswMxb*7r_6w`et}FPk3mtLa zLACUo zX-&J@Et1|3k)Z)`t!gpydam#%oS?~dxLf=B*FC4#8M8~-8W_SGX@w%~Kv zvc(_N}G&Y!EIfH9eleCN8SYAh-01Y}-S7 z(<2uz|9g(<-bzRN&2!J53oS@0OVHBT{Dz*{c9B5Z>hvW`*?T_lJ0GlF$ke62Bgob) z@BzWgGSNthHA;>7LOiI4G`!IQF8kO-Q=QHCT{&86NXp?OctvFSmXlWOG@N^Rx|{hP zh}YoF+gqZukD(>^P`QfH`N$Pw&vTh<8mtm`o3}MBe4N*Dm3hy{6t~^X8xLpM*o9Nt z-K^Wb*R$l`L!Ph2nQ6GI0#}F`?Ypv@?X@&B%faPh#~YAy9L(%CE@fuvp0nF`XSuMO zj^R5dQT99`i4_;vs;q^-rpgDD-d(Uy>aEU!@I^LHggJI6ZX>ceyfZ>r;(Xba*N>Mx zwYIuPoG!d#kz(4rP~H;GbUZ$)ZCh&pK_$fak!aA%Jtx_*#hP9BWLlB;){shjsU+#k z^*L-$bDg5acgzv2ldgML;I*TMR9Hkmd7ga!$@j!I^zT^h_b0V0s49_~?YNQ^jI6Zr zVTD{$q~$`UZ*e~JU)$Cs1{2%dXd>E_>C3QNWetj-B<0k*9R`apu!xb@Sxc{U#9u6; znR-N6LWfQ4#a4Wpwgt|$oSj=vnEAzTO}JKIXr4jKF^@#_a%{|dHNAA>l1kgFB`da& zJzCoHmFdOvgYHT;pWZfoC~0t4)v>GKK5kdRb9}q#mxgO3^cERXq^DGh5y zh)oXL?dGKJjjg8QqTVCl{qgi1orIbUJl4{nJC0wcwE`V;75A1E@U)n9p--;*gg(9cNI?4eue37Ve7trJuDR9^UFw?> zdi`8ougH+E@sbbj^>tBP_s%xo@PN?%xxScNFDMyqX}QZD_SdwxJY4Ug6wZCLNp$VK z>grD~i$V#F;_50wnE6k*EqNE2{y8Ekp_`AqQ0r{|H&lI|!@dzdct^ee1zAd9n*QX# zg*;qhBUAsX2)xL%7e@WfVT5~MHt_QO!EX-DQfHJ4dFJco`jmNuFK0-oEHynZY;ZwD zf?BZxH78(OXz-n@_Reuva=Hs!h0PtPMfTqhl`~mH*idQ4d|R_8e5*@z{MzV*()_vQ z;?{>2dlX1UKe8wKrg^|RR(jRS6%Q_Rk=vDf#(QScl)KX8)4ck~s$DC=Oz};X86#G? za)bGPKaR!kZ@O`9JMbp{d=(eEDx|4JS<2XEDVl;NuB_>jvg5yMYi0XT!awV+R10!x7ofCb zGHgG}IB(Ne>qAt^TMl)ay!F_fs`piek(XF-@%~VcM}j_NPOgj*4{E>pe?4#R%vknq zTj~L!y+JOV^ztuFhz*y8BE7&*|A^ zo$T%6(GJhpI1M%^#UE@dhH1z31yiXD5ljzuDu0TeK*>g+9HPJBQ*qIWHngBQ0&; zmgfxAVdM@u?Ez~lj$Hff@lY7^g-@P%70QJs_=tmkv|}N4S!IRRgF{NRy&1Xu0z5|h zeGkriqF#K=SJ1Fs|DHF)>b*VUCrfO_NV$@z>jLOV?UZDaVmdod#yb#2i!TW9(!b(b zQJ-CArEehKy1PMimx(pwEg!oxuWrs^mDAicPxiUF+SlE@fr|=?DJbg?Ec9^glvdtQ zsL!(AH%5&8Aisfv-4R_${FFD$4s8mt*(;tKt>ufPVV8fv^ch2aBg@S(KN~J~*Z`HYjq~2E#cFp%alGCNXkM5(5GFoZ*c6L!%n)>SZn`#%GT5SH5u+Ss=Sdud0mw9^yve%Nk^BM==dDCR7-!0m9RzW!Frt+ zp)M@+ubNY~r-m@!nA?xtWy}=6Yu&K34G@YE&h)3G+Gw{mTks5ehoev18~T|?w~wddQpdU+G7 zbPxV3HLprYz=y#x(Spubr{y*t+hNUyx|kDpX-{_gM%*-X=`b+df8wSF1+`N%{d$97vcpzyTfK)gODyg7 zYCivCcJg^VANFn2iTZrB=*dmP&=aP%q_u_D>(Ds@l&jH_YuH@*+fX)f3=avt@hCSP zBG8eSmLh2pp|UI|S9rtWiZAl)ZTCuxhVI=e@%w#Pk`5VsjAE`@yY!8O`f0K+83peI z+b?kvo;xn?@$EHhr0rFF9V!X2V@5AE6wf^%E9g*O_HB_M<08Hszm$am9T+}&)q5WW zR>mnmx^6|)zR?B4kYlEyv(0fN$vb8{*-+8@))IK0A#B9iHGx|7UPp+y+Zmj_(m z2tTrv=+)V@wD$|;ny#|-0kpZD+1YhhQUrP>4@k(D*>%)yRdcQJk(xm0yphp zt$36vdDqU|{C3hC%Qn43H%u50bnvfRTySmu7w#jbgaSf4<_VPF?$(oEZys|#oB4xY z?HTk8)L{0MV^H*o*S9N=QfBgnFv^RM?jOGAh9 z_^uQQ{vzpS$Hlvpvu(cWUW5E?p{oM78w5IV z(6C-)p)j+JI`)XbCZoXD^DsvHgPzEp)SR!PC$31#`rTn8w>*0Cv7*KLkCicx_lmz; zu#cSi(UVnev?g?~$mn_*E`5DSC}i@&N}j~ZbIE$Vg4n57D5W$1n#3`Q_ga|d5O363gCI4iK)>ZI4AvOPMI)FwTCL-@MNiktk9*Fz1lqZ}$Lx?PToe$I9| zzBQWUtB~u`?XNTOFl7`$bKMW$7dq19Y7?`Ok9e)HSpGQ)1vxIktN6JnE+bcQ@rx*r z&6Y+A(QQvElgus)CMk%Jt*ef@_Kfi`iLrm%o!pDcMNXktxB0eWF07Lx#AIaN3AQt+ zdTNKS(Yk?DKQ-zlRl_;fPDLfz3dWRco)pvgA7f9s?et{h+6T_;ceP_qe@Zm|{O>&) z+n@x!a`FgCcSFHc`GiI-b94d(=U+qd-Njm6{~hpW#HV z$_4fIl8eR8OV8Zkzit}DlPS3O#JlpnV!HZC(rb-2Z0e11|G>mq_}(qRQJYty_k45D zS$#6hj)PqsqNxq~8Ok*e+m5}KZ46@7>PK*MD5Tdht9)MxC7teA;`vJ|;!A zR|c%mlDe{yvu6Ws^t~7lS+vzfwkDQz)>4^kR!WYp2ZN6D9_{GD$a*BP-pp;}Uz2_G zLq2h4mi?-E$5x$6_Ica5PvGJP#co+AcP{Y_mKBzf58f;lq-yEoHzMDb@z%fT&R7<$w8jBLu12m_>Jd`#?>w0}+t2IC-CnB^q~h0A5LX^L zTId~L_OY^#;zX#|L21WL(#Htr7-q7FC^|^B)B5HIXjYxCYI|;8)+48QiTJ^>E%!XG z9$&)EXT7dQ!aL$bmzIDDMkeEMyU%VTH?n}XU(zE&&R9%_b@fGb-U!%FCUgx6I51IQC8}E0vaFk$WUn|S#>#N?4Ni2 zCcaH%$U_UiKYg&Hy$xPK00;m9AOHk_01yBIKmZ5;0U!VbfB+Bx0zd!=00AHX1b_e# z00KY&2mk>f00e*l5C8%|00;m9AOHk_01yBIKmZ5;0U!VbfB+Bx0zd!=00AHX1b_e# z00KY&2mk>f00e*l5C8%|00;m9AOHk_01yBIKmZ5;0U!VbrYwP;4f00e-*a00VaxIw9b!0@&J79aowfB+Bx z0zd!=00AHX1c1PlB{2CSuCprk;hlS7rJZp1JrI~c0#mk0LSR4u2mk>f00e*l5C8%| z00;nq;ROCa@!po>p((5GoZd2yBC9RW^DFdBj3Z2>Gm00;m9AOHk_ z01yBIKmZ5;fhkJ>i+JyD$q8{XQddCtZE~tQRz6AfT_1Wnii525Zaph(A59ryaXZq= z_8{KJ5hl3$V*-EHB%5-*HPF&G-`2EZOJDcaOa`s>tf(1V0Y-aoh3Qq;jgcW(}zIwu;w=Xte&T zidLj~HWdY$f3M+k8aF*-D_Rg^ZGw$FTEjcHd7%Baln3jfoef00e*l5SVlV zBkJF-vViMo^kt`*%C_!b5)2ma-L1Jk*U)HH>!)v$Qd1Mcoi3xLZzZ+#^rulUdlr|H zk{lP}dR+#6$sxHJ@zdQ>m=vFqk(-kq_tfGNTHY$Ip-^|^5|38|SGDbarBmk^2mwyM3owI&LgSFamX+R~R}TUFFe8ENB)s@A$xm&<4c zWA8U9neU_hZeB!RvW>58ZOQeyf|fV+jZVwTcpn!TQ}AQNA0#{w00KY&2mk>f00e*l z5C8(Ro508#r@O5r;_fwML|sA4$~`!_3|XMAf0TTXc>mB4cS{z18M16Zjgt7Dm z!?5x;WWO%%w%mmqA*C%Z0YW6YH8%94;Z_`tR!o2KtA(o!y-k z&;SBJ00;m9AOHk_01yBIvzfq8@&2K^yS}EnxG=vUH+#VNp|vvewclNRB}Bs;`ldH^ zBMa93H*LN>$4wQj?2`R`a2%U>|4{eF5G`$y*wXW%ts>Uvw(jLiGUyBP7m?}nm+oiu z-A6x2y!W&f1tLR`Xe9&3r_p&019Rq)c;E#D#zLUDAg`{r2C3mcYdf;@n^upA@|voO zqJlgm(~kD$lIL3J3r26MTASWGsmd9JS2UFc=}9ZyO{qsl)lH=@7=)J(EN9nP676ZJ zqjs^shRY!}+%dIpyuPg>(nMO?B%-RVts(KwMQQ!e@|NZdXH{gr{IA=Mu!{Dk+~=mq zOnN1K2j4eYRReS8$5M7U7YG0WAOHk_01yBIKmZ5;fiV*JjdqyGL*I3JcXwGyQDs?a zXM6jnPoF-2{`{ZJ>2AsQM<&s0_!PANBHpu|mC>s1Iird9hG--71+#>f&LY2S=nLA; z;VC(Vg*k7LDZ?X(cSOr~x0EFZxtJ&;Hv-@A%WducfCK{@5Eu)A?yj!N^0M-h;=%eI zTPs79duefDd1*1S)7#sNg- z_qMmS+7I#G-dgqMrmVD4WO+5B-DQo#kQ?Ni)16h&7i}W5 z3i9)Qyb8+e2d3877sUrWFz#ytdXF+1+uFubb~qOZ00AHX1b_e#00KY&2mpaG62PV% zCfGh8((7w$DoRTb+5V}w_hV1bf6Bdo(sD<>mpU?f{^Nf3fhqCGP`d#deLb*jV0;|w z$omiR-V|$sMjK-4`bR&zDuQ)?5$~5he=LGGFipCdgb)=`u4Wxm;K;VxF zAho)xysWXl?q}V`*3fFIE6YlX5!wFnV^3#iM_;nW_xF_0s&?LH3YYG@tLa}>t`cJ| zCui*Gcp0tk@qOj_TI6Rcv_WKL|0sNGF)|PS`^Y;oTfR2VMnU?f00e*l5C8%|00;nq_V457$h_jd zG56ly0cq2g`^5hKqu@91l2cO?qh2~+mqlMN45{cGJo4Vt-4Jhk5iPCj@+u)cEiuB= zNPeVy-aq^h?;ZI*$OE&lyGA5ud3ouv zekSs0b+3YU5br=>dBT0McyMO=?00KY& z2mk>f00e*l5SV2I280Z93ji|e{$tF&yCpBo)j~%Vxofv?yLiROF)*#Z8<9MN?s-Q} z{Lq{q=47PNr(xtZ^mG)^vR28>L(}{a?>)$4;6fa43_Mp3IYCL&{8>>)pN#6NPkLym zB&+V4-I)EzSWUJ+QyFDF`=D%Cxo&)P>%dipzXSDrfWshd{);*uNYgbi=KiBMXh`gn z>gwNDmG4jAnC61qwXW=x{&Qp;dCJ>Mhwo2L?5p8d%%0}{cpQ9NOYS4hJ`X=15Z~6( zTpIVtN>^#%NsCIl4w1-o`lfU*qn}OSx@|yu|MTO1gn=z)umb@g00e*l5C8%|00;m9 zATZ+z3Y7d z48D&Wfx-10TXO^Pj*Sf1fdCKy0zd!=00AHX1b_e#m_!19FW$TA6J7K#UmBS7tEhF$ zE2a#2^4qxSEYP+$u9a37AVx#PbTPRt=E70}6#l{kkLwC=t|$35 zO@y2d{?9THuF`y8=DeNarvY|=01yBI)11Kg^phj>rPG`XgbxJ9oxoTW_c)#l;(Z2* zR4B^G1VFrxd-nwnfxyHOm@D+`hj=I9x>Zza%R@#$Oh~-yN=BWp;5_QX&#K~8){x*4 zEIIz7JW7s<;@32dK@LB)Ix(klZm}&d+3?s2SE!}br^jYBR7bh{Csj0MT5YC45iLLA zoKjI$R#IA;dS7@U-tg1F0tA2n5SS7K#@tU1?@I}W77Y5yp+w;QY$Jf&emgO*-z$9( z?<4Cyu+AU?Al_$N?+WFeQ3M8kDV@9bMPr)Au1oK_@(i}0h-!~NLx)eWd5vx{k;>e;2 ztUzEY5CHK$+j>_h?~Eca=u0UHw`Je7c~Yc&gagy&7b8+V{LcA@U$-ZsnK%8C z2AMWLw+{y%_2CzFscI{cHSR{(`o5ILtF4&FW1ACpWd6K;FA6+&AhYf9$QXGJqOW^p zw&t2~_vH#35C8%|U@8(Ab3Zw}FI_V9Crjujr{a}|m?n|{vVJbEH{{2GF^Tu2NYnKr zAz6Dp^t)P52(dbINao&a5bsk#qe2W=2!MDWsTqR}2uu?KgT9oaCkV;*)Y{ zr_~3F(~zz+EocfliL5)1PqoLXvffK@?yqSg<@*<`!>2#>x-m}n`{G&XIt+I<((-6$hX+%ws!U+KXm`w z-BJDG2sPfEMM7rL6%7rIHOcoRmLbv_pK6=d%lw9hnwq+jH|8RXkumsR(rjhvd(Jxn z)5V0QH>c@`jwJm6HPV;Tg{u{xXP1|kl~q+`KULX40SngspauT}0U$7i2#ixdIYM7L zq>#{04gmshXB`1tD|f{In8o`~9TsJ?g#eGs;>}M(ax%th)Az43gQm?#-Qg#vp&${jv3Je5( z5MW~J6YsDA0U!VbfB-fE&`)9`19l)Vn80)w@BLb9=soXNRi;1bz|#@jkfcfqft_s|diC z(ph!6p|C&z2>b;B=qLXI8k{l<3CvXSPQh@_J1+L2PGYnKhccYWS3^>WwUJr@!K1)CJ2bu+konvq)*uXUq_(5PS;(chf#r_`Y z&9EPwpd%2&0BGO<9DX)As0>gUepUu#2kHaV2dEE&2|#@qOauA{s1Lud4>MT2KS9L% z*`-uMj)-_SZn(39~01QG!8KDaN!^*(&|!Drv#IyUL`VbTLY zXh00mD5g}SfI9i}azNXJw)wL%K)d*f0@?+(b}_5Odjc|To|uf^JRH>f1Zq~u>N^1t z?>{@_3D|)?A6uV40q}=p0oMWn0uZ1=4sI7vAD})!eHcst>ce0f&_6(Z_>9cnJGtfl9(=Z~E&)Q;{s?ehH&c+i+Y0Jj7{ybtb+aJ>(oeel^gxQ8zG>R$JD46)G4A3rqqJVaRtzArS@gC=Oitgt{9@t@4eio0cHjmu% zK787I-++5u;H|S;mQnO2CZbxgRmvm))~my49ATW&yfOsGLxq$0^_}rPwpF6m| z`osNCdVQGm01ze+12l@kO#|u!)CZ^!g9$)=7)%5DhpAj2K)g?5H3*?kD*_ce0HP#*@q(@OtA zu+x|Ti1)#t3%K5g&z-6Kxr6JgKivPM*M~_D0AT_#K%*GkG@w2}eSrEfm;ls=!8D+M zn9B8GDvS4TumOP?L||gX`{2G8_JIHp_zi(?H*Wmq==dI*3SWfAw?yC#2mk>fFunw! zpB!JF;BBT7n9Ab48#W*?g9w0lpQ*hllxvz20P#LeFC2so1c1PdBmm-lMqXAZ)VLD> z@jippArxgw69Dl(?%fwS1Oj6r0OEZt^x#||00e-*_!0o|KE6D`+e{?@;(bc%JqT_F z5g3zr|As=r3kduPfiZqo{Ye%xB~71rpDAUTIRzQ90>fnj0#l#Bh*kHmjZ?q85aFK? z_)P`)lhYv$5EzL7i1!(!4xuPhn!uRE`)~SxI0OWK62Sc2``ewdd-&U&C;mJbd7pUZ zqvVLeavYl-OL8y+fr%!78Sf0o-Qjo#hzox+ZRGv;7xDK;alsdS&J+R@upU@URAfPJ z_UF%^JKEc@y#{p6K(e12XG$wE2yV6$XwSLDLA=H&z3opy{H)l6>p8X-F{H`Nl>P?F zfnx%gG5a68hcSmRVGcmNPZ;Vy%?N`fAvQaf!1S|oK;HU5OmRui|UCYUl>*#JGlffW6pl; z9>yHPggF55K4GZ;G$Ra_gxKs@l7krtOf&(^cxO274#zt{T=)a=jti>bbLJ5M@s367 zfq9|{U>SKwL^m;te2KtS|BTw^`kXMI(4zM4uIk_mODTA6rnR(Y+}c7;cj8&)@1=Wp z_eg%a>cbV7NLHS(2}#aMi?o+wBxTo2>67$L@i#AN-Fp$0nw=Tzt+I}o>R4cHS9fKX1V-8`$9DsPAFw}pV5e7>_Y<4Wk!3+c@ngC|JGaPq^;~gL_{DFAK z1y%4l^9X==@7GoEXYvVP7w@F=#DnXH1=v;lN@g(%wdizU^?*1Ymf{x!GV(suPjmd` zWkZ`Z_1TEV?(WX&H|CPui%EVSr8)n)vAa1=W$7Gt^X&G1$8Bi_s|kM@c}Em|NBgj? z<41HL-hbkR9b6H>jM?$nJ&ZYo33CAAeZo-xX+{_<39;F+BnLAPm}ml+@y>AE9gcT^ zxbO$!9T!x==gcDj;{6we2X7{i0Cw?CMt$bT==h-UT2hR-2~nsy>^kvHgUr}=`|o-G z)lc&~wPggHR=FKRbNv2YHHtVeQ1Gcu%K^LPg_&AG^a@y z)8=Ph2RYqJgc)J5MvCn(xQg>}>hO3D#0f_erL;a^2VX!2`X2+5o%s^nG31G%M!*O>w-T~sm zABcBcPz9eej{u1G!2%EVCy_u$-W_g&1xH-dYMPpxTYuifK7#1(?rx0JT1&zx_o}w5 zt3FbRnV98rRQ-?H=~#*|lAo@+FuA2D%3V5-V>2?7B7Dqb{!xu==!HjgE5#N1h*2h-+fUjI4eN`x76 zL}T|b<`5>#0f_erL;a^2VX!2`X2+5o%s^nG31G%M!*O>w-T~smABcBcPz9eej{t~w z?0O51Oe}%U>Q~oxEJ0?%BioQi#r-Cd-*<+ct_4| z$$fNLh-F@1o+LDEdllUf#opcBmggzEiJFLb9u30=Nh5>JB>mIokpmqi&(-*skde-% zUb!1Bv25r)???(PTYab`i1$9qu;G*dX3XBl?qSR!Oqc@@?-PdlPcy<`Nr=skB{`UZ zz(fQzKJ)s|DOV!Qm?IjyhcSmR zVGcmNPZ;Vy%?N`fAvQafe z;Sa<+E~tXfnMVM`I~Jt{W*{)m1VFscy#8~_mFNZvHTKt(D;2H+0`ZP3vVZOO2KEa4 z*FNDyATR+0ZeXvve|=~I!k%JT%rx;n>ZPAz{2`p_LIA}3I4d-8H(3OlldY9xN7$4s z&)9`me2pI@WbpkN*KGm-f#0La`z-%Ib z=$+YATqr9L_)7vH-f<<>z%LN^l>mtMzwD&oG$4Q*0wCUT!xg*&0U!Vb{)PaE_rIYA z=gd9=Al`o!Snv)A;EDi<_u1FKLW!p|0TAy~`tm? zYTy?L{7L{<;{6*6h3)m1y#kyD1ZD*R5bv|%GLL&9vGuou?c<&)I0OQ-fB=a1>2#3? z_jp70r&BSeWvn3He-&8p4hZ0i0ItM4220O_&5k8Gn1R4-BLL!kwq5b@DKBO;H=`yP z%>f(-0<)6s1VFswj_pkLj2W$Pqb3;50UQScvy%Xb_vv)qF<64dX2+5o%zr@u#5-;U8+ac^ zpeag@j+p;(?XUxrW@s<+RXd{G~G z;CLv3))bwUL+a>8$Kvnf-F5y#WYm(*j&gjo1Sk|9^$v@)=Bj|R^yIu|X{~*pTGP#W z$refamH#?G{xg%th_j0*MPJnYG$1?mp%PS7$3p6n-4XmFZfkwF;|+u~XxjYm;%v$F zQQ5Ve965)OeyhU6?3TgVVclB{uO$tV(`{*nYsh%-_y0aHqW^&s zj(pGi2yu4Rhbu6VtUO^8lAM(mX)nb{%C48v|I0$ZqxPIz9K+k-YQwaak_Wta)-%ZWJnb z#Y$iVQQVgn5!Zw$7TwhUv~a(NuG&!9WfbdWFK(h(ayDSdZRx+}(VBXlg+joiqN^pv z>g*YdbKcRWd8VUV!9*h4z7k?_=yDEM5P|%%^Xc)-1v(#k^8O!xS5w}*Py^9&L z#l0_UX-zX+jYkLK{VzHwI0XpcjsS>v+_9a>o-v~pZqx*$Ie_CpV0ID!@jjidI|fUz z*z8!6gZVEAfO!8^0Kz+*6TmLsN#}_N_swwsb?d5qC9@cXT68+Fy6e{?L*F5j5pY`NVtb?6U9tchW0+U7n#QUV7pVk>;MvH#b z1fw~C<3M0`5&-c&ovu3uOR(7NSdxSJF9?8mA3+3y36}(#-d?09+Uij`Bo8d&x+zg_ z9Vw&Cljn*nNLV#vzRy@6a_*0}E%E9rsCO&w*{J$D>MGBUOCog3m13I*j$-lOcM!|8 z`C)PPO`9jB*yoLH$-HiC)8@OHTvHanK&VEzjNAl@fPvO+dL33OJ!y0&8pG7}!z zhCC|n*J<+&Z?CK->X+_)=OXf5aXH}%rO4mN_m2EK8&D*|zExe_HU0<5P#m{%+P~*J zl6dbQ5dXE+u$pAFeLrKwI9qZbT^3@Q*LM;L4clHtx9lM+?0r9Z*nchAuwdP2%#OSc1i7 z$C4b(e?b7m`!J0K1|WbF0%H>IH&CeGyhd#Kzex{=fB+Dd^aPIMYL#T|j>WNRha5jG{uxZw|p$6XlzzvnTD_mMhC zumJ%eFctzZ@;(-Na4rx40zhDV3Bbtv`0@mAGnK$p7Vi@f8)N|lCXB#X#5?kd1}`80 z1jd&DBHqW>A$S70jR1)EsVnv%vfmS^eX?s#fBjx-mev0Iq~mwA zJ=cnJpiyo0tor}lf_NXTH-h71BY^2Yecupks5@Mi=t z{mBOY{@EFjYB+(JBi@m+VfxEA@V9>#{s4jTA^_t3{}W)dICWE$933(L<62xH_`m%l z;+=G{TvXF90d>_UIij~LB}EztA@zFnv(MhxP+u{Bkn9iMEA&a?Q$K*Jpr_^difgXR1GFWx&V0@(0H!}@h9wi>p(>tJb==R;508weD+ci`rVXZdgHs3m_s!5l|FR)`TS?A?f$sueYE7 zGc#F+%nXYOkc8hnJd?>}<}B|yIpm#l=8QGP5AxoW!@*|+0mYq_{fsL0@ZCiXBpvCm zlN>!~9@rfh))n1U_Qd%fhVfr7wQ*;LV{Mnr7m7YVonH{P$;f1;EY7Zw&v4Lj=6 z7x%>cKg}ec z%W>G&qKczaJ-L`5V4nEtsp+0La*XRe{m_kbsTEIgdFT7j&#u4mVNX8B^?2>L^zk=C z9ndd_XKAy%h+_@Wz*Ywl5EJp@YctgodN@Q3_)1@w=*Q4&przImkavA~cKn8zNCLh# zPwnM-kBOcd?8e7; zo^d4a0?f%ba@nuQEJo`7e4GM3jIbRSKLnsck+4rR2i$f>tbaJUm;mH zfaf!F@3p)~4{lxD|5aj>@~(b%B*M{ePQvF?`nlLUxCc&Iex}&yW_XoUax})D=Q}q= zri)i2&tB0N!~B=t(m8)a@&1t)09u9-n=RZyyj^8(6ya)z=RZz4YX}H772~SG4hdS~F zc7pz&-Ityi-+fw2edY(>-GoIfA_1sF5#==Wku0!*$a+OU|y(bpyVF#>uGwA6Y6@=mEP7O*L%q=Bi{ zwW^h)gw#B59O>0Yzp(NNc zHf>7Y5mGS)t2wHKQ42=@EhjQWsI34Z+V4G4Q`N?BK5SVs0g!jS!@)+=1eoL+oq^=t z4h#4)hv;QDgrKfUj_oBH8asc4$oKu<$_?UcIK*g+Dg5fo?|JY;cRgl2o!0YSe{Vw& zy6Wu}x%^mKX3D|XAf6y%M}bz~mHAtTlHWw1>AUXLQ6i_wd%a|RAjc;zRkDAwyW504 zl56pP+<;Y-9J0u}Mo}usxM8%U-+d}4Z?JDGd3PH9UB2@Fo9_?M>WAxIc{@#+IoogOSC6EpX7=E7 zMK3SU{?A|6qTD&IW4C7>i}G4vzOb(y){-`jevGBoUJ5MOv`8UAl-ONH{^mexAaf6Mvke(~um0K+jZ@XO6|s{9M41mvA!aj@AG0VcUd z$0KiFV1 z;b{4TF9+gxeiDs&e1FdYqXv6*jl$*KhwmC1e=NJG60pv_Js z?*w&y;kMwH8$%1m@LP_McWMP-IEK$$Z7irBKvJ3`0P?PLO?YjF0Fzv!Q;2)sXQ$9z zSbk^2FnlJo;FZ*|?(C7Ugs)LN&G=>K+WD`)-5TkLVnC81^kbY@V2spBy&tY-lJ1!Rzu%c8wXbB%`*js-mKz zvi5(UKmSin_Li~J&eYsl;E%?hVpx~ySCm;XzPf9?80HYN`ElvqaP5TxLujzoz68XS z=$L*zwyK_J!!i!1QC*@RBV?|DxFVxVeSyt^OiNM-|2#6_ZF-ry3hNrFe_=xC6RhkkV^wb|H*JcRRUZ3CHe)JDz zMu)M;du`V0Aws{oznos!*I~ftH|TC}6pTj062AU8*`@b9?IS1;SEtFl2Kj$CG#6bi zDfqGr(db_FoyKGC8;bUZaqTCaG(7XJzVdN?{^Lr+Wr4c%k9%UhwKu^l?ye5tbf4dn z3G3Q_*t}i$@W`Mp=z=`gIpnj<`g_X)?On!yUy}7%u#m%XiP&CJaVQf1kI(J??v7C691fPNSAJR-lzQ(TMb2|e$vX?@Lote6OpT%%3Oug4dx zCq#JEaPS>Qb%}lqtp>VUYCQpYCri&F)?y+R17M`^ViAn$rPgpH;Ns2=`n7~k!ULz2qcx;lmaE_6nDuSs9= zl7nB|r7E>rmb$2qAYe(FOgDO*Ef%KmYcn=3T6N%JW^Q5r%|mnic|E9;zSHGhQ=9&2 zU(98~hO@UN=}GZJ?d?Y;<|#GGM~7qIU7GmA=}T8rPVf07(gkyze5eS2h8(fb?s-Qu zwwHx1I@XG7b zKmO+rjYd^^?O)No(OvMcbRYpS5jVazS3NNf2R(#02lC)6M9&9K8YvXvaXCrYC8=8zApG zg@f1T2sBh&T0T}gDVfou;u;T|ufG0Spgp1Pc#ufn7xuR6yC}6eeP;+?emC*W5xrdS z{#>rd;ONcQs`M8PG#UnZNB#GbeKDc+vfh$w3rZFw1qif^fS5RpT(|5DIEqfdM&+HJQP=|nOdWUq^1f^ZkB+UID%X^doUb;VIc1oR13&@ORg;_S&$SU&@uvI z;xKaEvNPZ)IsuS(IuqCf1n2}n-rL3YAd)s9P<3)5F%FU!l7Pm>x6`63*fyM)vW*w< zV|nZ11bL^oKd{Ga1jLk(sN0m?uxUg98Q-EIj5I0gtbM*!r#bpi%Q1A!MMV5+=7M?Hn`2L#v&=v#ZJCoLm@%X`a? zgu~jL0MuTnidIbkDzH@-Ut1&|szh5*g)j*MAnz}#VsKt73DjjLE{bJX7JZw}{?xWs z#$nNin=0@6e*~}r1b~1!2td!fIVeIHKmZ5;0rL>Bot}5|@PJT&05btgmiKl@8$f00e*l5NJ~Z?O-l9(ozcx^8WnuPnEKs z?T_>t@-V&QSadfkBn}9)l7PNqQ|md~H^S&E!+hxt_5uMQU;+W?c{c$boC*Yh01z-U z0pvSo4iSO_0=7s1e3rvZUh5&(H`lO_xT1p+Th0Ob8e$-#L*00;m9^AiAhH$PJd(H04SytmT8 z;BX-Df&@&J_g2lZsc)=Wbru{91UeG|T;4lVej&5%K>*rb_)Y-5*~G%vKuym01#j!06p() zWUOPqn37EDHf1+#nuP$!dn*kL4!0NrRlkhm5nqCrHa$?bSE`f+TL+WhywOL?TNi2j z$vaA*m`EhKCN^OO1b~1M0g!hiAn?`<1jIxbc-I>jbP599^3h=Oc(XUe#7vZEg6h$0K8?Dp=M@SZ~Sm9z648gsl@ zg+5jl9iJB&;9-Y<4~2eX=I+a>RyR6}{zjg6ByN-sAH#Uwp&uQ3Aa8U;?Tv-Lf>z19 zy6Vb0kax>%2O(vhk^snir!4k1&a{{apIo6R+Uhf7xfuX? zZ)9cgMx$YsWi!EPZTPImGswHDv+*&G~3eLxC?JDYM*!sA>Wa)b!D3bfPtGC<3D&mh`w<(j*cIwbm8Lds7bA$v#uuS=rC1A`jnP)Id^@{yNFgbLN5F zabaCie>BH)>=sE~`ET!ccN)1#qQDPP+}k|T(R=34&$K7d;WZJyT6QxbdXPKrk@g-z zQ`TnU{pn2{j|Wbd_j<`!0|kMrvZ8?}F=;9{$$LJ06!A2pH*3$B6dnm2B zJ`UIb0v$;J*5nP{CU1} zQ)IgIXyn-|`eK;>(px&`Zz$eBlH>IHS?wXRgR>%KU^uM6=as6}VnP zUKTKiyb~ciPde3D-kruADERH~E{&qq-S$rIq@99x^V~;ocpyDB&BI~P`uxXhAHkJ=b?meRWG=2`=vf_K-2G%d}+q-G#l;r65>tCPc9q`J()Z}%fL9>Up#(tQI~2c}A{SG_F}VTc(i%4>wjY+1xaem!*(6dDY$cl@ z?|O%WjV5Io$-5mE@MR9s%Whz$u1b#WB^nw#e}u^Q{ol$Bf@?U$Xp2eSt1rLj!4KW_ znCWz;s}otQ8an4 zm#h!u_{613_D^qZ9!W6z*nzAU6gNgdT5;b>O;_3U;`Q(_6 zCjz3&yJTG;h6QcV_H;|nMLBav=zGlT%X70b($4Q+66q!kS$VUGd)~G3ekK3J>>)#D zA1}DxQhC>?RZ7~T(otyxd3Olea9b*uD>UeP{ND<>yteS*Sdp%YYNGul4&i%7uD?@p z?(Obwlh6F|yx{B6UAR2&|2k6sY-bp8w>pNoPB>cr;LCx;ed$~mKR-7+jN{Pj^<71Z z)c3mcjQ9Auj@puy9EZBn9dz>U!V)saHEi9j;?p1agSzWV3tl^b0LXg>K<^AuiYb|F z^m|gfzjbXdc@m{HCgeT7zvqBagT1;&;qu+^6ZgE&PN6%m{LY49$iaBQD=A~$o1n=OzDDsh%;B0@{ZA10W>H+oG+Sjo_-lZmuSXe^Sf+r*gU$0GGOUF z>GAPi!xM{&w~Zi%&3Ab{wLWupH@xqi<2n6|H0P6k#)9n-viWi8-f*qpTO!6Vg)AJfFuCN$%HhsdeaDeCHS>^GW&$AZ%v@lvi3G%y z^C`b4DSKPn_BLvb9fp0251S{RsX`8$?}qx~?<^q4%6FN5MVS@ji`sB{OH1EFNfT@W zfet4C^4{S^V1@*UDPfr00OHpw8#iu!Lz#Y9qBtpW(a&OT5-BOQu1%14ow32ImO$*_~ zP4J4ls{=UQ=eK0SItv;$FDBX{a*Z}AZJJ&8@W`MpXu>+KbI50z_4k$q+PjSZz9j3j zU?GR&60yCc;!q^sd(Z9u?vHe_q=2D zknQ|tB|W;md91sBY(9}vSOJ0dCjj!^{>*JZMlq2^a*Z}kZhP_I8n?!nC~|*U@%Bhp zu5i#764}`(FX51lg|+A3LG#XY-6!rVll?f}ncmXU_uxUp0t76G0LZ%q6~>DtMNFJV zuFKh)lSRAQb|qkMEY_T8n4Kb*dFHRbf4Pa<6~$H|9^@Mp*o z3+#LLH5ub!{(jBzbjBQ{2P63|I(-`&b;AC zbY9!}&-mm$>TQm?+3N82)A$tMAyDz5Rc`RePR1=txA8fNbE>&lpv1hhz}3t>L#Km zBG#}?SVw-!xJFafn?v65GHKBwCXOQ4Ejj@X0s@_m0LXi%EAn>8u$YL0T(?7X5Cssh zAp#)pR$rK6A_wH!>N8`x831`_R4v$P1q2x7yg@S+4vmG|cu*784n>(KI3;7B0Q$q3-` z-pR5I`E7Fo(DuT23J3s!PD=n9z;-EmkoOl=F*uKfKwWm?qF9Dy(YNXBPiJEZ%cgdl zD)0Ix5jKDT5HJS;=y^8>MF;~300AIi9sV)-NJL{(wLS5P+Wd4uB3(0s$ZZ1Xu_l-(mR#b^`$* zU?2eU-sznZ0JIYUkat7716x4A0tkS-TRtDFHw`5inKW+hqpJ zHlK+0ba;1(aARO{4!<1*1>|n^^*Ed zCCF93jN=hs)R#6rP_|djanxk%F#2eD>mmhtC&9rQ2v`UKkar6y2uKDH00KY&5de9I zY5)XULZCCsySglCf@7Cy`*WUFR94lroA$NN^jdXvo65Vo?E7%0sx*A}gY*?aJg;}o zR;Y>8svaMhC~}PWSAJ`eD)Tl6qZnTLioE(D&-$!4um4(!LL*C#cF{*I>=E|H0VFyd!a=eE1l~^A7#!&;z;t1AL?Q#zJ2~>*QVW@EFLuzARw_2v`CEkatTc1xN!B z00KaOBmnXbH30~;gg|GM_xk%^4-gDVe28nEZ7gjn?;2I*{frybB*>}AKFMoYk(Q2kzdB=Lir`MsAjpV)mvh!JYvNKYCS~*sP z^;mdaFY65Qt}6NQ4L5F&*Vi05pOSL^*q(iNYA<((xT~)X}q%nKLuzBgPlN>!~9@rfh))n=)ay-XwL0!L! zyn}J$0zL5&_I$6Q(VNpM8<6u!Pfu}n4~y`(!`vc1{ra8$_L$?a&(p|0VR=E);&Hv5 z&tH@H@}1Zp@MR9+!Rpe(qXa!aMqbMr zFD~!)ePWisHOLvmxL#rNlL~bs=vmXlm|t278|^@+*l{9~Dk(b~N>4_62*bDKNpCI< za0ptSsaI>tLDWsA^x*Q&^Na}h_MLqR-NevX-Z?|JJt8l&$j-bb`o!HWQ2=<;4K z`D&mba8-7b&}-A;e7FNQ-q#UAZZ9n^EG(89cGRUW?uq$-nn{GC$XOM@@m*lJXz&6( z@70&z^Wc~+?|lFH+4VO*?8(Qt9ci`%%$!#f}V1V{oP?@$wf01yBImO}vK-EztTQew#jI+whY(pP_P zLy$nPgycSC1AUVW#Do@nx7 zg7f&TSu#~^PC~e_OVrsalpuC_XO5S=5t|$E(czo-vrjDxbr6i+UVsL#Hp4R;noLxev208U!c!e^kohb;G^x*Q&_nUuUNubxXpUc&Z^4?IB`@<}6%x}>R zymOvdX!5Rpb|k{lZ%)GJQ~J5sJGci6z?C&aeDo%_7GX}Ojqvk-A{BE4Orz}nV&F-{$ z9OS^^`@VJNSz4UG$F!9C%n!QZer`W-RbIvSuXwzi@T6pWs3TusC+Pp#ed&quB6^x& z4-fzX=wT~pw)ys2;74hDk%oAH01&WN0?n+m`^yyG{jhGsSeh-MXEPUdw)n zaPY%Nb|ZOr>4W-ZYp>1ob^iNlsj6_t%cAfjr440C6Gc9AQnVwo8%hp_I|i&G`_CJN zq1jT{x>V|4 z8RcE0QQTP-fMKHPKbJLgBRN}oNO_OHma}z)d*r?+HO%+CW0-5?`gF?W0h+wyS7p#m z?Ou_~kELa%9E=U(2_kmj7cuZfnZI=?`Q7rFzU!X;3IO_qChzr<^?@9pxKzph$?k3w z_DHV9`*9nUBipcfMX7|m!GO52fLx{DeJV#>)UunV%R3tX;TwIl^gsVr{`X&X7v}{E zFu~xj9!XEl?7`=XUS6L4pTDj}`At4kBUw6bL5BL_x>w##Q)bTgfv)%VZB!vPYasyg zZY?DR=>!5mpfeBvdG8FR40$x20LVLGc4&pnROk|Q!O$U#f6!2Ib@R+&-5m6wz2;o0 z!R5V6;OZPjUB)MUy#9GXrY<=!QiQr@YciMg(jTea@O(d|Mi&L`6_<4Tek;k&d2)FC zV*Ivmc6n!vw*i-TyS^*3$xi-;C%cC6yUrEY)-{zL#{AM!*k}i{yvwuK4B}#3tn0hF znd=&zM0vxO9<97*)D#~c?-8;o`$nS)>$La0r=Hk2qo<&EY;vXU5&>P_CF=q)ENFvv z)_v)@C}-{neUEv4d2Uul+WGxUBHe@`D{nS&&%0LMujHSYJ!Hu2;|14SD(@P#N=aK( zD7~tZq-Y=0<(=;rbGbBSUXYMu-)q*-&m^mZ1zgwA_+!~cB~NlMZcn@;zdD1E_xS#v z14a$@>KX;|Zv2IW_dq~T0OVbd0ycmE5C8%lP5|V+!;1hCU=;*F-gR<`%+%3ywyxKl z+$+2Iwg)dD_J{1!Iy7dw^7vSR*9WOOdB3YbGTPVcpBH87rw2!hhV6P%lkrI}{@|?z zEuIOFMbeGr{n?=~d)+(rH}qq+useDGt+Z1aYD-qmG4zG^R+c)UWJJes^W6zv&-*-bnt zB@d8iE$hS8T^ccD2@Q%5=Zj{XZ+w}?@Hx6>k7Xc&T}_i-knje`ke*- zXif$U>oWa{GAqW{(5o&8UYB38E6jb^xA?GmV!C~D*gTpC0Tv(t1n2}n-swzW4-fzX zK%k=tfV_7Ud5G7#2!Oontc^it@g7+FK?!-}z-#&KWqmNursQ3PhN%lhQ+|48xI0=G zI`b==ysMub8YSozpFs@nR@`0FpWD2=W5OvXD8uH5?=RZWEY~*z3Mw38w(cUnw{iKulvc|8XUC!n%)p zV!gFD!7J{r4&Zd3-;xRI*oMt3?r$83nL*wKLpB!Ho_`0;AkTH5xUWq1<9KI|uv;H5 zdyM1I@BLHKlI>wmm?(08S@HHrSFUi-7ZTaoD44L$x|(E2ZTk@bd2c_~5EBpp0zjZS z0wC|r5rWTw08RkpU1x9%GOI2-{W$$Rq@8g=#U#L2E$)AHV+mi`{s6LTH6^7zgB zxwli2HqD(8pW4LuY&LmEebn*2`2Ck%m#OQEPR96QSPSGG;|9ilpPqZ?^zxBHVdSny z_=I&$q=zBDIuvZL#`50qH0g~lb~<5KJvlg0BpScB&}fc0N@y(Up~$;NetUU8ykZ)j z^G*(%zm@jej+h`WHgJu84gtEnYiiR!?Tfig*l_l?Bt0p9sJ;EDM0Dvz`RH)$yGs*) zIDP4A%IQ6yM7m&(lMfZ?$4Aiac}KVL=d20lIz_BLla+OD!#EK)$izp*)uqS#W2X1K zBWEA8;@qR^>dH!K@zu>!yYVqzx9AfkO0`;Dlbf_4#F>N8@w_K(x>j0UT~nF8=gnUB zI89i901%)P0C}e~fjvL~2mpbOA^`HmmU1u5(L9nXP|#Gqa>=Icy&9;*}R1TQVuY1+N7TUIQmDJdDhrbzzlvbd&V23x>IJc+S2<-(3CqkQNM^ zx9>A&*_#8=%;FsHQHxGI))_QwdKmM|no{C}#`2CH?EaoNx8IT*`l0gj?9~Ig?$IYp zjrzK&p)#e1D(@O)UIP9&KZCsMzEC{3z{#H^2PGj^~IE59JzS#WTY;VI4K2 zjkndcl7nWDcO46O1p+|8bOIpnrZa>PfB+Bx0_GwB@@_7Y5RPpV=#28-SgYWjwGv?H zd2gqzv|irvgn_)}E@aJ&1VG-~$@d@{vlFN~ zIZ=Rr6?h@KX$j081wBAj!M5SVgmJuxAIs?f zU@ih6@8%*2;n+3-koTr^3qAt^<|AOLygx@%RKOn)00L$sfXh34r+@$u00KY&2mk>f zU_Ast-pwaxEFslpCoYO*SQdSo&i=GAmay7#x4F`3u5j8iuN@M$sq${ymk}X%K%m_T zK+k)-BZmlq01yBItOTIvofQpy00bxmELq;$A#D%^5NJ07rpP<`j|P8000@|u0Frm} z1_+@60U!VbfB+Bx0zjZm3ABT`+(=6;EXe!w&p%bldbU5(Yska&j?*FCqYx<&Xd?pp zicPKOY~Ki@uMFjS8*BmrAYdK>(DQB{jt~kE00Kb390ZW>m?Ibn0|?kS0g(4LGBpSm z2pACndAIS#6tZV+1VG-ct;8U`KmZ8XG69fxTP|J5oB0TUyc-!7yafVnL;&R7eC-y5 z1O&`L0OZ{a5FrR400e-5nFxTqn+YTYW8(xs-rLC3AXp$^M8H&ex1MP*VFqs?U=;*# zd55nR5C8%|00;m9AOHlchXBaCkzv7GAkanxOqF*Vzm5pm0|M<$0D9irn>fS=1b_e# zU?%`Q@9b>g6Chw9&?)6zU7h*ORDS_Z!6iD`qMq0GV&14M*g9AcxL#8KVy9c_SyjJ` z;}JFarA-f%?Ue@{HTm@!eYCuFk%GLF;9v~|EQA2ayM+`4Bm)Ql0U&?~fV@LB00J!` z&>7`jU6wS#vCFjmIZrDpt7_U!`&wsutvb4m^PgT6<%mub_4Eu6TG1#o2eg1uuVnSJ7&wT6xEM#i!Syla1uP|FZL0DB_f#R*n^6 zJr-Wq%Q}O+t4e-+!;RbH^)*M%r=*-ewr5{zDPGFT$3L(ABH_@<3n{7R4=x$wgmsI( zQr%QC6*+5zxsKs0Pi1DET|ZXD9kB8?Ro`1J@5+bU!}w;9cdpy$FU~!xtSBw7Di&{< z>chi$UgI}hE|OMORF!6a7v+avpFq35zFJaMSyh&`GpZ+X#iAum0UQGaIvW9y_s&-0 zkY6AG1T2{V$h#$%4y4U;2y`xaR~2p#Y0Ta*Y+m~7BuCGg2X@DWbw&NH9M7>^P}i>_ z?_k`xKu>&xJ>P3+^yak62IPFw(^H(?!y^3cFt>Yde-zX=9iX2Vh7&y&T*Zoy}>|n=gR=B%Uj8W{Wg@I zjP?+QZ_AV3TpHjIv^-O<*33a^n9_sGJI^yB+}n5dC3F)*V|nKc-G*N$K#T0mYeG)w z{t~{Vb;=;mWsbNQ5`r@9L|EHNmIEtKA z0UX~2hKmMh$U$p+-m5Ra=fN>u-ueFXv+Hks*prWOJzhI5ef-VPF2lAKRUDn_$;AW# z^Tbb2P50!8BKDRRZ;x>0Is~tfNPqi>7q@Yhhj%~#2#^Fo-k~M{0U!VbEQbKdyXBMx zq{Na5bS`-(rLX?ph9H4n3CVrP$bX$Az?^&|m;HLbs!o>wds6ZfB^nt1&4Lws&ZOn! z<=*^h@eqM~^w}ykF401}(2c2=*N1R0zxiiw9-iUl{r075yeE2|zeB&bw_VJBAW8jh zmY*`Ag4pGqIbQNcY;M3uhi~4`KD8{=K`?rI z0UEsCRC*ZmtAo+_l_Kxzx+lpihS~`tc0SY&j#m}#pWy5gIyK0t_rfcbLG6u$Am6d1 z2bXug-~0nh0==gFT&`x6_lBC>A7*)Dev5A4o%6&(lXvyABN2{%a}qwE($B@-!98%w z@-xLoL-=k{{tyW8K>72izc>hR_)9Yuohscs=x^jo_exkc* zz$)*`{DeXDFFQULK||TeXfM;{o$ERMRC(s&AO{ZL_pLL}(&GF*rlr(pe$Wl~bNhj- z@+!W6#pC6KCneiM9r*$~LI2P0OHYg!(bEKbfB+D{Fpzhs1wa4@00GM(0P=1*WdSL% zWC9@XIu%4RYlrE2yLCGoy_WqD;oygl>_+nL(g*d+)?S-_iAQdQxOmqp=6N*l_O zCW?IKq-aNEH}>( zTF%xH?veYR)G*)kj$y8m>(eQh2Waw+UzI^OwR=S_KbDr6axgZCCy3aAU&O!{W&YNo zeic(3&4WlLf?o&D9 zqL$q>UEb0758vpcrT_W2^1uJ8yErdUfC&bF^+o@`+?;Xb;Vg>?000Vly|7XP53;_Bv^!@4=>(Rt0eQiIETm%!CIin@$X`gr~Gf=pd7_qXyW#nMN{ucG+AA*U_Wf3po%7`I_{I2b-|X_v7;ghE?{+`jyzhPy=D*><6>Rk)y-VT9EwK6 zmL9FVXVerQ9`6ydDf>pF3G1}?yr-VnIHRYacWiQ{?h*lA-X-e-F)V0Qg9TjI(D-B7MI}#iFK$n~BfmO>koWlho&!b=_Ual1 z@^1Wvg!e!|PXOdyj{-J;01yBI9Zmq`y~B$D5?~bsK;CtxiDcH%bGEM6oZKtB__hZx zAohps(mFI|y7Kr~f!7DAI(fgVKr-6b>z@~8>Zb=siiYiaQj_sXFaF@I1(aTCUFgiO zERt>{@6Qf}+3W6kNAgaOmr34zVv)Qzl^&-2GN+R0dDq|bUVAgX7sv188`_)O>vO*i z6S~j%{?eL3!oKm>*)LR}u-Ve1llMAx<>{!d0Usaym@?bE;huMO*^jT<3nm_~&?b{6 z?+rzJMqqXmPfE!He?}qc- zO_z6P)T@4Hfj^p)0mHgXzoN{F@ip|S3xe0>m+T62ANDOiY@V2IpBy%i=0Si32mk>( z0g!h(6W9X;fB+EaC;}kw9Yr4EwJri6?>cK^kXgJ3)_zbz9y#z@etTIT%(E$ZSD|6* zLeZ3;o*C|r)`iae$|mpXXNN`!dc|iDgS!=X*YxK$FYlOe$_dJ_`QbYXiDC1s>0!t( zb0Sf{aiaTwxOalc>DAqjlxk^mOgBNu*JzeM)&(Cn&y*g$ylXVo zSLXV8hediD9u;ShcTMFllLc7lzG5w2n!Ib!Ty)*gTy(kQ)N`^6(db_FosW%5qoHVT z7}tK%Nqlkva;dL;oS*-=k~(4C$33y$+MD1NcUK2+y3cRPgmrAg<`wrh4#dnL?}8y4 z3v186gJzKDx=-9!Ci`)`Ge_91kC#2hap?E{DQU^}FegkDxxcJ}(WF zSZ7^LGNiWs2!On|A8UvS2mk>f&>R7f_vQ$}=Rg1_0P?OgI0l(jmmUARv&-bYc?ylX z`gY=ESFCAyZ%|8rkL!uKj$3*B=Kb8;DM_2=&WKNKVth86yrVwq_+I?}%dX4R^+hLR z{4lHq@{Vx>W4}+&y>oi`NTD!t*CTYvp{evR!)sur0MWXS03ytQ8qlCti9*Vqchtrp?rkvjMNu&$rIQdYKetZP& zo_CE#k+UY4>lCs2Ojg#p4dX=IAQK-ISC<~|kD1={j+}kWigS;ut1By|#aA~^?Z(G= z-J(yFDAj6pO>WYH5N8fT$Mc@F=~`)ZbxmdVo;Q2h<1}Fb0ziOH0OXy{1oi*{AOHk9 ziU7!aN0Enkt&0H2yUr~cWw!p|(by55_5v5L9w9R~tQ+OfSZC0z z>0!(-b4rcm9X+J&+)OvDPu#{gy}A9C+|Un|muIgY$aRlCS!&eRO%0VPJydzuDDx8V z$N3rLUH66Jxdl%CBq?7vB|Ouk;!s4jl6^6u_{07%2fwk4PY{pHYbd+8Vp>QKXC5Au zp!!fB+CM8v$J2;X4HcfB+Bx0zd!=00HYE0P=1=Ib#W_E<15i zEW@(s+jRD)m9d1?mb=ZBPIHCRmU-=vuuYYB+rEqlxdQ_2P5^q|+Z{PX2n2ut5MU($ zJ@2e&-~%8)Az;b!-VSMlD1bn_5imvG(SJ1f0|G$6yabTEn>RoR4F~`MAOHk_01yBI zZAzdW%;iQ}YGFa%pMUQw1Ya;;i zZfzw7=>-Bnz?KPsyxVf=Lf*_r0OZ}su;48aXd?n3@8)Z_AS57Q1_B`OW`GDm00AHX z1k6MLJ2o z%5K;M0zklq3D{cCyO>f|)NRUc*aQMEK)^QTU0JYoupn@~q@G#B)YX~aO!XJwxLl%> zE$Vq~%n5F8Z!`IA?sO~tyy};6Jfh0KwCRDez4CygCckH+kCwMCQjm8N9ISzWg%ALF zw~&G`BtuMWl54|W*a8ATpi>aAHF-ycCMF7wToaqH0s^KJ=#28NE=!u=*k#)OoTn9) zRWz%U|Y9h6&#|I{g93%df-&&-~yv@NV zhL^q~ueQjuKI_fvzgD8q$daR7^id0YguTDxmW+%Gj}Xbbuv=VOZ6j1_+3npi;XQ@u zG&|3sF~^Hl=wnsU@p+K}9(H(GLccL{_vKU@f@yTR{*65ENZcqNK8EqULq9t7K(7A) z->AK@&{xnJc_$J8@~$sS*Z=~SKmg?35=x;_8pOmqa^2_ycmo80fbA0idAI#Ch8&uM zKxdTq`ukrG5DZCth-;l~ENv?98dc@}j2rlJX>%wC8~jx=@h0P5xl%2=9M^*%@L2{D zXm!QecfAEKe|=ZcYNlFw$9l!5*P)Y*kRU)D*5pZ zH*SyD*Bm*Yl5+moo_(pMcquC%|Gf5#ghMAUq@&R{a6uqz{=ZHeQ&kA6A3U~-Z^d)cT1#7bm2iQyK^{ZfFs8oZ2*J;1Ue}JkavqK zcrlS8a*Z~5-QW66^}Oo4k&eWESOEbbVABL_S>8osf0RG}Q?0_6@{?1$*mOZc=GvHm zwaB|#b~7P*kUK6b_8vh~)@Bk4rz+eYA_(|0hww#p>ETg=o*(1>hs&&epP1!u4RXdX zu2Tl(Ej@^Q~eieBK(j}QFV=Y3@{1y5O%G#!X(?>91D#^WiAbuX>})7K8SNnq z-&7T$z5x7U6ty1IiF0>2Xn0k4A2nX|d+r{h$lGN{J`3Zwp-)W*Jn!K3cJbr7IOjVnc5H9Qzb+!tnh2^3I zYrMF;Gv&9b^f2aE2ZQ;QLEiDS?w{c75;`@=srSMwltJxGL9nC;mv_G3`~yn@y{7$K zu4a_?hML?TW_e?Ni*DeZ^Ta}vclEO)5srRy5GiYPLuAP_UAe<|Kha$@V3l`ee!?JnyP%(Y z!3^@Q3!UdadcyAlAmg_4wPK>pQ2ux}~rLoZ zLli)u;|bWHyd$V$0xarz2YK)KDrO@ouo8K%zWkmCKXlh)gFg{2#v-{y&pYPux8vo+ zoy|2@KJ3a5*`^;R&noYBn64L}G(Dqr*$)v8e)!04B+)K?P`_;LwRyhIe?Ki%74CRh z6n><%p)6^l$Y)N9c0_hV$-!{PfK}wU0Hd(Tw|M%wZn*ZN1rJ5r-OiFPws_TqywmfG zZtiDK4{qX3=a-gbMtRq06n9nyV3=t7&t=WrNY0iXQr_dQo6 zBmd||&evxnO%Y@R2(&i=koWc`-jevl#6cX_vD-6`Mfo@l-30R95^Qh`5U>FPHZJdV ze<@_Oit2)k8(;G!CSkIHB7-b+2mvdRceONSQ6L8s^?xO5?y|(w_qFqlu}CfJrBM$}I2l>@|b97#HjMu5RW!=Cd^#w)AM_J)@@h@OY1qP1!dZ zO<1SB=RNhr#u+^Yy-@Hz1*D9@ypJ&^Iw0-5fh9_e1PAf+*op-9SXBI-1BZEvp%uS z%e$lJY+bK8>7TNTZ+q|pVt>dktwVkOmB+^lygo?P$@^UelF`0i|GX$uKRq~7G;G(C znv73+@ds}$Xz@&Vjni+qXTR}&eZEL}r^m}A?|6RE#Rc~CAQPwMm&`Tmnn~X4bH5D} zy3hFj(wafSzVX-DFI1pV+0vtv_d0du>8P#&A0PafGTXf2o_BTGkFVMbCLXWQCXgoY z4MlrKV0IHvO34G{Sl&!}+2a=Nn(9F?^0L*)R>8-(^X|=FyA_0ZZ>m zkB=8wck=_O2Lc^Q0OY+R>9fTxMjzPqUy@NzvJ z)1PaQcT70t1ZCL#@EwIZr)KSWHa6K8i@Ylf_f8Nwy}J96QY}r6=_UyI8qM;@y0E23 zFYg*n^_97P-eHm6hDXI2YY&_vyKJPA?xR6h`iPq@TL1#qzE$JN|cP zm&tqc6dHB)?ZnBhSkv;}pqBm~*AsIcxAOSS`?x`D$9; z8S>jyddwj24NsHa=whc6cGZ)E6Gfu&dkgiTb#knKWl0Z3-Zk>u%lqL~-SC`ua@hQ> zwBL5b1aYx}YxHvn(B)lIoBnBE%w@ucv$rMbN%2GN?MEe|OE1bthhyJen)t)%OIK4) z@A)Ls1#_Hys7QA$hknmH8s(9*CYb9KvHDC_*0~MiMBE_L9u-F>z;tBa^6Bu9x1Udx)8@ESOI;bCO{tP88WYZ&v@q`b4_mo+^m%R73o`+MHpeoJoXhsw*d zR}bX6N1rU!77kOsnbJd*ca1VH0e_sILEdqc_<}B5PW~h*UpFN@)1%^0gtd}=F`@Xw z{xAo>v5QX-j|gliySQRn2=RA}!3Q7`b6V~DBmggOb9qElK9LICShlg?v zvEm=HO<0G2#7XTYT00@|a0Q9_@gCc|h z1b_e#Fb@G+>v=a16$k|g7!$B$d2ffbK@>os-3XW>@8~}o`~d+VU|s@9-pv~zga!nF z01yBIKmZ5;fi@-34(4(rEw!*9@6SK~R4MD({z$JO57RqNhjfoZq(GpJ2#uwe-JrDo_CKG_3casr906+i;00FZRK)z$Pupl5HV7mlB-rLC3AXp$^L;&R7 zcH2?NnN<=1dAG`9gG2)XAYh{eK;CV%U?E#(CIIqoWLWSP2(%FakasgTUJx7*FpU7n zyJ`I3Y#;yxfPgs(fV`WNCWK|X1VG-~$kZTMAYeqmRC%|&=`PJMxin-72y`3)T;4k_ zc8IzW0sXHmC=nn41b~1I5P&w#1`5$qvjFmLWLWSP2(%FaQ{`R%j{r7+01z+-0qA)* z2Ssy)A*KXE-KOk@O&|aSY@UGa^t_8HWkubl?1oJs@WKRaQ{I&YTL%jQ*GuY|HB4Qd z`OQ>+0S?V2I@zM0*T$US=Jqy|-{wxY($A}Y8OI|k{!5!4DBCL!IBN3SHu`9J>mmht zC&9rQ2v`UKkar6y2s{~LA}!>a*n|}j00NzjfbGaTDmgJxdgPkegcT4l7lFTa@>`2knYTF@h5yo5()T;SnNv z7j}zFt0f}Wt<7{u{{Ghk1Va)Z;#y}LOFPIr$LVi-uHVVdNIkZ0swZX_ zvFj1Sr%kBBECUI&y5j7+-h!9EzN=_8Q?0yXz2ejB(8)&f-hbKoEEI9dPbt&rm-c=<(zTw90@%ox0=TlP7AKSApwG=O9<>Q~%evxqKnTnjX!Cc4im8UYZ&aNLT;tp7Oo2u`vmv=lsbI3c-Yy8(&OR6fX%CdGw^(3xF zyy#aS&I1CSodC$Y1=RpCkruS(bQ!zlN}(M6Hp%&ae&paP3rZ#=1qc9vwj*GZ^3Llz zCE;qZ;*UT6Xehs)_zyq(w&MpOcNPNHBJXP1&4lPd?i^Gu_8vh~)@Bk4rz+eYA_(|0 zhww#p>ETg=o*(1>hs&&epP1!u4RXdXu2^{dD`7&k7^6CYvE_Zk|#Ijyn*IiK|O6leFa2!A`wE#lL!-|26UIS%_g zjqDSa7bGnn*V_r5VAp;0yzld<&PUTlBK`g!teO+n-4Vka17{t~*Qb*qU##)6VZ#dD5Fp0~~^uljXu346&Cf zJ-EE{JR`!reP>@nH!(Dpch1ml_;mub$j-bb`o!HWQ2=<;4K`D&mba8-7b&}-A; ze7FNQ-Z$J+p_CRE78XklJL=LG_r&}^%_PE6J0CI01#+70g(5Wvug7r#Y7DFTIe4!?&aX9v(?!k?*tTB z0fEj!z&7RGdrb7yU^hO-bAL6lSaC7R3s)IffPe`EtVG@wl63=kJ~Q`T%X{?T*2Vo_ zB{nbb$l3!wI(+kf_Nir|4ua9!3-p7z>+fv{66lqX6hUOGiY?T_9ccESA#?;H}LpYe<{4+NX&+zho`%*RD z6Ftx0q2JrvE@nTFq<%NcPZ+%VP7^)R!>k@~*CXlDuN5ogiZ8LoH8L;rI{oO&<3LK)QFI0*6`OL}m5 z=ljh+uq4oH+Rx=`MtN_j$^BuLH|DqK2HrVOEHrsnKRXiP=r>b<#rz}5H ztS@!)9FP&C^;DJ7_f>Q7hn_?`4&$<*A3Tx zwBVs=yW3gv#TKuckav21(artr=|S?|On&uAZgkH(hV_l!dbNyl&w=93ssIcVP5-&9 znH$O3(nHF7{I#5|BitkRJ*i>7=N-dbBiE->E)US;9WPkaZQ~WW{8(CM%E8zmo*-g} z?xKw{f9p{4o8mKl*FF6e0F+6Zyw^+C2XcJkQYHH*ySq);Be@pu$8A)OY(4LaQc1=Q zqb2?BQ@Mf&&~$lso_wZ8vUJ>n4E4ixue_b6%$)55UGJtee{gQ+CIIqoS>-RLBnRZ3 z0s}UIKqnz!+w#u$|LAhX^@V-mj>k??o!c;*RwD0eY09EN4kqgVO4QtCiKp*t=Nn^@ zTteRM`mV?(JG~p8>>9@JI#;Z_S(;Veg)UJS3>~t#yEar@-8^$xHwS$Qc+I&|gUfrD zz|}d5x{Ocyc>VK&OkHwdqzHA*)?_Z}r9V=;;rV__joyNdH}Le^_ghJJ&XdFb7vsbJ zS@OjeZv!sx4Ee2VDm_Tv>G?HIAo-r?d3Tz$^J?bx^E*EXuycRoC@~Kl`Kdg6%^)tu z#k#($o4JlT6pe;0Jz9Css3|@?-XmmF_Kijp)@ko~Pd%}5Mo&TS*yKvxB?7vn}NCf-#8?@H>6|C$@Qccl4aC>oq6+Q+Dxf4_-j*580)4sL#Lh_*jA02dO%FzpFqp+Slu!7iH?F z2S+BaQP}pqg(aC$Ay7F{X*MN@? zeoUEd-f+*my6neS?FAE$S7?(-llO+AJtHu?i6^Dx0rIS6eYml6I1Dv!{*VP4zK_LAn;-YK;B=BTU(tarUVS~PJscN zK%kQluvvK*4p^96a%1IiXSm(HlT_t4&ZZT~yH2lUm)`TVk02hht$ucBl%Q991~CX) zad%CBu0h^0;gl1UVe`Xx6zZIswddVfX7LVF`#}kL#*%K3cb0rLDenyV#fPc0rsqZF9Sv*PHiGZ+#xFQrW#QflBBxh(KT@it z$uZpoAz!0e{#X~b^yuYXqp7|!*UvjF(%bN;ID@=vDu0xSl{ z%O$6tlU;~L_p0wSzSp9mXm1$Te$q*NashIwuY8=J|G1JmVco|)vEJI7;1zdQ2XMO2 zZ^?vpY{TZ&b?GQT(|g`AQRM!z;_Z>HT;ZTEB(k$nFkxLAw~r9KO%nilx1iz`6KNsW zXcOd}-~lTj(5VR6l)Q_HqC;ytzgbC-Zf_pz4)-~Bs@mL^nY9vmug%!FXw`v>nYo4e zHxJG6=k?G|{#}<5-;3XW*>#z^zUX9(ABIun9peVZexIIu=k)TCLSf{tNBXJDS}gDC zvg3bucA304PoYs)-%gzDiZw0o4QlD{aXm5DaVwACyq|kJC27;#8S$x2jL&A1chpDC zl&_}cogu$XrRRm^UDNRNhe?ihqjo&3f13107dxG>tDYR3C=!j|Tc`)ElVklWOL{2s zu94qf-Vd+vhUdJK!{%?L{k9_}h>Hzeqn|^7F7KM!^iTU@E)zDKy)8*kiXUokKPnMj zdQm<)9Q*Fl#2-#yx|(u&&nJ;CnB(L_MY?M_^n2dXD36>q!Ca?^)n~G@&TSYc;s%-i zsJJ!ec~qSDq)pdKtE+1&v-iB&3m!PqmTe=1ZSw>`-Yuwz#Y9^0wNvtut|9rj@VZI{Q3VjsEDN|>&rp-6RcnX0wxf!5_y;3O?-1i zFBklouUwD8(VMSTX?tH)CBH5h=E~tY`wo3`_2)wFL3ed5i)bbx={{I4x7i*BriC&WKw_&UL+1)11B#$jLe^PVU>3c zW4@Y{cb5FJrsu`w9X+J&+)OvDPu#{gy}A9C+|Un|muIgY$aRlCS=z+N1E%y)2z0GvUrZ?eus_VfZ|vd|#3KS5$}X;$7Sh9+ zcx14k`-oXvu2xWzNSm+@FE4rCk=T*m=nRhMhz}3t8e+viWSg)K|BP*s=b54Bod5wV zAOHl+LIC95EEvrbh?oe5T$?9E2n7fL0V^Y5lk#q5WdO;w1_D+h?`%c{`#UiKhMxC! zqVXc~uF-(JTSJQoY3xJg#J_4r7`*RF~KOg`E%trv1 zck_h?L77BA|04!U1PA~DAYcOopiQ%ZLbTK@fV`Ve&R9aK%T8Pr%djl^Hl6)xWh`N} zCAYdK>w$t-&9v%=15MU-? z$@1O~X@e+$K)VqzMc&bWH24DoK)}2Nki45WKnM*800AHX1b_e#00M1FpdHNRMp|lN zLEfK#{;5*dv;C1?LmsAgoDS(8g-C%w8xhb~Y-&Ac`$iajWtcC$!CoK$1WX_RJ?|#K zgHwS35C8&ZCV+g$%ppQ>K)@CWfV{VnsX?$nz=#0IyDhe$kS8l90P=3dg$GFo0zkm# z2!OoXT#-VC+JpeeyOCkRTOiOz1VG-~qzQvSfxwFr0C|5=a&R6H00Kb3`~*PW&Ce7< zv_%3S?`>pi5G)WdA^`Gki!CVR$%+YpyjyYMLDGQ$5U@D{An!I;q>!ODApr7jWLWSP z2(%FakoPue!XQu}@S+4j-d~g)oCgGe01z-g0g!j|GldXskpReh8<`pe%RoR?xIIJ= z@MVsI;WM-EQsyTN5(I6yS8w)^Uob$BcUx>hAx~CJ0OZ|@3lEYG1b~3e5de9&xgv!O zwFv=`_ZKuVTRcsfw>cQqvX{P+5W*|Z`m8sv|5}McBTJ5U(N{lVkFfW5+>)uABT$}}C4#5Txuml1i@0L&skOm+C z1b_fZ0OTEN0uX2k0g(5mm8(;Is+D)FSA2RM%D9od_g{8C>rQq?%1lnWBRA$!M^pptk_j$O3;_}Y(j0pGkoqb7WEbpA5 z+a9S18nQF52|1zrOB&eNDDJH6XY}nFzPkt=PV~I@nV-0HLJvC(69&#Yn6DqyF8y_q zqvy;6yW_&TqJC|T=h!W%%O53zA)OkHBJW__xIj+F7Q4=VuL?y7a|8G5=5hKYQl^*TnS) z@Iyve;sQjF;Xs@qZn3CUTvcnW3T~~+P?RBB!Q$TjQL$>>KwUVHA#OnfC|hI*2qF%a z%rFvbMa%y#VT6zi7s{}+Qo(1h=J2n?BYDH4d==`g0wfa z_j!^Kb-}*3T!*=#4b$pTiKZZGdSl%KQ;W)rGamZi&#A)6lffv9-M@D8>5zz|^t5MJ zT+Aq)twW2@dHmHmK9kfG1~~c0r9}U2*QXtV5R&&6?K0>EcUS4FkJz7FK}+?rP}5ly zl!tyhP?LLZq@3EUQ1pupY%9J$zeBrWr*ay<#K7*dZ~2R6vMafQxg*GXOE^#h1jI-H z5} z-W3d7Ba;pf?>zQwPAT_$-Vvn3*j>@zea}0hK0Aad>{S_uOqH5euS4Zs5o!7nOARki zj={>iXsK*~&Gbj*+Cs5|^_`E*oeOTxR3j$uob57qFS>7Us6N=}^#L9a~S zWg@5J5T1N)O6N{ir;{UH4ccMc8uOujNRD~Ru|>alS3zU$2=dPL6a8FC&9n#;pV>*YPBG}mup7xM#&Pn#`R zSAWlY`1O5r^eH{;?-#bRWF5|xcctEcBrP^M--9ynk^W_J6#@4UR$93BLNtiZI!sXp(^J+R z2IbMt`bdwBajXUFUTia#({*HDunuq9Je|2CTzTi`%mj6TfY1qmybB#MGynvE01zNd z0OXx8DyS&a1VG-|+)`%V(my_Q&__B<@VxdcH7y~`|A5^b*YJ}11?ya6n9qqz@L;YO z-}Ib!*0lM!h+D^3_HBps-_CZgH&<}gul^jW&}p`Ba$#9{IgKg$e9AimCr^6bwV&E+ zOgWQIW6( zaHpOWW48$AP5!i`?E~AXS#Ar7kH5Wpf_l5Y#2*#69Uc`Y(`Q=fJP8SaypwQHASECG z1Z0)~$h*uAJ#?He0wC{P#Z&qVD>ARTO*YoR4i;st{!`ZZp(f0BNJVUxT! z99Qz4Os1^&&uIPm<~0QmJjUyxGtbeD?NMv|~matdea zdqw)+_9M0Bv4`0WU*((DIt45QwpFCVmG_222>u2Fq#ywDPKsfGB!B=A00K+`An$M> z00ANdK;Btu1%CnoVG{s(CvrxDIzT{V1VG+Jh8h|I0zd!=v`PTvy;Vd|0SKT3K;DI| zY!Dv^un2&>!zmXCkct4vJE?{Pk^urhK*kAxyvz6j0Np1@0OTFi5(tQfK%3-!JA%Lq z2mk?r62RnLpaCHo5C8%|00;m9AOHk}N&w_tG~yZ-bIibGyw!eMxZV7j{b`V zFCYK}1WN#wcfkgPXg~l600AHX1b_e#5Gnx?n9I|M@a)X=+S=Ocs!F^U%WGKG8XZUM z*K8pHARs^jjR!XSagO&J!SO32L*FMtSAl@22*8zhQIUprfB+Bx0<9B3eW&$GPy-0a zJOPk*0ooaa0s=e;fV|86=@tNxivY+wxyA#s0Rlikwh4f|%l7y~?}-usdFNqU@DUIY zAOVnfqGu(j2Lwby0OVaHn4u9M00e*lAp#)pgfKxRnI{19ED z{$DbGeggnNfCmAPcOG!W_R)8o=t#JW*ziHaKtO^CNTUZn|y8r%w=?4d* z2lRkF$xPv`i2uEZe4ic3G)D1#YmLSuU8Vb|<;UZS>8-73m=FjmHqY0Rm(o0P;?TQQ*vh%2^bM<@=ih1b@CJ@tiY)6oH(w+t(G1(*l@=nHa zr;;%#{&JFnF7Vf3s0{=JLjdGmFdW4mg(~(8q&xwT_f`~CT0gGH^mm!iLk&H=6?Mm~ zxsZ-IC?@annwA#YddnUZbIQBi;G8)+`OAL$>b4QSOj)MYz1OnnE0P-$g{@h!qaxa#o zQYq+yB;kf!rH25>yOfM2RZ99n+HQcn;~A(lm(z-qhabNkY^G``&UL z=7u&*t4HOXf~e_@bq`D}Dlg7>=zl+_3MWqnqbzp++Rdj!B9hY6o?USCc3R3ftuWN zBjwa)g`!_Ob%pF1ATf%`7ARtBpAn#&?kJ~gA z_Y;ZvKnl7bF{~j`sUiUKE+xZBm6Cptwi_VtED@8bKk0e?lhk!qgq5&*UGvt*Le+R{ z5)HfZu3+FAnRIw~=dovVO1adqefX_Kw5V^_JhtX9{{{ z@-7oO9f$Dbb5lBZvO1j{>1xmp8hELq3piZ(WFUa9vViA>$4fAAYk(RX3q zUXQXzynNghb&Y)LUwb-iZ4Azby?~TI+Z-4+9 z2!OnkVH7xXpmG*S-p^9d1<8XB8A}5JkauYqMYIo8Dd`7ky8-gf6g}DcqdaE4p@Qk* zOx7*zO?_{W_i}n+@Z7G(&OXj;tIapv^G?sZ{G$?O(zSx7J-NNZk@v<&#j)hwnN8kR zHJ3Ha24Dun%ac)jZ&4R{WBZGVAIi~7;)U17Q?z~yXUe;Qg4vP!epROK>(Be1cUIP1 z@??Hc@qG7C^v-ZB9+|fNq%-9@7%mo%FD3n=ql>duAob>HQO5Hoxv!1Y-gZ7YOHqC zqvD$6olzJtg@TMYo6E6#vsmbT=~0flN@FhOu@yI4ZN7DR$IBDDkgYVxtNsdmMS^=z zL=%(un%wgi6dgM%%e6}$EbdHb+I-7A(Ui;Lx0$IJ*aZZy>!sXp(^J+R2IbMt`bdwB zajXUFUTia#({*HDunuq9Je|2CTzQxL^Ck2^stAC*lW{nyWK4>`oTQ)&{B;;=0|CJh z0C^V-N3lntiai4FQqvN`{14d8aSbo2U$D+KhWVVh z1P|tl@lDTpXHA=ri@0@sW#4v4|Ltt|dUFL={p!!53Y}*ACKr~Km(!S{&!@aIaPp+* zUHhrM#*{PZGzPsS!Fx&vgeC9jf_1)=+IODin@OXWryRFJ*U~32ZJtY>jMC`M1C$LM z9u(2(#oejy*Td%N+f%N!}ZN6XZLYOj+-r(faevYYHBCjMqbFo}(Mvqv9GCrEC4l zJ2nd3@? zN1i27zndsA)g8+K)%SHh6ni;^Gxfb9{crn`+Va@L?1r!MO>3P376RKU(&5T`!yyEJ z0|8PH0C^|HFmNP6<@i|wf0TkQNFa4cSqcb%yi36#VqKt0Nk2&24Ul)1TEU+{K-dI8 z-bs5Jgv4Z%0LVKT$DK;Xr1;B83cA2whoLqQ5DWp3cfoKJdlahJGm!EGK;DI|Y!Dv^ zun2&>OZmwZx+iG_K;FqXVpK9F#a~WR&;|ZF47GuPUNy!#{R8k2_PUc0&S6Z^j|c10RbQ&SOTcL3pOA`0|Gz*2mk>f00e-5Pzi{@ zT%JaRXJ@9@*49>6RpPx^Uc;)^=s04(W(x@b0Ra+dJh0i1bG+XOj$avB{c;id4FrTp z0Is|X5iW!V0zd!=@JRsm9X|Jf>Oepi34pu{(9R$f5a2-oa@nPC!6d1VG+}MHb=$0U!Vb_$L7J z&ObBQLly~uybI9IAQTYbK>*}k7SFKIXA%$cQOtpm2gtTYZ49#6@dT{5F-KU zly|BShzcX75YmK@LLvb2EAO3nQgU*x$~({wut4DZ2!OnQA2;FdMI{`bcum3~p&}3f0%9Zp@=g>!m1sq%CzS+1 z-bJCHAn&4}%&1B~I1v3U9k7RG=@s$6_mJJ{lA?^1aR zg-%H>0g!hxjvbY7Qp9T#4ha>301yx(0g!j1@To*ALOrP@0P-#%H{%%w0K9y)i zs3(;KK;8vqj#!+kmj?zY8razXWYR@VNx7S)Yfx?#R?d|7o{rudt-32Bh>FQVpA2jU zcSV9nF9nnBFB)dk7lqF2s6P4fdpfocw+$~oR`+AzWL3@i=TA9|>Z*Vsa+>4+hhB1K z(2JuF+n9EiLl54L1Lhu#DynISTazEQ&t^zhG#^CWXzbd{S*$tb6`B4n6MCqjrHZ;^ z)?7%hVAZdF8?s@nE*e;^?>u)0V@iQ;$LCidr zy7Zm4Betv|Pn^HG#lhrVUenS-TW{HeVorHi>bcTm!JzgC(oSoXqklH98T7R0p1nDK z+lQTcQ^TmqzqMRfZR7zAEQ3KyIXF^Pd;X30jYx4)MT^U$UGx!8#@#!&$D6mj zue_tyZfxuKEHyF6eS|V)%&|=7*D5^5nA@~@dcoaQ`syS0Cs)u?y)4vp76s+8sXMkB zK+CfPdar#&?zxe2Y9Q||;Xnxx5F-JQcQL}pZJLVv3FimIYjW-hKLY_EKt=)}??gw1 zO0*)>lS%?0?>zL4?~j=Bu3>!_z3hu_Wsz%iDHi8)YnWHw5%t+2%=@RSG7gz4)vsPx znYMqBQZJ7L^!hfvFlctiPIE#Ed9;cbAKL|$cSVF_QM}^N+3l4qecv(#lm70)j}*0; z!B`SyQI2|Y#@jen(4*)1Pg2)e5mv%Vq2{fRg{tw^Bw9`GISa)O)^|Q)<@AD^Gu4R6 zJ7+$4@fnPgM@zdXj5zt4&4gJwaQzc64olu$Ba;pf?>zQwPHD4y-Vx=g*I3_+ls;b7 zRl)q|EA(3xUK=-gN4sBi-`-Gtu)X7Ob-m@c@|!12`;Z*-lw*s2@vefFyvsyR2jpEU zPodB$$t3{tPR6mL5>ASEO~N6eA`k!qVk7|aP82?sXho|WEdHEZ^pJ8&XWU{k< zRrBiX<3kh;T+n&s*z|Ix-hU)AuduVGmt)1~R+Z^JRJq5-xC(kf;H-|C^Y1bR8LwTu z_*i{Z-c>Z_)_-rn3Q(PS#7v>P(=%pE=-lm?^@a)q54@~m(BJutQs}(oQN5)%G*=$$ zX2^MzYc3Bf#U_2r4?LL8x>jA8ywgOH(3N-2eDLCDSW|WE8_ZP@e`9iuPJ^$%pk4jS+e|^fLEal571#XU@apW7qg9Puqu&I~?9g@D zL)JBWyj<|&WA&N$yf16GYR-&MjXoibFL}r8-t=%L=Ot-W-VGGYj?|Y|rta&{^`7_l zzN3^l?s;#X5A)jtF7a92rM-&@_-lvbtO2SBs9sBQ<_loDchoUP5$Pe`7oZAo6=B4r+37wK!0wC{X99k;jq=?rf91`FWYhkyVT;Fl(`inPD z?4WD=xRiGuc=55lxX3%>W9TpHP1EMzW7Fnm1o56WucAKf3g;4RHM!?4C^`+7s!JX$ z?p!}@p8no$E)L8ANN5wUb3v=51u;baB-%+qPfxbs?EzngOb1|=ZaasH}GZh27fZ%n#l>2RZ z+I;Q;-n4mod9*VuSSOVyQ0SB-699Q9w5&(H83ZF`}BGi*g z0wC|r-K=dtG36SOGhXEvothA^!JMM{=thvcMz3}!TO+?q`uO}&~5vLdFBb{u5S#!PX7p${86PBF$GB)U->jCD1bsrx( z=p!8_cwT#!nwAjef52{zYdGqs)j7VC+IODin@OXWryRFJ*P>@ln@4BjyBaF=agQpd zSH8Kq(f~nt$~!tco_l;oS^E>re$Y5^Ic&i-+gTqFBUj)*yJ5s$)CAmeB*Q8 z(FN;F>@P&8JrDL6siHFWWL9en)>XgybErb6*}lnzW##2G*3Ipu(VGV-8#p{DqSK4R zoqAG?-6D!x%$?_U4AGLd!=vJ)@(c={l3)TL?_?Z2D&eGv*CZSgDgpr@AVvZp??mBK ziB^PqQb_>hottWXZy6@f5iu}8%z>sdHlYyCyhV}QnqgwwqaP80za`Nr<2HR}g zWX5~iJeFofCb#$%FT8Dr8*0d-t+wl8YJD)W>5+EWPFyx_aoFXZQI+mxj)rTLccq>y z+->@+qfgP(9_@7fb!+O5Hd#~fz+=1~1_(izkBTda`rSl{sqR=psJ^f3q1ekQoS42> zq{D)BOqB2k5FiTykax0-1bZG-_8)k@Ctj0h82Atf00EK^0C^`m5LBWSp`KI{0D0#k zhTmO;$u*__zBC^9YjcT>E?PH?VpzX|9hc9WioP#?)Bf;IoCHALrScRCoswJvAn#-x zJ1XI%h}R?>5-I`#ARtBpAn!!sQ;AlDdQwRM!i-CK0`cB!xx*wL~kd1E}PS#XxAdnz9=?!?v=AV(yo(?=XaWd`j6hrD z9sL&#UO)f{2$ldU?}7~o(SQID00KY&2mk>fAXEY(Fqfwh;n|t#wY9a?Rh4)zme;VV zH9AgM1ujT00AH%^8`@ek$DCH z00^{B0OVbQZ4gqIC;}kwt)Gve1`rS-0g!hQ!iJ`R01yBItq=ftZv_y13ktI* zMetW0ssRBY(3}9sdvhL=_7mPIQ3U0Zh6?fp0un(0s$d6$fHB4jBu1VG*;d#I^mN?%;=riv+j zakVR^?n1LbKx70!-ie~760In#dSXvNSRIp$xFGK$b~uS_PCDehGIei1ikbJTYB7uf zEosLn_D5de87ikeEaqOj_TJpo~LOfuqv zyo_dIeUO8Q;vC;fbxbnig1pO+o449kro3xd-({`k zRu;KNmtt`)w}vIx>a#;IVP{lj95Pj^U%jp}ZT}#pULFbP^>cb*(Cm(#=7bdDw}Reu zK1p3?MOX=|O3hmz3svK-=rVYiytnJL=mGPC>g?k~>Q~2O%DeK^Ypm}BN*}N4s$hPU z*R=PNM@zdXj5ztahFcOXM?oD(5SnIQo3F4;p(6;t}+YFA9%g=T?($OwSE6GcrWT2WZ_#GZh#Iwl!$ zLEan03;ssE9KG_cWU{kt@LLYoWP3th7G9C+iA6TYOC36?<)FwaciJ8wfxGIJ$)6KSKj%~voRTZ zbybV4n$D;MdFLE=_!$U@p8&|a_{X3v8Bp7@a~t**SG#RU8FmE%5L=Ox=ZMfq=*efV>k$O(j}USoOr7 zfUr6y8F4}0>%|NHLJ2UZ&8tki&YGrPe1CBl#nETqu%^v7KIgr;yfbQYeaETmFWx+{ zgRbr4Ql1#G>F6rz)2_VdoYl@t-jT+9nA7Hm9nWsz{@fcaey~(i$?{TuL=Ox=ZMfq=*efV>k$ zO(j}USoOr7fUr6y8F4}08^jC#u9tU2&UlqybZSDt26Kw)k7r-kFIa~s?+p6;%ac{m zqg{7(1dj>rOuY1u4;}Q84ih}DJxfhX2=hN+H^(&`z0sYgyd&*Q>@P&8JrDL6siHFW zWEQUl>&jyGIc+_EFE%YZfr{nuSh$VduUKLlL^zkb0w zKJ#q-*r6qDheyRp#wii9lpO*f?~*;%R57J5u6D)LU1$~vh>QTpJ5khBq7{WzPwWW@ zt7DQ87v#Nl@sgby%zNH@+isfI7ky$|JMA&f0dJZf6~}$rJPL=Ne`C5TqPr%t$&>Ms zRb*aun{2Fs{dOp8^`ElNFTH-Xd2U}0VAJN6daiJ{>939;a@wPvuD|A`?&!noUU=IK zH`G8M{f4ybVrqRbvWV>>e@l5szczRmx^Zl`b_k-@*V=Qf38nwOG*%0I<%!?jrcWx; zVZl1dI444uGD865U9yLoDyHfbxbnig1k5B z6}-db9rM?w`^1SbK^LtXMlq~k!H&odJbI444uGD865 zU9yLoDyHfbxbnig1igV&m=q;-|}8vR`4dl zZ*ez;zT0209`-I-1n5Okr~e9!dsAHUKIX(M&Gr+SkF^(4A3)wEI{`$jo7lTA+X;ZYw@t`k?-m5g6TO}6xol2{qIo_@u0Sp6 z9w`B)m4>vFP7J^ zsx>-})v5q^0RgEY(0E|8ALn?#5gflVLi+9w!U6$VCIDC7WqI_W??3)81VG+pcIctwKmZ7kkO0U#2?qsIA|U~gcd2nh=m^OPfV`9N1SoAO z)gcJpOWL|Bfc}8I3jm^EL*N~~XgO>^faC<==xy@=Nuj*MQPJk30s^!o0P;?9#c;%$)03;;C1n`bhymA>vh1Yc{ly|(* z$1BG}1LZ(~jR45I)VLv+j@aEf^6pz+@Pnxmy7b@LsHb08M=1UBwm>c&6i~lr>_~|& z{f4#l>4Tf2u$D;#d1pKEz+2%EpyGtZE61rWBgG)^q#J0w0~N2FbRB?%WS9WnQHobC z!>I7O4)Tsi2Fif|I{}b);VGf`BMVvHr?@A-K@Xt()aCY=@J`#7S@^B`yl0@5V?_9; z#v|)%NlxzJ?ZK12SF|U&#=WfNL*A$F$tkZb*}9IfgWKNP_VQ~@Qv3?nTfeLen)1DQ zwldrf_dwp+&phy6C?_*$UEr<8t*{GD<@qCAR!qhfOnMQmCG8CD1f5y_7_5aO{PhPVQ3qEygdVb?!$9j{S zXl=`l7%Mo&r}++z)8@JL*9wnwL#mBAbG}&}cCEY);#&ti%@<7dFNEQR$Y(Z3Yb*Z z)qN>BzBOo)!`*$)|7E<4x3Oc%J9-~CE#&OuRl8$DitB3PBWIz(9Uh!7{PrREA?sfF zSx53}J{5R6<4dk>uuB;I-{N=PUJsZ2@#Ii6<8$82l@2Uu2i=C6?z|Vf0|o-`hT?`@9bwD zcrO$JRGg@IZAwZ$2$ z(D$|>n-l-7PKf%Y-axr1{3Ms?_|N~`-XF~B$fWi0Y5!LHZV6;wd1qYR{ov2se_x!x zJ)QeK?{#&IlCwK`-}4^q67~7(o5cAI0?tm1%a!-FkrAK1C7-RIDlqp{@t4m99t}6S zw_V=x`pc4cE}R?CO?7!-zbkxovsc(}u7T73NPGX^KOpbyXC8Pj6arM7sCeZ#)n%j@ z9Yj&tYC6 zJQDk9$E%N=) z&JFTzWqWgq9p`JZZNOBJclMJGycZq;Do$v;a-8ZiQVjA=x`DG~D)z{Bvv9C7YI1zo4OU(1yZ}G=( z@$UXq*Dz1Nw7}<;pX6%qi-Q0a zr%}9eoa!=C4DwF8fyO&f@ybcp0Z2%O3E&;2c;zyT3a{%R?|5XO90;%z5Q408h6H)% zEv*9hlzGql=agr&nHQ{Q9(-5%wd_FswE3pzyf>5gRX45AmV7FIcj4ui(kD-*H(opD z_6D0q{-rji#fo-~@@};%*y#zQBB!K+?NM=!@^0nyEUvaLq37s<}L1d$LlX^+B_G| z4XNTyo1e5g>^dx1$9~>{_d+5-#fghoj#FJmib38tR842_27p%jR z_kc;RF>zne@%|LFhs}$*re_=C8qTO=6#E?yTk7%9`9yL^LYA{*{epE@nTyMzE7&tv zdT)BpJ8Rm!-JYn!RCHDNs`Fd01?q8LLH5_Oea}VMdE8mFGwycje%j%$? z95`nSa7mzryrc2C_Ln8^buBsL_N%eK@TfTUvktr$8UZR!WV~{m>M~Lc@=m&e#ye2) z%1PG&NJxeW;2ouS@_#l6O>Wk7JKrYm)bd`A!V%-o21*`a=letf|5Wt-j9l7rPNa1 z(Q+w~GDerHuHQgsps71TGM{~b@ zydU-xUv0^9np#keouoSOjzd1pWKzI7O4)Tsi2Fif|I{}dQ?~!FO`Xkq-`ISnC2R=pU1oeLs0>Xc0dnlVUpy0|!P=)+* zZr*O2#M&YJqfdCL_ z0|B`5-UfKED-ZwzKtR9*r0~kSfC)i3Ab=4dv%HHSH)sL~h>Sp6lLjdGmitG@<Uma@3M1Vg`P?T0g!iz7$!&(2mk>YApr6& zBLfZHY$E}XcT)QvBqv1#K;GMUvVz@#fM5xLybG2mL<0gq00^{&0LXh==)u0SLjdGm zitG@<Uma@3M1VC0$SJ(DhA-y-1h35EBA<7b08;4FrHdBLRY^U-oK^`^wTAkat-c zZRqRw699Q9weLZ4QbYjc{rk^TuxA?yP>JnNuo|&o{mn2!Onc!VasmkC{`9wrV+0uj0cjvW<+Bs~ z*5@-kX{&?0lXhqzF;Wo#c^9ZXzC18M(ZI(3CzCE}O3K|VU4wF~u=q@Q@9F5h(W<*5 zf~c4*^vS?xa91RF^inX{{-R+veNpJVj_Q*yzo+BnRD}~CtN$@@va06%^QRm}byYwR zInD9^LoYcq=*7{8ZA?4Mp$A>Z0do&V71cDvuE`JEXEUTLnh&CGGb0u@YQ}msg-i(_M11CPc z_?egWAZDIQUHVSj5nI-fC(hs8;$ZSFuW4zat+(t!F{ivM^<3$(U{HGmX{R;H(LcM@ z8T4FumgnDEuB$fk00x%9prsrfsj5By#`{L3IH{t=<@ZO@-twGf??oYVI%>?kk&o-{ z47~VQrl@RE5H-EA?t!UA<;58f{qN^g(Tnaa)k1WwPdrXep`KdU9qF<#w2&E|mU3W( zlHvf{Gml=Rr#`*0-|Zl#%k<($YmAh8FFJZJ@nv%OiG>C#1GizxRpG6l3!% z@2IsK+xk6AO$>4$p-dTbER*@Q3jP>#;vC=n3>DzSD5RwEXS{Ix*d$v;MrArO!T0#rUb!Eb#&!;`i; z$UA9=1`;C`0g!imedGTVrd(@S-$gI`qFY(y8eNLTx!fA&m3Ksab_gcyjH--7rb_jz z*HxzNAEeaFBLTg>O)m_Z-Lcc0kV32u&W0BstB%U1BEqpKUUBH`_DYt%Z<&Hge|O?Z5%7;(ewN#sq3r=D`7QX^VY{g)p%Jx5m|QEF?5tnaygK{%5JdwQbRIc2y?5yeKSTVX)WqJ=)?y)hhf?g0f ztE1-pyG%jGYZxy+Rv(p36^*&|-y5(3RA(MBQ|RvWjM)-8cROaip~AoeFRK{zcRr&O zIxl%tZ|M!qmB+dnavq(U%fm{sN#F7V52mxORaYkOG*KjU<()Ghy!faRe++Xnkwet` zjGJrc?j4+3fZ%r7HJwoj^3Hi&!Ox;4Kqb~3!D_^Uk-rwmJNd^5G6VwB zK!D0;C-|+;XL!<92YDy$&_H6OA^`Hy_~liW$M2ET<>{*?>kC~XMU zyf_W=UQRCzp4-*f*~gh}wRsMC*RgM1-Z^=)@~n8idnme6fc!vD&bj?CZJt!;Hb{nz z0F~`MkGBM?@rWQ%AA!6})NnzvKtN&%Q2ET9-}-!pCvA0*chU|GBt|L%Anz_#%IP%V@$@LwluD^Km#16W)k4t&yffpa!i;KK7K8F6H z-ZX9gJvMEAMiB35^D64ou5d2FR+D?)f}+!Ksk-FB;?DKc=IQT!M^g-4W0;rrX)m_- zX~$FEvFYyI;y3Sf@q?wBN|u-Mo0qcxgcqk#-qCsZkL?V!M~&5PdQ@D~xG<;94?CXC z`5gs&6Wn>CHOk_*nW-4q1q83_rQC1R)8=y*@TSev%cGrP!8%f%_+%{^DzOd|tVS#t z`D=l^lYfjLLm(gx1gLy=g5Ualh9_-xkayA!4J1Y?0wC|rm91?*G36SOGhXEvothA^ z!JMM{I>b(DeXw!McwR9rTe76FjdyOHE4%^FLrW$2A=F z)9M`GN$oq&^39~t%Ttb9p=;5zrp==>@m&oS`nX3G(<|THTxozHJmnpo9nU>Jqbz2h z)7JC%V$-rSp82jYlJCAYiWduoVu`%PJ=IU^QaF z$X^TOo%~}283F-mAVB4_6a3caGdyXlgS?Y=Xdp3C5deATrdr=yhRL;3Z`)1t`l_O? zs6ECx;7!w`;u@yYH=j0-Hbu|BFsmyKH-c6n!1rF)s9;Tq*#spkrJoBrzPQ}nb)J6(U>in?>{xO0Kfq*m+pz_%Xe(UoYp0w3L-bp(&kQk{5 zfV>M*=lGWE>av1234V*aDfHd`g7vU>p6T!%pJz1qP_zU<-br=pldWW^#JWqc8nIyH zuLbf>{xO0Kfq*m+pz_%Xe(UoYp0w3L-bp(&kQk{5fV>M*;P{nm+KX+*=sfOjR=d!< z#t9_CZ+rqFp^C@|v`OB#BM7{JKwAhP1h%%sm%x27d6&SnA!i@}1SF3DffI036*w;e z0U!Vb@Cksti_G1KHdLPI?PSkob2=2w`$2L<8<3EC!sa0C_$@HEN!}6IfB+B>Fafyo zE?}S#4hR4NAkYQ^aOJ%X@L*RNB0y$&7eQ{&1P~Azfwssy`Y#&1fB+B>ECE#B1sf2e z0RbQY1b_e#00KZjs02h{E>9!Evoq6cYip~kD)C+{uVGbdbetBKE};MjNHBrM1DpLg z$NP=o_?3~N?-QY`KtNOk;L5wGNJBe700;nq)(N1#(|RSS0R&{80LZ%p+aRPaQ3OEV zW&U&v0LVoEb4p5=;Q(o#Hz_f5CC}> z31(;n2mk>fK!^ayJ0VO^N#+TFyi2eRLh2Gl0OVcfPqzSoTm(Sg$u%C34G@rG0(A%? zf|rB?1bLV60fh8LL;&PnqWlk%m0$uO?;<*>K{G&r7y*!XVw|8B5C8&gCO~a-gjNHH zpovy}$h!pFV5_NDXCE`C7;j0UwOUiK6{<21n^H`6C07bI>~}{K z7l-BvgS^YiSrz&zAp}6)C1ju=O&}oo1gOIAf(V)rawkCEg$x+NO9=sx_vV5nT|bFS zT0!1h9!C}FAn#Ig(u8hE3jvUKX&FiA2M{1V0jlsb6hRY0?gYrYkO4z@DIoyz-cqxq zrv&7kHJ0My&~zlxl6DLPd6$xtCUiqu2!Omx%Sb{$fB@+UP=%kN2$~RbCqUkX3>d;o z2?3DzCc%>2cU3PB3{W(%vH!`Wi<**hH%r%`+$yX$Olj@u=)KXZyCQ<9m@M?kz-F>n zBzW{vFxmd1VK#kH=)8{VlP|xg^B_=>>F+Y3hZ=g=E9#C}b0NK=F}~4nTUU(IRYefh zhWHHZ%DYm}l^zQQwMUS4TB98Ovw6;-$IBmU<741tRn7V5PdSY0s(>JJn&bbMOk>c} zeHq1~dr*kPh*yyZE|-it!!bkvx6BOl-0>BW!M7%BH&bo5^0%jEDA3k_5T zZo_uQq!^7q@o;=`by<>^g-SO zUy*xmq?{VadrLS_0tCcJ0OVba@S$lSAX@~e!tbsKnh-OIaZschgHU5-{Ri*nSHGv3CzLLc)>25ua1 z^5M}gz39HZq55EZ$KmRF%WvhgsXMw8?L%_RQ;seA#k&ex@-7oO9gue^IcY*Sq=f*; zyR?iX^aBWxo&Z(&8H%6@A$J1gUC4kTyp#|CdFSD867vxzze*-M>sNQjELzdP1+`gB zT9tbLk;uHlPXFLHnxc;tqgz#`_fX{?8{;bI1%b0VYR-T(p85CC~6%}_uhKtS3FP=((?5i}v>PJp}%88C#G5&|IaEv!uf3o!Xb zr@_}>aISvkZKlAqbWGkG9~H-vYiE|cqdt3bw5pM7^qYX09l9=i$hu~a)AjP0^@a+j zhcjDTI>(F8Mc#GnTakBe`D6K@60NGatl_FZE5qV@i@L}g+h0ulP>x>uF1$9LqV-#N zEAo!R0jJB{+hta+c)oimdPlwdKu>H&KKlmK=B4DU2;Gno0wC`)GSJXXARvAMRN{IKKME!@AcNxb~A3S8tJyO6Ck$Sa+7 z7kx#7drw4@Det_d&Es)sOoHPLmv*rlW%1k0R1E9_g4gv@?zib_^K1Ng)8^^r(ax}7 zos^t1p&Qae0OVbI#u9o01V~PRD*XIJ(1egX0rD!jw{G57|=gHbkIjSOz^z+EHy15%>RJh z9M^EvTY1Vm($2*GLUh{mV2_b1Dq~M(wYp$k%lxrKxJWcT@7ho8HKv?Nr!nXy3EopW zAPw@4E&12O1Wv!{yMTx2ys#?J^jp(VGV-8#p{DqSK4RoqAG? z-6D!x%$?^Jke0L^9u+4g=S=8^)DQr9mztr3jsO9&6QBw|K@l_|N(#kM-SL$uMX+Jy#O8bpxwHJ{FXVKD6uwRJz8yi}1q6VAKnY;- zF3^Aw4F~`MAb?8%5%LCSGavv2WPWMs`Hpx2z8xQ~j0ww@g-USR4!T|vw00i1V0Is~Z0UqosLj=ey?;^+zng9YKBhVIk zNB>2G7Z3mff+c{;yI=!CG#~&3fB+Bx0zd!=2$g^c%;jlBcy?xbZEbCJRVChwvn5C8%|pmhSM@3dYC zY5)P5Cjjy;4O$3&kOTrC?=pY71pwqC0P;?*@qlcA01%LE0wC|QJ^s*pq69$RB|-Zj zM`<7c@=o-u1oeP`NC<$uiv%+?0tA2n5FkVVwKH!A9sCqaS`yHJf4UWWT||$b87K;YMbYSFhb*yB_^}?Qa`wt!!61 zud+27J64soyQ+J3`TUt~uSawYud#X8_g*g@>W7;7_olt>o*JG0_t0q?fmR6>r~Vw2 zHPhl-%@#l8;Bkk3y=s!oCI;&L{2H2K=D+JYH>ar%rk^oo>8- z_O-0n*|2`M>THfZ&%M9GxAQAotMgs6`7%yma-CayAjeH^n+W4P$s`c9VC`ACu}5WSn4dDeat>)8OjO3-gx@)Ao297vb8@Pt-Z`466EiVKd)m(#nfv;BzYg=!-aG7M{Mtds z3oRn;J9wNQTsiq+ukgI2h@KwamHP7WIv$5crkd*h?{-3T)X&{##vYilTt8x%(UIY` z8&>!xmA%#pEL=2s!@sY#rrKTAKDT?d&UJ;ft4h;O|Lvo9Ugt|m(0cQwZwDFn8q+E2 z<9}Y)sFQD;xqtuEU!@x_Ic^Ty`Xz7k#(5|7zW6-R7?hdeW~}x5FMljubxh;ysBVYa zcUZn+-M>HTr0C2^(D5=KTl?tAzkjUUz0kuU@`SRM*2l09Nzp%O)5d*>P~>KTT=NskGRo1r)JCxhf4E(}=NZ%5!?Y3o1T?w@J-YLs;;!|2s0bH$2{!3p=e zTKehk+qZX!!qrZTFLWN`mu5R}P}fnNvey0b(e3&cuQT^&`G2hL_tQNOd*5?osIh0A zk{GUx2PQKnEmny;7n+m4`Xt;@_6@0a!XFwgiamP%gXTBiTu>Ku&53bvX*XL z6S)6Y`j>=1_g7K|9CRoyQp~E?Av_iql;%sSIg*~ z8@g4!e%1HH%3j%Ox4tFK-+Aoifhu1!^^T#F;-Y4n+a>!2o39W5V?ovO>tptx{}>;c zUUfzJz3t%P`>1!1D!+VI;e1eoe(Sf6zr>zgzPKyBs^)#vFr}KY8&0iHU2Pg z%U5>O3r~EultC{JcwDnz>%;!RuV39PT=eG5lJaq*XP^2ucHqlOL|oL z9PV|0^47f_Ep_$Jm;H8P)A+zKmQ!PjeS1I1Q}^4tK4x`-@2+D{sTcJWvOBIiTsq;O z4xI-)_-k{=UmRSI?p`T>Ffg|yXx~pOypC!Yd7h=d=(=~?=MWsHWvzJh}$<zWI zi>;B_FTdH_s+vu7cG_U;w871Yc_RH))$CVWH|LG(SK7K^XH+A!+Ir`eb8I&lEkfT~ zO*S%{YwNzjY}z_>=Ltrvzb6_k!75HhBN+`Jj<)kF_Twb?4O8Z9Ku^6!LmP@FI_m9}VXG~C2FMvKriHlU|zCnGZ}+uv8OwEcC;geBN%8f&@!lMxO3&!4qojqS<} z%$=DTj2vZzzR(6)d!W0S&9q&$`nL(r?r6S)h7LhL8#!W>(TKr=m#CWkxPAlkgTY4T z!-ks<89vNt&( z_%iulw|Xu5=e1cV;*F?uoTPfmIBRH%b*H{Bdkq*c6#cIzDBRU*tX0*ek-B3&^5;zc zHsw;6DepIEj`N^*Ui!tLCh?--KmTRxE%o}-X7)dE7wxybKfe0 zRCRs%+kelsYmvn z{B(kTZAj%i_m_sx{9g@MANeJ@)XJpp-?U!UbDS+ax;%@y7~ww5Yj5S~VPh(me*O0K z$;G6XpLV**`OUoITidDIUU`RiKb)gmC|`&xium`c@7VTv?)0j@USn#HRr$+%TJBwN zG;Wwd_`b|v?wvSpc=UfupDgnna(Hi?d|#^n@n43#ax|Y{*+ZdtWypyWL7$Mm$;0R_ z$G!YK`*wBoD#)AX{P6N`UjDClsxZ`lc-?W7WBUZHAI=_f=on2qViA5n?Z_vS!3IMP zMZM2op&4~|`xXn2>e#U#O`h0AE!nB#6`Q6o<;1r`?+(oHjinz*b9fjYR~sGk;bqOF zRK}h;Z%(y?B~y3chNP%dR{w|-vfNiVkc8>DBe zw$Hw7176MQV>kV#M@pwHCUs#Nd9N?fHix=Q^k2Jt zrqNtA^SJ+pzB;Q_tKyUOtK-tJY=x}fL%mF=W*?Yx>_FanYh=)qfM4e?|5xRm=L+9f zf2*!A>>XS)ZNQc}YL5f5Ja63e481wwQNr_#9X$%VOg!gaXIhyu+gbU-EB*XSrR~=~ z3LDmK&XbW|k@vS+sqH$oaa?d-zfa}LhblgP>HhC$?JC7(@BSFO?M3Fkl+E&Q7SDgP z{C2XF#mgIgzb60h!<77qub%9EyInJ`c!hOd&vQw+Lynk*g;&Uj#M?~k-`jHL=DK*R zFI#n%O%DC(dRXV~bGHAKd3#uS`*B4|PuC7otBSAC8FX`Q+0Q33`qBHWJ)vQ+F*Vcm z<@tYhM#leoC}GsjN#}N)4F1!isM6F%vHzfX|8{58UOe*PaeQ_+xwo;i^tzp!Z2b zbhdt8yuH1PUi`^@*?N!75@T&*AATKgHt)RE`^XFKiOWMf#~A%|WqA1EIuFZ|nbm&p z;v=8On6+P2Q83Z@<&i57I<))Equ*A=XP3V$>8ScwB~|14?KMSir(&+JrO!+6sy*3p z_UxPc1CYbpPZ}v@=b#=8F{&dk%4ywIU^62Zmw2x`G{~U7fn6EKosa9$D z^?-lq`Qv1VHG4XzA0<9zO~c|{90KKbSJNo%_yH^Y+G_Z#J|)In$V-^IV~ zzpCCdZ2lr+Bf09FBkR-Ue|nfw5MVuix?}N*K}(jZDZ4+mj_;}Mcwoh%3t@wj!dEzc zHi~#|aBhaF{hyA8+bny2sx>*XaPTm1>P7Pl88aS)e_fJuHh)}~6U+2%H<#LKeHwMR zPpmex2jrY7gSIFv3`%Ljr+r&_uNR(3R06-S*#hJI4$jl z{;=@KE|*oaCsp>PY#F>Mg<{k9klL=)w_1^nuSdTscl8b)IjC&X>F%)x*FU)LNWORM z?Yx6?ZHBwe9<=zH<+dvPc|qWi+jHGkB*OzOz?X%UM??u#D!$!>Uif@y%Oi7 z7}f31U)Htclk&^LXW5qS@s*u6y!!9RR_7sG{x$yRVX}7Iw;)T6ylKPwlyCbMlUo;S zFk{L}&py#<^aWp#0a|0DmmGb(JY)){jqX-_EZyt zLr1$^*4BB|NhQSKNFVp-)Q*>XzuXr-GVhr6f2R+O&F`;pboHpB35Ka}i{AI1pcuPw zM2~3uLj91vvmJ^dGwQrZ#k^g<}e_QMQ%m0qPvN={}t}-Sqci)6Tt5!_A zx#04TqYnMyn=0Su;57@QLDv3PX1t5{oKNw4FmzIk$G9@;wAEic)<&qm8gaHm(RlCO zK5xG*-(ljZ`oGje(evfD|MEy-oX=sUP99yNf_`+?i4J$D&g^w=?ue28v!nbvC12jP z*X|GHk6HK2JKC?b8>{@f#(e1YA9g(nJ=)I4e*RzkXN@zR+U}3vZM^TE&E)x@-mD3dDxEAGlI5%eX_#f>n8faV}lQmU;m?L+2Osve4SCY z_Z)S~UHkkInNhj)p;<@5rXTsL5Tjh({|Ddh$2TVY{d$#4Y}V4RhC?d$-B+Oc2K79( zeO>3OJ9J06WxZwx-&w!w@y98?o5$-a51V8fxKCeU&MT8+u1_cdbw8Zhx?8@}Xpc=B zzG#g2^(1|YzPtXuH@W*4?@jx-^0UXU8GjE{zc=pC!egD1Q)YMVUy=8s^rLc}RaA}q z>&m{n%T>Jwo85UHT+#QF%^OJ54h)-ec>Yej({K?~MN6##;xpwLD?NIK?SaTuN~YBq1cExEH6m6!+q8g+j5S zE$&j>OAEzai@Qs4cXz(@{_gj__j2EpKQiaZ?9QIqnLSC)KC@L-ZS$UdE{{5>P28JY z_87L~E4RCI7PlRr*ComHE#mV6AFsD^x#=2({PqYAQ-#0#l6SB4-H6g!;Q9L;AC(-> z{*6}jC^7y5`y!UT;f%1=`G^n%DMD$KmnRa3h|3=VFZj{s+i-()bM!VR3z0s|841DO zhmZbb2x*`d?~bj|{Mp9;m8|y_gl|zX6&)dfmR876#V1~0=P;OHOGaH-V(r5Jzyd)9 zH}O=OB~XLRi80}Bs^L!iOc3Zt>Kl&MM#QEX(or_9nVs7cag)Xi1@3~ znL(Er6sIyebA#>|mXw5L^Vvekq;X)INq57Tu=mF6*f+(Yv?1+demXPbggKPbFnRJMYMDO@;e(* zI*6&#JyQ)c*6evI-@JeJ=XHc{boX!%yz`PV;X6dzUpk5C<*Lj zUr3DAsmKD=27=e))7V&l(my-50z9|Xqkgb%BbDzjW{M}C3= zSoxUM|C^vttC~zBzWJ$LYiUPoevg8&P;#OmI%QZ`aE%=!-x|l3wi~~VQCOVY;o9_3 zZ!*{Q<(K*n#0bfwnAw2$#Z~ zc|wtRm#+%A7RSToQu$pH@+VXrY#LtWV-!=ogDXc9p@{WA9anTPb+yTyGs(=k)#M`@ zCXugH{TPYGmDLiLIL)!N*xJh@8#6*?;ip_xwPO_T{~Tc(l{z-c7I8J~_+x|baLWFI zLbWm%QhVqF(%g%^^93tyYMK{o^HyZ}Ibb~l7A*l*fmnAR%NCpO&r&cyqw5*K5;zIi z7yYzx8?PL8kHexl{2u_X$7W5XVhnlpo=k<{eH3c2juZO+t&B-4jI1Jxzd6V5xqNKi zU~DY{N45@dAVHF4L58q1NRQ){FK7j8%YPH{kzHm9BkL>sk`!3}C11WZ&BjxnLdqYa zT>39w;wt1K5=NZ|A0}$MTKcf_XLBWel&$u`z5!UuOEtggPbenYQomS!(_h_JtR}tU z4^BDpA2M$^t9~=`hUGc<9l|G-zGzB0EptVv0Cg{do@^P89YG?Jvga7yF5)NhH{XyE zD?m?3HlsY1c5=s``yLg;UghB|!A{sOP+~1pV}{TnHc>UW+mG0& zBWI%FCbfoei6dp0Y8@TW3XdHooO-n)Fg9Lw3MnnQ8T;%kp;{m|f7P-Y#0MN;bXP27 zN+JC6n2DC(aC+!NUgI(%%FBHk_&z*wp7-u9(<#$QUujG12;r_I%=t{@8%)DG{d&NS zO?gXZDoaeMu#K6>{wF8?uCH0D+Ku9dJ zy8jLH_SH5;<)X^l>#-3+0@B!QK%>y!{s_~r4>8vmAEkR5m$cKn&%m@}hVe*W6$n9h za+rRF?g`&w(6-byjlPaUCNE2W-=GBleiwpDQa4VNb(pA;iF9WDE+mqS@yTEZhf0U{ z%6!dS@>5m=z2B9E34%`~9O~FqKE2i!3*gP*$oo2hyVSsVy9gKbm8?EzCT|7f&lVB?_f5%N;D325j}6J$WuP<&7T$6akj0`u9X ze%YZVsLJqw&n z|HVU%*ec6+>=45KIq+_9)dT4Z&qK;-nwV7G^R{8hgQ9k6Hmr^umRiEE$qj)7DT zfvwD2TY9SGKVMpyP`?(iM^GtXf+=ZI?BPi8a4u=bzbTX~T51_K!fHF5i2}D`F~16u z+96{eC77`DlX|0S^`ao}KFk;4V@5d(OPG3||3Lf*`2ZC=+7Bd;kcF_J0QTuGZdeTE z=X@X`O@+QyQ{S`hii}8*9;oxHeLW)TdtX3(G_zdC@nS5#@2dK=45J2t3jyi%b2j(< zjOZRzLn{l5A4U{yk+T#`8q!~A)QxnbMtIH@OFeu|Yv%1W3|)M`PrC>6?(ysjsXHUI zYR@26?L>l;WBuROXdZsz7PNPtxo2%DLk$y>i;4k{vtZO|0_>*i{cU$dQ4OEG>gG#- z#aqloRd>Ah5uc7fF;u&`p?)qlm{vS?!RcKMxF#&{>2c<{X4R-=I^x5EV7}wLDuxmd zY!|6G!RZ;qA?;TW*83Ope379{O~(Au{!CK-zcuajWLKl-)(|7~FOn1QV&_io@{HV$>=kXlhKv?ZGlBQ@{Roh5Xp%x=(0{ob1E-_9YD zkdbJMOU&Nuw05fJb#cBFs2tqXVkSfB&s@d47OJXati0o`Wwh!yS<>3I(yUn6|52?= zb@!^bbvr*;_+1F%I}=uSZuTH`^JK+Dg({|9pxRhDu*FS&tzA}BtwlC}I4+Nj!){ zUeG_yMAjzgj-(v8g=>}saYNm60j8s~ZmuugV7?c%qr zTbVg=_bIFs>hnI^8E2*>wNT8Qblp)y@$I^;m^_vAdXJTC(yA=n4B1puLgl||zCS`M zTD3awHK^><6TWn#EjhE*mzhIL@2ZG9iCSdCp!wvE*!(<{w3yGvuc-&YV)6Xx%!P^o z?BlUY+Y>4rsIbNMi@@<;=~eA4p{m?`a(1g;pf$@mR`bZ@ei=<1$%W4Brk?@q$B-oq zOQO{2!Fp2?m*Dc8!HpF5s@0z(72$6Ab|324uS;B8kWR5*F`rIs!fx%~1j zb<}D_Wc3vTu)-h zqIf!d48`B==FX16g&v)e|LUDOKWg1}aCzz({g}<_S;i}bTqVkZviyDccYe8gp~3>g z5uREi?m4$yY8i^Wu>$+GspQg-$UZh3la- z#2O#RnOiX*8dNl|x1-%<2rGg&vk5pSUtj2%P_=LtrIwbb>yOAuGHDARRd2r>wzH;e z;Fq?sHMzA0M+6#hno7d6Ax)5%T+hoUT@$Z$-{I>MDp8U!+>6=4%4*yZSD| zx}?O1U0|%p5~IS4jbTD=M_Nc!To4NV*=@7QRE1=9a}pK(!OKFAnOV^jPanW`CL`lq zN6d*?`d!A$EMAu-RK3Gtl|)e^8Es7MKsRz_(pK;1tjk5PmO-g^{|Fn4U$*i5CF-JR z>1v&uxJBPws&3E}8sf|LlG3;^ox9&%>ilzh;&_+bJ{r<>F9VsLvc7yN=jCtug=$Z( z$J*EWqSRQO!aWMH9&jjVGOHH(Ez3TNb)H;}WtI1-lxskA7dO+4!Wk}kAg7;4mt2N} zK*Q%Cg;3I(6|=2fq7a*icc^oEBcxTy_4)itwfMAYKSs7xJD3%U(Ygei_`HSX(-gKh zmdMx5O5E)fuxxAuKa<#uDo!xzW1SrGPq%~9sOn@z^~V_GssK1VkvkcP6&^0NfX@K{ z!m*2*IKGBGnoF%#;A<9HxhEB)T$fD*zQNMBAYT!!&YhyS<^gn zahi8Y;&aS4mC%_ag{o++)a_vvoK>Cb4?}mvYum~@s(}o;4nWD2WZlMC4 zhfAnv^`BU~`wdpMg!=cNGBsVZeHj0p(e{GdlQe0Wz7?UFY6knJNZ!l_guM&e&RY)1 z?0hbYy?$!$EdvU8b1UvG^Q_d!A)6;+_V}{G*}>y<{q%H`=-%^0nM}vAe8BvpyFA+Y zh}UwIB64c;!oXL&mCL3}4v#y+*UC+5(~MCKXm&%*ME(s#ehW4dCLE-Q*Ur@j$bnZ+ zY?2AtkD9wQ-#=L~zFjy~hNc7xPWCnDZC7$-Bt#2a+hP`3umt{mUCf|apr=)+>_@un zwm+88s%;cRiUs_hJcqc$-Q|>+*`nKX#Gv1kWquslY>oU}>HV;|h{NwiiD%gCGpj#H zm(D=bKF7Jd@6y9LYW=_xvMIm=Rae>d(U>hTaf(xNA|oZEioipB9)*2LQs5CoJ?x|C z@4C?qxQ{2ah7aopPMN{A-!rCS&GScw@XPEms`Bi#f0)88ew6LJTOdLkqL63eZa%iw9WN0IK}9H8&$7V4Xf5NA$R&0$>R(!=lw!l_ zyfN*3?n<-F9QuqNP>CC2ukr4yAGpU6e5Xy#VGdKKNL*?NH#u5K0|cwS`x5h#0j0Pn zUe=jDGvE^N>E2g0WktZK5)o6iv&0`r_*zOq=p3rzC++QCf*O z$uCjlmp?%+*?!ZUHpSBOB8i;0((4sS01MeHQ*HTqGWwZM(Vhv4(nzcN#TmuTEIRzv zFX?gh3G?QRSlifVQP7-{h}{Y(-w=diZVBt_yeu;YzV5T@jzh|GW5&~K7r6R4K$`*7 zseWHE|BGv;$|dNA(j6`OGA>)jmf1&m!s8@@35x^D2)Obqd+Wqofd5fGt+o3?j`Hhs z{=%Pts|bB1k(m@~2~8jwDZ&aa1X*^g-A@O_^9g-_-PX&VXu);tM94(jR=MlVL7Gv0 z`>UHuXIRXAZFn^iEsgIKa(*nWh1(>PC4izW=s7l!}UdDw;sxuYE@tmq45Xd%|@>K*BMAmXHm^xH7IJ zly8{~z%kdrjcc{+X$~!1Kc5x{+obDU=&aB++lS`za6-hMoAk(ns{?e#{kX_VOz4XY9mMrf5;HJsPt%VpBO=Y2NX63UA5|^o-LrdlpMnui; z#;E3eJ?qkQ3}IovQk-3%=8C$57O${ZYwzY&N-F%<0peHQplg9bPI@#5 z|3h!;+#>q0VqjV{A^t+{?VdP?VVLmP31q0(&557mX$_K(8Qe^Z zzkdg&0sK!T5fW>plM!h$D;p&ODW9rmN~__rw_5wF)Dj`t0E`S+8Rv>4_~arm{w{wk z?n8{PgIYd9gBr%>j&Ov8I+nxBY@Z3Rx&unhFv~AhE?Pa4$Qqnq>>_@$o)a~gL2XYk zhmB__RCsGAeaR2r^A*-730d&VS(u{Ama~;{yPHZRlOp>j25Q2MX z#YZd>evtR8G}-6wywp6mEIk;UpvXclPxw~O!Nu@9^f;^YP`|mhnNp`)RK&SUBNdkR*ZsKypskVqfjhVyVNLCMx@V(sIt53S z4H*)sO|u1AK~;BA{sfCAt)7qXzNw!PHxk)xN&f?$)MD5&i6Pu68z+-^ItHILXJ5SlaxJ_T#eYMc#USOqPY(j zRagdsHmle#fE%IjIt#k!s{GLL(Ap~eCMZ09e|6;H&g~ZFtlJ?fb)@A|Xq}&m>X!>p zM|8;Pu!E|m+051|BXbk_MoO^(_h0M3wP-9o*>Ur}K40SuJ`nxMUMDX)DkAeCw12*t z0_~-pr%mMf!n|6cVeV|r8x-_{de=p3TcXtW0TkjVw0Oe!ufdru4+clVir73Iy!H^m ziQ^pHccM?1iTzeP^8`Z^Eo52>Q$_*?^38-!`<>0_6ENc=$#<{-tRCbL-kN9Pwqu4?W{+3Vt6k_V0>N8B_amvZEKjmu;0_}ZANQM`84 zs);YE+!hHOv1SlVV(yFeVqIQ;Foa3T2g-U-@t@hGr`2oB6uet6is@OyBt=4oWQ z{mi)=BOHO`y|B0MyWLoZmuMZ(oh7)p3s`$6n>DoR?Jak1NHDt02p4G|k4 zK-~|H&@O9iF{l)-*n1X-C`zFi>1eF-JXPt4GY#fCK#tlo&O1X0pyF8z*8m(CigogoIE^TqC){QxrV98mN3DLOzRrpTD z&1O!K9i@B?f&wgwQ}>69-BxSoWa*K|x_pU^h@iW+!$rFUGfJVZjXnKvlL263r46!7 z*b8T-*H=N#B$cw+66H)5td7v|3ty%j=IeOn{>jdSb5)+ZKRrsY8kO8O5bJEUPt~HnQ;T#e_oaCZ(O0Gz zLiW~-aqVdiG{!fdmZrzD^H)lrra%N(WbH^+$#|lvDUte2iCoSo(p`VB{oKeqD21bm>J0&p@+*pI)l2lq*q|kay%ycUWP~ zogg>*76Z~LFtJoQXM}FL1qZ_TFZTukcY`qjLg9iBi-PrhSzA&Ei(mTm_%&y6yV>0Q zzwPK_O7c!>G_^1ExbVfU0coPuS3jFzJJxKDzcNENyf+RW??i=Y^_VaD&r8dXe`w_C zUBGQsfPPq@j9NpBv^Cpl+1U2ub0mQZ#_*dGU4FwktBiafG+J!XG86c1>f>r35|0Fl z0`jY&t7MJN4USeFLCO@@Hi{VIx964F@3AsdJ7sOdQ;_bD)=zC$IRQ<^x@LD?5jUKp zy<*TC`wrYLs^ptZbjZW*ntq4b4i)b8-DPut|8;*BHneY4_E~eW=rXMCGV8|s|p)qz#($8w_^Fk^}xsygj=FAyQ_*IRsX%s%NWPY7P z!C5;*-wz3V-GzDg9PMFiY%QIAf!gbn;oE)A54z8}>R>Oy3=VQ7loFcC&e!slttwxt zY``u%JoXjkuO@<=cB=X2)T!*0>r|94Lj6|bXf|4q>-64wGl-4(L4hC}moGV)UCc%UKZz? zH0^7!8)bXW5CMu_SR2&ql|h?-A&fHWAB^^Psj$ANj1d2%$_K@5dWh)OOFZIvvsBl( ztye6jOR0|>pq*9E?A4gwu)q7A_Q8erSK)2QL+p@`d!W+kR|8?>{kS#rMde)-&6#KT z!bbbMnJduI&eegph&u6)&%mQavV_v-aHTTk`Dl5mwt z(lH5JsNR@E1LwzH-wW3;$4@sOQC{*>qr^_9$Eg)FnukUx(W!FU6&!8uWDAgsA>;`}`zH9OPHe5peoF%kwPImH9 ze=U5xD^9ouA-HDUd%}X1NVYICoBun5r#72!wkVND|J!J9llg2a#)aKiY~z#`VG0^2 z)QAZl^1loNS>i?uS?jlUeOlDsUOIS{E9}T}^##hA-0mv`Q1Q?v?~G6+?kT>s7-iNK zj&9wsSZP&ZibfU*nN-|GC0%uQ%TzU~(ku2EBhobJPMbr0gTdG1Xu0n>HkPzXo!*=- z3}zt=N^0{#u~Q2`8p&ZZv0#~ZI#K1(pQ^MMy1JmkU^QI0aznO-ZKj%Gw`F|RY=5tS z!6-vt5uWk(Nt?Qym4UH`rJ~-KY5&8M<&x0op_Q?_t#t*@h|3eadpB{Py4oqfYFr=V z-z3YHoc=f-$L5L0q}@(Qb91ANL*%xy$_fTivd_aL1FVeYdcNsxmXr$Lt8uC4-}JfD zhRk3cF#BP*Di~7+97x%k>*a}He94;Z%7dES0#CVjBLt|UF5Z9xJ8zcEBwuWjr${d^ z_5UE?dj@%l+VnlTy7SmQDFQ0bZv&orH$`vf!yT2OXmrLznFSAM3-(Hq zFw=v6R5Y;EbXfduuFo5~gWcZi-EB3^zi%;jhwe!oIN;y6eCQSP-&cS(30C^Id8;DF zS=V?o4-VyybT;w2xZX9>7Kt3tR)ifz4}n_FU-ViHD%(HXn3?}pY7&jtqk~4f#D^hd zNbPYO$zUvD{C-SPBg#aFj7gh|IPXQ%##2c^U2fySb4e@1wsoA}lo8H-oQf7nrCfQq?)1@$$aE>vR?UH;?*(Cbeu@DXAZm?=-M^oKYv?tq8UUJaNscO z(kv2R(^g7M`2RGNb{pBu#L!I$FKAsE*WIE--qs>%{OhM0D*YJIT2gKm?itD%ck$~u z4z=kpN+->##LaeVH+NpWa5n#f50XShz?Hr1~M5%Qi!X;A-{7)|(lQ#cLo? zN|QV`_Bto0c7@Uz(jsj&>WXzX0DedLQ9`6aI{^8`Ood1IHpm*+6-iN zhAIHGfUhGdMcb`?pxZmisK8X|ZB#St^=;?*Cn2}S9vw%-Q;36+qu380im4apgl)># zTg(C)T_OfM^6Re&nO?6%t^gwJutyKQ!1SX};lJEG(I0JIABSX<ci5WyS{_^DhZJw*!J4$ht0w~^wel|qV;uwDVYmJ~u<(`o zX{tcPD*xTOKoJS6CoNmAMvUOXA73_BG=%~OsaS#j1n5`7&zP;iT&Sr*_Xe>5<1Zzl zuVT5j7U33mQEQ5yR8N?C+>~yH9I&S1;E%68W8SOJH;lh9SofgN(e=yTH+nCpr;JxZ z#ptsXUmAfQ^V)zx#y6@^$1$37X_nYEjsG`%3(!kKL_EbL1HNWYiv-L!*Ns_uOipXO zj@TIdp8~Sqhgxi^X{)PQ*f{3K@t;auek4hZ`(ZFGBWL@eVY+z6GD6@g8^r1&}28fhuN z5GD$h-t#KAxhI7qIZ<D#n#kVDMlL>m{CYV@{8hP&}^etde)qN+%0!( z&wC5X4t`ln)I8)JVSmGmjc#8q;(iPX8`g!7`K!Cf2$nC%*u;{EYBs}m0IR6D@4bCx zFE3fQ>zRVFRHqmY(iG0$xrQhETMflaWYxY>oF$Ib`AloqiC`a?K~yZh4K=3eLm93` zF`h{F?h@eWb&rHP+qImbNoCr}-CmL+Kk&JWJj_#_aEBZ~d_a9WpSI!y@~`g7Q6U?q^VoPLFTOQk zxS#YMg-*MhAQ!SSQ^$@C6l@!|_6Fi!!{~UaiK4Z?Nhv)A)Maz`H86cN9=i124&Bx7 z6HzD4nX`XjQ;uVOU{B#L#g-|v&11$&M}I|AC^<%N%$de>!FmLik%#&Qwt5Tmk1xy$ z3RtJ6P&dH%`CkP*EZjQXF6-N7`I+J%pB#bZ6IyzcUk4D=J}c)~&*xX?5_btlnv@vE zU363EP2D7}RiJNt=A!;&r>Rckm)Nn|v9a2Wp{Yj0Msd+=_!Ye1D$!8L6` zt&JQlIE};~npI6FODofUv){aa8_@ftZhctV!!C2Q{j~!6w!GD0|CQ3u&VsT#&McM` z)K~np2=hB)m$p?Hd~Sw>@zbsYyo~`h{O{+Cof}QLTrzQH$UkLLF8O*ARwgey#CjLp z3vmb^wjn@$5PuY$xWzh9b>fKRN~AHndcP1GO(9oupIP71*l2$n&iIM0?6R43iI$&K zK~P)gwp{)4@b_fv2G2WD zq@RPaF)rB>jV+&8wcHx*2Bn;TZw&)NM6oa9S($eOeo5Wz(oy3ONRKaw9)nRb_C&v` zP_qQ(6P4~xU;n!DAnX!CUiLhyU&GDX^_CoGapjIsCw0Zg%HdXTOY{-N_;7YaLjGRq z9TQbC-_9v31OAH=c5=pncJrm-q`|aPGX)e>l#QMUl-1@DrnzSO*EM_hage&{1X;jT zqG1<>vM1vQIaK3k7A|GLlD$_oMPc#lgxbVO#d*UCd7dM}#>^NPsQF!lgDNb;mFVv& zG-|nlOQ~vUJUe*@)jp2d&dK(s{S%kjZ|6r3xE#H!AdZ#Z{B=ulQVMlb@pFgY$~c=| zwbd`6waKdOQLHA0g;EZ->tPJ8vaTe)Jvw{4v9XPts>Bx@q#^S=8{_qtOSHmbTK1hb zFfXH`j85z>eZ9ZbXw2bA_Nk+q9d_53J-X)|>QmyKe&ufkjxk0}s|=aa0>0`@abwwb z{&|RcXj6g=RO)-Sf-SXf!@MWb9I^gW&m>=$n~-IAYZm0XY-deC+~cu>f}Z*zzlN&i zic;>~v848k+IrV$mcf3am$0d@7n{p;DQdMd`j^No%AlYe2ZA_vuu&m@s-k#Or(83Z zYfY5$sdJzGfq8D1(_jF&vZ$fip{h9N$oz|uCejntvIr4@8hfFIu-r1DhB5{32+6iB zRkwMCyGEbzgT0{DdMLx)!p$d*JL{d*GvL#@$s3Xu4(Z|2g9HZzE*(1LR_LnVMVa+!|80@Mw4fv zNwrs8X}|bXx)=m$*0${pdDz<4(eI&$BR)E+(?MxEjRvoqDC`ezwpl;-8a&fpe>+I4 z(@y__y?IR9?iQ`y8&e=n0YR}{kWMac6L75EkO7KVMN?Ii>6cKC8I!+3U)d)Jv=!(( zHh!{6LQI?L{fX7CJ|TwoY^yh>_4bCG$2s zj1)xLc*j@<_iOOPW+%kLXk?loJy@2u>+osM8m+izW zX9^zcKLH`!dr^pU?zphNy=Tr*=kp(UayrD_N`Le6lpIit5|xW zV)p4x;c7VthAM>bNJjWmv*db4qq_?sxBKqvRY&_U;VdAZ)baB#VsFesv#{K(R_eZ3 z>|Cy%&BhxO5o%w0rKWZue?YIzf5x?KK+|skoR|!LQdsF?)w+({IIo$8qN+lk_q7?d0G>t$`-0=@n(LT+w%`{PB@jH`V(x7eLKXl`lTt-y!m z21@@(d21zvuxgu;sfNDiVis)8_{O&eR>b?ECT+ht_EZ>0)F3$`%)`#+Mt5f}T|VN+>D{8>zyG zLqX~>T*jiXuINz@+-d`3dEFfh8{jLhy_ zx~&h4RsgA1eFa91BD~lw4#26{kh)viTc-1 z`-(&2-z<&}chRHvn&U@4?8|MiOp9J-k0$F+5ELKo$M#=>``Uwz~BdzT-dM7{q3ucTsm*-k~VB7BkyM?Aet@RUZy*({G0b&Ob|0 z;T#gdOKmny#Bn58(mAw1`Q1r+K$`63czk+^y8n`N-k8#xlCiBVKF3YW0gh+k~kmvM{?$Z0p zNTa(L<;<} z!;t$%6+EZwt-w{wKif^tr}f9!-&>;J00Yr)!mt_9p{S-hk(?!OvvUTXH<6IcEssOg zZx7~eMzQ3d`F?`$@U`og+RH>1X6LvG1LlM_rPIu}6#o3&mbo+Dnl!#5h3%%aYcnXU zpG*<;EffEjS3T=qF;17y<@2pVLS{N&(ddbpR1cs@V2frnndhtR@TI{A^wBvVlmF7- z|8Tqi&E@{Xf_MBwgLj5gzkwi3P8kbhM>u($8~TR^PRsqLyoeGlvx z|2mO1Ff_6HL&&G)ly|oNGduwNgj1208OS0a0Q_49!DZ0jG8bIt`dbFWW$@oJH(cia zTZX`8$lo#)E<^v8dEhe7-!cp?!~T|m0Qd>;|5*OZ^#5-g_{aEP#QlF<;y=AD3NPB? zWa~i73@6XiLOFmOJS^}Fb+9#dHi8#v`4{?^s)enM*q`D7%wn%V03Zaw4Fm&$+#nDP z-b~Kc_}`y#0RR9l5D3ij4+pzBn3!S$XnD9W;UE5e(EjyKYfAeE145uYJV5w7{W)lD z{>ETn2%OLVPwX!l0H5SP$KQH?$$w(w5ytiZ(BuAp=s^JRq6YtJ3xsh0iLOT&>`#pS z8-sH5JZ=jwWdM8J7Q_t&{TG7);9>W#{1pa!g2jvDn_8$xY`j1^0fcsC9|H}pp$OV3E1I7dUv!wi64+a819v=+G^Vs)5 zAc%|SQCm0$<$h!X2;|~^+#g&G0DjyS1clGizsCXu@c?+hk1#H{Umnc|kP8ZU9J_D~ z%=O4uKrjpje%zKD00um^!3_j(Jsux74Em>Z$3J}q+xLjz_|Xa2M@o;|J0)SXS{#_5Fqr? z^};dmqg;hg1{Ci8f3^K{ui%ES{{QR`2!Vm2e{T2xumQ*5YX8u4axk#4GI7BCQ=LrN z!o%dx{fJY^*4BykuP*@bdOK1!rna Date: Mon, 30 May 2016 00:36:07 +0200 Subject: [PATCH 015/206] bug fixing for new L1 scheduling, updates to vcd tracing --- openair1/PHY/defs.h | 2 + openair1/SCHED/phy_procedures_lte_eNb.c | 78 ++++++++++++++----------- openair2/UTIL/LOG/vcd_signal_dumper.c | 1 + openair2/UTIL/LOG/vcd_signal_dumper.h | 1 + targets/RT/USER/eNB_usrp.gtkw | 20 +++---- targets/RT/USER/lte-enb.c | 7 ++- 6 files changed, 63 insertions(+), 46 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index c483035abc..e18c0b1d91 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -210,6 +210,8 @@ typedef struct { pthread_t pthread_tx; /// pthread structure for rx processing thread pthread_t pthread_rx; + /// flag to indicate first RX acquisition + int first_rx; /// pthread attributes for tx processing thread pthread_attr_t attr_tx; /// pthread attributes for rx processing thread diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index c2dc89c2c5..a444686758 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2487,6 +2487,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl int subframe = proc->subframe_rx; int frame = proc->frame_rx; + if (subframe==9) { subframe=0; frame++; @@ -2515,7 +2516,10 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl fp->nb_antennas_rx); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is"); + if (proc->first_rx == 0) + AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is"); + else + proc->first_rx = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, frame ); @@ -2526,7 +2530,42 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl exit_fun( "problem receiving samples" ); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - + + // wake up TX thread + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc->instance_cnt_tx ); + exit_fun( "error locking mutex_tx" ); + return; + } + + int cnt_tx = ++proc->instance_cnt_tx; + // We have just received and processed the common part of the first slot of a subframe, say n. + // TX_rx is the last received timestamp (start of 1st slot), TX_tx is the desired + // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, + // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+3 + proc->timestamp_tx = proc->timestamp_rx + (3*fp->samples_per_tti); + proc->frame_tx = (subframe > 6) ? (frame+1) : frame; + proc->subframe_tx = (subframe + 3)%10; + + pthread_mutex_unlock( &proc->mutex_tx ); + + if (cnt_tx == 0){ + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB TX thread busy!! (cnt_tx %i)\n", frame, cnt_tx ); + exit_fun( "TX thread busy" ); + return; + } + // now do common RX processing for first slot in subframe + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); remove_7_5_kHz(eNB,subframe<<1); for (l=0; lsymbols_per_tti/2; l++) slot_fep_ul(fp, @@ -2540,6 +2579,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (eNB->node_function == NGFI_RRU_IF4) { //send_IF4(eNB,subframe<<1); } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); for (i=0; inb_antennas_rx; i++) rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][(fp->samples_per_tti>>1)+(subframe*fp->samples_per_tti)]; @@ -2552,6 +2592,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl fp->nb_antennas_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); remove_7_5_kHz(eNB,(subframe<<1)+1); for (l=0; lsymbols_per_tti/2; l++) slot_fep_ul(fp, @@ -2561,6 +2602,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl 0, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); if (eNB->node_function == NGFI_RRU_IF4) { //send_IF4(eNB,(subframe<<1)+1); } @@ -2610,39 +2652,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } - // wake up TX thread - // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc->instance_cnt_tx ); - exit_fun( "error locking mutex_tx" ); - return; - } - - int cnt_tx = ++proc->instance_cnt_tx; - // We have just received and processed the common part of an entire subframe, say n. - // TX_rx is the last received timestamp (start of 2nd slot), TX_tx is the desired - // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_per_frame) was (n+.5)*samples_per_tti, - // we want to generate subframe (n+3), so TS_tx = TX_rx+2.5*samples_per_tti, - // and proc->subframe_tx = proc->subframe_rx+3 - proc->timestamp_tx = proc->timestamp_rx + (fp->samples_per_tti<<1) + (fp->samples_per_tti>>1); - proc->frame_tx = (subframe > 6) ? (frame+1) : frame; - proc->subframe_tx = (subframe + 3)%10; - pthread_mutex_unlock( &proc->mutex_tx ); - - if (cnt_tx == 0){ - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB TX thread busy!! (cnt_tx %i)\n", frame, cnt_tx ); - exit_fun( "TX thread busy" ); - return; - } } diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 1972993a94..9e855696c4 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -230,6 +230,7 @@ const char* eurecomFunctionsNames[] = { "phy_procedures_eNb_rx", "phy_procedures_eNb_rx_common", "phy_procedures_eNb_rx_uespec", + "phy_eNB_slot_fep", "phy_procedures_ue_tx", "phy_procedures_ue_rx", "phy_procedures_eNB_lte", diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index f0a3e70274..192bebd976 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -204,6 +204,7 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, + VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE, diff --git a/targets/RT/USER/eNB_usrp.gtkw b/targets/RT/USER/eNB_usrp.gtkw index 677e214f31..474d2d1cf3 100644 --- a/targets/RT/USER/eNB_usrp.gtkw +++ b/targets/RT/USER/eNB_usrp.gtkw @@ -1,15 +1,15 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Fri May 27 01:34:58 2016 +[*] Sun May 29 20:10:01 2016 [*] [dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Fri May 27 01:33:50 2016" -[dumpfile_size] 12743642 +[dumpfile_mtime] "Sun May 29 20:07:25 2016" +[dumpfile_size] 16398004 [savefile] "/home/papillon/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw" -[timestart] 10801070000 -[size] 1535 845 -[pos] -1 -1 -*-21.793451 10817350000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[timestart] 10806270000 +[size] 1535 724 +[pos] 309 0 +*-18.793451 10806918339 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [sst_width] 284 [signals_width] 254 [sst_expanded] 1 @@ -28,10 +28,12 @@ variables.subframe_number_RX_eNB[63:0] functions.eNB_thread_rx0 functions.eNB_thread_tx0 functions.phy_procedures_eNb_tx -@29 functions.phy_enb_sfgen +@29 +functions.phy_eNB_slot_fep @28 functions.phy_procedures_eNb_rx +functions.phy_enb_prach_rx @24 variables.dci_info[63:0] variables.ue0_BO[63:0] @@ -46,8 +48,6 @@ functions.macxface_SR_indication @420 variables.ue0_SR_ENERGY[63:0] variables.ue0_SR_THRES[63:0] -@24 -variables.dci_info[63:0] @28 functions.phy_enb_ulsch_decoding0 @24 diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index a8444edfc9..dcf970e44e 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -372,7 +372,7 @@ static void* eNB_thread_tx( void* param ) } - LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] TX thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -868,7 +868,7 @@ static void* eNB_thread_prach( void* param ) } - LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -975,6 +975,9 @@ void init_eNB_proc(void) proc->instance_cnt_tx = -1; proc->instance_cnt_prach = -1; proc->CC_id = CC_id; + + proc->first_rx=1; + pthread_mutex_init( &proc->mutex_tx, NULL); pthread_cond_init( &proc->cond_tx, NULL); pthread_cond_init( &proc->cond_prach, NULL); From 7d6746b4b03688bb35ca7f69ebb41c127c4d37d4 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 30 May 2016 09:58:48 +0200 Subject: [PATCH 016/206] added lte-enb to lte-softmodem-noS1 target --- cmake_targets/CMakeLists.txt | 2447 +++++++++++++++++----------------- 1 file changed, 1224 insertions(+), 1223 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 43b7f63e22..5eca2e8d41 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -616,1229 +616,1230 @@ add_boolean_option(NAS_ADDRESS_FIX False "specific to oaisim: for nasmesh driver add_boolean_option(NAS_NETLINK False "???? Must be True to compile nasmesh driver without rtai") add_boolean_option(OAISIM False "specific to oaisim") add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????") -add_boolean_option(USE_MME False "this flag is used only one time in lte-softmodem.c") -add_list_string_option(PACKAGE_NAME "NotDefined" "As per attribute name") -add_boolean_option(MESSAGE_CHART_GENERATOR False "For generating sequence diagrams") -add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams") -add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams") - -add_boolean_option(ENB_AGENT True "enable eNB agent to inteface with a SDN contrller") - -######################## -# Include order -########################## -add_boolean_option(ENB_MODE True "Swap the include directories between openair2 and openair3" ) - -########################## -# Emulation options -########################## -add_boolean_option(ENABLE_PGM_TRANSPORT False "specific to oaisim, emulation through ethernet, reliable multicast") -add_boolean_option(ADDR_CONF False "specific to oaisim, IP autoconf of user-plane IP interface") -add_boolean_option(OPENAIR_EMU False "specific to oaisim") -add_boolean_option(OAI_EMU False "specific to oaisim") -add_boolean_option(PHY_ABSTRACTION False "specific to oaisim") - -########################## -# SCHEDULING/REAL-TIME/PERF options -########################## -add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME True "Add data in vcd traces: disable it if perf issues") -add_boolean_option(ENABLE_VCD True "always true now, time measurements of proc calls and var displays") -add_boolean_option(ENABLE_VCD_FIFO True "time measurements of proc calls and var displays sent to FIFO (one more thread)") -add_boolean_option(HARD_RT False "???") -add_boolean_option(LINUX False "used in weird memcpy() in pdcp.c ???") -add_boolean_option(LINUX_LIST False "used only in lists.c: either use OAI implementation of lists or Linux one (should be True, but it is False") -add_boolean_option(LOG_NO_THREAD True "Disable thread for log, seems always set to true") -add_boolean_option(OPENAIR_LTE True "Seems legacy: keep it to true") - -########################## -# PHY options -########################## -add_boolean_option(DRIVER2013 True "only relevant for EXMIMO") -add_boolean_option(ENABLE_FXP True "????") -add_boolean_option(ENABLE_NEW_MULTICAST False "specific to oaisim") -add_boolean_option(EXMIMO_IOT True "????") -add_boolean_option(LARGE_SCALE False "specific to oaisim: defines max eNB=2 and max UE=120") -add_boolean_option(LOCALIZATION False "???") -add_integer_option(MAX_NUM_CCs 1 "????") -add_boolean_option(MU_RECEIVER False "????") -add_boolean_option(NEW_FFT True "????") -add_boolean_option(OPENAIR1 True "????") -add_boolean_option(PBS_SIM False "????") -add_boolean_option(PC_DSP True "????") -add_boolean_option(PC_TARGET True "????") -add_boolean_option(PERFECT_CE False "????") -add_boolean_option(PHYSIM True "for L1 simulators (dlsim, ulsim, ...)") -add_boolean_option(PHY_CONTEXT True "not clear: must remain False for dlsim") -add_boolean_option(PHY_EMUL False "not clear: must remain False for dlsim") -add_boolean_option(PUCCH True "????") -add_boolean_option(RANDOM_BF False "????") -add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator") -add_boolean_option(DEBUG_PHY False "Enable PHY layer debugging options") -add_boolean_option(DEBUG_PHY_PROC False "Enable debugging of PHY layer procedures") -add_boolean_option(DEBUG_DLSCH False "Enable debugging of DLSCH physical layer channel") - -########################## -# 802.21 options -########################## -add_boolean_option(ENABLE_RAL False "ENABLE 802.21 INTERFACE") -add_boolean_option(USE_3GPP_ADDR_AS_LINK_ADDR False "As per attribute name") - -########################## -# NAS LAYER OPTIONS -########################## -add_boolean_option(ENABLE_NAS_UE_LOGGING True "????") -add_boolean_option(NAS_BUILT_IN_UE True "UE NAS layer present in this executable") -add_boolean_option(NAS_UE True "NAS UE INSTANCE (<> NAS_MME)") - - -########################## -# ACCESS STRATUM LAYER2 OPTIONS -########################## -add_boolean_option(MAC_CONTEXT True "specific to oaisim") -add_boolean_option(JUMBO_FRAME True "ENABLE LARGE SDU in ACCESS STRATUM (larger than common MTU)") - -########################## -# RLC LAYER OPTIONS -########################## -add_boolean_option(OPENAIR2 True "Access Stratum layer 2 built in executable") -add_boolean_option(TRACE_RLC_PAYLOAD False "Fatal assert in this case") -add_boolean_option(RLC_STOP_ON_LOST_PDU False "Fatal assert in this case") - -add_boolean_option(TRACE_RLC_MUTEX True "TRACE for RLC, possible problem in thread scheduling") -add_boolean_option(TRACE_RLC_AM_BO False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_FREE_SDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_HOLE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_PDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_RESEGMENT False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_RX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_RX_DECODE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_TX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_TX_STATUS False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_STATUS_CREATION False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") - -add_boolean_option(STOP_ON_IP_TRAFFIC_OVERLOAD False "") -add_boolean_option(TRACE_RLC_UM_DAR False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_UM_DISPLAY_ASCII_DATA False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_UM_PDU False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_UM_RX False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_UM_SEGMENT False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_UM_TX_STATUS False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") - - -########################## -# PDCP LAYER OPTIONS -########################## -add_boolean_option(PDCP_USE_NETLINK False "For eNB, PDCP communicate with a NETLINK socket if connected to network driver, else could use a RT-FIFO") -add_boolean_option(PDCP_USE_NETLINK_QUEUES False "When PDCP_USE_NETLINK is true, incoming IP packets are stored in queues") -add_boolean_option(LINK_ENB_PDCP_TO_IP_DRIVER False "For eNB, PDCP communicate with a IP driver") -add_boolean_option(LINK_ENB_PDCP_TO_GTPV1U True "For eNB, PDCP communicate with GTP-U protocol (eNB<->S-GW)") - -########################## -# RRC LAYER OPTIONS -########################## -add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "Otherwise it is UM, configure params are actually set in rrc_eNB.c:rrc_eNB_generate_defaultRRCConnectionReconfiguration(...)") - - -########################## -# S1AP LAYER OPTIONS -########################## -# none - -########################## -# PROJECTS (IST, FRENCH COLL., etc) -# SPECIFIC OPTIONS -########################## -add_boolean_option(SPECTRA False "???") -add_boolean_option(MIH_C_MEDIEVAL_EXTENSIONS False "EXTENSIONS TO MIH 802.21 IN CONTEXT OF IST PROJECT CALLED MEDIEVAL") - - - -add_boolean_option(EMOS False "????") -if(${EMOS}) - add_definitions("-D_FILE_OFFSET_BITS=64") - set(EMOS_LIB gps) -endif(${EMOS}) - - - # add the binary tree to the search path for include files -####################################################### -# We will find ConfigOAI.h after generation in target directory -include_directories("${OPENAIR_BIN_DIR}") -# add directories to find all include files -# the internal rule is to use generic names such as defs.h -# but to make it uniq name as adding the relative path in the include directtive -# example: #include "RRC/LITE/defs.h" -#find_path (include_dirs_all *.h ${OPENAIR_DIR}) -#find_path (include_dirs_all *.h PATHS /usr/include NO_CMAKE_PATH) -#include_directories("${include_dirs_all}") - -# Legacy exact order -if(ENB_MODE) - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") -else() - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") -endif() -include_directories("${OPENAIR1_DIR}") -include_directories("${OPENAIR2_DIR}/NAS") -include_directories("${OPENAIR2_DIR}") -include_directories("${OPENAIR2_DIR}/LAYER2/RLC") -include_directories("${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0") -include_directories("${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0") -include_directories("${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0") -include_directories("${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0") -include_directories("${OPENAIR2_DIR}/RRC/LITE/MESSAGES") -include_directories("${OPENAIR2_DIR}/RRC/LITE") -include_directories("${OPENAIR3_DIR}/RAL-LTE/INTERFACE-802.21/INCLUDE") -include_directories("${OPENAIR3_DIR}/RAL-LTE/LTE_RAL_ENB/INCLUDE") -include_directories("${OPENAIR3_DIR}/RAL-LTE/LTE_RAL_UE/INCLUDE") -include_directories("${OPENAIR_DIR}/common/utils") -include_directories("${OPENAIR_DIR}/common/utils/itti") -include_directories("${OPENAIR3_DIR}/NAS/COMMON") -include_directories("${OPENAIR3_DIR}/NAS/COMMON/API/NETWORK") -include_directories("${OPENAIR3_DIR}/NAS/COMMON/EMM/MSG") -include_directories("${OPENAIR3_DIR}/NAS/COMMON/ESM/MSG") -include_directories("${OPENAIR3_DIR}/NAS/COMMON/IES") -include_directories("${OPENAIR3_DIR}/NAS/COMMON/UTIL") -include_directories("${OPENAIR3_DIR}/SECU") -include_directories("${OPENAIR3_DIR}/SCTP") -include_directories("${OPENAIR3_DIR}/S1AP") -include_directories("${OPENAIR2_DIR}/X2AP") -include_directories("${OPENAIR3_DIR}/UDP") -include_directories("${OPENAIR3_DIR}/GTPV1-U") -include_directories("${OPENAIR_DIR}/targets/COMMON") -include_directories("${OPENAIR_DIR}/targets/ARCH/COMMON") -include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/USERSPACE/LIB/") -include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS") -include_directories("${OPENAIR2_DIR}/ENB_APP") -include_directories("${OPENAIR2_DIR}/UTIL/OSA") -include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc") -include_directories("${OPENAIR2_DIR}/UTIL/MEM") -include_directories("${OPENAIR2_DIR}/UTIL/LISTS") -include_directories("${OPENAIR2_DIR}/UTIL/FIFO") -include_directories("${OPENAIR2_DIR}/UTIL/OCG") -include_directories("${OPENAIR2_DIR}/UTIL/MATH") -include_directories("${OPENAIR2_DIR}/UTIL/TIMER") -include_directories("${OPENAIR2_DIR}/UTIL/OMG") -include_directories("${OPENAIR2_DIR}/UTIL/OTG") -include_directories("${OPENAIR2_DIR}/UTIL/CLI") -include_directories("${OPENAIR2_DIR}/UTIL/OPT") -include_directories("${OPENAIR2_DIR}/UTIL/OMV") -include_directories("${OPENAIR2_DIR}/RRC/LITE/MESSAGES") -include_directories("${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/shared") -include_directories("${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/include") -include_directories("${OPENAIR_DIR}") - -# Utilities Library -################ -add_library(HASHTABLE - ${OPENAIR_DIR}/common/utils/collection/hashtable/hashtable.c - ${OPENAIR_DIR}/common/utils/collection/hashtable/obj_hashtable.c -) -include_directories(${OPENAIR_DIR}/common/utils/collection/hashtable) - -if (MESSAGE_CHART_GENERATOR) - add_library(MSC - ${OPENAIR_DIR}/common/utils/msc/msc.c - ) - set(MSC_LIB MSC) -endif() -include_directories(${OPENAIR_DIR}/common/utils/msc) - -set(UTIL_SRC - ${OPENAIR2_DIR}/UTIL/CLI/cli.c - ${OPENAIR2_DIR}/UTIL/CLI/cli_cmd.c - ${OPENAIR2_DIR}/UTIL/CLI/cli_server.c - ${OPENAIR2_DIR}/UTIL/FIFO/pad_list.c - ${OPENAIR2_DIR}/UTIL/LISTS/list.c - ${OPENAIR2_DIR}/UTIL/LISTS/list2.c - ${OPENAIR2_DIR}/UTIL/LOG/log.c - ${OPENAIR2_DIR}/UTIL/LOG/vcd_signal_dumper.c - ${OPENAIR2_DIR}/UTIL/MATH/oml.c - ${OPENAIR2_DIR}/UTIL/MEM/mem_block.c - ${OPENAIR2_DIR}/UTIL/OCG/OCG.c - ${OPENAIR2_DIR}/UTIL/OCG/OCG_create_dir.c - ${OPENAIR2_DIR}/UTIL/OCG/OCG_detect_file.c - ${OPENAIR2_DIR}/UTIL/OCG/OCG_generate_report.c - ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_filename.c - ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_XML.c - ${OPENAIR2_DIR}/UTIL/OCG/OCG_save_XML.c - ${OPENAIR2_DIR}/UTIL/OMG/client_traci_OMG.c - ${OPENAIR2_DIR}/UTIL/OMG/common.c - ${OPENAIR2_DIR}/UTIL/OMG/grid.c - ${OPENAIR2_DIR}/UTIL/OMG/id_manager.c - ${OPENAIR2_DIR}/UTIL/OMG/job.c - ${OPENAIR2_DIR}/UTIL/OMG/mobility_parser.c - ${OPENAIR2_DIR}/UTIL/OMG/omg.c - ${OPENAIR2_DIR}/UTIL/OMG/omg_hashtable.c - ${OPENAIR2_DIR}/UTIL/OMG/rwalk.c - ${OPENAIR2_DIR}/UTIL/OMG/rwp.c - ${OPENAIR2_DIR}/UTIL/OMG/socket_traci_OMG.c - ${OPENAIR2_DIR}/UTIL/OMG/static.c - ${OPENAIR2_DIR}/UTIL/OMG/steadystaterwp.c - ${OPENAIR2_DIR}/UTIL/OMG/storage_traci_OMG.c - ${OPENAIR2_DIR}/UTIL/OMG/trace.c - ${OPENAIR2_DIR}/UTIL/OMG/trace_hashtable.c - ${OPENAIR2_DIR}/UTIL/OPT/probe.c - ${OPENAIR2_DIR}/UTIL/OTG/otg_tx.c - ${OPENAIR2_DIR}/UTIL/OTG/otg.c - ${OPENAIR2_DIR}/UTIL/OTG/otg_kpi.c - ${OPENAIR2_DIR}/UTIL/OTG/otg_models.c - ${OPENAIR2_DIR}/UTIL/OTG/otg_form.c - ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c - ) -add_library(UTIL ${UTIL_SRC}) - -set(SECU_OSA_SRC - ${OPENAIR2_DIR}/UTIL/OSA/osa_key_deriver.c - ${OPENAIR2_DIR}/UTIL/OSA/osa_rijndael.c - ${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c - ${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eea.c - ${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c - ) -add_library(SECU_OSA ${SECU_OSA_SRC}) - -set(SECU_CN_SRC - ${OPENAIR3_DIR}/SECU/kdf.c - ${OPENAIR3_DIR}/SECU/rijndael.c - ${OPENAIR3_DIR}/SECU/snow3g.c - ${OPENAIR3_DIR}/SECU/key_nas_deriver.c - ${OPENAIR3_DIR}/SECU/nas_stream_eea1.c - ${OPENAIR3_DIR}/SECU/nas_stream_eia1.c - ${OPENAIR3_DIR}/SECU/nas_stream_eea2.c - ${OPENAIR3_DIR}/SECU/nas_stream_eia2.c - ) -add_library(SECU_CN ${SECU_CN_SRC}) - -# Scheduler -################################" -file(GLOB SCHED_SRC ${OPENAIR1_DIR}/SCHED/*.c) -add_library(SCHED_LIB ${SCHED_SRC}) - -# Layer 1 -############################# -set(PHY_SRC - # depend on code generation from asn1c - ${RRC_FULL_DIR}/asn1_constants.h - # actual source - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pss.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots_mbsfn.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_coding.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_modulation.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_demodulation.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_llr_computation.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/power_control.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_decoding.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_scrambling.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/uci_tools.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pbch.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/phich.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pcfich.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pucch.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/srs_modulation.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/drs_modulation.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_modulation.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_coding.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_decoding.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/rar_tools.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/print_stats.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/initial_sync.c - ${OPENAIR1_DIR}/PHY/MODULATION/ofdm_mod.c - ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep.c - ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_mbsfn.c - ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c - ${OPENAIR1_DIR}/PHY/MODULATION/ul_7_5_kHz.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_time.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_timefreq.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_est_freq_offset.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ue_measurements.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_eNB_measurements.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/adjust_gain.c - ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_cell_spec.c - ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_uespec.c - ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold.c - ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold_mbsfn.c - ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_mbsfn.c - ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_ul_ref.c - ${OPENAIR1_DIR}/PHY/CODING/lte_segmentation.c - ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte.c - ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_lte.c - ${OPENAIR1_DIR}/PHY/CODING/3gpplte_sse.c - ${OPENAIR1_DIR}/PHY/CODING/crc_byte.c - ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c - ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c - ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c - ${OPENAIR1_DIR}/PHY/CODING/lte_rate_matching.c - ${OPENAIR1_DIR}/PHY/CODING/rate_matching.c - ${OPENAIR1_DIR}/PHY/CODING/viterbi.c - ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c - ${OPENAIR1_DIR}/PHY/INIT/lte_init.c - ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c - ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c - ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c - ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c - ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c - ${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c - ${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c - ${OPENAIR1_DIR}/PHY/TOOLS/cdot_prod.c - ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c - ${OPENAIR1_DIR}/PHY/TOOLS/dB_routines.c - ${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c - ${OPENAIR1_DIR}/PHY/TOOLS/time_meas.c - ${OPENAIR1_DIR}/PHY/TOOLS/lut.c - ) -if (${SMBV}) - set(PHY_SRC "${PHY_SRC} ${OPENAIR1_DIR}/PHY/TOOLS/smbv.c") -endif (${SMBV}) -add_library(PHY ${PHY_SRC}) - -#Layer 2 library -##################### -set(MAC_DIR ${OPENAIR2_DIR}/LAYER2/MAC) -set(RLC_DIR ${OPENAIR2_DIR}/LAYER2/RLC) -set(RLC_UM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0) -set(RLC_AM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0) -set(RLC_TM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0) -set(RRC_DIR ${OPENAIR2_DIR}/RRC/LITE) -set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0) -set(L2_SRC - ${OPENAIR2_DIR}/LAYER2/openair2_proc.c - ${PDCP_DIR}/pdcp.c - ${PDCP_DIR}/pdcp_fifo.c - ${PDCP_DIR}/pdcp_sequence_manager.c - ${PDCP_DIR}/pdcp_primitives.c - ${PDCP_DIR}/pdcp_util.c - ${PDCP_DIR}/pdcp_security.c - ${PDCP_DIR}/pdcp_netlink.c - ${RLC_AM_DIR}/rlc_am.c - ${RLC_AM_DIR}/rlc_am_init.c - ${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c - ${RLC_AM_DIR}/rlc_am_timer_reordering.c - ${RLC_AM_DIR}/rlc_am_timer_status_prohibit.c - ${RLC_AM_DIR}/rlc_am_segment.c - ${RLC_AM_DIR}/rlc_am_segments_holes.c - ${RLC_AM_DIR}/rlc_am_in_sdu.c - ${RLC_AM_DIR}/rlc_am_receiver.c - ${RLC_AM_DIR}/rlc_am_retransmit.c - ${RLC_AM_DIR}/rlc_am_windows.c - ${RLC_AM_DIR}/rlc_am_rx_list.c - ${RLC_AM_DIR}/rlc_am_reassembly.c - ${RLC_AM_DIR}/rlc_am_status_report.c - ${RLC_TM_DIR}/rlc_tm.c - ${RLC_TM_DIR}/rlc_tm_init.c - ${RLC_UM_DIR}/rlc_um.c - ${RLC_UM_DIR}/rlc_um_fsm.c - ${RLC_UM_DIR}/rlc_um_control_primitives.c - ${RLC_UM_DIR}/rlc_um_segment.c - ${RLC_UM_DIR}/rlc_um_reassembly.c - ${RLC_UM_DIR}/rlc_um_receiver.c - ${RLC_UM_DIR}/rlc_um_dar.c - ${RLC_DIR}/rlc_mac.c - ${RLC_DIR}/rlc.c - ${RLC_DIR}/rlc_rrc.c - ${RLC_DIR}/rlc_mpls.c - ${RRC_DIR}/rrc_UE.c - ${RRC_DIR}/rrc_eNB.c - ${RRC_DIR}/rrc_eNB_S1AP.c - ${RRC_DIR}/rrc_eNB_UE_context.c - ${RRC_DIR}/rrc_common.c - ${RRC_DIR}/L2_interface.c - ) -set (MAC_SRC - ${MAC_DIR}/lte_transport_init.c - ${MAC_DIR}/main.c - ${MAC_DIR}/ue_procedures.c - ${MAC_DIR}/ra_procedures.c - ${MAC_DIR}/l1_helpers.c - ${MAC_DIR}/rar_tools.c - ${MAC_DIR}/eNB_scheduler.c - ${MAC_DIR}/eNB_scheduler_dlsch.c - ${MAC_DIR}/eNB_scheduler_ulsch.c - ${MAC_DIR}/eNB_scheduler_mch.c - ${MAC_DIR}/eNB_scheduler_bch.c - ${MAC_DIR}/eNB_scheduler_primitives.c - ${MAC_DIR}/eNB_scheduler_RA.c - ${MAC_DIR}/pre_processor.c - ${MAC_DIR}/config.c - ) - -set (ENB_APP_SRC - ${OPENAIR2_DIR}/ENB_APP/enb_app.c - ${OPENAIR2_DIR}/ENB_APP/enb_config.c - ) - -add_library(L2 - ${L2_SRC} - ${MAC_SRC} - ${ENB_APP_SRC}) -# ${OPENAIR2_DIR}/RRC/L2_INTERFACE/openair_rrc_L2_interface.c) - -# L3 Libs -########################## - -set(RAL_LTE_DIR ${OPENAIR3_DIR}/RAL-LTE/) -if (${ENABLE_RAL}) - set(RAL_LTE_SRC - ${RRC_DIR}/rrc_UE_ral.c - ${RRC_DIR}/rrc_eNB_ral.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_action.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_main.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_mih_msg.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_parameters.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_process.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_rrc_msg.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_subscribe.c - ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_thresholds.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_action.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_main.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_mih_msg.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_parameters.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_process.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_rrc_msg.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_subscribe.c - ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_thresholds.c - ) - add_library(RAL ${RAL_LTE_SRC}) - set(RAL_LIB RAL) -endif() - -if(${MIH_C_MEDIEVAL_EXTENSIONS}) - set(MIH_SRC - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_header_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_msg_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_primitive_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F1_basic_data_types_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F2_general_data_types_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F3_data_types_for_address_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F4_data_types_for_links_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F9_data_types_for_qos_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F13_data_types_for_information_elements_codec.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_L2_type_values_for_tlv_encoding.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_Medieval_extensions.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_bit_buffer.c - ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C.c - ) - add_library(MIH ${MIH_SRC}) - set(MIH_LIB MIH) -endif() - -# CN libs -########################## - -add_library(CN_UTILS - ${OPENAIR3_DIR}/UTILS/conversions.c - ${OPENAIR3_DIR}/UTILS/enum_string.c - ${OPENAIR3_DIR}/UTILS/log.c - ${OPENAIR3_DIR}/UTILS/mcc_mnc_itu.c - ) - -set(GTPV1U_DIR ${OPENAIR3_DIR}/GTPV1-U) -set (GTPV1U_SRC - ${RRC_DIR}/rrc_eNB_GTPV1U.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTrxn.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uMsg.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1u.c - ${GTPV1U_DIR}/gtpv1u_teid_pool.c -) -add_library(GTPV1U ${GTPV1U_SRC}) - -set(SCTP_SRC - ${OPENAIR3_DIR}/SCTP/sctp_common.c - ${OPENAIR3_DIR}/SCTP/sctp_eNB_task.c - ${OPENAIR3_DIR}/SCTP/sctp_eNB_itti_messaging.c -) -add_library(SCTP_CLIENT ${SCTP_SRC}) - -add_library(UDP ${OPENAIR3_DIR}/UDP/udp_eNB_task.c) - - -set(NAS_SRC ${OPENAIR3_DIR}/NAS/) -set(libnas_api_OBJS - ${NAS_SRC}COMMON/API/NETWORK/as_message.c - ${NAS_SRC}COMMON/API/NETWORK/nas_message.c - ${NAS_SRC}COMMON/API/NETWORK/network_api.c - ) - -set(libnas_emm_msg_OBJS - ${NAS_SRC}COMMON/EMM/MSG/AttachAccept.c - ${NAS_SRC}COMMON/EMM/MSG/AttachComplete.c - ${NAS_SRC}COMMON/EMM/MSG/AttachReject.c - ${NAS_SRC}COMMON/EMM/MSG/AttachRequest.c - ${NAS_SRC}COMMON/EMM/MSG/AuthenticationFailure.c - ${NAS_SRC}COMMON/EMM/MSG/AuthenticationReject.c - ${NAS_SRC}COMMON/EMM/MSG/AuthenticationRequest.c - ${NAS_SRC}COMMON/EMM/MSG/AuthenticationResponse.c - ${NAS_SRC}COMMON/EMM/MSG/CsServiceNotification.c - ${NAS_SRC}COMMON/EMM/MSG/DetachAccept.c - ${NAS_SRC}COMMON/EMM/MSG/DetachRequest.c - ${NAS_SRC}COMMON/EMM/MSG/DownlinkNasTransport.c - ${NAS_SRC}COMMON/EMM/MSG/EmmInformation.c - ${NAS_SRC}COMMON/EMM/MSG/emm_msg.c - ${NAS_SRC}COMMON/EMM/MSG/EmmStatus.c - ${NAS_SRC}COMMON/EMM/MSG/ExtendedServiceRequest.c - ${NAS_SRC}COMMON/EMM/MSG/GutiReallocationCommand.c - ${NAS_SRC}COMMON/EMM/MSG/GutiReallocationComplete.c - ${NAS_SRC}COMMON/EMM/MSG/IdentityRequest.c - ${NAS_SRC}COMMON/EMM/MSG/IdentityResponse.c - ${NAS_SRC}COMMON/EMM/MSG/SecurityModeCommand.c - ${NAS_SRC}COMMON/EMM/MSG/SecurityModeComplete.c - ${NAS_SRC}COMMON/EMM/MSG/SecurityModeReject.c - ${NAS_SRC}COMMON/EMM/MSG/ServiceReject.c - ${NAS_SRC}COMMON/EMM/MSG/ServiceRequest.c - ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateAccept.c - ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateComplete.c - ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateReject.c - ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateRequest.c - ${NAS_SRC}COMMON/EMM/MSG/UplinkNasTransport.c -) - -set(libnas_esm_msg_OBJS - ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.c - ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.c - ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextRequest.c - ${NAS_SRC}COMMON/ESM/MSG/ActivateDefaultEpsBearerContextAccept.c - ${NAS_SRC}COMMON/ESM/MSG/ActivateDefaultEpsBearerContextReject.c - ${NAS_SRC}COMMON/ESM/MSG/ActivateDefaultEpsBearerContextRequest.c - ${NAS_SRC}COMMON/ESM/MSG/BearerResourceAllocationReject.c - ${NAS_SRC}COMMON/ESM/MSG/BearerResourceAllocationRequest.c - ${NAS_SRC}COMMON/ESM/MSG/BearerResourceModificationReject.c - ${NAS_SRC}COMMON/ESM/MSG/BearerResourceModificationRequest.c - ${NAS_SRC}COMMON/ESM/MSG/DeactivateEpsBearerContextAccept.c - ${NAS_SRC}COMMON/ESM/MSG/DeactivateEpsBearerContextRequest.c - ${NAS_SRC}COMMON/ESM/MSG/EsmInformationRequest.c - ${NAS_SRC}COMMON/ESM/MSG/EsmInformationResponse.c - ${NAS_SRC}COMMON/ESM/MSG/esm_msg.c - ${NAS_SRC}COMMON/ESM/MSG/EsmStatus.c - ${NAS_SRC}COMMON/ESM/MSG/ModifyEpsBearerContextAccept.c - ${NAS_SRC}COMMON/ESM/MSG/ModifyEpsBearerContextReject.c - ${NAS_SRC}COMMON/ESM/MSG/ModifyEpsBearerContextRequest.c - ${NAS_SRC}COMMON/ESM/MSG/PdnConnectivityReject.c - ${NAS_SRC}COMMON/ESM/MSG/PdnConnectivityRequest.c - ${NAS_SRC}COMMON/ESM/MSG/PdnDisconnectReject.c - ${NAS_SRC}COMMON/ESM/MSG/PdnDisconnectRequest.c -) - -set(libnas_ies_OBJS - ${NAS_SRC}COMMON/IES/AccessPointName.c - ${NAS_SRC}COMMON/IES/AdditionalUpdateResult.c - ${NAS_SRC}COMMON/IES/AdditionalUpdateType.c - ${NAS_SRC}COMMON/IES/ApnAggregateMaximumBitRate.c - ${NAS_SRC}COMMON/IES/AuthenticationFailureParameter.c - ${NAS_SRC}COMMON/IES/AuthenticationParameterAutn.c - ${NAS_SRC}COMMON/IES/AuthenticationParameterRand.c - ${NAS_SRC}COMMON/IES/AuthenticationResponseParameter.c - ${NAS_SRC}COMMON/IES/CipheringKeySequenceNumber.c - ${NAS_SRC}COMMON/IES/Cli.c - ${NAS_SRC}COMMON/IES/CsfbResponse.c - ${NAS_SRC}COMMON/IES/DaylightSavingTime.c - ${NAS_SRC}COMMON/IES/DetachType.c - ${NAS_SRC}COMMON/IES/DrxParameter.c - ${NAS_SRC}COMMON/IES/EmergencyNumberList.c - ${NAS_SRC}COMMON/IES/EmmCause.c - ${NAS_SRC}COMMON/IES/EpsAttachResult.c - ${NAS_SRC}COMMON/IES/EpsAttachType.c - ${NAS_SRC}COMMON/IES/EpsBearerContextStatus.c - ${NAS_SRC}COMMON/IES/EpsBearerIdentity.c - ${NAS_SRC}COMMON/IES/EpsMobileIdentity.c - ${NAS_SRC}COMMON/IES/EpsNetworkFeatureSupport.c - ${NAS_SRC}COMMON/IES/EpsQualityOfService.c - ${NAS_SRC}COMMON/IES/EpsUpdateResult.c - ${NAS_SRC}COMMON/IES/EpsUpdateType.c - ${NAS_SRC}COMMON/IES/EsmCause.c - ${NAS_SRC}COMMON/IES/EsmInformationTransferFlag.c - ${NAS_SRC}COMMON/IES/EsmMessageContainer.c - ${NAS_SRC}COMMON/IES/GprsTimer.c - ${NAS_SRC}COMMON/IES/GutiType.c - ${NAS_SRC}COMMON/IES/IdentityType2.c - ${NAS_SRC}COMMON/IES/ImeisvRequest.c - ${NAS_SRC}COMMON/IES/KsiAndSequenceNumber.c - ${NAS_SRC}COMMON/IES/LcsClientIdentity.c - ${NAS_SRC}COMMON/IES/LcsIndicator.c - ${NAS_SRC}COMMON/IES/LinkedEpsBearerIdentity.c - ${NAS_SRC}COMMON/IES/LlcServiceAccessPointIdentifier.c - ${NAS_SRC}COMMON/IES/LocationAreaIdentification.c - ${NAS_SRC}COMMON/IES/MessageType.c - ${NAS_SRC}COMMON/IES/MobileIdentity.c - ${NAS_SRC}COMMON/IES/MobileStationClassmark2.c - ${NAS_SRC}COMMON/IES/MobileStationClassmark3.c - ${NAS_SRC}COMMON/IES/MsNetworkCapability.c - ${NAS_SRC}COMMON/IES/MsNetworkFeatureSupport.c - ${NAS_SRC}COMMON/IES/NasKeySetIdentifier.c - ${NAS_SRC}COMMON/IES/NasMessageContainer.c - ${NAS_SRC}COMMON/IES/NasRequestType.c - ${NAS_SRC}COMMON/IES/NasSecurityAlgorithms.c - ${NAS_SRC}COMMON/IES/NetworkName.c - ${NAS_SRC}COMMON/IES/Nonce.c - ${NAS_SRC}COMMON/IES/PacketFlowIdentifier.c - ${NAS_SRC}COMMON/IES/PagingIdentity.c - ${NAS_SRC}COMMON/IES/PdnAddress.c - ${NAS_SRC}COMMON/IES/PdnType.c - ${NAS_SRC}COMMON/IES/PlmnList.c - ${NAS_SRC}COMMON/IES/ProcedureTransactionIdentity.c - ${NAS_SRC}COMMON/IES/ProtocolConfigurationOptions.c - ${NAS_SRC}COMMON/IES/ProtocolDiscriminator.c - ${NAS_SRC}COMMON/IES/PTmsiSignature.c - ${NAS_SRC}COMMON/IES/QualityOfService.c - ${NAS_SRC}COMMON/IES/RadioPriority.c - ${NAS_SRC}COMMON/IES/SecurityHeaderType.c - ${NAS_SRC}COMMON/IES/ServiceType.c - ${NAS_SRC}COMMON/IES/ShortMac.c - ${NAS_SRC}COMMON/IES/SsCode.c - ${NAS_SRC}COMMON/IES/SupportedCodecList.c - ${NAS_SRC}COMMON/IES/TimeZoneAndTime.c - ${NAS_SRC}COMMON/IES/TimeZone.c - ${NAS_SRC}COMMON/IES/TmsiStatus.c - ${NAS_SRC}COMMON/IES/TrackingAreaIdentity.c - ${NAS_SRC}COMMON/IES/TrackingAreaIdentityList.c - ${NAS_SRC}COMMON/IES/TrafficFlowAggregateDescription.c - ${NAS_SRC}COMMON/IES/TrafficFlowTemplate.c - ${NAS_SRC}COMMON/IES/TransactionIdentifier.c - ${NAS_SRC}COMMON/IES/UeNetworkCapability.c - ${NAS_SRC}COMMON/IES/UeRadioCapabilityInformationUpdateNeeded.c - ${NAS_SRC}COMMON/IES/UeSecurityCapability.c - ${NAS_SRC}COMMON/IES/VoiceDomainPreferenceAndUeUsageSetting.c -) - -set (libnas_utils_OBJS - ${NAS_SRC}COMMON/UTIL/device.c - ${NAS_SRC}COMMON/UTIL/memory.c - ${NAS_SRC}COMMON/UTIL/nas_log.c - ${NAS_SRC}COMMON/UTIL/nas_timer.c - ${NAS_SRC}COMMON/UTIL/socket.c - ${NAS_SRC}COMMON/UTIL/stty.c - ${NAS_SRC}COMMON/UTIL/TLVEncoder.c - ${NAS_SRC}COMMON/UTIL/TLVDecoder.c - ${NAS_SRC}COMMON/UTIL/OctetString.c -) - -if(NAS_UE) - set(libnas_ue_api_OBJS - ${NAS_SRC}UE/API/USER/at_command.c - ${NAS_SRC}UE/API/USER/at_error.c - ${NAS_SRC}UE/API/USER/at_response.c - ${NAS_SRC}UE/API/USER/user_api.c - ${NAS_SRC}UE/API/USER/user_indication.c - ${NAS_SRC}UE/API/USIM/aka_functions.c - ${NAS_SRC}UE/API/USIM/usim_api.c - ) - set(libnas_ue_emm_OBJS - ${NAS_SRC}UE/EMM/Attach.c - ${NAS_SRC}UE/EMM/Authentication.c - ${NAS_SRC}UE/EMM/Detach.c - ${NAS_SRC}UE/EMM/emm_main.c - ${NAS_SRC}UE/EMM/EmmStatusHdl.c - ${NAS_SRC}UE/EMM/Identification.c - ${NAS_SRC}UE/EMM/IdleMode.c - ${NAS_SRC}UE/EMM/LowerLayer.c - ${NAS_SRC}UE/EMM/SecurityModeControl.c - ${NAS_SRC}UE/EMM/ServiceRequestHdl.c - ${NAS_SRC}UE/EMM/TrackingAreaUpdate.c - ) - set(libnas_ue_emm_sap_OBJS - ${NAS_SRC}UE/EMM/SAP/emm_as.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttachNeeded.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregistered.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredLimitedService.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoImsi.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNormalService.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredPlmnSearch.c - ${NAS_SRC}UE/EMM/SAP/emm_esm.c - ${NAS_SRC}UE/EMM/SAP/emm_fsm.c - ${NAS_SRC}UE/EMM/SAP/EmmNull.c - ${NAS_SRC}UE/EMM/SAP/emm_recv.c - ${NAS_SRC}UE/EMM/SAP/emm_reg.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c - ${NAS_SRC}UE/EMM/SAP/EmmRegistered.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredLimitedService.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNoCellAvailable.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNormalService.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredPlmnSearch.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredUpdateNeeded.c - ${NAS_SRC}UE/EMM/SAP/emm_sap.c - ${NAS_SRC}UE/EMM/SAP/emm_send.c - ${NAS_SRC}UE/EMM/SAP/EmmServiceRequestInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c - ) - set (libnas_ue_esm_OBJS - ${NAS_SRC}UE/ESM/DedicatedEpsBearerContextActivation.c - ${NAS_SRC}UE/ESM/DefaultEpsBearerContextActivation.c - ${NAS_SRC}UE/ESM/EpsBearerContextDeactivation.c - ${NAS_SRC}UE/ESM/esm_ebr.c - ${NAS_SRC}UE/ESM/esm_ebr_context.c - ${NAS_SRC}UE/ESM/esm_ip.c - ${NAS_SRC}UE/ESM/esm_main.c - ${NAS_SRC}UE/ESM/esm_pt.c - ${NAS_SRC}UE/ESM/EsmStatusHdl.c - ${NAS_SRC}UE/ESM/PdnConnectivity.c - ${NAS_SRC}UE/ESM/PdnDisconnect.c - ) - set(libnas_ue_esm_sap_OBJS - ${NAS_SRC}UE/ESM/SAP/esm_recv.c - ${NAS_SRC}UE/ESM/SAP/esm_send.c - ${NAS_SRC}UE/ESM/SAP/esm_sap.c - ) - add_library(LIB_NAS_UE - ${NAS_SRC}UE/nas_itti_messaging.c - ${NAS_SRC}UE/nas_network.c - ${NAS_SRC}UE/nas_parser.c - ${NAS_SRC}UE/nas_proc.c - ${NAS_SRC}UE/nas_user.c - ${libnas_api_OBJS} - ${libnas_ue_api_OBJS} - ${libnas_emm_msg_OBJS} - ${libnas_esm_msg_OBJS} - ${libnas_ies_OBJS} - ${libnas_utils_OBJS} - ${libnas_ue_emm_OBJS} - ${libnas_ue_emm_sap_OBJS} - ${libnas_ue_esm_OBJS} - ${libnas_ue_esm_sap_OBJS} - ) - set(NAS_UE_LIB LIB_NAS_UE) - - include_directories(${NAS_SRC}UE) - include_directories(${NAS_SRC}UE/API/USER) - include_directories(${NAS_SRC}UE/API/USIM) - include_directories(${NAS_SRC}UE/EMM) - include_directories(${NAS_SRC}UE/EMM/SAP) - include_directories(${NAS_SRC}UE/ESM) - include_directories(${NAS_SRC}UE/ESM/SAP) -endif() - - - -# Make lfds as a own source code (even if it is a outside library) -# For better intergration with compilation flags & structure of cmake -################################################################### -set(lfds ${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/src/) -file(GLOB lfds_queue ${lfds}/lfds611_queue/*.c) -file(GLOB lfds_ring ${lfds}/lfds611_ringbuffer/*.c) -file(GLOB lfds_slist ${lfds}/lfds611_slist/*.c) -file(GLOB lfds_stack ${lfds}/lfds611_stack/*.c) -file(GLOB lfds_freelist ${lfds}/lfds611_freelist/*.c) - -include_directories(${lfds}) -add_library(LFDS - ${lfds_queue} ${lfds_ring} ${lfds_slist} ${lfds_stack} ${lfds_freelist} - ${lfds}/lfds611_liblfds/lfds611_liblfds_abstraction_test_helpers.c - ${lfds}/lfds611_liblfds/lfds611_liblfds_aligned_free.c - ${lfds}/lfds611_liblfds/lfds611_liblfds_aligned_malloc.c - ${lfds}/lfds611_abstraction/lfds611_abstraction_free.c - ${lfds}/lfds611_abstraction/lfds611_abstraction_malloc.c -) - -# Simulation library -########################## -add_library(SIMU -${OPENAIR1_DIR}/SIMULATION/TOOLS/random_channel.c -${OPENAIR1_DIR}/SIMULATION/TOOLS/rangen_double.c -${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c -${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_channel.c -${OPENAIR1_DIR}/SIMULATION/TOOLS/abstraction.c -${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_tv_channel.c -${OPENAIR1_DIR}/SIMULATION/RF/rf.c -${OPENAIR1_DIR}/SIMULATION/RF/dac.c -${OPENAIR1_DIR}/SIMULATION/RF/adc.c -) - -add_library(SIMU_ETH -${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c -${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c -${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c -${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/bypass_session_layer.c -${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/emu_transport.c -${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/pgm_link.c -) - -add_library(OPENAIR0_LIB - ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c -) - -# System packages that are required -# We use either the cmake buildin, in ubuntu are in: /usr/share/cmake*/Modules/ -# or cmake provide a generic interface to pkg-config that widely used -################################### -include(FindPkgConfig) - -pkg_search_module(LIBXML2 libxml-2.0 REQUIRED) -include_directories(${LIBXML2_INCLUDE_DIRS}) - -pkg_search_module(LIBXSLT libxslt REQUIRED) -include_directories(${LIBXSLT_INCLUDE_DIRS}) - -pkg_search_module(OPENSSL openssl REQUIRED) -include_directories(${OPENSSL_INCLUDE_DIRS}) - -pkg_search_module(CONFIG libconfig REQUIRED) -include_directories(${CONFIG_INCLUDE_DIRS}) - -pkg_search_module(CRYPTO libcrypto REQUIRED) -include_directories(${CRYPTO_INCLUDE_DIRS}) - -#use native cmake method as this package is not in pkg-config -if (${RF_BOARD} STREQUAL "OAI_USRP") - find_package(Boost REQUIRED) - include_directories(${LIBBOOST_INCLUDE_DIR}) -endif (${RF_BOARD} STREQUAL "OAI_USRP") - -pkg_search_module(OPENPGM openpgm-5.1) -if(NOT ${OPENPGM_FOUND}) - message("PACKAGE openpgm-5.1 is required by binaries such as oaisim: will fail later if this target is built") -else() - include_directories(${OPENPGM_INCLUDE_DIRS}) -endif() - -pkg_search_module(NETTLE nettle) -if(NOT ${NETTLE_FOUND}) - message("PACKAGE nettle not found: some targets will fail") -else() - include_directories(${NETTLE_INCLUDE_DIRS}) -endif() - -pkg_search_module(XPM xpm) -if(NOT ${XPM_FOUND}) - message("PACKAGE xpm not found: some targets will fail") -else() - include_directories(${XPM_INCLUDE_DIRS}) -endif() - -# Atlas is required by some packages, but not found in pkg-config -if(EXISTS "/usr/include/atlas/cblas.h") - include_directories("/usr/include/atlas") - list(APPEND ATLAS_LIBRARIES lapack cblas atlas) -else() - message("No Blas/Atlas libs found, some targets will fail") -endif() - -if (${XFORMS}) - include_directories ("/usr/include/X11") - set(XFORMS_SOURCE - ${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope.c - ) - set(XFORMS_SOURCE_SOFTMODEM - ${OPENAIR_TARGETS}/RT/USER/stats.c - ) - set(XFORMS_LIBRARIES "forms") -endif (${XFORMS}) - -set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") - - -# Hack on a test of asn1c version (already dirty) -add_definitions(-DASN1_MINIMUM_VERSION=924) - -################################# -# add executables for operation -################################# - -# lte-softmodem is both eNB and UE implementation -################################################### - -add_executable(lte-softmodem - ${rrc_h} - ${s1ap_h} - ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c - ${OPENAIR_TARGETS}/RT/USER/lte-ue.c - ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c - ${OPENAIR_TARGETS}/RT/USER/lte-enb.c - ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c - ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c - ${OPENAIR_TARGETS}/COMMON/create_tasks.c - ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c - ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c - ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c - ${GTPU_need_ITTI} - ${HW_SOURCE} - ${TRANSPORT_SOURCE} - ${RTAI_SOURCE} - ${XFORMS_SOURCE} - ${XFORMS_SOURCE_SOFTMODEM} - ) - -target_link_libraries (lte-softmodem - -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} - -Wl,--end-group ) - - -target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) -target_link_libraries (lte-softmodem ${LIBBOOST_LIBRARIES}) -target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) - -# lte-softmodem-nos1 is both eNB and UE implementation -################################################### -add_executable(lte-softmodem-nos1 - ${rrc_h} - ${s1ap_h} - ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c - ${OPENAIR_TARGETS}/RT/USER/lte-ue.c - ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c - ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c - ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c - ${OPENAIR_TARGETS}/COMMON/create_tasks.c - ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c - #${OPENAIR2_DIR}/RRC/NAS/nas_config.c # enable if you want rrc to mount ip interface - #${OPENAIR2_DIR}/RRC/NAS/rb_config.c - ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} - ${RTAI_SOURCE} - ${XFORMS_SOURCE} - ${XFORMS_SOURCE_SOFTMODEM} - ) -target_link_libraries (lte-softmodem-nos1 - -Wl,--start-group - RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} - -Wl,--end-group ) - -target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) -target_link_libraries (lte-softmodem-nos1 ${LIBBOOST_LIBRARIES}) -target_link_libraries (lte-softmodem-nos1 ${LIB_LMS_LIBRARIES}) - -# rrh -################################ -#Note: only one RF type (USRP) is currently supported for RRH -add_executable(rrh_gw - ${OPENAIR_TARGETS}/RT/USER/rrh_gw.c - ${OPENAIR_TARGETS}/RT/USER/eNB_transport_IQ.c - ${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c - ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c - ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} - ) -target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti) -target_link_libraries(rrh_gw - -Wl,--start-group - UTIL LFDS - -Wl,--end-group ) -target_link_libraries (rrh_gw rt pthread m ) -target_link_libraries (rrh_gw ${option_HW_lib} ${option_TP_lib} ${LIBBOOST_LIBRARIES} ) -target_link_libraries (rrh_gw ${LIB_LMS_LIBRARIES}) - -Message("-- option_HW_lib=${option_HW_lib}") -Message("-- HW_SOURCE=${HW_SOURCE}") -Message("-- option_TP_lib=${option_TP_lib}") -Message("-- TRANSPORT_SOURCE=${TRANSPORT_SOURCE}") - -if (${RF_BOARD} STREQUAL "OAI_LMSSDR") - add_dependencies(lte-softmodem LMS7002M LMS_SDR Si5351C) - add_dependencies(lte-softmodem-nos1 LMS7002M LMS_SDR Si5351C) - add_dependencies(rrh_gw LMS7002M LMS_SDR Si5351C) -endif (${RF_BOARD} STREQUAL "OAI_LMSSDR") - - - -# USIM process -################# -#add_executable(usim -# ${OPENAIR3_DIR}/NAS/TOOLS/usim_data.c -# ${OPENAIR3_DIR}/NAS/USER/API/USIM/usim_api.c -# ${OPENAIR3_DIR}/NAS/USER/API/USIM/aka_functions.c -# ${OPENAIR3_DIR}/NAS/COMMON/UTIL/memory.c -# ${OPENAIR3_DIR}/NAS/COMMON/UTIL/nas_log.c -# ${OPENAIR3_DIR}/NAS/COMMON/UTIL/OctetString.c -# ${OPENAIR3_DIR}/NAS/COMMON/UTIL/TLVEncoder.c -# ) -#target_link_libraries (usim ${NAS_LIB} UTIL ${ITTI_LIB} LFDS pthread rt nettle crypto m) - -# ??? -##################### -#add_executable(nvram -# ${OPENAIR3_DIR}/NAS/TOOLS/ue_data.c -# ${OPENAIR3_DIR}/NAS/COMMON/UTIL/memory.c -# ${OPENAIR3_DIR}/NAS/COMMON/UTIL/nas_log.c -# ) -#target_link_libraries (nvram LIB_NAS_UE UTIL ${ITTI_LIB} LFDS pthread rt nettle crypto m) - - -###################################" -# Addexecutables for tests -#################################### - -# A all in one network simulator -################ -add_executable(oaisim - ${rrc_h} - ${s1ap_h} - ${x2ap_h} - ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c - ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c - ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c - ${OPENAIR_TARGETS}/SIMU/USER/sinr_sim.c - ${OPENAIR_TARGETS}/SIMU/USER/cor_SF_sim.c - ${OPENAIR_TARGETS}/SIMU/USER/oaisim_functions.c - ${OPENAIR_TARGETS}/SIMU/USER/event_handler.c - ${OPENAIR_TARGETS}/SIMU/USER/oaisim.c - ${OPENAIR2_DIR}/RRC/NAS/nas_config.c - ${OPENAIR2_DIR}/RRC/NAS/rb_config.c - ${OPENAIR2_DIR}/UTIL/OMG/sumo.c - ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c - ${GTPU_need_ITTI} - ${OPENAIR_TARGETS}/COMMON/create_tasks.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} - ${XFORMS_SOURCE} -) - - -target_include_directories(oaisim PUBLIC ${OPENAIR_TARGETS}/SIMU/USER) -target_link_libraries (oaisim - -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} LIB_NAS_UE SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} - -Wl,--end-group ) - -target_link_libraries (oaisim ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) -target_link_libraries (oaisim pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} - ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES}) -#Force link with forms, regardless XFORMS option -target_link_libraries (oaisim forms) - - - -# A all in one network simulator -################ -add_executable(oaisim_nos1 - ${rrc_h} - ${s1ap_h} - ${x2ap_h} - ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c - ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c - ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c - ${OPENAIR_TARGETS}/SIMU/USER/sinr_sim.c - ${OPENAIR_TARGETS}/SIMU/USER/cor_SF_sim.c - ${OPENAIR_TARGETS}/SIMU/USER/oaisim_functions.c - ${OPENAIR_TARGETS}/SIMU/USER/event_handler.c - ${OPENAIR_TARGETS}/SIMU/USER/oaisim.c - ${OPENAIR2_DIR}/RRC/NAS/nas_config.c - ${OPENAIR2_DIR}/RRC/NAS/rb_config.c - ${OPENAIR2_DIR}/UTIL/OMG/sumo.c - ${OPENAIR_TARGETS}/COMMON/create_tasks.c - ${HW_SOURCE} - ${TRANSPORT_SOURCE} - ${XFORMS_SOURCE} -) -target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER) -target_link_libraries (oaisim_nos1 - -Wl,--start-group - RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} - -Wl,--end-group ) - -target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) -target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} - ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES}) -#Force link with forms, regardless XFORMS option -target_link_libraries (oaisim_nos1 forms) - - -# Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator -##################################### - -foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) - add_executable(${myExe} - ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c - ${XFORMS_SOURCE} - ) - target_link_libraries (${myExe} - -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group - pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} - ) -endforeach(myExe) - -add_executable(test_epc_generate_scenario - ${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.h - ${OPENAIR2_DIR}/ENB_APP/enb_config.h - ${OPENAIR2_DIR}/COMMON/commonDef.h - ${OPENAIR2_DIR}/COMMON/messages_def.h - ${OPENAIR2_DIR}/COMMON/messages_types.h - ${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h - ${OPENAIR_BIN_DIR}/messages_xml.h - ) -target_link_libraries (test_epc_generate_scenario - -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} - ) - -add_executable(test_epc_play_scenario - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_decode.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_display.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_fsm.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_parse.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap_eNB_defs.h - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_sctp.c - ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.h - ${OPENAIR2_DIR}/COMMON/commonDef.h - ${OPENAIR2_DIR}/COMMON/messages_def.h - ${OPENAIR2_DIR}/COMMON/messages_types.h - ${OPENAIR_BIN_DIR}/messages_xml.h - ) -target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c) -target_link_libraries (test_epc_play_scenario - -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} - ) - - -#unitary tests for Core NEtwork pieces -################################# -foreach(myExe s1ap - secu_knas_encrypt_eia1 - secu_kenb - aes128_ctr_encrypt - aes128_ctr_decrypt - secu_knas_encrypt_eea2 - secu_knas secu_knas_encrypt_eea1 - kdf - aes128_cmac_encrypt - secu_knas_encrypt_eia2) - add_executable(test_${myExe} - ${OPENAIR3_DIR}/TEST/test_util.c - ${OPENAIR3_DIR}/TEST/test_${myExe}.c - ) - target_link_libraries (test_${myExe} - -Wl,--start-group SECU_CN UTIL LFDS -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} - ) -endforeach(myExe) - -# to be added -#../targets/TEST/PDCP/test_pdcp.c -#../targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c + add_boolean_option(USE_MME False "this flag is used only one time in lte-softmodem.c") + add_list_string_option(PACKAGE_NAME "NotDefined" "As per attribute name") + add_boolean_option(MESSAGE_CHART_GENERATOR False "For generating sequence diagrams") + add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams") + add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams") + + add_boolean_option(ENB_AGENT True "enable eNB agent to inteface with a SDN contrller") + + ######################## + # Include order + ########################## + add_boolean_option(ENB_MODE True "Swap the include directories between openair2 and openair3" ) + + ########################## + # Emulation options + ########################## + add_boolean_option(ENABLE_PGM_TRANSPORT False "specific to oaisim, emulation through ethernet, reliable multicast") + add_boolean_option(ADDR_CONF False "specific to oaisim, IP autoconf of user-plane IP interface") + add_boolean_option(OPENAIR_EMU False "specific to oaisim") + add_boolean_option(OAI_EMU False "specific to oaisim") + add_boolean_option(PHY_ABSTRACTION False "specific to oaisim") + + ########################## + # SCHEDULING/REAL-TIME/PERF options + ########################## + add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME True "Add data in vcd traces: disable it if perf issues") + add_boolean_option(ENABLE_VCD True "always true now, time measurements of proc calls and var displays") + add_boolean_option(ENABLE_VCD_FIFO True "time measurements of proc calls and var displays sent to FIFO (one more thread)") + add_boolean_option(HARD_RT False "???") + add_boolean_option(LINUX False "used in weird memcpy() in pdcp.c ???") + add_boolean_option(LINUX_LIST False "used only in lists.c: either use OAI implementation of lists or Linux one (should be True, but it is False") + add_boolean_option(LOG_NO_THREAD True "Disable thread for log, seems always set to true") + add_boolean_option(OPENAIR_LTE True "Seems legacy: keep it to true") + + ########################## + # PHY options + ########################## + add_boolean_option(DRIVER2013 True "only relevant for EXMIMO") + add_boolean_option(ENABLE_FXP True "????") + add_boolean_option(ENABLE_NEW_MULTICAST False "specific to oaisim") + add_boolean_option(EXMIMO_IOT True "????") + add_boolean_option(LARGE_SCALE False "specific to oaisim: defines max eNB=2 and max UE=120") + add_boolean_option(LOCALIZATION False "???") + add_integer_option(MAX_NUM_CCs 1 "????") + add_boolean_option(MU_RECEIVER False "????") + add_boolean_option(NEW_FFT True "????") + add_boolean_option(OPENAIR1 True "????") + add_boolean_option(PBS_SIM False "????") + add_boolean_option(PC_DSP True "????") + add_boolean_option(PC_TARGET True "????") + add_boolean_option(PERFECT_CE False "????") + add_boolean_option(PHYSIM True "for L1 simulators (dlsim, ulsim, ...)") + add_boolean_option(PHY_CONTEXT True "not clear: must remain False for dlsim") + add_boolean_option(PHY_EMUL False "not clear: must remain False for dlsim") + add_boolean_option(PUCCH True "????") + add_boolean_option(RANDOM_BF False "????") + add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator") + add_boolean_option(DEBUG_PHY False "Enable PHY layer debugging options") + add_boolean_option(DEBUG_PHY_PROC False "Enable debugging of PHY layer procedures") + add_boolean_option(DEBUG_DLSCH False "Enable debugging of DLSCH physical layer channel") + + ########################## + # 802.21 options + ########################## + add_boolean_option(ENABLE_RAL False "ENABLE 802.21 INTERFACE") + add_boolean_option(USE_3GPP_ADDR_AS_LINK_ADDR False "As per attribute name") + + ########################## + # NAS LAYER OPTIONS + ########################## + add_boolean_option(ENABLE_NAS_UE_LOGGING True "????") + add_boolean_option(NAS_BUILT_IN_UE True "UE NAS layer present in this executable") + add_boolean_option(NAS_UE True "NAS UE INSTANCE (<> NAS_MME)") + + + ########################## + # ACCESS STRATUM LAYER2 OPTIONS + ########################## + add_boolean_option(MAC_CONTEXT True "specific to oaisim") + add_boolean_option(JUMBO_FRAME True "ENABLE LARGE SDU in ACCESS STRATUM (larger than common MTU)") + + ########################## + # RLC LAYER OPTIONS + ########################## + add_boolean_option(OPENAIR2 True "Access Stratum layer 2 built in executable") + add_boolean_option(TRACE_RLC_PAYLOAD False "Fatal assert in this case") + add_boolean_option(RLC_STOP_ON_LOST_PDU False "Fatal assert in this case") + + add_boolean_option(TRACE_RLC_MUTEX True "TRACE for RLC, possible problem in thread scheduling") + add_boolean_option(TRACE_RLC_AM_BO False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_FREE_SDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_HOLE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_PDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_RESEGMENT False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_RX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_RX_DECODE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_TX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_TX_STATUS False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_AM_STATUS_CREATION False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") + + add_boolean_option(STOP_ON_IP_TRAFFIC_OVERLOAD False "") + add_boolean_option(TRACE_RLC_UM_DAR False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_UM_DISPLAY_ASCII_DATA False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_UM_PDU False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_UM_RX False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_UM_SEGMENT False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") + add_boolean_option(TRACE_RLC_UM_TX_STATUS False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG") + + + ########################## + # PDCP LAYER OPTIONS + ########################## + add_boolean_option(PDCP_USE_NETLINK False "For eNB, PDCP communicate with a NETLINK socket if connected to network driver, else could use a RT-FIFO") + add_boolean_option(PDCP_USE_NETLINK_QUEUES False "When PDCP_USE_NETLINK is true, incoming IP packets are stored in queues") + add_boolean_option(LINK_ENB_PDCP_TO_IP_DRIVER False "For eNB, PDCP communicate with a IP driver") + add_boolean_option(LINK_ENB_PDCP_TO_GTPV1U True "For eNB, PDCP communicate with GTP-U protocol (eNB<->S-GW)") + + ########################## + # RRC LAYER OPTIONS + ########################## + add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "Otherwise it is UM, configure params are actually set in rrc_eNB.c:rrc_eNB_generate_defaultRRCConnectionReconfiguration(...)") + + + ########################## + # S1AP LAYER OPTIONS + ########################## + # none + + ########################## + # PROJECTS (IST, FRENCH COLL., etc) + # SPECIFIC OPTIONS + ########################## + add_boolean_option(SPECTRA False "???") + add_boolean_option(MIH_C_MEDIEVAL_EXTENSIONS False "EXTENSIONS TO MIH 802.21 IN CONTEXT OF IST PROJECT CALLED MEDIEVAL") + + + + add_boolean_option(EMOS False "????") + if(${EMOS}) + add_definitions("-D_FILE_OFFSET_BITS=64") + set(EMOS_LIB gps) + endif(${EMOS}) + + + # add the binary tree to the search path for include files + ####################################################### + # We will find ConfigOAI.h after generation in target directory + include_directories("${OPENAIR_BIN_DIR}") + # add directories to find all include files + # the internal rule is to use generic names such as defs.h + # but to make it uniq name as adding the relative path in the include directtive + # example: #include "RRC/LITE/defs.h" + #find_path (include_dirs_all *.h ${OPENAIR_DIR}) + #find_path (include_dirs_all *.h PATHS /usr/include NO_CMAKE_PATH) + #include_directories("${include_dirs_all}") + + # Legacy exact order + if(ENB_MODE) + include_directories("${OPENAIR2_DIR}/COMMON") + include_directories("${OPENAIR2_DIR}/UTIL") + include_directories("${OPENAIR2_DIR}/UTIL/LOG") + include_directories("${OPENAIR3_DIR}/COMMON") + include_directories("${OPENAIR3_DIR}/UTILS") + else() + include_directories("${OPENAIR3_DIR}/COMMON") + include_directories("${OPENAIR3_DIR}/UTILS") + include_directories("${OPENAIR2_DIR}/COMMON") + include_directories("${OPENAIR2_DIR}/UTIL") + include_directories("${OPENAIR2_DIR}/UTIL/LOG") + endif() + include_directories("${OPENAIR1_DIR}") + include_directories("${OPENAIR2_DIR}/NAS") + include_directories("${OPENAIR2_DIR}") + include_directories("${OPENAIR2_DIR}/LAYER2/RLC") + include_directories("${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0") + include_directories("${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0") + include_directories("${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0") + include_directories("${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0") + include_directories("${OPENAIR2_DIR}/RRC/LITE/MESSAGES") + include_directories("${OPENAIR2_DIR}/RRC/LITE") + include_directories("${OPENAIR3_DIR}/RAL-LTE/INTERFACE-802.21/INCLUDE") + include_directories("${OPENAIR3_DIR}/RAL-LTE/LTE_RAL_ENB/INCLUDE") + include_directories("${OPENAIR3_DIR}/RAL-LTE/LTE_RAL_UE/INCLUDE") + include_directories("${OPENAIR_DIR}/common/utils") + include_directories("${OPENAIR_DIR}/common/utils/itti") + include_directories("${OPENAIR3_DIR}/NAS/COMMON") + include_directories("${OPENAIR3_DIR}/NAS/COMMON/API/NETWORK") + include_directories("${OPENAIR3_DIR}/NAS/COMMON/EMM/MSG") + include_directories("${OPENAIR3_DIR}/NAS/COMMON/ESM/MSG") + include_directories("${OPENAIR3_DIR}/NAS/COMMON/IES") + include_directories("${OPENAIR3_DIR}/NAS/COMMON/UTIL") + include_directories("${OPENAIR3_DIR}/SECU") + include_directories("${OPENAIR3_DIR}/SCTP") + include_directories("${OPENAIR3_DIR}/S1AP") + include_directories("${OPENAIR2_DIR}/X2AP") + include_directories("${OPENAIR3_DIR}/UDP") + include_directories("${OPENAIR3_DIR}/GTPV1-U") + include_directories("${OPENAIR_DIR}/targets/COMMON") + include_directories("${OPENAIR_DIR}/targets/ARCH/COMMON") + include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/USERSPACE/LIB/") + include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS") + include_directories("${OPENAIR2_DIR}/ENB_APP") + include_directories("${OPENAIR2_DIR}/UTIL/OSA") + include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc") + include_directories("${OPENAIR2_DIR}/UTIL/MEM") + include_directories("${OPENAIR2_DIR}/UTIL/LISTS") + include_directories("${OPENAIR2_DIR}/UTIL/FIFO") + include_directories("${OPENAIR2_DIR}/UTIL/OCG") + include_directories("${OPENAIR2_DIR}/UTIL/MATH") + include_directories("${OPENAIR2_DIR}/UTIL/TIMER") + include_directories("${OPENAIR2_DIR}/UTIL/OMG") + include_directories("${OPENAIR2_DIR}/UTIL/OTG") + include_directories("${OPENAIR2_DIR}/UTIL/CLI") + include_directories("${OPENAIR2_DIR}/UTIL/OPT") + include_directories("${OPENAIR2_DIR}/UTIL/OMV") + include_directories("${OPENAIR2_DIR}/RRC/LITE/MESSAGES") + include_directories("${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/shared") + include_directories("${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/include") + include_directories("${OPENAIR_DIR}") + + # Utilities Library + ################ + add_library(HASHTABLE + ${OPENAIR_DIR}/common/utils/collection/hashtable/hashtable.c + ${OPENAIR_DIR}/common/utils/collection/hashtable/obj_hashtable.c + ) + include_directories(${OPENAIR_DIR}/common/utils/collection/hashtable) + + if (MESSAGE_CHART_GENERATOR) + add_library(MSC + ${OPENAIR_DIR}/common/utils/msc/msc.c + ) + set(MSC_LIB MSC) + endif() + include_directories(${OPENAIR_DIR}/common/utils/msc) + + set(UTIL_SRC + ${OPENAIR2_DIR}/UTIL/CLI/cli.c + ${OPENAIR2_DIR}/UTIL/CLI/cli_cmd.c + ${OPENAIR2_DIR}/UTIL/CLI/cli_server.c + ${OPENAIR2_DIR}/UTIL/FIFO/pad_list.c + ${OPENAIR2_DIR}/UTIL/LISTS/list.c + ${OPENAIR2_DIR}/UTIL/LISTS/list2.c + ${OPENAIR2_DIR}/UTIL/LOG/log.c + ${OPENAIR2_DIR}/UTIL/LOG/vcd_signal_dumper.c + ${OPENAIR2_DIR}/UTIL/MATH/oml.c + ${OPENAIR2_DIR}/UTIL/MEM/mem_block.c + ${OPENAIR2_DIR}/UTIL/OCG/OCG.c + ${OPENAIR2_DIR}/UTIL/OCG/OCG_create_dir.c + ${OPENAIR2_DIR}/UTIL/OCG/OCG_detect_file.c + ${OPENAIR2_DIR}/UTIL/OCG/OCG_generate_report.c + ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_filename.c + ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_XML.c + ${OPENAIR2_DIR}/UTIL/OCG/OCG_save_XML.c + ${OPENAIR2_DIR}/UTIL/OMG/client_traci_OMG.c + ${OPENAIR2_DIR}/UTIL/OMG/common.c + ${OPENAIR2_DIR}/UTIL/OMG/grid.c + ${OPENAIR2_DIR}/UTIL/OMG/id_manager.c + ${OPENAIR2_DIR}/UTIL/OMG/job.c + ${OPENAIR2_DIR}/UTIL/OMG/mobility_parser.c + ${OPENAIR2_DIR}/UTIL/OMG/omg.c + ${OPENAIR2_DIR}/UTIL/OMG/omg_hashtable.c + ${OPENAIR2_DIR}/UTIL/OMG/rwalk.c + ${OPENAIR2_DIR}/UTIL/OMG/rwp.c + ${OPENAIR2_DIR}/UTIL/OMG/socket_traci_OMG.c + ${OPENAIR2_DIR}/UTIL/OMG/static.c + ${OPENAIR2_DIR}/UTIL/OMG/steadystaterwp.c + ${OPENAIR2_DIR}/UTIL/OMG/storage_traci_OMG.c + ${OPENAIR2_DIR}/UTIL/OMG/trace.c + ${OPENAIR2_DIR}/UTIL/OMG/trace_hashtable.c + ${OPENAIR2_DIR}/UTIL/OPT/probe.c + ${OPENAIR2_DIR}/UTIL/OTG/otg_tx.c + ${OPENAIR2_DIR}/UTIL/OTG/otg.c + ${OPENAIR2_DIR}/UTIL/OTG/otg_kpi.c + ${OPENAIR2_DIR}/UTIL/OTG/otg_models.c + ${OPENAIR2_DIR}/UTIL/OTG/otg_form.c + ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c + ) + add_library(UTIL ${UTIL_SRC}) + + set(SECU_OSA_SRC + ${OPENAIR2_DIR}/UTIL/OSA/osa_key_deriver.c + ${OPENAIR2_DIR}/UTIL/OSA/osa_rijndael.c + ${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c + ${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eea.c + ${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c + ) + add_library(SECU_OSA ${SECU_OSA_SRC}) + + set(SECU_CN_SRC + ${OPENAIR3_DIR}/SECU/kdf.c + ${OPENAIR3_DIR}/SECU/rijndael.c + ${OPENAIR3_DIR}/SECU/snow3g.c + ${OPENAIR3_DIR}/SECU/key_nas_deriver.c + ${OPENAIR3_DIR}/SECU/nas_stream_eea1.c + ${OPENAIR3_DIR}/SECU/nas_stream_eia1.c + ${OPENAIR3_DIR}/SECU/nas_stream_eea2.c + ${OPENAIR3_DIR}/SECU/nas_stream_eia2.c + ) + add_library(SECU_CN ${SECU_CN_SRC}) + + # Scheduler + ################################" + file(GLOB SCHED_SRC ${OPENAIR1_DIR}/SCHED/*.c) + add_library(SCHED_LIB ${SCHED_SRC}) + + # Layer 1 + ############################# + set(PHY_SRC + # depend on code generation from asn1c + ${RRC_FULL_DIR}/asn1_constants.h + # actual source + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pss.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots_mbsfn.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_coding.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_modulation.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_demodulation.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_llr_computation.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/power_control.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_decoding.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_scrambling.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/uci_tools.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pbch.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/phich.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pcfich.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pucch.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/srs_modulation.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/drs_modulation.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_modulation.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_coding.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_decoding.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/rar_tools.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/print_stats.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/initial_sync.c + ${OPENAIR1_DIR}/PHY/MODULATION/ofdm_mod.c + ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep.c + ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_mbsfn.c + ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c + ${OPENAIR1_DIR}/PHY/MODULATION/ul_7_5_kHz.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_time.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_timefreq.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_est_freq_offset.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ue_measurements.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_eNB_measurements.c + ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/adjust_gain.c + ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_cell_spec.c + ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_uespec.c + ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold.c + ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold_mbsfn.c + ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_mbsfn.c + ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_ul_ref.c + ${OPENAIR1_DIR}/PHY/CODING/lte_segmentation.c + ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte.c + ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_lte.c + ${OPENAIR1_DIR}/PHY/CODING/3gpplte_sse.c + ${OPENAIR1_DIR}/PHY/CODING/crc_byte.c + ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c + ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c + ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c + ${OPENAIR1_DIR}/PHY/CODING/lte_rate_matching.c + ${OPENAIR1_DIR}/PHY/CODING/rate_matching.c + ${OPENAIR1_DIR}/PHY/CODING/viterbi.c + ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c + ${OPENAIR1_DIR}/PHY/INIT/lte_init.c + ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c + ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c + ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c + ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c + ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c + ${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c + ${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c + ${OPENAIR1_DIR}/PHY/TOOLS/cdot_prod.c + ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c + ${OPENAIR1_DIR}/PHY/TOOLS/dB_routines.c + ${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c + ${OPENAIR1_DIR}/PHY/TOOLS/time_meas.c + ${OPENAIR1_DIR}/PHY/TOOLS/lut.c + ) + if (${SMBV}) + set(PHY_SRC "${PHY_SRC} ${OPENAIR1_DIR}/PHY/TOOLS/smbv.c") + endif (${SMBV}) + add_library(PHY ${PHY_SRC}) + + #Layer 2 library + ##################### + set(MAC_DIR ${OPENAIR2_DIR}/LAYER2/MAC) + set(RLC_DIR ${OPENAIR2_DIR}/LAYER2/RLC) + set(RLC_UM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0) + set(RLC_AM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0) + set(RLC_TM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0) + set(RRC_DIR ${OPENAIR2_DIR}/RRC/LITE) + set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0) + set(L2_SRC + ${OPENAIR2_DIR}/LAYER2/openair2_proc.c + ${PDCP_DIR}/pdcp.c + ${PDCP_DIR}/pdcp_fifo.c + ${PDCP_DIR}/pdcp_sequence_manager.c + ${PDCP_DIR}/pdcp_primitives.c + ${PDCP_DIR}/pdcp_util.c + ${PDCP_DIR}/pdcp_security.c + ${PDCP_DIR}/pdcp_netlink.c + ${RLC_AM_DIR}/rlc_am.c + ${RLC_AM_DIR}/rlc_am_init.c + ${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c + ${RLC_AM_DIR}/rlc_am_timer_reordering.c + ${RLC_AM_DIR}/rlc_am_timer_status_prohibit.c + ${RLC_AM_DIR}/rlc_am_segment.c + ${RLC_AM_DIR}/rlc_am_segments_holes.c + ${RLC_AM_DIR}/rlc_am_in_sdu.c + ${RLC_AM_DIR}/rlc_am_receiver.c + ${RLC_AM_DIR}/rlc_am_retransmit.c + ${RLC_AM_DIR}/rlc_am_windows.c + ${RLC_AM_DIR}/rlc_am_rx_list.c + ${RLC_AM_DIR}/rlc_am_reassembly.c + ${RLC_AM_DIR}/rlc_am_status_report.c + ${RLC_TM_DIR}/rlc_tm.c + ${RLC_TM_DIR}/rlc_tm_init.c + ${RLC_UM_DIR}/rlc_um.c + ${RLC_UM_DIR}/rlc_um_fsm.c + ${RLC_UM_DIR}/rlc_um_control_primitives.c + ${RLC_UM_DIR}/rlc_um_segment.c + ${RLC_UM_DIR}/rlc_um_reassembly.c + ${RLC_UM_DIR}/rlc_um_receiver.c + ${RLC_UM_DIR}/rlc_um_dar.c + ${RLC_DIR}/rlc_mac.c + ${RLC_DIR}/rlc.c + ${RLC_DIR}/rlc_rrc.c + ${RLC_DIR}/rlc_mpls.c + ${RRC_DIR}/rrc_UE.c + ${RRC_DIR}/rrc_eNB.c + ${RRC_DIR}/rrc_eNB_S1AP.c + ${RRC_DIR}/rrc_eNB_UE_context.c + ${RRC_DIR}/rrc_common.c + ${RRC_DIR}/L2_interface.c + ) + set (MAC_SRC + ${MAC_DIR}/lte_transport_init.c + ${MAC_DIR}/main.c + ${MAC_DIR}/ue_procedures.c + ${MAC_DIR}/ra_procedures.c + ${MAC_DIR}/l1_helpers.c + ${MAC_DIR}/rar_tools.c + ${MAC_DIR}/eNB_scheduler.c + ${MAC_DIR}/eNB_scheduler_dlsch.c + ${MAC_DIR}/eNB_scheduler_ulsch.c + ${MAC_DIR}/eNB_scheduler_mch.c + ${MAC_DIR}/eNB_scheduler_bch.c + ${MAC_DIR}/eNB_scheduler_primitives.c + ${MAC_DIR}/eNB_scheduler_RA.c + ${MAC_DIR}/pre_processor.c + ${MAC_DIR}/config.c + ) + + set (ENB_APP_SRC + ${OPENAIR2_DIR}/ENB_APP/enb_app.c + ${OPENAIR2_DIR}/ENB_APP/enb_config.c + ) + + add_library(L2 + ${L2_SRC} + ${MAC_SRC} + ${ENB_APP_SRC}) + # ${OPENAIR2_DIR}/RRC/L2_INTERFACE/openair_rrc_L2_interface.c) + + # L3 Libs + ########################## + + set(RAL_LTE_DIR ${OPENAIR3_DIR}/RAL-LTE/) + if (${ENABLE_RAL}) + set(RAL_LTE_SRC + ${RRC_DIR}/rrc_UE_ral.c + ${RRC_DIR}/rrc_eNB_ral.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_action.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_main.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_mih_msg.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_parameters.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_process.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_rrc_msg.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_subscribe.c + ${RAL_LTE_DIR}LTE_RAL_ENB/SRC/lteRALenb_thresholds.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_action.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_main.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_mih_msg.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_parameters.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_process.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_rrc_msg.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_subscribe.c + ${RAL_LTE_DIR}LTE_RAL_UE/SRC/lteRALue_thresholds.c + ) + add_library(RAL ${RAL_LTE_SRC}) + set(RAL_LIB RAL) + endif() + + if(${MIH_C_MEDIEVAL_EXTENSIONS}) + set(MIH_SRC + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_header_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_msg_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_primitive_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F1_basic_data_types_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F2_general_data_types_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F3_data_types_for_address_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F4_data_types_for_links_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F9_data_types_for_qos_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_F13_data_types_for_information_elements_codec.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_L2_type_values_for_tlv_encoding.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_Medieval_extensions.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C_bit_buffer.c + ${RAL_LTE_DIR}INTERFACE-802.21/C/MIH_C.c + ) + add_library(MIH ${MIH_SRC}) + set(MIH_LIB MIH) + endif() + + # CN libs + ########################## + + add_library(CN_UTILS + ${OPENAIR3_DIR}/UTILS/conversions.c + ${OPENAIR3_DIR}/UTILS/enum_string.c + ${OPENAIR3_DIR}/UTILS/log.c + ${OPENAIR3_DIR}/UTILS/mcc_mnc_itu.c + ) + + set(GTPV1U_DIR ${OPENAIR3_DIR}/GTPV1-U) + set (GTPV1U_SRC + ${RRC_DIR}/rrc_eNB_GTPV1U.c + ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.c + ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTrxn.c + ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uMsg.c + ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1u.c + ${GTPV1U_DIR}/gtpv1u_teid_pool.c + ) + add_library(GTPV1U ${GTPV1U_SRC}) + + set(SCTP_SRC + ${OPENAIR3_DIR}/SCTP/sctp_common.c + ${OPENAIR3_DIR}/SCTP/sctp_eNB_task.c + ${OPENAIR3_DIR}/SCTP/sctp_eNB_itti_messaging.c + ) + add_library(SCTP_CLIENT ${SCTP_SRC}) + + add_library(UDP ${OPENAIR3_DIR}/UDP/udp_eNB_task.c) + + + set(NAS_SRC ${OPENAIR3_DIR}/NAS/) + set(libnas_api_OBJS + ${NAS_SRC}COMMON/API/NETWORK/as_message.c + ${NAS_SRC}COMMON/API/NETWORK/nas_message.c + ${NAS_SRC}COMMON/API/NETWORK/network_api.c + ) + + set(libnas_emm_msg_OBJS + ${NAS_SRC}COMMON/EMM/MSG/AttachAccept.c + ${NAS_SRC}COMMON/EMM/MSG/AttachComplete.c + ${NAS_SRC}COMMON/EMM/MSG/AttachReject.c + ${NAS_SRC}COMMON/EMM/MSG/AttachRequest.c + ${NAS_SRC}COMMON/EMM/MSG/AuthenticationFailure.c + ${NAS_SRC}COMMON/EMM/MSG/AuthenticationReject.c + ${NAS_SRC}COMMON/EMM/MSG/AuthenticationRequest.c + ${NAS_SRC}COMMON/EMM/MSG/AuthenticationResponse.c + ${NAS_SRC}COMMON/EMM/MSG/CsServiceNotification.c + ${NAS_SRC}COMMON/EMM/MSG/DetachAccept.c + ${NAS_SRC}COMMON/EMM/MSG/DetachRequest.c + ${NAS_SRC}COMMON/EMM/MSG/DownlinkNasTransport.c + ${NAS_SRC}COMMON/EMM/MSG/EmmInformation.c + ${NAS_SRC}COMMON/EMM/MSG/emm_msg.c + ${NAS_SRC}COMMON/EMM/MSG/EmmStatus.c + ${NAS_SRC}COMMON/EMM/MSG/ExtendedServiceRequest.c + ${NAS_SRC}COMMON/EMM/MSG/GutiReallocationCommand.c + ${NAS_SRC}COMMON/EMM/MSG/GutiReallocationComplete.c + ${NAS_SRC}COMMON/EMM/MSG/IdentityRequest.c + ${NAS_SRC}COMMON/EMM/MSG/IdentityResponse.c + ${NAS_SRC}COMMON/EMM/MSG/SecurityModeCommand.c + ${NAS_SRC}COMMON/EMM/MSG/SecurityModeComplete.c + ${NAS_SRC}COMMON/EMM/MSG/SecurityModeReject.c + ${NAS_SRC}COMMON/EMM/MSG/ServiceReject.c + ${NAS_SRC}COMMON/EMM/MSG/ServiceRequest.c + ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateAccept.c + ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateComplete.c + ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateReject.c + ${NAS_SRC}COMMON/EMM/MSG/TrackingAreaUpdateRequest.c + ${NAS_SRC}COMMON/EMM/MSG/UplinkNasTransport.c + ) + + set(libnas_esm_msg_OBJS + ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.c + ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.c + ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextRequest.c + ${NAS_SRC}COMMON/ESM/MSG/ActivateDefaultEpsBearerContextAccept.c + ${NAS_SRC}COMMON/ESM/MSG/ActivateDefaultEpsBearerContextReject.c + ${NAS_SRC}COMMON/ESM/MSG/ActivateDefaultEpsBearerContextRequest.c + ${NAS_SRC}COMMON/ESM/MSG/BearerResourceAllocationReject.c + ${NAS_SRC}COMMON/ESM/MSG/BearerResourceAllocationRequest.c + ${NAS_SRC}COMMON/ESM/MSG/BearerResourceModificationReject.c + ${NAS_SRC}COMMON/ESM/MSG/BearerResourceModificationRequest.c + ${NAS_SRC}COMMON/ESM/MSG/DeactivateEpsBearerContextAccept.c + ${NAS_SRC}COMMON/ESM/MSG/DeactivateEpsBearerContextRequest.c + ${NAS_SRC}COMMON/ESM/MSG/EsmInformationRequest.c + ${NAS_SRC}COMMON/ESM/MSG/EsmInformationResponse.c + ${NAS_SRC}COMMON/ESM/MSG/esm_msg.c + ${NAS_SRC}COMMON/ESM/MSG/EsmStatus.c + ${NAS_SRC}COMMON/ESM/MSG/ModifyEpsBearerContextAccept.c + ${NAS_SRC}COMMON/ESM/MSG/ModifyEpsBearerContextReject.c + ${NAS_SRC}COMMON/ESM/MSG/ModifyEpsBearerContextRequest.c + ${NAS_SRC}COMMON/ESM/MSG/PdnConnectivityReject.c + ${NAS_SRC}COMMON/ESM/MSG/PdnConnectivityRequest.c + ${NAS_SRC}COMMON/ESM/MSG/PdnDisconnectReject.c + ${NAS_SRC}COMMON/ESM/MSG/PdnDisconnectRequest.c + ) + + set(libnas_ies_OBJS + ${NAS_SRC}COMMON/IES/AccessPointName.c + ${NAS_SRC}COMMON/IES/AdditionalUpdateResult.c + ${NAS_SRC}COMMON/IES/AdditionalUpdateType.c + ${NAS_SRC}COMMON/IES/ApnAggregateMaximumBitRate.c + ${NAS_SRC}COMMON/IES/AuthenticationFailureParameter.c + ${NAS_SRC}COMMON/IES/AuthenticationParameterAutn.c + ${NAS_SRC}COMMON/IES/AuthenticationParameterRand.c + ${NAS_SRC}COMMON/IES/AuthenticationResponseParameter.c + ${NAS_SRC}COMMON/IES/CipheringKeySequenceNumber.c + ${NAS_SRC}COMMON/IES/Cli.c + ${NAS_SRC}COMMON/IES/CsfbResponse.c + ${NAS_SRC}COMMON/IES/DaylightSavingTime.c + ${NAS_SRC}COMMON/IES/DetachType.c + ${NAS_SRC}COMMON/IES/DrxParameter.c + ${NAS_SRC}COMMON/IES/EmergencyNumberList.c + ${NAS_SRC}COMMON/IES/EmmCause.c + ${NAS_SRC}COMMON/IES/EpsAttachResult.c + ${NAS_SRC}COMMON/IES/EpsAttachType.c + ${NAS_SRC}COMMON/IES/EpsBearerContextStatus.c + ${NAS_SRC}COMMON/IES/EpsBearerIdentity.c + ${NAS_SRC}COMMON/IES/EpsMobileIdentity.c + ${NAS_SRC}COMMON/IES/EpsNetworkFeatureSupport.c + ${NAS_SRC}COMMON/IES/EpsQualityOfService.c + ${NAS_SRC}COMMON/IES/EpsUpdateResult.c + ${NAS_SRC}COMMON/IES/EpsUpdateType.c + ${NAS_SRC}COMMON/IES/EsmCause.c + ${NAS_SRC}COMMON/IES/EsmInformationTransferFlag.c + ${NAS_SRC}COMMON/IES/EsmMessageContainer.c + ${NAS_SRC}COMMON/IES/GprsTimer.c + ${NAS_SRC}COMMON/IES/GutiType.c + ${NAS_SRC}COMMON/IES/IdentityType2.c + ${NAS_SRC}COMMON/IES/ImeisvRequest.c + ${NAS_SRC}COMMON/IES/KsiAndSequenceNumber.c + ${NAS_SRC}COMMON/IES/LcsClientIdentity.c + ${NAS_SRC}COMMON/IES/LcsIndicator.c + ${NAS_SRC}COMMON/IES/LinkedEpsBearerIdentity.c + ${NAS_SRC}COMMON/IES/LlcServiceAccessPointIdentifier.c + ${NAS_SRC}COMMON/IES/LocationAreaIdentification.c + ${NAS_SRC}COMMON/IES/MessageType.c + ${NAS_SRC}COMMON/IES/MobileIdentity.c + ${NAS_SRC}COMMON/IES/MobileStationClassmark2.c + ${NAS_SRC}COMMON/IES/MobileStationClassmark3.c + ${NAS_SRC}COMMON/IES/MsNetworkCapability.c + ${NAS_SRC}COMMON/IES/MsNetworkFeatureSupport.c + ${NAS_SRC}COMMON/IES/NasKeySetIdentifier.c + ${NAS_SRC}COMMON/IES/NasMessageContainer.c + ${NAS_SRC}COMMON/IES/NasRequestType.c + ${NAS_SRC}COMMON/IES/NasSecurityAlgorithms.c + ${NAS_SRC}COMMON/IES/NetworkName.c + ${NAS_SRC}COMMON/IES/Nonce.c + ${NAS_SRC}COMMON/IES/PacketFlowIdentifier.c + ${NAS_SRC}COMMON/IES/PagingIdentity.c + ${NAS_SRC}COMMON/IES/PdnAddress.c + ${NAS_SRC}COMMON/IES/PdnType.c + ${NAS_SRC}COMMON/IES/PlmnList.c + ${NAS_SRC}COMMON/IES/ProcedureTransactionIdentity.c + ${NAS_SRC}COMMON/IES/ProtocolConfigurationOptions.c + ${NAS_SRC}COMMON/IES/ProtocolDiscriminator.c + ${NAS_SRC}COMMON/IES/PTmsiSignature.c + ${NAS_SRC}COMMON/IES/QualityOfService.c + ${NAS_SRC}COMMON/IES/RadioPriority.c + ${NAS_SRC}COMMON/IES/SecurityHeaderType.c + ${NAS_SRC}COMMON/IES/ServiceType.c + ${NAS_SRC}COMMON/IES/ShortMac.c + ${NAS_SRC}COMMON/IES/SsCode.c + ${NAS_SRC}COMMON/IES/SupportedCodecList.c + ${NAS_SRC}COMMON/IES/TimeZoneAndTime.c + ${NAS_SRC}COMMON/IES/TimeZone.c + ${NAS_SRC}COMMON/IES/TmsiStatus.c + ${NAS_SRC}COMMON/IES/TrackingAreaIdentity.c + ${NAS_SRC}COMMON/IES/TrackingAreaIdentityList.c + ${NAS_SRC}COMMON/IES/TrafficFlowAggregateDescription.c + ${NAS_SRC}COMMON/IES/TrafficFlowTemplate.c + ${NAS_SRC}COMMON/IES/TransactionIdentifier.c + ${NAS_SRC}COMMON/IES/UeNetworkCapability.c + ${NAS_SRC}COMMON/IES/UeRadioCapabilityInformationUpdateNeeded.c + ${NAS_SRC}COMMON/IES/UeSecurityCapability.c + ${NAS_SRC}COMMON/IES/VoiceDomainPreferenceAndUeUsageSetting.c + ) + + set (libnas_utils_OBJS + ${NAS_SRC}COMMON/UTIL/device.c + ${NAS_SRC}COMMON/UTIL/memory.c + ${NAS_SRC}COMMON/UTIL/nas_log.c + ${NAS_SRC}COMMON/UTIL/nas_timer.c + ${NAS_SRC}COMMON/UTIL/socket.c + ${NAS_SRC}COMMON/UTIL/stty.c + ${NAS_SRC}COMMON/UTIL/TLVEncoder.c + ${NAS_SRC}COMMON/UTIL/TLVDecoder.c + ${NAS_SRC}COMMON/UTIL/OctetString.c + ) + + if(NAS_UE) + set(libnas_ue_api_OBJS + ${NAS_SRC}UE/API/USER/at_command.c + ${NAS_SRC}UE/API/USER/at_error.c + ${NAS_SRC}UE/API/USER/at_response.c + ${NAS_SRC}UE/API/USER/user_api.c + ${NAS_SRC}UE/API/USER/user_indication.c + ${NAS_SRC}UE/API/USIM/aka_functions.c + ${NAS_SRC}UE/API/USIM/usim_api.c + ) + set(libnas_ue_emm_OBJS + ${NAS_SRC}UE/EMM/Attach.c + ${NAS_SRC}UE/EMM/Authentication.c + ${NAS_SRC}UE/EMM/Detach.c + ${NAS_SRC}UE/EMM/emm_main.c + ${NAS_SRC}UE/EMM/EmmStatusHdl.c + ${NAS_SRC}UE/EMM/Identification.c + ${NAS_SRC}UE/EMM/IdleMode.c + ${NAS_SRC}UE/EMM/LowerLayer.c + ${NAS_SRC}UE/EMM/SecurityModeControl.c + ${NAS_SRC}UE/EMM/ServiceRequestHdl.c + ${NAS_SRC}UE/EMM/TrackingAreaUpdate.c + ) + set(libnas_ue_emm_sap_OBJS + ${NAS_SRC}UE/EMM/SAP/emm_as.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttachNeeded.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregistered.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredLimitedService.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoImsi.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNormalService.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredPlmnSearch.c + ${NAS_SRC}UE/EMM/SAP/emm_esm.c + ${NAS_SRC}UE/EMM/SAP/emm_fsm.c + ${NAS_SRC}UE/EMM/SAP/EmmNull.c + ${NAS_SRC}UE/EMM/SAP/emm_recv.c + ${NAS_SRC}UE/EMM/SAP/emm_reg.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c + ${NAS_SRC}UE/EMM/SAP/EmmRegistered.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredLimitedService.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNoCellAvailable.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNormalService.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredPlmnSearch.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredUpdateNeeded.c + ${NAS_SRC}UE/EMM/SAP/emm_sap.c + ${NAS_SRC}UE/EMM/SAP/emm_send.c + ${NAS_SRC}UE/EMM/SAP/EmmServiceRequestInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c + ) + set (libnas_ue_esm_OBJS + ${NAS_SRC}UE/ESM/DedicatedEpsBearerContextActivation.c + ${NAS_SRC}UE/ESM/DefaultEpsBearerContextActivation.c + ${NAS_SRC}UE/ESM/EpsBearerContextDeactivation.c + ${NAS_SRC}UE/ESM/esm_ebr.c + ${NAS_SRC}UE/ESM/esm_ebr_context.c + ${NAS_SRC}UE/ESM/esm_ip.c + ${NAS_SRC}UE/ESM/esm_main.c + ${NAS_SRC}UE/ESM/esm_pt.c + ${NAS_SRC}UE/ESM/EsmStatusHdl.c + ${NAS_SRC}UE/ESM/PdnConnectivity.c + ${NAS_SRC}UE/ESM/PdnDisconnect.c + ) + set(libnas_ue_esm_sap_OBJS + ${NAS_SRC}UE/ESM/SAP/esm_recv.c + ${NAS_SRC}UE/ESM/SAP/esm_send.c + ${NAS_SRC}UE/ESM/SAP/esm_sap.c + ) + add_library(LIB_NAS_UE + ${NAS_SRC}UE/nas_itti_messaging.c + ${NAS_SRC}UE/nas_network.c + ${NAS_SRC}UE/nas_parser.c + ${NAS_SRC}UE/nas_proc.c + ${NAS_SRC}UE/nas_user.c + ${libnas_api_OBJS} + ${libnas_ue_api_OBJS} + ${libnas_emm_msg_OBJS} + ${libnas_esm_msg_OBJS} + ${libnas_ies_OBJS} + ${libnas_utils_OBJS} + ${libnas_ue_emm_OBJS} + ${libnas_ue_emm_sap_OBJS} + ${libnas_ue_esm_OBJS} + ${libnas_ue_esm_sap_OBJS} + ) + set(NAS_UE_LIB LIB_NAS_UE) + + include_directories(${NAS_SRC}UE) + include_directories(${NAS_SRC}UE/API/USER) + include_directories(${NAS_SRC}UE/API/USIM) + include_directories(${NAS_SRC}UE/EMM) + include_directories(${NAS_SRC}UE/EMM/SAP) + include_directories(${NAS_SRC}UE/ESM) + include_directories(${NAS_SRC}UE/ESM/SAP) + endif() + + + + # Make lfds as a own source code (even if it is a outside library) + # For better intergration with compilation flags & structure of cmake + ################################################################### + set(lfds ${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/src/) + file(GLOB lfds_queue ${lfds}/lfds611_queue/*.c) + file(GLOB lfds_ring ${lfds}/lfds611_ringbuffer/*.c) + file(GLOB lfds_slist ${lfds}/lfds611_slist/*.c) + file(GLOB lfds_stack ${lfds}/lfds611_stack/*.c) + file(GLOB lfds_freelist ${lfds}/lfds611_freelist/*.c) + + include_directories(${lfds}) + add_library(LFDS + ${lfds_queue} ${lfds_ring} ${lfds_slist} ${lfds_stack} ${lfds_freelist} + ${lfds}/lfds611_liblfds/lfds611_liblfds_abstraction_test_helpers.c + ${lfds}/lfds611_liblfds/lfds611_liblfds_aligned_free.c + ${lfds}/lfds611_liblfds/lfds611_liblfds_aligned_malloc.c + ${lfds}/lfds611_abstraction/lfds611_abstraction_free.c + ${lfds}/lfds611_abstraction/lfds611_abstraction_malloc.c + ) + + # Simulation library + ########################## + add_library(SIMU + ${OPENAIR1_DIR}/SIMULATION/TOOLS/random_channel.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/rangen_double.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_channel.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/abstraction.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_tv_channel.c + ${OPENAIR1_DIR}/SIMULATION/RF/rf.c + ${OPENAIR1_DIR}/SIMULATION/RF/dac.c + ${OPENAIR1_DIR}/SIMULATION/RF/adc.c + ) + + add_library(SIMU_ETH + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/bypass_session_layer.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/emu_transport.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/pgm_link.c + ) + + add_library(OPENAIR0_LIB + ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c + ) + + # System packages that are required + # We use either the cmake buildin, in ubuntu are in: /usr/share/cmake*/Modules/ + # or cmake provide a generic interface to pkg-config that widely used + ################################### + include(FindPkgConfig) + + pkg_search_module(LIBXML2 libxml-2.0 REQUIRED) + include_directories(${LIBXML2_INCLUDE_DIRS}) + + pkg_search_module(LIBXSLT libxslt REQUIRED) + include_directories(${LIBXSLT_INCLUDE_DIRS}) + + pkg_search_module(OPENSSL openssl REQUIRED) + include_directories(${OPENSSL_INCLUDE_DIRS}) + + pkg_search_module(CONFIG libconfig REQUIRED) + include_directories(${CONFIG_INCLUDE_DIRS}) + + pkg_search_module(CRYPTO libcrypto REQUIRED) + include_directories(${CRYPTO_INCLUDE_DIRS}) + + #use native cmake method as this package is not in pkg-config + if (${RF_BOARD} STREQUAL "OAI_USRP") + find_package(Boost REQUIRED) + include_directories(${LIBBOOST_INCLUDE_DIR}) + endif (${RF_BOARD} STREQUAL "OAI_USRP") + + pkg_search_module(OPENPGM openpgm-5.1) + if(NOT ${OPENPGM_FOUND}) + message("PACKAGE openpgm-5.1 is required by binaries such as oaisim: will fail later if this target is built") + else() + include_directories(${OPENPGM_INCLUDE_DIRS}) + endif() + + pkg_search_module(NETTLE nettle) + if(NOT ${NETTLE_FOUND}) + message("PACKAGE nettle not found: some targets will fail") + else() + include_directories(${NETTLE_INCLUDE_DIRS}) + endif() + + pkg_search_module(XPM xpm) + if(NOT ${XPM_FOUND}) + message("PACKAGE xpm not found: some targets will fail") + else() + include_directories(${XPM_INCLUDE_DIRS}) + endif() + + # Atlas is required by some packages, but not found in pkg-config + if(EXISTS "/usr/include/atlas/cblas.h") + include_directories("/usr/include/atlas") + list(APPEND ATLAS_LIBRARIES lapack cblas atlas) + else() + message("No Blas/Atlas libs found, some targets will fail") + endif() + + if (${XFORMS}) + include_directories ("/usr/include/X11") + set(XFORMS_SOURCE + ${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope.c + ) + set(XFORMS_SOURCE_SOFTMODEM + ${OPENAIR_TARGETS}/RT/USER/stats.c + ) + set(XFORMS_LIBRARIES "forms") + endif (${XFORMS}) + + set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") + + + # Hack on a test of asn1c version (already dirty) + add_definitions(-DASN1_MINIMUM_VERSION=924) + + ################################# + # add executables for operation + ################################# + + # lte-softmodem is both eNB and UE implementation + ################################################### + + add_executable(lte-softmodem + ${rrc_h} + ${s1ap_h} + ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c + ${OPENAIR_TARGETS}/RT/USER/lte-ue.c + ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c + ${OPENAIR_TARGETS}/RT/USER/lte-enb.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c + ${OPENAIR_TARGETS}/COMMON/create_tasks.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${GTPU_need_ITTI} + ${HW_SOURCE} + ${TRANSPORT_SOURCE} + ${RTAI_SOURCE} + ${XFORMS_SOURCE} + ${XFORMS_SOURCE_SOFTMODEM} + ) + + target_link_libraries (lte-softmodem + -Wl,--start-group + RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} + -Wl,--end-group ) + + + target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES}) + target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) + target_link_libraries (lte-softmodem ${LIBBOOST_LIBRARIES}) + target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) + + # lte-softmodem-nos1 is both eNB and UE implementation + ################################################### + add_executable(lte-softmodem-nos1 + ${rrc_h} + ${s1ap_h} + ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c + ${OPENAIR_TARGETS}/RT/USER/lte-ue.c + ${OPENAIR_TARGETS}/RT/USER/lte-enb.c + ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c + ${OPENAIR_TARGETS}/COMMON/create_tasks.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + #${OPENAIR2_DIR}/RRC/NAS/nas_config.c # enable if you want rrc to mount ip interface + #${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${HW_SOURCE} + ${TRANSPORT_SOURCE} + ${RTAI_SOURCE} + ${XFORMS_SOURCE} + ${XFORMS_SOURCE_SOFTMODEM} + ) + target_link_libraries (lte-softmodem-nos1 + -Wl,--start-group + RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} + -Wl,--end-group ) + + target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES}) + target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) + target_link_libraries (lte-softmodem-nos1 ${LIBBOOST_LIBRARIES}) + target_link_libraries (lte-softmodem-nos1 ${LIB_LMS_LIBRARIES}) + + # rrh + ################################ + #Note: only one RF type (USRP) is currently supported for RRH + add_executable(rrh_gw + ${OPENAIR_TARGETS}/RT/USER/rrh_gw.c + ${OPENAIR_TARGETS}/RT/USER/eNB_transport_IQ.c + ${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c + ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${HW_SOURCE} + ${TRANSPORT_SOURCE} + ) + target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti) + target_link_libraries(rrh_gw + -Wl,--start-group + UTIL LFDS + -Wl,--end-group ) + target_link_libraries (rrh_gw rt pthread m ) + target_link_libraries (rrh_gw ${option_HW_lib} ${option_TP_lib} ${LIBBOOST_LIBRARIES} ) + target_link_libraries (rrh_gw ${LIB_LMS_LIBRARIES}) + + Message("-- option_HW_lib=${option_HW_lib}") + Message("-- HW_SOURCE=${HW_SOURCE}") + Message("-- option_TP_lib=${option_TP_lib}") + Message("-- TRANSPORT_SOURCE=${TRANSPORT_SOURCE}") + + if (${RF_BOARD} STREQUAL "OAI_LMSSDR") + add_dependencies(lte-softmodem LMS7002M LMS_SDR Si5351C) + add_dependencies(lte-softmodem-nos1 LMS7002M LMS_SDR Si5351C) + add_dependencies(rrh_gw LMS7002M LMS_SDR Si5351C) + endif (${RF_BOARD} STREQUAL "OAI_LMSSDR") + + + + # USIM process + ################# + #add_executable(usim + # ${OPENAIR3_DIR}/NAS/TOOLS/usim_data.c + # ${OPENAIR3_DIR}/NAS/USER/API/USIM/usim_api.c + # ${OPENAIR3_DIR}/NAS/USER/API/USIM/aka_functions.c + # ${OPENAIR3_DIR}/NAS/COMMON/UTIL/memory.c + # ${OPENAIR3_DIR}/NAS/COMMON/UTIL/nas_log.c + # ${OPENAIR3_DIR}/NAS/COMMON/UTIL/OctetString.c + # ${OPENAIR3_DIR}/NAS/COMMON/UTIL/TLVEncoder.c + # ) + #target_link_libraries (usim ${NAS_LIB} UTIL ${ITTI_LIB} LFDS pthread rt nettle crypto m) + + # ??? + ##################### + #add_executable(nvram + # ${OPENAIR3_DIR}/NAS/TOOLS/ue_data.c + # ${OPENAIR3_DIR}/NAS/COMMON/UTIL/memory.c + # ${OPENAIR3_DIR}/NAS/COMMON/UTIL/nas_log.c + # ) + #target_link_libraries (nvram LIB_NAS_UE UTIL ${ITTI_LIB} LFDS pthread rt nettle crypto m) + + + ###################################" + # Addexecutables for tests + #################################### + + # A all in one network simulator + ################ + add_executable(oaisim + ${rrc_h} + ${s1ap_h} + ${x2ap_h} + ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c + ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c + ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c + ${OPENAIR_TARGETS}/SIMU/USER/sinr_sim.c + ${OPENAIR_TARGETS}/SIMU/USER/cor_SF_sim.c + ${OPENAIR_TARGETS}/SIMU/USER/oaisim_functions.c + ${OPENAIR_TARGETS}/SIMU/USER/event_handler.c + ${OPENAIR_TARGETS}/SIMU/USER/oaisim.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR2_DIR}/UTIL/OMG/sumo.c + ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${GTPU_need_ITTI} + ${OPENAIR_TARGETS}/COMMON/create_tasks.c + ${HW_SOURCE} + ${TRANSPORT_SOURCE} + ${XFORMS_SOURCE} + ) + + + target_include_directories(oaisim PUBLIC ${OPENAIR_TARGETS}/SIMU/USER) + target_link_libraries (oaisim + -Wl,--start-group + RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} LIB_NAS_UE SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} + -Wl,--end-group ) + + target_link_libraries (oaisim ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) + target_link_libraries (oaisim pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} + ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES}) + #Force link with forms, regardless XFORMS option + target_link_libraries (oaisim forms) + + + + # A all in one network simulator + ################ + add_executable(oaisim_nos1 + ${rrc_h} + ${s1ap_h} + ${x2ap_h} + ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c + ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c + ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c + ${OPENAIR_TARGETS}/SIMU/USER/sinr_sim.c + ${OPENAIR_TARGETS}/SIMU/USER/cor_SF_sim.c + ${OPENAIR_TARGETS}/SIMU/USER/oaisim_functions.c + ${OPENAIR_TARGETS}/SIMU/USER/event_handler.c + ${OPENAIR_TARGETS}/SIMU/USER/oaisim.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR2_DIR}/UTIL/OMG/sumo.c + ${OPENAIR_TARGETS}/COMMON/create_tasks.c + ${HW_SOURCE} + ${TRANSPORT_SOURCE} + ${XFORMS_SOURCE} + ) + target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER) + target_link_libraries (oaisim_nos1 + -Wl,--start-group + RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} + -Wl,--end-group ) + + target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) + target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} + ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES}) + #Force link with forms, regardless XFORMS option + target_link_libraries (oaisim_nos1 forms) + + + # Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator + ##################################### + + foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) + add_executable(${myExe} + ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c + ${XFORMS_SOURCE} + ) + target_link_libraries (${myExe} + -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group + pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} + ) + endforeach(myExe) + + add_executable(test_epc_generate_scenario + ${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.h + ${OPENAIR2_DIR}/ENB_APP/enb_config.h + ${OPENAIR2_DIR}/COMMON/commonDef.h + ${OPENAIR2_DIR}/COMMON/messages_def.h + ${OPENAIR2_DIR}/COMMON/messages_types.h + ${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h + ${OPENAIR_BIN_DIR}/messages_xml.h + ) + target_link_libraries (test_epc_generate_scenario + -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} + ) + + add_executable(test_epc_play_scenario + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_decode.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_display.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_fsm.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_parse.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap_eNB_defs.h + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_sctp.c + ${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.h + ${OPENAIR2_DIR}/COMMON/commonDef.h + ${OPENAIR2_DIR}/COMMON/messages_def.h + ${OPENAIR2_DIR}/COMMON/messages_types.h + ${OPENAIR_BIN_DIR}/messages_xml.h + ) + target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c) + target_link_libraries (test_epc_play_scenario + -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} + ) + + + #unitary tests for Core NEtwork pieces + ################################# + foreach(myExe s1ap + secu_knas_encrypt_eia1 + secu_kenb + aes128_ctr_encrypt + aes128_ctr_decrypt + secu_knas_encrypt_eea2 + secu_knas secu_knas_encrypt_eea1 + kdf + aes128_cmac_encrypt + secu_knas_encrypt_eia2) + add_executable(test_${myExe} + ${OPENAIR3_DIR}/TEST/test_util.c + ${OPENAIR3_DIR}/TEST/test_${myExe}.c + ) + target_link_libraries (test_${myExe} + -Wl,--start-group SECU_CN UTIL LFDS -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} + ) + endforeach(myExe) + + # to be added + #../targets/TEST/PDCP/test_pdcp.c + #../targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c From deab4aa2084d190ef7731af6d0e811a4d680af27 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 1 Jun 2016 20:44:57 +0200 Subject: [PATCH 017/206] debugging with USRP --- openair1/SCHED/phy_procedures_lte_eNb.c | 82 +++------- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 2 + .../CONF/enb.band7.tm1.usrpb210.conf | 32 ++-- targets/RT/USER/lte-enb.c | 140 +++++++++++++----- 4 files changed, 137 insertions(+), 119 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index a444686758..381d29d44a 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2491,6 +2491,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (subframe==9) { subframe=0; frame++; + frame&=1023; } else subframe++; @@ -2512,62 +2513,34 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl rxs = openair0.trx_read_func(&openair0, &proc->timestamp_rx, rxp, - fp->samples_per_tti>>1, + fp->samples_per_tti, fp->nb_antennas_rx); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - if (proc->first_rx == 0) - AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is"); + if (proc->first_rx == 0) { + AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)",proc->subframe_rx,subframe); + AssertFatal(proc->frame_rx == frame, "Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)",proc->frame_rx,frame); + } else proc->first_rx = 0; + // printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, frame ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, subframe ); - if (frame > 20){ - if (rxs != fp->samples_per_tti>>1) - exit_fun( "problem receiving samples" ); - } + + if (rxs != fp->samples_per_tti) + exit_fun( "problem receiving samples" ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - // wake up TX thread - // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc->instance_cnt_tx ); - exit_fun( "error locking mutex_tx" ); - return; - } - - int cnt_tx = ++proc->instance_cnt_tx; - // We have just received and processed the common part of the first slot of a subframe, say n. - // TX_rx is the last received timestamp (start of 1st slot), TX_tx is the desired - // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, - // and proc->subframe_tx = proc->subframe_rx+3 - proc->timestamp_tx = proc->timestamp_rx + (3*fp->samples_per_tti); - proc->frame_tx = (subframe > 6) ? (frame+1) : frame; - proc->subframe_tx = (subframe + 3)%10; - - pthread_mutex_unlock( &proc->mutex_tx ); - - if (cnt_tx == 0){ - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB TX thread busy!! (cnt_tx %i)\n", frame, cnt_tx ); - exit_fun( "TX thread busy" ); - return; - } // now do common RX processing for first slot in subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); remove_7_5_kHz(eNB,subframe<<1); - for (l=0; lsymbols_per_tti/2; l++) + remove_7_5_kHz(eNB,1+(subframe<<1)); + for (l=0; lsymbols_per_tti/2; l++) { slot_fep_ul(fp, &eNB->common_vars, l, @@ -2575,35 +2548,18 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl 0, 0 ); - - if (eNB->node_function == NGFI_RRU_IF4) { - //send_IF4(eNB,subframe<<1); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); - - for (i=0; inb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][(fp->samples_per_tti>>1)+(subframe*fp->samples_per_tti)]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - rxs = openair0.trx_read_func(&openair0, - &proc->timestamp_rx, - rxp, - fp->samples_per_tti>>1, - fp->nb_antennas_rx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); - remove_7_5_kHz(eNB,(subframe<<1)+1); - for (l=0; lsymbols_per_tti/2; l++) slot_fep_ul(fp, &eNB->common_vars, l, - (subframe<<1)+1, + 1+(subframe<<1), 0, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); + if (eNB->node_function == NGFI_RRU_IF4) { + //send_IF4(eNB,subframe<<1); //send_IF4(eNB,(subframe<<1)+1); } diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 72e79b44de..3c1e1796e6 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -174,6 +174,8 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, { usrp_state_t *s = (usrp_state_t*)device->priv; s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); + + if(flags) s->tx_md.has_time_spec = true; else diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index 967b0c0ca8..ae2b076a49 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -28,7 +28,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 25; @@ -64,15 +64,15 @@ eNBs = srs_ackNackST =; srs_MaxUpPts =;*/ - pusch_p0_Nominal = -90; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -103; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; rach_numberOfRA_Preambles = 64; rach_preamblesGroupAConfig = "DISABLE"; @@ -82,7 +82,7 @@ eNBs = rach_messagePowerOffsetGroupB = ; */ rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; + rach_preambleInitialReceivedTargetPower = -104; rach_preambleTransMax = 10; rach_raResponseWindowSize = 10; rach_macContentionResolutionTimer = 48; @@ -130,7 +130,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.11"; + mme_ip_address = ( { ipv4 = "127.0.0.3"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -139,11 +139,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index dcf970e44e..7e779bc88b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -167,10 +167,11 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) unsigned int aa,slot_offset, slot_offset_F; int dummy_tx_b[7680*4] __attribute__((aligned(32))); - int i, tx_offset; + int i,j, tx_offset; int slot_sizeF = (phy_vars_eNB->frame_parms.ofdm_symbol_size)* ((phy_vars_eNB->frame_parms.Ncp==1) ? 6 : 7); - int len; + int len,len2; + int16_t *txdata; slot_offset_F = (subframe<<1)*slot_sizeF; @@ -220,27 +221,52 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) dummy_tx_b[i+2] = 0xff00; dummy_tx_b[i+3] = 0xff000000; }*/ - for (i=0; icommon_vars.txdata[0][aa][(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)+tx_offset]; + len2 = -(slot_offset+time_offset[aa]); + len2 = (len2>len) ? len : len2; + for (i=0; i<(len2<<1); i++) { + txdata[i] = ((int16_t*)dummy_tx_b)[i]<common_vars.txdata[0][aa][0]; + for (j=0; i<(len<<1); i++,j++) { + txdata[j++] = ((int16_t*)dummy_tx_b)[i]<(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) { - - if (tx_offset<0) - tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; + tx_offset = (int)slot_offset+time_offset[aa]; + txdata = (int16_t*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset]; + len2 = -tx_offset+LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; + for (i=0; i<(len2<<1); i++) { + txdata[i] = ((int16_t*)dummy_tx_b)[i]<common_vars.txdata[0][aa][0]; + for (j=0; i<(len<<1); i++,j++) { + txdata[j++] = ((int16_t*)dummy_tx_b)[i]<common_vars.txdata[0][aa][tx_offset]; - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; + for (i=0; i<(len<<1); i++) { + txdata[i] = ((int16_t*)dummy_tx_b)[i]<common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<frame_parms,subframe) == SF_S) { for (i=0; icommon_vars.txdata[0][aa][tx_offset++] = 0x00010001; } } - + */ if ((((phy_vars_eNB->frame_parms.tdd_config==0) || (phy_vars_eNB->frame_parms.tdd_config==1) || (phy_vars_eNB->frame_parms.tdd_config==2) || @@ -420,12 +446,13 @@ static void* eNB_thread_tx( void* param ) /* run PHY TX procedures the one after the other for all CCs to avoid race conditions * (may be relaxed in the future for performance reasons) */ + if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n"); exit_fun("nothing to add"); break; } - /* wait for our turn or oai_exit */ + // wait for our turn or oai_exit while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) { pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx, &sync_phy_proc.mutex_phy_proc_tx); @@ -436,6 +463,7 @@ static void* eNB_thread_tx( void* param ) exit_fun("nothing to add"); } + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_ENB, proc->subframe_tx ); @@ -488,14 +516,15 @@ static void* eNB_thread_tx( void* param ) for (i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; // if symb_written < spp ==> error - if (proc->frame_tx > 50) { - openair0.trx_write_func(&openair0, - (proc->timestamp_tx+openair0_cfg[0].tx_sample_advance), - txp, - PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, - PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, - 1); - } + openair0.trx_write_func(&openair0, + (proc->timestamp_tx+openair0_cfg[0].tx_sample_advance), + txp, + PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, + PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, + 1); + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); @@ -658,7 +687,7 @@ static void* eNB_thread_rx( void* param ) memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); policy = SCHED_FIFO ; s = pthread_setschedparam(pthread_self(), policy, &sparam); @@ -719,8 +748,10 @@ static void* eNB_thread_rx( void* param ) if ((((fp->frame_type == TDD )&&(subframe_select(fp,proc->subframe_rx)==SF_UL)) || (fp->frame_type == FDD))) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); - // this spawns the prach and TX threads inside and updates the frame and subframe counters + // this spawns the prach inside and updates the frame and subframe counters phy_procedures_eNB_common_RX(eNB, 0); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); if (eNB->node_function != NGFI_RRU_IF4) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); @@ -729,10 +760,39 @@ static void* eNB_thread_rx( void* param ) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); } } - - if ((subframe_select(fp,proc->subframe_rx) == SF_S)) { - phy_procedures_eNB_S_RX(eNB, 0, no_relay ); + + // wake up TX for subframe n+4 + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc->instance_cnt_tx ); + exit_fun( "error locking mutex_tx" ); + break; } + int cnt_tx = ++proc->instance_cnt_tx; + // We have just received and processed the common part of a subframe, say n. + // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired + // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, + // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+3 + proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); + proc->frame_tx = (proc->frame_rx > 5) ? (proc->frame_rx+1)&1023 : proc->frame_rx; + proc->subframe_tx = (proc->subframe_rx + 4)%10; + + pthread_mutex_unlock( &proc->mutex_tx ); + + if (cnt_tx == 0){ + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_tx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + break; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB TX thread busy!! (cnt_tx %i)\n", proc->frame_tx, cnt_tx ); + exit_fun( "TX thread busy" ); + break; + } stop_meas( &softmodem_stats_rx_sf ); #ifdef LOWLATENCY @@ -747,17 +807,17 @@ static void* eNB_thread_rx( void* param ) } - - //stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); - - + + //stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); + + #ifdef DEBUG_THREADS - printf( "Exiting eNB thread RX\n"); + printf( "Exiting eNB thread RX\n"); #endif - - eNB_thread_rx_status = 0; - return &eNB_thread_rx_status; + + eNB_thread_rx_status = 0; + return &eNB_thread_rx_status; } @@ -848,7 +908,7 @@ static void* eNB_thread_prach( void* param ) memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-2; policy = SCHED_FIFO ; s = pthread_setschedparam(pthread_self(), policy, &sparam); @@ -868,7 +928,7 @@ static void* eNB_thread_prach( void* param ) } - LOG_I( HW, "[SCHED][eNB] RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + LOG_I( HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -962,7 +1022,7 @@ void init_eNB_proc(void) pthread_attr_setschedparam (&proc->attr_tx, &proc->sched_param_tx); pthread_attr_setschedpolicy (&proc->attr_tx, SCHED_FIFO); - proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; pthread_attr_setschedparam (&proc->attr_rx, &proc->sched_param_rx); pthread_attr_setschedpolicy (&proc->attr_rx, SCHED_FIFO); From ba93bbe99e05dd57dbd7d319bc89b28dad8b9506 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 1 Jun 2016 21:40:59 -0700 Subject: [PATCH 018/206] corrected frame_tx calculation in lte-enb.c --- targets/RT/USER/lte-enb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 7e779bc88b..1fe49bf6af 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -776,7 +776,7 @@ static void* eNB_thread_rx( void* param ) // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, // and proc->subframe_tx = proc->subframe_rx+3 proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); - proc->frame_tx = (proc->frame_rx > 5) ? (proc->frame_rx+1)&1023 : proc->frame_rx; + proc->frame_tx = (proc->subframe_rx > 5) ? (proc->frame_rx+1)&1023 : proc->frame_rx; proc->subframe_tx = (proc->subframe_rx + 4)%10; pthread_mutex_unlock( &proc->mutex_tx ); From f895f42c9dd67ca78bd40d58c9747a028c8ad43e Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 2 Jun 2016 09:34:56 +0200 Subject: [PATCH 019/206] frame/subframe numbering --- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 2 ++ openair1/SCHED/phy_procedures_lte_eNb.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 0850836b36..d63ed32fda 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -288,11 +288,13 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, if (harq_pid==255) { LOG_E(PHY, "FATAL ERROR: illegal harq_pid, returning\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); return -1; } if (ulsch_harq->Nsymb_pusch == 0) { LOG_E(PHY, "FATAL ERROR: harq_pid %d, Nsymb 0!\n",harq_pid); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); return 1+ulsch->max_turbo_iterations; } if (llr8_flag == 0) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 381d29d44a..cfcec35460 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -845,9 +845,9 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const in LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; eNB_proc_t *proc = &eNB->proc; int frame = proc->frame_tx; - int subframe = proc->frame_rx; + int subframe = proc->subframe_tx; - LOG_D(PHY, + LOG_I(PHY, "[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8"), aggregation %d\n", eNB->Mod_id, subframe2harq_pid(fp, From a2234d18a637fd56c6ddbe0a99bf98cb604d0b3b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 2 Jun 2016 00:41:28 -0700 Subject: [PATCH 020/206] new procedures document --- targets/DOCS/oai_L1_L2_procedures.pdf | Bin 1696869 -> 1652669 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/targets/DOCS/oai_L1_L2_procedures.pdf b/targets/DOCS/oai_L1_L2_procedures.pdf index e14948f5af9195b59e06b4b4aefafa065756d09f..0f47195db1c70b27f17b907a3b95174d45e4f292 100755 GIT binary patch delta 110207 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 z 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 Date: Thu, 2 Jun 2016 06:16:50 -0700 Subject: [PATCH 021/206] tx_scheduling_advance removed and tx_sample_advance added to trx_write in lte-enb.c --- targets/RT/USER/lte-enb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 1fe49bf6af..6290953e8b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -517,7 +517,7 @@ static void* eNB_thread_tx( void* param ) txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; // if symb_written < spp ==> error openair0.trx_write_func(&openair0, - (proc->timestamp_tx+openair0_cfg[0].tx_sample_advance), + (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), txp, PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, From 4996f9855d8d41a5a1ef4a7646919ed31287e2de Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 2 Jun 2016 19:13:20 +0200 Subject: [PATCH 022/206] first draft of the send_if function --- openair1/PHY/TOOLS/if4tools.c | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 openair1/PHY/TOOLS/if4tools.c diff --git a/openair1/PHY/TOOLS/if4tools.c b/openair1/PHY/TOOLS/if4tools.c new file mode 100644 index 0000000000..70e598e2a1 --- /dev/null +++ b/openair1/PHY/TOOLS/if4tools.c @@ -0,0 +1,47 @@ +/* +typedef struct data_block_type { + +} data_block; +*/ + +/* +void allocate_data_block(long *data_block ,int length){ + data_block = malloc(length*sizeof(long)); +} +*/ + +void send_IF4(PHY_VARS_eNB eNB, int subframe){ + eNB_proc_t *proc = &eNB->proc; + //int frame=proc->frame_tx; + //int subframe=proc->subframe_tx; + + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int i,j; + + float *data_block = malloc(length*sizeof(long)); + + + // find number of consecutive non zero in values in symbol + // NrOfNonZeroValues + + // how many values does the atan function output? + + for(i = 0; i <= fp->symbols_per_tti; i++){ + for(j = 0; j < NrOfNonZeroValues; j=j+2){ + + symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] + + data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); + data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); + // use memset? + } + + } + +/* +memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], + 0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t)); + } + */ + +} From fd70527bf2b03ede4b54e1cf01362a54bd515c04 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 2 Jun 2016 16:00:02 -0700 Subject: [PATCH 023/206] updates for 2 RXn-TXnp4 threads --- openair1/PHY/INIT/lte_init.c | 10 +- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 7 +- openair1/PHY/LTE_TRANSPORT/phich.c | 17 +- openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c | 3 +- openair1/PHY/LTE_TRANSPORT/pmch.c | 10 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 8 +- openair1/PHY/LTE_TRANSPORT/proto.h | 17 +- openair1/PHY/LTE_TRANSPORT/pucch.c | 5 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 12 +- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 16 +- openair1/PHY/TOOLS/lte_phy_scope.c | 2 +- openair1/PHY/defs.h | 51 ++- openair1/SCHED/defs.h | 18 +- openair1/SCHED/phy_mac_stub.c | 44 +- openair1/SCHED/phy_procedures_lte_eNb.c | 377 +++++++++--------- openair2/LAYER2/MAC/proto.h | 2 +- openair2/UTIL/LOG/vcd_signal_dumper.c | 24 +- openair2/UTIL/LOG/vcd_signal_dumper.h | 24 +- targets/RT/USER/lte-enb.c | 218 +++++----- 19 files changed, 442 insertions(+), 423 deletions(-) diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 5c8a5ec436..e3128d7296 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -121,7 +121,7 @@ void phy_config_sib2_eNB(uint8_t Mod_id, //int32_t rx_total_gain_eNB_dB = PHY_vars_eNB_g[Mod_id][CC_id]->rx_total_gain_eNB_dB; int i; - LOG_D(PHY,"[eNB%d] CCid %d Frame %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc.frame_tx); + LOG_D(PHY,"[eNB%d] CCid %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id); frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; LOG_D(PHY,"prach_config_common.rootSequenceIndex = %d\n",frame_parms->prach_config_common.rootSequenceIndex ); @@ -388,7 +388,7 @@ void phy_config_sib13_eNB(uint8_t Mod_id,int CC_id,int mbsfn_Area_idx, LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; - LOG_I(PHY,"[eNB%d] Frame %d: Applying MBSFN_Area_id %d for index %d\n",Mod_id,PHY_vars_eNB_g[Mod_id][CC_id]->proc.frame_tx,mbsfn_AreaId_r9,mbsfn_Area_idx); + LOG_I(PHY,"[eNB%d] Applying MBSFN_Area_id %d for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx); if (mbsfn_Area_idx == 0) { frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; @@ -409,7 +409,7 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB) physicalConfigDedicated = eNB->physicalConfigDedicated[UE_id]; if (physicalConfigDedicated != NULL) { - LOG_I(PHY,"[eNB %d] Frame %d: Sent physicalConfigDedicated=%p for UE %d\n",eNB->Mod_id, eNB->proc.frame_tx,physicalConfigDedicated,UE_id); + LOG_I(PHY,"[eNB %d] Frame %d: Sent physicalConfigDedicated=%p for UE %d\n",eNB->Mod_id,physicalConfigDedicated,UE_id); LOG_D(PHY,"------------------------------------------------------------------------\n"); if (physicalConfigDedicated->pdsch_ConfigDedicated) { @@ -644,7 +644,7 @@ void phy_config_dedicated_eNB(uint8_t Mod_id, int8_t UE_id = find_ue(rnti,eNB); if (UE_id == -1) { - LOG_E( PHY, "[eNB %"PRIu8"] Frame %d: find_ue() returns -1\n", Mod_id, eNB->proc.frame_tx ); + LOG_E( PHY, "[eNB %"PRIu8"] Frame %d: find_ue() returns -1\n", Mod_id); return; } @@ -653,7 +653,7 @@ void phy_config_dedicated_eNB(uint8_t Mod_id, eNB->physicalConfigDedicated[UE_id] = physicalConfigDedicated; LOG_I(PHY,"phy_config_dedicated_eNB: physicalConfigDedicated=%p\n",physicalConfigDedicated); } else { - LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, eNB->proc.frame_tx,UE_id); + LOG_E(PHY,"[eNB %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, UE_id); return; } diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 4538deee13..18e232e967 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -7078,6 +7078,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, } int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, void *dci_pdu, uint16_t rnti, DCI_format_t dci_format, @@ -7095,7 +7096,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, ANFBmode_t AckNackFBMode = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode; LTE_eNB_ULSCH_t *ulsch=eNB->ulsch[UE_id]; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; - int subframe = eNB->proc.subframe_tx; + int subframe = proc->subframe_tx; uint32_t cqi_req = 0; uint32_t dai = 0; @@ -7116,7 +7117,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, harq_pid = subframe2harq_pid(frame_parms, pdcch_alloc2ul_frame(frame_parms, - eNB->proc.frame_tx, + proc->frame_tx, subframe), pdcch_alloc2ul_subframe(frame_parms,subframe)); @@ -7637,7 +7638,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d)\n", - eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift); + eNB->Mod_id,harq_pid,proc->frame_tx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift); diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index 54564637d6..223afcfdd9 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -1416,7 +1416,8 @@ void rx_phich(PHY_VARS_UE *ue, } void generate_phich_top(PHY_VARS_eNB *eNB, - int16_t amp, + eNB_rxtx_proc_t *proc, + int16_t amp, uint8_t sect_id, uint8_t abstraction_flag) { @@ -1431,7 +1432,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, uint8_t pusch_subframe; uint8_t UE_id; uint32_t pusch_frame; - int subframe = eNB->proc.subframe_tx; + int subframe = proc->subframe_tx; // compute Ngroup_PHICH (see formula at beginning of Section 6.9 in 36-211 @@ -1443,7 +1444,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, if (frame_parms->Ncp == 1) NSF_PHICH = 2; - pusch_frame = phich_frame2_pusch_frame(frame_parms,eNB->proc.frame_tx,subframe); + pusch_frame = phich_frame2_pusch_frame(frame_parms,proc->frame_tx,subframe); pusch_subframe = phich_subframe2_pusch_subframe(frame_parms,subframe); harq_pid = subframe2harq_pid(frame_parms,pusch_frame,pusch_subframe); @@ -1452,7 +1453,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, if (ulsch[UE_id]->harq_processes[harq_pid]->phich_active == 1) { LOG_D(PHY,"[eNB][PUSCH %d/%x] Frame %d subframe %d (pusch_subframe %d,pusch_frame %d) phich active %d\n", - harq_pid,ulsch[UE_id]->rnti,eNB->proc.frame_tx,subframe,pusch_subframe,pusch_frame,ulsch[UE_id]->harq_processes[harq_pid]->phich_active); + harq_pid,ulsch[UE_id]->rnti,proc->frame_tx,subframe,pusch_subframe,pusch_frame,ulsch[UE_id]->harq_processes[harq_pid]->phich_active); ngroup_PHICH = (ulsch[UE_id]->harq_processes[harq_pid]->first_rb + ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%Ngroup_PHICH; @@ -1466,7 +1467,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, nseq_PHICH = ((ulsch[UE_id]->harq_processes[harq_pid]->first_rb/Ngroup_PHICH) + ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS)%(2*NSF_PHICH); LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Generating PHICH, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d dci_alloc %d)\n", - eNB->Mod_id,harq_pid,eNB->proc.frame_tx, + eNB->Mod_id,harq_pid,proc->frame_tx, subframe,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH, ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, ulsch[UE_id]->harq_processes[harq_pid]->first_rb, @@ -1474,7 +1475,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, if (ulsch[UE_id]->Msg3_active == 1) { LOG_D(PHY,"[eNB %d][PUSCH %d][RAPROC] Frame %d, subframe %d: Generating Msg3 PHICH for UE %d, ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d\n", - eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe, + eNB->Mod_id,harq_pid,proc->frame_tx,subframe, UE_id,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH,ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK, ulsch[UE_id]->harq_processes[harq_pid]->first_rb); } @@ -1504,7 +1505,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, (ulsch[UE_id]->harq_processes[harq_pid]->rar_alloc == 0) ) { if (ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK==0 ) { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d, subframe %d : PHICH NACK / (no format0 DCI) Setting subframe_scheduling_flag\n", - eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe); + eNB->Mod_id,harq_pid,proc->frame_tx,subframe); ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; ulsch[UE_id]->harq_processes[harq_pid]->rvidx = rv_table[ulsch[UE_id]->harq_processes[harq_pid]->round&3]; ulsch[UE_id]->harq_processes[harq_pid]->O_RI = 0; @@ -1514,7 +1515,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, } else { LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d PHICH ACK (no format0 DCI) Clearing subframe_scheduling_flag, setting round to 0\n", - eNB->Mod_id,harq_pid,eNB->proc.frame_tx,subframe); + eNB->Mod_id,harq_pid,proc->frame_tx,subframe); ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; ulsch[UE_id]->harq_processes[harq_pid]->round=0; } diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c index b32d56f5be..8a76ef6e77 100644 --- a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c +++ b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c @@ -42,6 +42,7 @@ int generate_mbsfn_pilot(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, int32_t **txdataF, int16_t amp) @@ -49,7 +50,7 @@ int generate_mbsfn_pilot(PHY_VARS_eNB *eNB, LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; uint32_t subframe_offset,Nsymb,samples_per_symbol; - int subframe = eNB->proc.subframe_tx; + int subframe = proc->subframe_tx; if (subframe<0 || subframe>= 10) { diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 084b2b1793..325e0918a5 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -286,11 +286,11 @@ void fill_UE_dlsch_MCH(PHY_VARS_UE *ue,int mcs,int ndi,int rvidx,int eNB_id) } } -void generate_mch(PHY_VARS_eNB *eNB,uint8_t *a,int abstraction_flag) +void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a,int abstraction_flag) { int G; - int subframe = eNB->proc.subframe_tx; + int subframe = proc->subframe_tx; if (abstraction_flag != 0) { if (eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]!=0) @@ -312,9 +312,9 @@ void generate_mch(PHY_VARS_eNB *eNB,uint8_t *a,int abstraction_flag) eNB->frame_parms.N_RB_DL, eNB->dlsch_MCH->harq_processes[0]->rb_alloc, get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1, - 2,eNB->proc.frame_tx,subframe); + 2,proc->frame_tx,subframe); - generate_mbsfn_pilot(eNB, + generate_mbsfn_pilot(eNB,proc, eNB->common_vars.txdataF[0], AMP); @@ -323,7 +323,7 @@ void generate_mch(PHY_VARS_eNB *eNB,uint8_t *a,int abstraction_flag) &eNB->frame_parms, 1, eNB->dlsch_MCH, - eNB->proc.frame_tx, + proc->frame_tx, subframe, &eNB->dlsch_rate_matching_stats, &eNB->dlsch_turbo_encoding_stats, diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 829b05530e..a175f4cb8e 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -568,7 +568,7 @@ int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length) uint32_t ulsch_round_attempts[4]= {0,0,0,0},ulsch_round_errors[4]= {0,0,0,0}; uint32_t dlsch_round_attempts[4]= {0,0,0,0},dlsch_round_errors[4]= {0,0,0,0}; uint32_t UE_id_mac, RRC_status; - + eNB_rxtx_proc_t *proc = &eNB->proc.proc_rxtx[0]; if (eNB==NULL) return 0; @@ -583,7 +583,7 @@ int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length) for (eNB_id=0; eNB_idproc.frame_tx, + proc->frame_tx, eNB->rx_total_gain_dB, eNB->measurements[eNB_id].n0_power_tot_dBm, eNB->measurements[eNB_id].n0_power_dB[0], @@ -621,9 +621,9 @@ int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length) - len += sprintf(&buffer[len],"Total DLSCH %d kbits / %d frames ",(eNB->total_transmitted_bits/1000),eNB->proc.frame_tx+1); + len += sprintf(&buffer[len],"Total DLSCH %d kbits / %d frames ",(eNB->total_transmitted_bits/1000),proc->frame_tx+1); len += sprintf(&buffer[len],"Total DLSCH throughput %d kbps ",(eNB->total_dlsch_bitrate/1000)); - len += sprintf(&buffer[len],"Total DLSCH trans %d / %d frames\n",success,eNB->proc.frame_tx+1); + len += sprintf(&buffer[len],"Total DLSCH trans %d / %d frames\n",success,proc->frame_tx+1); //len += sprintf(&buffer[len],"[eNB PROC] FULL MU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->FULL_MUMIMO_transmissions,eNB->check_for_total_transmissions); //len += sprintf(&buffer[len],"[eNB PROC] MU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->check_for_MUMIMO_transmissions,eNB->check_for_total_transmissions); //len += sprintf(&buffer[len],"[eNB PROC] SU-MIMO Transmissions/Total Transmissions = %d/%d\n",eNB->check_for_SUMIMO_transmissions,eNB->check_for_total_transmissions); diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index fc9e800760..1f8f0723e6 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -232,10 +232,11 @@ int mch_modulation(int32_t **txdataF, @param abstraction_flag */ -void generate_mch(PHY_VARS_eNB *phy_vars_eNB,uint8_t *a,int abstraction_flag); +void generate_mch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t *a,int abstraction_flag); /** \brief This function generates the frequency-domain pilots (cell-specific downlink reference signals) @param phy_vars_eNB Pointer to eNB variables + @param proc Pointer to RXn-TXnp4 proc information @param mcs MCS for MBSFN @param ndi new data indicator @param rdvix @@ -299,7 +300,8 @@ int32_t generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, int first_pilot_only); int32_t generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB, - int32_t **txdataF, + eNB_rxtx_proc_t *proc, + int32_t **txdataF, int16_t amp); int32_t generate_pss(int32_t **txdataF, @@ -1408,6 +1410,7 @@ int32_t generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue, double sinr_eff_cqi_calc(PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id); int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB, + eNB_rxtx_proc_t *proc, void *dci_pdu, rnti_t rnti, DCI_format_t dci_format, @@ -1419,7 +1422,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB, uint8_t use_srs); -void dump_ulsch(PHY_VARS_eNB *phy_vars_eNb,uint8_t UE_id); +void dump_ulsch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id); void dump_dlsch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); @@ -1474,12 +1477,14 @@ void generate_RIV_tables(void); int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode); void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, - uint8_t eNB_id, // this is the effective sector id + eNB_rxtx_proc_t *proc, + uint8_t eNB_id, // this is the effective sector id uint8_t UE_id, LTE_eNB_ULSCH_t **ulsch, uint8_t cooperation_flag); void rx_ulsch_emul(PHY_VARS_eNB *phy_vars_eNB, + eNB_rxtx_proc_t *proc, uint8_t sect_id, uint8_t UE_index); @@ -1518,6 +1523,7 @@ int32_t ulsch_encoding_emul(uint8_t *ulsch_buffer, /*! \brief Decoding of PUSCH/ACK/RI/ACK from 36-212. @param phy_vars_eNB Pointer to eNB top-level descriptor + @param proc Pointer to RXTX proc variables @param UE_id ID of UE transmitting this PUSCH @param subframe Index of subframe for PUSCH @param control_only_flag Receive PUSCH with control information only @@ -1526,6 +1532,7 @@ int32_t ulsch_encoding_emul(uint8_t *ulsch_buffer, @returns 0 on success */ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, + eNB_rxtx_proc_t *proc, uint8_t UE_id, uint8_t control_only_flag, uint8_t Nbundled, @@ -1536,6 +1543,7 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, uint16_t *crnti); void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, + eNB_rxtx_proc_t *proc, int16_t amp, uint8_t sect_id, uint8_t abstraction_flag); @@ -1663,6 +1671,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, uint8_t pucch1_thres); int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, + eNB_rxtx_proc_t *proc, uint8_t UE_index, PUCCH_FMT_t fmt, uint8_t n1_pucch_sel, diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 547a0f2217..ce5f756145 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -1064,6 +1064,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, int32_t rx_pucch_emul(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, uint8_t UE_index, PUCCH_FMT_t fmt, uint8_t n1_pucch_sel, @@ -1072,7 +1073,7 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *eNB, { uint8_t UE_id; uint16_t rnti; - int subframe = eNB->proc.subframe_rx; + int subframe = proc->subframe_rx; uint8_t CC_id = eNB->CC_id; rnti = eNB->ulsch[UE_index]->rnti; @@ -1095,7 +1096,7 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *eNB, payload[0] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[0]; payload[1] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[1]; } else - LOG_E(PHY,"[eNB] Frame %d: Can't handle formats 2/2a/2b\n",eNB->proc.frame_rx); + LOG_E(PHY,"[eNB] Frame %d: Can't handle formats 2/2a/2b\n",proc->frame_rx); if (PHY_vars_UE_g[UE_id][CC_id]->pucch_sel[subframe] == n1_pucch_sel) return(99); diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index d63ed32fda..02bf98c372 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -218,7 +218,7 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) -unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, +unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, uint8_t UE_id, uint8_t control_only_flag, uint8_t Nbundled, @@ -259,7 +259,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, int16_t cseq[6*14*1200]; int off; int status[20]; - int subframe = eNB->proc.subframe_rx; + int subframe = proc->subframe_rx; LTE_UL_eNB_HARQ_t *ulsch_harq; uint8_t (*tc)(int16_t *y, @@ -278,7 +278,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, time_stats_t *, time_stats_t *); - harq_pid = subframe2harq_pid(frame_parms,eNB->proc.frame_rx,subframe); + harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1); @@ -1501,18 +1501,18 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb #endif -uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, +uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t UE_index, uint16_t *crnti) { uint8_t UE_id; uint16_t rnti; - int subframe = eNB->proc.subframe_rx; + int subframe = proc->subframe_rx; uint8_t harq_pid; uint8_t CC_id = eNB->CC_id; - harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc.frame_rx,subframe); + harq_pid = subframe2harq_pid(&eNB->frame_parms,proc->frame_rx,subframe); rnti = eNB->ulsch[UE_index]->rnti; #ifdef DEBUG_PHY diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 53cab326f1..59cf11a06c 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1577,6 +1577,7 @@ int32_t avgU[2]; int32_t avgU_0[2],avgU_1[2]; // For the Distributed Alamouti Scheme void rx_ulsch(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, uint8_t eNB_id, // this is the effective sector id uint8_t UE_id, LTE_eNB_ULSCH_t **ulsch, @@ -1602,9 +1603,9 @@ void rx_ulsch(PHY_VARS_eNB *eNB, uint8_t Qm; uint16_t rx_power_correction; int16_t *llrp; - int subframe = eNB->proc.subframe_rx; + int subframe = proc->subframe_rx; - harq_pid = subframe2harq_pid(frame_parms,eNB->proc.frame_rx,subframe); + harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe); Qm = get_Qm_ul(ulsch[UE_id]->harq_processes[harq_pid]->mcs); #ifdef DEBUG_ULSCH msg("rx_ulsch: eNB_id %d, harq_pid %d, nb_rb %d first_rb %d, cooperation %d\n",eNB_id,harq_pid,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,ulsch[UE_id]->harq_processes[harq_pid]->first_rb, @@ -1885,24 +1886,25 @@ void rx_ulsch(PHY_VARS_eNB *eNB, } void rx_ulsch_emul(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, uint8_t sect_id, uint8_t UE_index) { - msg("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",eNB->Mod_id,eNB->proc.subframe_rx,sect_id,UE_index); + msg("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",eNB->Mod_id,proc->subframe_rx,sect_id,UE_index); eNB->pusch_vars[UE_index]->ulsch_power[0] = 31622; //=45dB; eNB->pusch_vars[UE_index]->ulsch_power[1] = 31622; //=45dB; } -void dump_ulsch(PHY_VARS_eNB *eNB,uint8_t UE_id) + void dump_ulsch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id) { - + uint32_t nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; uint8_t harq_pid; - int subframe = eNB->proc.subframe_rx; + int subframe = proc->subframe_rx; - harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc.frame_rx,subframe); + harq_pid = subframe2harq_pid(&eNB->frame_parms,proc->frame_rx,subframe); printf("Dumping ULSCH in subframe %d with harq_pid %d, for NB_rb %d, mcs %d, Qm %d, N_symb %d\n", subframe,harq_pid,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,get_Qm_ul(eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs), diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 28c407b088..8af3fcf8d1 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -183,7 +183,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, float time[FRAME_LENGTH_COMPLEX_SAMPLES]; float time2[2048]; float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; - int frame = phy_vars_enb->proc.frame_tx; + int frame = phy_vars_enb->proc.proc_rxtx[0].frame_tx; uint32_t total_dlsch_bitrate = phy_vars_enb->total_dlsch_bitrate; int coded_bits_per_codeword = 0; uint8_t harq_pid; // in TDD config 3 it is sf-2, i.e., can be 0,1,2 diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index e18c0b1d91..89fc1cd7ed 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -178,6 +178,34 @@ typedef struct ral_threshold_phy_s { } ral_threshold_phy_t; #endif +/// Context data structure for RX/TX portion of subframe processing +typedef struct { + /// Component Carrier index + uint8_t CC_id; + /// timestamp transmitted to HW + openair0_timestamp timestamp_tx; + /// subframe to act upon for transmission + int subframe_tx; + /// subframe to act upon for reception + int subframe_rx; + /// frame to act upon for transmission + int frame_tx; + /// frame to act upon for reception + int frame_rx; + /// \brief Instance count for RXn-TXnp4 processing thread. + /// \internal This variable is protected by \ref mutex_rxtx. + int instance_cnt_rxtx; + /// pthread structure for RXn-TXnp4 processing thread + pthread_t pthread_rxtx; + /// pthread attributes for RXn-TXnp4 processing thread + pthread_attr_t attr_rxtx; + /// condition variable for tx processing thread + pthread_cond_t cond_rxtx; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex_rxtx; + /// scheduling parameters for RXn-TXnp4 thread + struct sched_param sched_param_rxtx; +} eNB_rxtx_proc_t; /// Context data structure for eNB subframe processing typedef struct { /// Component Carrier index @@ -186,54 +214,37 @@ typedef struct { int thread_index; /// timestamp received from HW openair0_timestamp timestamp_rx; - /// timestamp transmitted to HW - openair0_timestamp timestamp_tx; - /// subframe to act upon for transmission - int subframe_tx; /// subframe to act upon for reception int subframe_rx; /// subframe to act upon for PRACH int subframe_prach; - /// frame to act upon for transmission - int frame_tx; /// frame to act upon for reception int frame_rx; /// frame to act upon for PRACH int frame_prach; - /// \brief Instance count for tx processing thread. - /// \internal This variable is protected by \ref mutex_tx. - int instance_cnt_tx; /// \brief Instance count for rx processing thread. /// \internal This variable is protected by \ref mutex_prach. int instance_cnt_prach; - /// pthread structure for tx processing thread - pthread_t pthread_tx; /// pthread structure for rx processing thread pthread_t pthread_rx; /// flag to indicate first RX acquisition int first_rx; - /// pthread attributes for tx processing thread - pthread_attr_t attr_tx; /// pthread attributes for rx processing thread pthread_attr_t attr_rx; /// pthread attributes for prach processing thread pthread_attr_t attr_prach; - /// scheduling parameters for tx thread - struct sched_param sched_param_tx; /// scheduling parameters for rx thread struct sched_param sched_param_rx; /// scheduling parameters for prach thread struct sched_param sched_param_prach; - /// condition variable for tx processing thread - pthread_t pthread_prach; /// condition variable for prach processing thread - pthread_cond_t cond_tx; + pthread_t pthread_prach; /// condition variable for rx processing thread; pthread_cond_t cond_prach; /// mutex for tx processing thread - pthread_mutex_t mutex_tx; - /// mutex for tx processing thread pthread_mutex_t mutex_prach; + /// set of scheduling variables RXn-TXnp4 threads + eNB_rxtx_proc_t proc_rxtx[2]; } eNB_proc_t; //! \brief Number of eNB TX and RX threads. diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index 2174684126..62e0a7d9ce 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -226,17 +226,19 @@ void phy_procedures_UE_S_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abst @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param phy_vars_rn pointer to the RN variables */ -void phy_procedures_eNB_TX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); +void phy_procedures_eNB_TX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); /*! \brief Scheduling for eNB RX UE-specific procedures in normal subframes. @param phy_vars_eNB Pointer to eNB variables on which to act + @param proc Pointer to RXn-TXnp4 proc information @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for eNB TX procedures in TDD S-subframes. @param phy_vars_eNB Pointer to eNB variables on which to act + @param proc Pointer to RXn-TXnp4 proc information @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ @@ -260,10 +262,11 @@ void phy_procedures_eNB_S_TX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type); /*! \brief Scheduling for eNB PRACH RX procedures @param phy_vars_eNB Pointer to eNB variables on which to act + @param proc Pointer to RXn-TXnp4 proc information @param abstraction_flag Indicator of PHY abstraction */ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag); @@ -393,10 +396,11 @@ uint8_t is_SR_TXOp(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); @param UE_id ID of UE which may be issuing the SR @returns 1 if TXOp is active. */ -uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id); +uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id); /*! \brief Gives the UL subframe corresponding to a PDDCH order in subframe n @param frame_parms Pointer to DL frame parameters + @param proc Pointer to RXn-TXnp4 proc information @param n subframe of PDCCH @returns UL subframe corresponding to pdcch order */ @@ -447,7 +451,8 @@ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, /*! \brief This function retrives the resource (n1_pucch) corresponding to a PDSCH transmission in subframe n-4 which is acknowledged in subframe n (for FDD) according to n1_pucch = Ncce + N1_pucch. For TDD, this routine computes the procedure described in Section 10.1 of 36.213 (through tables 10.1-1,10.1-2) -@param phy_vars_eNB Pointer to UE variables +@param phy_vars_eNB Pointer to eNB variables +@param proc Pointer to RXn-TXnp4 proc information @param eNB_id Index of eNB @param subframe Index of subframe @param b Pointer to PUCCH payload (b[0],b[1]) @@ -457,6 +462,7 @@ TDD, this routine computes the procedure described in Section 10.1 of 36.213 (th @param n1_pucch3 Pointer to n1_pucch3 */ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, + eNB_rxtx_proc_t *proc, uint8_t UE_id, int16_t *n1_pucch0, int16_t *n1_pucch1, @@ -467,6 +473,7 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, /*! \brief This function retrieves the harq_pid of the corresponding DLSCH process and updates the error statistics of the DLSCH based on the received ACK info from UE along with the round index. It also performs the fine-grain rate-adaptation based on the error statistics derived from the ACK/NAK process. @param UE_id Local UE index on which to act @param phy_vars_eNB Pointer to eNB variables on which to act + @param proc Pointer to RXn-TXnp4 proc information @param pusch_flag Indication that feedback came from PUSCH @param pucch_payload Resulting payload from pucch @param pucch_sel Selection of n1_pucch0 or n1_pucch1 (TDD specific) @@ -474,6 +481,7 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *phy_vars_eNB, */ void process_HARQ_feedback(uint8_t UE_id, PHY_VARS_eNB *phy_vars_eNB, + eNB_rxtx_proc_t *proc, uint8_t pusch_flag, uint8_t *pucch_payload, uint8_t pucch_sel, diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c index 564a7951c6..b7f2e57f7c 100644 --- a/openair1/SCHED/phy_mac_stub.c +++ b/openair1/SCHED/phy_mac_stub.c @@ -48,7 +48,7 @@ #include "SCHED/phy_procedures_emos.h" #endif -void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) +void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { @@ -57,7 +57,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) uint32_t rballoc = 0x7FFF; //uint32_t rballoc2 = 0x000F; - int subframe = eNB->proc.subframe_tx; + int subframe = proc->subframe_tx; LTE_eNB_DLSCH_t *DLSCH_ptr = eNB->dlsch[0][0]; @@ -89,7 +89,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_1_5MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -100,7 +100,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_1_5MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -117,7 +117,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_5MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -128,7 +128,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_5MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -144,7 +144,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_10MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -155,7 +155,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; @@ -171,7 +171,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->type = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rv = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->mcs = 1; ((DCI1A_20MHz_FDD_t*)&bcch_pdu)->harq_pid = 0; @@ -182,7 +182,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->type = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3); - ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->ndi = proc->frame_tx&1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1; ((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->harq_pid = 0; @@ -236,7 +236,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -267,7 +267,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1; ((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -303,7 +303,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1; ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t)); @@ -334,7 +334,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1; ((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t)); @@ -369,7 +369,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1; ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t)); @@ -400,7 +400,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs; //((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28); - ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = eNB->proc.frame_tx&1; + ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1; ((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rv = 0; memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_20MHz_TDD_t)); @@ -437,10 +437,10 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tpmi = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv1 = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi1 = eNB->proc.frame_tx&1; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi1 = proc->frame_tx&1; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs1 = eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->rv2 = 0; - ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi2 = eNB->proc.frame_tx&1; + ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->ndi2 = proc->frame_tx&1; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->mcs2 = eNB->target_ue_dl_mcs; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->tb_swap = 0; ((DCI2_5MHz_2A_FDD_t*) (&DCI_pdu->dci_alloc[0].dci_pdu))->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]; @@ -459,7 +459,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback DLSCH_alloc_pdu1E.rv = 0; - DLSCH_alloc_pdu1E.ndi = eNB->proc.frame_tx&1; + DLSCH_alloc_pdu1E.ndi = proc->frame_tx&1; //DLSCH_alloc_pdu1E.mcs = cqi_to_mcs[eNB->eNB_UE_stats->DL_cqi[0]]; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); DLSCH_alloc_pdu1E.mcs = eNB->target_ue_dl_mcs; @@ -482,7 +482,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) //DLSCH_alloc_pdu1E.mcs = eNB->target_ue_dl_mcs; //DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28); //DLSCH_alloc_pdu1E.mcs = (unsigned char) ((eNB->frame%1024)%28); - DLSCH_alloc_pdu1E.mcs = (unsigned char) (((eNB->proc.frame_tx%1024)/3)%28); + DLSCH_alloc_pdu1E.mcs = (unsigned char) (((proc->frame_tx%1024)/3)%28); eNB->UE_stats[1].dlsch_mcs1 = DLSCH_alloc_pdu1E.mcs; memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t)); @@ -533,7 +533,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) UL_alloc_pdu.hopping = 0; UL_alloc_pdu.rballoc = computeRIV(25,2,eNB->ue_ul_nb_rb); UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; - UL_alloc_pdu.ndi = eNB->proc.frame_tx&1; + UL_alloc_pdu.ndi = proc->frame_tx&1; UL_alloc_pdu.TPC = 0; UL_alloc_pdu.cshift = 0; UL_alloc_pdu.dai = 0; @@ -555,7 +555,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB) else UL_alloc_pdu.rballoc = computeRIV(25,0,eNB->ue_ul_nb_rb); UL_alloc_pdu.mcs = eNB->target_ue_ul_mcs; - UL_alloc_pdu.ndi = eNB->proc.frame_tx&1; + UL_alloc_pdu.ndi = proc->frame_tx&1; UL_alloc_pdu.TPC = 0; if ((cooperation_flag==0) || (cooperation_flag==1)) UL_alloc_pdu.cshift = 0; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index cfcec35460..9d43f21106 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -101,10 +101,9 @@ extern uint8_t smbv_frame_cnt; extern int rx_sig_fifo; #endif -uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,uint8_t UE_id) +uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id) { - eNB_proc_t *proc = &eNB->proc; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; @@ -339,10 +338,9 @@ void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB) -void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,uint8_t abstraction_flag,relaying_type_t r_type) +void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type) { UNUSED(r_type); - eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; #ifdef DEBUG_PHY_PROC @@ -435,14 +433,13 @@ int QPSK2[4]= {AMP_OVER_2|(AMP_OVER_2<<16),AMP_OVER_2|((65536-AMP_OVER_2)<<16),( unsigned int taus(void); -void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) { +void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) { #ifdef Rel10 MCH_PDU *mch_pduP; MCH_PDU mch_pdu; // uint8_t sync_area=255; #endif - eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_tx; if (abstraction_flag==0) { @@ -508,7 +505,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int abstraction_flag,rel if (mch_pduP) { fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0, abstraction_flag); // Generate PMCH - generate_mch(eNB,(uint8_t*)mch_pduP->payload,abstraction_flag); + generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload,abstraction_flag); } else { LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe); } @@ -516,12 +513,11 @@ void pmch_procedures(PHY_VARS_eNB *eNB,PHY_VARS_RN *rn, int abstraction_flag,rel #endif } -void common_signal_procedures (PHY_VARS_eNB *eNB,int abstraction_flag) { +void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstraction_flag) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int **txdataF = eNB->common_vars.txdataF[0]; uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; - eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_tx; int frame = proc->frame_tx; @@ -703,10 +699,9 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,int abstraction_flag) { } -void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { +void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,const int UE_id) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - eNB_proc_t *proc = &eNB->proc; int frame = proc->frame_tx; int subframe = proc->subframe_tx; @@ -839,11 +834,10 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const in } -void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const int UE_id) { +void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,const int UE_id) { int harq_pid; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - eNB_proc_t *proc = &eNB->proc; int frame = proc->frame_tx; int subframe = proc->subframe_tx; @@ -862,6 +856,7 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const in 1<L); generate_eNB_ulsch_params_from_dci(eNB, + proc, &dci_alloc->dci_pdu[0], dci_alloc->rnti, format0, @@ -904,9 +899,8 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,DCI_ALLOC_t *dci_alloc,const in } -void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols,int abstraction_flag) { +void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols,int abstraction_flag) { - eNB_proc_t *proc = &eNB->proc; int frame=proc->frame_tx; int subframe=proc->subframe_tx; int harq_pid = dlsch->current_harq_pid; @@ -1112,12 +1106,12 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t } void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, uint8_t abstraction_flag, relaying_type_t r_type, PHY_VARS_RN *rn) { UNUSED(rn); - eNB_proc_t *proc = &eNB->proc; int frame=proc->frame_tx; int subframe=proc->subframe_tx; // uint16_t input_buffer_length; @@ -1177,11 +1171,11 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, } if (is_pmch_subframe(frame,subframe,fp)) { - pmch_procedures(eNB,rn,abstraction_flag,r_type); + pmch_procedures(eNB,proc,rn,abstraction_flag,r_type); } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH - common_signal_procedures(eNB,abstraction_flag); + common_signal_procedures(eNB,proc,abstraction_flag); } #if defined(SMBV) @@ -1207,7 +1201,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #ifdef EMOS_CHANNEL fill_dci_emos(DCI_pdu,eNB); #else - fill_dci(DCI_pdu,eNB); + fill_dci(DCI_pdu,eNB,proc); #endif } @@ -1265,7 +1259,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, } else UE_id=0; - generate_eNB_dlsch_params(eNB,dci_alloc,UE_id); + generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id); } @@ -1287,7 +1281,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti); mac_xface->macphy_exit("FATAL\n"); } - generate_eNB_ulsch_params(eNB,dci_alloc,UE_id); + generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id); } } @@ -1335,7 +1329,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if (eNB->dlsch_SI->active == 1) { - pdsch_procedures(eNB,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols,abstraction_flag); #if defined(SMBV) @@ -1368,7 +1362,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); - pdsch_procedures(eNB,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols,abstraction_flag); eNB->dlsch_ra->active = 0; @@ -1381,7 +1375,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&& (eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) { - pdsch_procedures(eNB,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols,abstraction_flag); } @@ -1402,6 +1396,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if (is_phich_subframe(fp,subframe)) { generate_phich_top(eNB, + proc, AMP, 0, abstraction_flag); @@ -1437,10 +1432,9 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, } -void process_Msg3(PHY_VARS_eNB *eNB,uint8_t UE_id, uint8_t harq_pid) +void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid) { // this prepares the demodulation of the first PUSCH of a new user, containing Msg3 - eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; @@ -1475,13 +1469,13 @@ void process_Msg3(PHY_VARS_eNB *eNB,uint8_t UE_id, uint8_t harq_pid) void process_HARQ_feedback(uint8_t UE_id, PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, uint8_t pusch_flag, uint8_t *pucch_payload, uint8_t pucch_sel, uint8_t SR_payload) { - eNB_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe; LTE_eNB_DLSCH_t *dlsch = eNB->dlsch[(uint32_t)UE_id][0]; @@ -1745,6 +1739,7 @@ void process_HARQ_feedback(uint8_t UE_id, } void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, uint8_t UE_id, int16_t *n1_pucch0, int16_t *n1_pucch1, @@ -1752,7 +1747,6 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, int16_t *n1_pucch3) { - eNB_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms; uint8_t nCCE0,nCCE1; int sf; @@ -1892,9 +1886,8 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) uint16_t preamble_max,preamble_energy_max; uint16_t i; int8_t UE_id; - eNB_proc_t *proc = &eNB->proc; - int subframe = proc->subframe_rx; - int frame = proc->frame_rx; + int subframe = eNB->proc.subframe_prach; + int frame = eNB->proc.frame_prach; uint8_t CC_id = eNB->CC_id; memset(&preamble_energy_list[0],0,64*sizeof(uint16_t)); @@ -2002,7 +1995,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) } } -void pucch_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0}; @@ -2012,7 +2005,6 @@ void pucch_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abs int32_t metric0=0,metric1=0,metric0_SR=0; ANFBmode_t bundling_flag; PUCCH_FMT_t format; - eNB_proc_t *proc = &eNB->proc; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; @@ -2021,159 +2013,160 @@ void pucch_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abs (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { // check SR availability - do_SR = is_SR_subframe(eNB,UE_id); - // do_SR = 0; - + do_SR = is_SR_subframe(eNB,proc,UE_id); + // do_SR = 0; + // Now ACK/NAK // First check subframe_tx flag for earlier subframes - get_n1_pucch_eNB(eNB, - UE_id, - &n1_pucch0, - &n1_pucch1, - &n1_pucch2, - &n1_pucch3); + get_n1_pucch_eNB(eNB, + proc, + UE_id, + &n1_pucch0, + &n1_pucch1, + &n1_pucch2, + &n1_pucch3); + + LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n", + eNB->Mod_id,eNB->dlsch[UE_id][0]->rnti, + frame,subframe, + n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR); + + if ((n1_pucch0==-1) && (n1_pucch1==-1) && (do_SR==0)) { // no TX PDSCH that have to be checked and no SR for this UE_id + } else { + // otherwise we have some PUCCH detection to do + + // Null out PUCCH PRBs for noise measurement + switch(fp->N_RB_UL) { + case 6: + eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5 + break; + case 15: + eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14 + break; + case 25: + eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24 + break; + case 50: + eNB->rb_mask_ul[0] |= 0x1; + eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32) + break; + case 75: + eNB->rb_mask_ul[0] |= 0x1; + eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64) + break; + case 100: + eNB->rb_mask_ul[0] |= 0x1; + eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96) + break; + default: + LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL); + break; + } + + if (do_SR == 1) { + eNB->UE_stats[UE_id].sr_total++; - LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n", - eNB->Mod_id,eNB->dlsch[UE_id][0]->rnti, - frame,subframe, - n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR); - - if ((n1_pucch0==-1) && (n1_pucch1==-1) && (do_SR==0)) { // no TX PDSCH that have to be checked and no SR for this UE_id - } else { - // otherwise we have some PUCCH detection to do - - // Null out PUCCH PRBs for noise measurement - switch(fp->N_RB_UL) { - case 6: - eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5 - break; - case 15: - eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14 - break; - case 25: - eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24 - break; - case 50: - eNB->rb_mask_ul[0] |= 0x1; - eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32) - break; - case 75: - eNB->rb_mask_ul[0] |= 0x1; - eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64) - break; - case 100: - eNB->rb_mask_ul[0] |= 0x1; - eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96) - break; - default: - LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL); - break; + if (abstraction_flag == 0) + metric0_SR = rx_pucch(eNB, + pucch_format1, + UE_id, + eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, + 0, // n2_pucch + 0, // shortened format, should be use_srs flag, later + &SR_payload, + subframe, + PUCCH1_THRES); + +#ifdef PHY_ABSTRACTION + else { + metric0_SR = rx_pucch_emul(eNB, + UE_id, + pucch_format1, + 0, + &SR_payload); + LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",eNB->Mod_id, + eNB->ulsch[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); } - - if (do_SR == 1) { - eNB->UE_stats[UE_id].sr_total++; - - if (abstraction_flag == 0) - metric0_SR = rx_pucch(eNB, - pucch_format1, - UE_id, - eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, - 0, // n2_pucch - 0, // shortened format, should be use_srs flag, later - &SR_payload, - subframe, - PUCCH1_THRES); - -#ifdef PHY_ABSTRACTION - else { - metric0_SR = rx_pucch_emul(eNB, - UE_id, - pucch_format1, - 0, - &SR_payload); - LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",eNB->Mod_id, - eNB->ulsch[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex); - } - + #endif - - if (SR_payload == 1) { - LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id, - eNB->ulsch[UE_id]->rnti,frame,subframe); - eNB->UE_stats[UE_id].sr_received++; - - if (eNB->first_sr[UE_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4 - /* is this test necessary? */ - if (eNB->dlsch[UE_id][0]->harq_processes[0]->status != SCH_IDLE) - put_harq_pid_in_freelist(eNB->dlsch[UE_id][0], 0); - eNB->first_sr[UE_id] = 0; - eNB->dlsch[UE_id][0]->harq_processes[0]->round=0; - eNB->dlsch[UE_id][0]->harq_processes[0]->status=SCH_IDLE; - LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n", - eNB->Mod_id, - eNB->ulsch[UE_id]->rnti,frame,subframe); - } - - if (eNB->mac_enabled==1) { - mac_xface->SR_indication(eNB->Mod_id, - eNB->CC_id, - frame, - eNB->dlsch[UE_id][0]->rnti,subframe); - } - } - }// do_SR==1 - - if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR - } else if (fp->frame_type==FDD) { // FDD - // if SR was detected, use the n1_pucch from SR, else use n1_pucch0 - // n1_pucch0 = (SR_payload==1) ? eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0; - - LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload); - - if (abstraction_flag == 0) { - - - - metric0 = rx_pucch(eNB, - pucch_format1a, - UE_id, - (uint16_t)n1_pucch0, - 0, //n2_pucch - 0, // shortened format - pucch_payload0, - subframe, - PUCCH1a_THRES); - - if (metric0 < metric0_SR) - metric0=rx_pucch(eNB, - pucch_format1a, - UE_id, - eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, - 0, //n2_pucch - 0, // shortened format - pucch_payload0, - subframe, - PUCCH1a_THRES); + + if (SR_payload == 1) { + LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id, + eNB->ulsch[UE_id]->rnti,frame,subframe); + eNB->UE_stats[UE_id].sr_received++; + + if (eNB->first_sr[UE_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4 + /* is this test necessary? */ + if (eNB->dlsch[UE_id][0]->harq_processes[0]->status != SCH_IDLE) + put_harq_pid_in_freelist(eNB->dlsch[UE_id][0], 0); + eNB->first_sr[UE_id] = 0; + eNB->dlsch[UE_id][0]->harq_processes[0]->round=0; + eNB->dlsch[UE_id][0]->harq_processes[0]->status=SCH_IDLE; + LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n", + eNB->Mod_id, + eNB->ulsch[UE_id]->rnti,frame,subframe); } - else { + + if (eNB->mac_enabled==1) { + mac_xface->SR_indication(eNB->Mod_id, + eNB->CC_id, + frame, + eNB->dlsch[UE_id][0]->rnti,subframe); + } + } + }// do_SR==1 + + if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR + } else if (fp->frame_type==FDD) { // FDD + // if SR was detected, use the n1_pucch from SR, else use n1_pucch0 + // n1_pucch0 = (SR_payload==1) ? eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0; + + LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload); + + if (abstraction_flag == 0) { + + + + metric0 = rx_pucch(eNB, + pucch_format1a, + UE_id, + (uint16_t)n1_pucch0, + 0, //n2_pucch + 0, // shortened format + pucch_payload0, + subframe, + PUCCH1a_THRES); + + if (metric0 < metric0_SR) + metric0=rx_pucch(eNB, + pucch_format1a, + UE_id, + eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex, + 0, //n2_pucch + 0, // shortened format + pucch_payload0, + subframe, + PUCCH1a_THRES); + } + else { #ifdef PHY_ABSTRACTION - metric0 = rx_pucch_emul(eNB,UE_id, - pucch_format1a, - 0, - pucch_payload0, - subframe); + metric0 = rx_pucch_emul(eNB,UE_id, + pucch_format1a, + 0, + pucch_payload0, + subframe); #endif - } - + } + #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n", - eNB->Mod_id, - eNB->dlsch[UE_id][0]->rnti, - frame,subframe, - pucch_payload0[0],metric0); + LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n", + eNB->Mod_id, + eNB->dlsch[UE_id][0]->rnti, + frame,subframe, + pucch_payload0[0],metric0); #endif - - process_HARQ_feedback(UE_id,eNB, + + process_HARQ_feedback(UE_id,eNB,proc, 0,// pusch_flag pucch_payload0, 2, @@ -2304,7 +2297,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abs frame,subframe, metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]); #endif - process_HARQ_feedback(UE_id,eNB, + process_HARQ_feedback(UE_id,eNB,proc, 0,// pusch_flag pucch_payload, pucch_sel, @@ -2315,9 +2308,8 @@ void pucch_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abs } } -void cba_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) { - eNB_proc_t *proc = &eNB->proc; uint8_t access_mode; int num_active_cba_groups; const int subframe = proc->subframe_rx; @@ -2342,7 +2334,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstr #endif if (abstraction_flag==0) { - rx_ulsch(eNB, + rx_ulsch(eNB,proc, eNB->UE_stats[UE_id].sector, // this is the effective sector id UE_id, eNB->ulsch, @@ -2351,7 +2343,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstr #ifdef PHY_ABSTRACTION else { - rx_ulsch_emul(eNB, + rx_ulsch_emul(eNB,proc, subframe, eNB->UE_stats[UE_id].sector, // this is the effective sector id UE_id); @@ -2360,7 +2352,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstr #endif if (abstraction_flag == 0) { - ret = ulsch_decoding(eNB, + ret = ulsch_decoding(eNB,proc, UE_id, 0, // control_only_flag eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI, @@ -2479,11 +2471,11 @@ void cba_procedures(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,const uint8_t abstr void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { - eNB_proc_t *proc = &eNB->proc; int i,l; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; void *rxp[fp->nb_antennas_rx]; unsigned int rxs; + eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; @@ -2617,11 +2609,10 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } } -void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag,const relaying_type_t r_type) +void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const uint8_t abstraction_flag,const relaying_type_t r_type) { //RX processing for ue-specific resources (i UNUSED(r_type); - eNB_proc_t *proc = &eNB->proc; uint32_t l, ret=0,i,j,k; uint32_t harq_pid, harq_idx, round; uint8_t nPRS; @@ -2683,7 +2674,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl // Do PUCCH processing first for (i=0; imac_enabled==1) { if (eNB->UE_stats[i].mode == RA_RESPONSE) { - process_Msg3(eNB,i,harq_pid); + process_Msg3(eNB,proc,i,harq_pid); } } @@ -2772,7 +2763,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl start_meas(&eNB->ulsch_demodulation_stats); if (abstraction_flag==0) { - rx_ulsch(eNB, + rx_ulsch(eNB,proc, eNB->UE_stats[i].sector, // this is the effective sector id i, eNB->ulsch, @@ -2781,7 +2772,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl #ifdef PHY_ABSTRACTION else { - rx_ulsch_emul(eNB, + rx_ulsch_emul(eNB,proc, subframe, eNB->UE_stats[i].sector, // this is the effective sector id i); @@ -2794,7 +2785,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl start_meas(&eNB->ulsch_decoding_stats); if (abstraction_flag == 0) { - ret = ulsch_decoding(eNB, + ret = ulsch_decoding(eNB,proc, i, 0, // control_only_flag eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI, @@ -2803,7 +2794,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl #ifdef PHY_ABSTRACTION else { - ret = ulsch_decoding_emul(eNB, + ret = ulsch_decoding_emul(eNB,proc, i, &rnti); } @@ -3120,7 +3111,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl i); #endif process_HARQ_feedback(i, - eNB, + eNB,proc, 1, // pusch_flag 0, 0, @@ -3183,7 +3174,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } // CBA (non-LTE) - cba_procedures(eNB,i,harq_pid,abstraction_flag); + cba_procedures(eNB,proc,i,harq_pid,abstraction_flag); } // loop i=0 ... NUMBER_OF_UE_MAX-1 if (abstraction_flag == 0) { diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index 7a2a747741..b6b223bd6a 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -786,7 +786,7 @@ rrc_get_estimated_ue_distance( const int CC_idP, const uint8_t loc_typeP); -void fill_dci(DCI_PDU *DCI_pdu, PHY_VARS_eNB *phy_vars_eNB); +void fill_dci(DCI_PDU *DCI_pdu, PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc); #endif /** @}*/ diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 9e855696c4..3f8ddd89ef 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -183,26 +183,10 @@ const char* eurecomFunctionsNames[] = { "rt_sleep", "trx_read", "trx_write", - "eNB_thread_tx0", - "eNB_thread_rx0", - "eNB_thread_tx1", - "eNB_thread_rx1", - "eNB_thread_tx2", - "eNB_thread_rx2", - "eNB_thread_tx3", - "eNB_thread_rx3", - "eNB_thread_tx4", - "eNB_thread_rx4", - "eNB_thread_tx5", - "eNB_thread_rx5", - "eNB_thread_tx6", - "eNB_thread_rx6", - "eNB_thread_tx7", - "eNB_thread_rx7", - "eNB_thread_tx8", - "eNB_thread_rx8", - "eNB_thread_tx9", - "eNB_thread_rx9", + "eNB_thread_rxtx0", + "eNB_thread_rxtx1", + "eNB_thread_rx", + "eNB_thread_prach", "ue_thread_tx", "ue_thread_rx", diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index 192bebd976..11401f17af 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -157,26 +157,10 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP=0, VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX1, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX1, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX2, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX2, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX3, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX3, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX4, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX4, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX5, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX5, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX6, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX6, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX7, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX7, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX8, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX8, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX9, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX9, + VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0, + VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX1, + VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, + VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_PRACH, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 6290953e8b..daeca00f42 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -139,7 +139,7 @@ extern int sync_var; time_stats_t softmodem_stats_mt; // main thread time_stats_t softmodem_stats_hw; // hw acquisition -time_stats_t softmodem_stats_tx_sf; // total tx time +time_stats_t softmodem_stats_rxtx_sf; // total tx time time_stats_t softmodem_stats_rx_sf; // total rx time int32_t **rxdata; int32_t **txdata; @@ -290,16 +290,15 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) } /*! - * \brief The transmit thread of eNB. - * \ref NUM_ENB_THREADS threads of this type are active at the same time. + * \brief The RX UE-specific and TX thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_tx( void* param ) +static void* eNB_thread_rxtx( void* param ) { - static int eNB_thread_tx_status; + static int eNB_thread_rxtx_status; - eNB_proc_t *proc = (eNB_proc_t*)param; + eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param; FILE *tx_time_file = NULL; char tx_time_name[101]; void *txp[PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx]; @@ -309,7 +308,7 @@ static void* eNB_thread_tx( void* param ) tx_time_file = fopen(tx_time_name,"w"); } // set default return value - eNB_thread_tx_status = 0; + eNB_thread_rxtx_status = 0; MSC_START_USE(); @@ -332,10 +331,10 @@ static void* eNB_thread_tx( void* param ) if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB tx thread: sched_setattr failed\n"); - return &eNB_thread_tx_status; + return &eNB_thread_rxtx_status; } - LOG_I( HW, "[SCHED] eNB TX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); #else //LOW_LATENCY int policy, s, j; @@ -414,31 +413,40 @@ static void* eNB_thread_tx( void* param ) while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX\n"); + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RXn-TXnp4\n"); exit_fun("nothing to add"); break; } - while (proc->instance_cnt_tx < 0) { + while (proc->instance_cnt_rxtx < 0) { // most of the time the thread is waiting here - // proc->instance_cnt_tx is -1 - pthread_cond_wait( &proc->cond_tx, &proc->mutex_tx ); // this unlocks mutex_tx while waiting and then locks it again + // proc->instance_cnt_rxtx is -1 + pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); // this unlocks mutex_rxtx while waiting and then locks it again } - if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { + if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX\n"); exit_fun("nothing to add"); break; } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0, 1 ); - start_meas( &softmodem_stats_tx_sf ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); + start_meas( &softmodem_stats_rxtx_sf ); if (oai_exit) break; + // UE-specific RX processing for subframe n + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); + // this is the ue-specific processing for the subframe and can be multi-threaded later + phy_procedures_eNB_uespec_RX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); + } + + // TX processing for subframe n+4 if (((PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.frame_type == TDD) && ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_DL) || (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_S))) || @@ -470,7 +478,7 @@ static void* eNB_thread_tx( void* param ) if (oai_exit) break; if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { - phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); + phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay, NULL ); /* we're done, let the next one proceed */ if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { @@ -531,42 +539,42 @@ static void* eNB_thread_tx( void* param ) } - if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n"); exit_fun("nothing to add"); break; } - proc->instance_cnt_tx--; + proc->instance_cnt_rxtx--; - if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { + if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc\n"); exit_fun("nothing to add"); break; } - stop_meas( &softmodem_stats_tx_sf ); + stop_meas( &softmodem_stats_rxtx_sf ); #ifdef LOWLATENCY if (opp_enabled){ - if(softmodem_stats_tx_sf.diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_tx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); + if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); } } #endif - print_meas_now(&softmodem_stats_tx_sf,"eNB_TX_SF",tx_time_file); + print_meas_now(&softmodem_stats_rxtx_sf,"eNB_TX_SF",tx_time_file); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); #ifdef DEBUG_THREADS printf( "Exiting eNB thread TX\n"); #endif - eNB_thread_tx_status = 0; - return &eNB_thread_tx_status; + eNB_thread_rxtx_status = 0; + return &eNB_thread_rxtx_status; } #if defined(ENABLE_ITTI) @@ -592,12 +600,11 @@ static void wait_system_ready (char *message, volatile int *start_flag) #endif /*! - * \brief The receive thread of eNB. - * \ref NUM_ENB_THREADS threads of this type are active at the same time. + * \brief The RX common thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_rx( void* param ) +static void* eNB_thread_rx_common( void* param ) { static int eNB_thread_rx_status; @@ -721,7 +728,7 @@ static void* eNB_thread_rx( void* param ) // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe of TX and RX threads - printf( "waiting for sync (eNB_thread_rx)\n"); + printf( "waiting for sync (eNB_thread_rx_common)\n"); pthread_mutex_lock( &sync_mutex ); while (sync_var<0) @@ -739,7 +746,7 @@ static void* eNB_thread_rx( void* param ) while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); start_meas( &softmodem_stats_rx_sf ); @@ -753,67 +760,63 @@ static void* eNB_thread_rx( void* param ) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); - if (eNB->node_function != NGFI_RRU_IF4) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); - // this is the ue-specific processing for the subframe and can be multi-threaded later - phy_procedures_eNB_uespec_RX(eNB, 0, no_relay ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); - } } + // choose even or odd thread for RXn-TXnp4 processing + eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[proc->subframe_rx&1]; + // wake up TX for subframe n+4 // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_lock(&proc->mutex_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc->instance_cnt_tx ); - exit_fun( "error locking mutex_tx" ); + if (pthread_mutex_lock(&proc_rxtx->mutex_rxtx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc_rxtx->instance_cnt_rxtx ); + exit_fun( "error locking mutex_rxtx" ); break; } - int cnt_tx = ++proc->instance_cnt_tx; + int cnt_rxtx = ++proc_rxtx->instance_cnt_rxtx; // We have just received and processed the common part of a subframe, say n. // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, + // The last (TS_rx mod samples_pexr_frame) was n*samples_per_tti, // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, // and proc->subframe_tx = proc->subframe_rx+3 - proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); - proc->frame_tx = (proc->subframe_rx > 5) ? (proc->frame_rx+1)&1023 : proc->frame_rx; - proc->subframe_tx = (proc->subframe_rx + 4)%10; + proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); + proc_rxtx->frame_rx = proc->frame_rx; + proc_rxtx->subframe_rx = proc->subframe_rx; + proc_rxtx->frame_tx = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx; + proc_rxtx->subframe_tx = (proc_rxtx->subframe_rx + 4)%10; - pthread_mutex_unlock( &proc->mutex_tx ); + pthread_mutex_unlock( &proc_rxtx->mutex_rxtx ); - if (cnt_tx == 0){ + if (cnt_rxtx == 0){ // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_tx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TX thread\n"); + if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); exit_fun( "ERROR pthread_cond_signal" ); break; } } else { - LOG_W( PHY,"[eNB] Frame %d, eNB TX thread busy!! (cnt_tx %i)\n", proc->frame_tx, cnt_tx ); + LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, cnt_rxtx ); exit_fun( "TX thread busy" ); break; } - stop_meas( &softmodem_stats_rx_sf ); + stop_meas( &softmodem_stats_rxtx_sf ); #ifdef LOWLATENCY if (opp_enabled){ - if(softmodem_stats_rx_sf.diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, (softmodem_stats_rx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); + if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); } } #endif // LOWLATENCY print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); } - //stop_meas( &softmodem_stats_rx_sf[proc->thread_index] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0, 0 ); - #ifdef DEBUG_THREADS - printf( "Exiting eNB thread RX\n"); + printf( "Exiting eNB thread RXn-TXnp4\n"); #endif eNB_thread_rx_status = 0; @@ -954,8 +957,8 @@ static void* eNB_thread_prach( void* param ) while (proc->instance_cnt_prach < 0) { // most of the time the thread is waiting here - // proc->instance_cnt_tx is -1 - pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_tx while waiting and then locks it again + // proc->instance_cnt_prach is -1 + pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_rxtx while waiting and then locks it again } if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { @@ -1000,13 +1003,14 @@ void init_eNB_proc(void) int CC_id; PHY_VARS_eNB *eNB; eNB_proc_t *proc; + eNB_rxtx_proc_t *proc_rxtx; for (CC_id=0; CC_idproc; - + proc_rxtx = proc->proc_rxtx; #ifndef LOWLATENCY /* pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); @@ -1018,9 +1022,12 @@ void init_eNB_proc(void) perror("[ENB_PROC_RX] setting thread stack size failed\n"); */ // set the kernel scheduling policy and priority - proc->sched_param_tx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_tx, &proc->sched_param_tx); - pthread_attr_setschedpolicy (&proc->attr_tx, SCHED_FIFO); + proc_rxtx[0].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc_rxtx[0].attr_rxtx, &proc_rxtx[0].sched_param_rxtx); + pthread_attr_setschedpolicy (&proc_rxtx[0].attr_rxtx, SCHED_FIFO); + proc_rxtx[1].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); + pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; pthread_attr_setschedparam (&proc->attr_rx, &proc->sched_param_rx); @@ -1032,27 +1039,35 @@ void init_eNB_proc(void) printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); #endif - proc->instance_cnt_tx = -1; + proc_rxtx[0].instance_cnt_rxtx = -1; + proc_rxtx[1].instance_cnt_rxtx = -1; proc->instance_cnt_prach = -1; proc->CC_id = CC_id; proc->first_rx=1; - pthread_mutex_init( &proc->mutex_tx, NULL); - pthread_cond_init( &proc->cond_tx, NULL); + pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); + pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); + pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); pthread_cond_init( &proc->cond_prach, NULL); #ifndef LOWLATENCY - pthread_create( &proc->pthread_tx, &proc->attr_tx, eNB_thread_tx, &eNB->proc ); - pthread_create( &proc->pthread_rx, &proc->attr_rx, eNB_thread_rx, &eNB->proc ); + pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); + pthread_create( &proc->pthread_rx, &proc->attr_rx, eNB_thread_rx_common, &eNB->proc ); pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); #else - pthread_create( &proc->pthread_tx, NULL, eNB_thread_tx, &eNB->proc ); - pthread_create( &proc->pthread_rx, NULL, eNB_thread_rx, &eNB->proc ); + pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); + pthread_create( &proc->pthread_rx, NULL, eNB_thread_rx_common, &eNB->proc ); pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); #endif char name[16]; - snprintf( name, sizeof(name), "TX %d", i ); - pthread_setname_np( proc->pthread_tx, name ); + snprintf( name, sizeof(name), "RXTX0 %d", i ); + pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); + snprintf( name, sizeof(name), "RXTX1 %d", i ); + pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); snprintf( name, sizeof(name), "RX %d", i ); pthread_setname_np( proc->pthread_rx, name ); } @@ -1073,46 +1088,57 @@ void kill_eNB_proc(void) int *status; PHY_VARS_eNB *eNB; eNB_proc_t *proc; + eNB_rxtx_proc_t *proc_rxtx; for (int CC_id=0; CC_idproc; + proc_rxtx = &proc->proc_rxtx[0]; #ifdef DEBUG_THREADS printf( "Killing TX CC_id %d thread %d\n", CC_id, i ); #endif - proc->instance_cnt_tx = 0; // FIXME data race! - pthread_cond_signal( &proc->cond_tx ); + proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race! + proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race! + pthread_cond_signal( &proc_rxtx[0].cond_rxtx ); + pthread_cond_signal( &proc_rxtx[0].cond_rxtx ); pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); #ifdef DEBUG_THREADS - printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i ); + printf( "Joining eNB TX CC_id %d thread\n", CC_id); #endif - int result = pthread_join( proc->pthread_tx, (void**)&status ); + int result,i; + for (i=0;i<1;i++) { + pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status ); #ifdef DEBUG_THREADS - if (result != 0) { - printf( "Error joining thread.\n" ); - } else { - if (status) { - printf( "status %d\n", *status ); + if (result != 0) { + printf( "Error joining thread.\n" ); } else { - printf( "The thread was killed. No status available.\n" ); + if (status) { + printf( "status %d\n", *status ); + } else { + printf( "The thread was killed. No status available.\n" ); + } } - } #else - UNUSED(result) + UNUSED(result); #endif - + + pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx ); + pthread_cond_destroy( &proc_rxtx[i].cond_rxtx ); + + + } #ifdef DEBUG_THREADS - printf( "Killing RX CC_id %d thread %d\n", CC_id, i ); + printf( "Killing RX CC_id %d thread\n", CC_id); #endif #ifdef DEBUG_THREADS - printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i ); + printf( "Joining eNB RX CC_id %d thread ...\n", CC_id); #endif result = pthread_join( proc->pthread_rx, (void**)&status ); @@ -1131,9 +1157,9 @@ void kill_eNB_proc(void) #else UNUSED(result); #endif - - pthread_mutex_destroy( &proc->mutex_tx ); - pthread_cond_destroy( &proc->cond_tx ); + + pthread_mutex_destroy( &proc->mutex_prach ); + pthread_cond_destroy( &proc->cond_prach ); } } @@ -1262,7 +1288,7 @@ void reset_opp_meas(void) { reset_meas(&softmodem_stats_hw); for (sfn=0; sfn < 10; sfn++) { - reset_meas(&softmodem_stats_tx_sf); + reset_meas(&softmodem_stats_rxtx_sf); reset_meas(&softmodem_stats_rx_sf); } } @@ -1274,7 +1300,7 @@ void print_opp_meas(void) { print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL); for (sfn=0; sfn < 10; sfn++) { - print_meas(&softmodem_stats_tx_sf,"[eNB][total_phy_proc_tx]",NULL, NULL); + print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL); print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL); } } From bba649ac9103fd064f14db40e7260f9621854fd5 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 3 Jun 2016 09:54:49 +0200 Subject: [PATCH 024/206] removal of slot_fep_ul in phy_procedures_rx_uespec --- openair1/SCHED/phy_procedures_lte_eNb.c | 35 +++---------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index cfcec35460..969970d917 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1954,7 +1954,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits eNB->UE_stats[(uint32_t)UE_id].sector = 0; - LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, frame, @@ -2647,30 +2647,6 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl - if (abstraction_flag == 0) { - start_meas(&eNB->ofdm_demod_stats); - - for (l=0; lsymbols_per_tti/2; l++) { - - slot_fep_ul(fp, - &eNB->common_vars, - l, - subframe<<1, - 0, - 0 - ); - slot_fep_ul(fp, - &eNB->common_vars, - l, - (subframe<<1)+1, - 0, - 0 - ); - } - - stop_meas(&eNB->ofdm_demod_stats); - } - // Check for active processes in current subframe harq_pid = subframe2harq_pid(fp, frame,subframe); @@ -2705,18 +2681,14 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) { // UE is has ULSCH scheduling round = eNB->ulsch[i]->harq_processes[harq_pid]->round; - + for (int rb=0; rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb; rb++) { int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb; eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); } -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Scheduling PUSCH/ULSCH Reception for rnti %x (UE_id %d)\n", - eNB->Mod_id,harq_pid, - frame,subframe,eNB->ulsch[i]->rnti,i); -#endif + if (eNB->ulsch[i]->Msg3_flag == 1) { LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n", @@ -2726,6 +2698,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl eNB->UE_stats[i].sector); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1); } else { + LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n", eNB->Mod_id, frame, From d420f75f3db8aea868aa411564d106b84c88532e Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 3 Jun 2016 14:01:34 +0200 Subject: [PATCH 025/206] nothing special --- openair1/SCHED/phy_procedures_lte_eNb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index cfcec35460..cc4dc07283 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2570,6 +2570,9 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl //recv_IF4(eNB,subframe<<1); //recv_IF4(eNB,1+(subframe<<1)); + // Tobi aka mr monaco: ETH + + } else { // should not get here AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); From a396fdc5b09892f9e53be6050bc7976e2fefc188 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 3 Jun 2016 14:04:01 +0200 Subject: [PATCH 026/206] moving if4tools.c --- openair1/PHY/{TOOLS => LTE_TRANSPORT}/if4tools.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openair1/PHY/{TOOLS => LTE_TRANSPORT}/if4tools.c (100%) diff --git a/openair1/PHY/TOOLS/if4tools.c b/openair1/PHY/LTE_TRANSPORT/if4tools.c similarity index 100% rename from openair1/PHY/TOOLS/if4tools.c rename to openair1/PHY/LTE_TRANSPORT/if4tools.c From 448b26f62562a931eba6aa06a37a40324948560e Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 3 Jun 2016 15:39:36 +0200 Subject: [PATCH 027/206] added draft of IF4 packet frame structure --- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 135 +++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 openair1/PHY/LTE_TRANSPORT/if4_tools.h diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h new file mode 100644 index 0000000000..977e5f36c5 --- /dev/null +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -0,0 +1,135 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/*! \file PHY/LTE_TRANSPORT/if4_tools.h +* \brief +* \author S. Sandeep Kumar, Raymond Knopp +* \date 2016 +* \version 0.1 +* \company Eurecom +* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr +* \note +* \warning +*/ + +#include + +/// IF4 Frame Status (32 bits) +struct IF4_frame_status { + /// Antenna Numbers + uint32_t ant_num:3; + /// Antenna Start + uint32_t ant_start:3; + /// Radio Frame Number + uint32_t rf_num:16; + /// Sub-frame Number + uint32_t sf_num:4; + /// Symbol Number + uint32_t sym_num:4; + /// Reserved + uint32_t rsvd:2; +}; + +/// IF4 PRACH Configuration (32 bits) +struct IF4_lte_prach_conf { + /// Reserved + uint32_t rsvd:3; + /// Antenna Indication + uint32_t ant:3; + /// Radio Frame Number + uint32_t rf_num:16; + /// Sub-frame Number + uint32_t sf_num:4; + /// FFT Exponent Output + uint32_t exponent:6; +}; + +/// IF4 Antenna Gain +struct IF4_gain { + /// Reserved + uint32_t rsvd:10; + /// FFT Exponent Output + uint32_t exponent:6; +}; + +struct IF4_dl_packet { + /// Destination Address + + /// Source Address + + /// Type + + /// Sub-Type + + /// Reserved + + /// Frame Status + + /// Data Blocks + + /// Frame Check Sequence + +}; + +struct IF4_ul_packet { + /// Destination Address + + /// Source Address + + /// Type + + /// Sub-Type + + /// Reserved + + /// Frame Status + + /// Gain 0 + /// Gain 1 + /// Gain 2 + /// Gain 3 + /// Gain 4 + /// Gain 5 + /// Gain 6 + /// Gain 7 + + /// Data Blocks + + /// Frame Check Sequence + uint32_t fcs; +}; + +struct IF4_prach_packet { + + +}; + +void send_IF4(PHY_VARS_eNB *eNB, int subframe); + +void recv_IF4(PHY_VARS_eNB *eNB, int subframe); From 7b3fe853584067d5bcae80752271a17466f83675 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 3 Jun 2016 16:23:22 +0200 Subject: [PATCH 028/206] fixed file name, updated the IF4 frame structure, added dummy functions for frame generation --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 114 +++++++++++++++++++++++++ openair1/PHY/LTE_TRANSPORT/if4_tools.h | 65 +++++++++----- openair1/PHY/LTE_TRANSPORT/if4tools.c | 47 ---------- 3 files changed, 160 insertions(+), 66 deletions(-) create mode 100644 openair1/PHY/LTE_TRANSPORT/if4_tools.c delete mode 100644 openair1/PHY/LTE_TRANSPORT/if4tools.c diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c new file mode 100644 index 0000000000..a3e6d75ac8 --- /dev/null +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -0,0 +1,114 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/*! \file PHY/LTE_TRANSPORT/if4_tools.c +* \brief +* \author Mauricio Gunther, Raymond Knopp, S. Sandeep Kumar +* \date 2016 +* \version 0.1 +* \company Eurecom +* \email: knopp@eurecom.fr, ee13b1025@iith.ac.in +* \note +* \warning +*/ + +#include "PHY/LTE_TRANSPORT/if4_tools.h" + +/* +typedef struct data_block_type { + +} data_block; +*/ + +/* +void allocate_data_block(long *data_block ,int length){ + data_block = malloc(length*sizeof(long)); +} +*/ + +void send_IF4(PHY_VARS_eNB *eNB, int subframe){ + eNB_proc_t *proc = &eNB->proc; + //int frame=proc->frame_tx; + //int subframe=proc->subframe_tx; + + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int i,j; + + float *data_block = malloc(length*sizeof(long)); + + + // find number of consecutive non zero in values in symbol + // NrOfNonZeroValues + + // how many values does the atan function output? + + for(i = 0; i <= fp->symbols_per_tti; i++){ + for(j = 0; j < NrOfNonZeroValues; j=j+2){ + + symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] + + data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); + data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); + // use memset? + } + + } + +/* +memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], + 0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t)); + } + */ + +} + +void recv_IF4( ) { + +} + +IF4_dl_packet gen_IF4_dl_packet( ) { + + IF4_dl_packet dl_packet; + + return dl_packet; +} + +IF4_ul_packet gen_IF4_ul_packet( ) { + + IF4_ul_packet ul_packet; + + return ul_packet; +} + +IF4_prach_packet gen_IF4_prach_packet( ) { + + IF4_prach_packet prach_packet; + + return prach_packet; +} diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 977e5f36c5..363dbf444d 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -56,7 +56,15 @@ struct IF4_frame_status { uint32_t rsvd:2; }; -/// IF4 PRACH Configuration (32 bits) +/// IF4 Antenna Gain +struct IF4_gain { + /// Reserved + uint32_t rsvd:10; + /// FFT Exponent Output + uint32_t exponent:6; +}; + +/// IF4 LTE PRACH Configuration (32 bits) struct IF4_lte_prach_conf { /// Reserved uint32_t rsvd:3; @@ -69,14 +77,6 @@ struct IF4_lte_prach_conf { /// FFT Exponent Output uint32_t exponent:6; }; - -/// IF4 Antenna Gain -struct IF4_gain { - /// Reserved - uint32_t rsvd:10; - /// FFT Exponent Output - uint32_t exponent:6; -}; struct IF4_dl_packet { /// Destination Address @@ -84,17 +84,17 @@ struct IF4_dl_packet { /// Source Address /// Type - + uint16_t type; /// Sub-Type - + uint16_t sub_type; /// Reserved - + uint32_t rsvd; /// Frame Status - + IF4_frame_status frame_status; /// Data Blocks /// Frame Check Sequence - + uint32_t fcs; }; struct IF4_ul_packet { @@ -103,22 +103,29 @@ struct IF4_ul_packet { /// Source Address /// Type - + uint16_t type; /// Sub-Type - + uint16_t sub_type; /// Reserved - + uint32_t rsvd; /// Frame Status - + IF4_frame_status frame_status; /// Gain 0 + IF4_gain gain0; /// Gain 1 + IF4_gain gain1; /// Gain 2 + IF4_gain gain2; /// Gain 3 + IF4_gain gain3; /// Gain 4 + IF4_gain gain4; /// Gain 5 + IF4_gain gain5; /// Gain 6 + IF4_gain gain6; /// Gain 7 - + IF4_gain gain7; /// Data Blocks /// Frame Check Sequence @@ -126,10 +133,30 @@ struct IF4_ul_packet { }; struct IF4_prach_packet { + /// Destination Address + /// Source Address + /// Type + uint16_t type; + /// Sub-Type + uint16_t sub_type; + /// Reserved + uint32_t rsvd; + /// LTE Prach Configuration + IF4_lte_prach_conf prach_conf; + /// Prach Data Block (one antenna) + + /// Frame Check Sequence + uint32_t fcs; }; +IF4_dl_packet gen_IF4_dl_packet(); + +IF4_ul_packet gen_IF4_ul_packet(); + +IF4_prach_packet gen_IF4_prach_packet(); + void send_IF4(PHY_VARS_eNB *eNB, int subframe); void recv_IF4(PHY_VARS_eNB *eNB, int subframe); diff --git a/openair1/PHY/LTE_TRANSPORT/if4tools.c b/openair1/PHY/LTE_TRANSPORT/if4tools.c deleted file mode 100644 index 70e598e2a1..0000000000 --- a/openair1/PHY/LTE_TRANSPORT/if4tools.c +++ /dev/null @@ -1,47 +0,0 @@ -/* -typedef struct data_block_type { - -} data_block; -*/ - -/* -void allocate_data_block(long *data_block ,int length){ - data_block = malloc(length*sizeof(long)); -} -*/ - -void send_IF4(PHY_VARS_eNB eNB, int subframe){ - eNB_proc_t *proc = &eNB->proc; - //int frame=proc->frame_tx; - //int subframe=proc->subframe_tx; - - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - int i,j; - - float *data_block = malloc(length*sizeof(long)); - - - // find number of consecutive non zero in values in symbol - // NrOfNonZeroValues - - // how many values does the atan function output? - - for(i = 0; i <= fp->symbols_per_tti; i++){ - for(j = 0; j < NrOfNonZeroValues; j=j+2){ - - symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] - - data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); - data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); - // use memset? - } - - } - -/* -memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], - 0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t)); - } - */ - -} From ad1114c7f75b677b99a51e88e902df5352e7bc38 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 3 Jun 2016 17:54:32 +0200 Subject: [PATCH 029/206] added more structural changes --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 156 ++++++++++++++++++------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 4 +- 2 files changed, 117 insertions(+), 43 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index a3e6d75ac8..669b7a6739 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -29,28 +29,19 @@ /*! \file PHY/LTE_TRANSPORT/if4_tools.c * \brief -* \author Mauricio Gunther, Raymond Knopp, S. Sandeep Kumar +* \author Mauricio Gunther, S. Sandeep Kumar, Raymond Knopp * \date 2016 * \version 0.1 * \company Eurecom -* \email: knopp@eurecom.fr, ee13b1025@iith.ac.in +* \email: knopp@eurecom.fr * \note * \warning */ #include "PHY/LTE_TRANSPORT/if4_tools.h" -/* -typedef struct data_block_type { - -} data_block; -*/ +// Define how data blocks are stored and transferred -/* -void allocate_data_block(long *data_block ,int length){ - data_block = malloc(length*sizeof(long)); -} -*/ void send_IF4(PHY_VARS_eNB *eNB, int subframe){ eNB_proc_t *proc = &eNB->proc; @@ -58,57 +49,138 @@ void send_IF4(PHY_VARS_eNB *eNB, int subframe){ //int subframe=proc->subframe_tx; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - int i,j; + uint32_t i,j; float *data_block = malloc(length*sizeof(long)); + // Generate IF4 packet (for now DL) with frame status information + dl_packet = gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ); - // find number of consecutive non zero in values in symbol - // NrOfNonZeroValues - - // how many values does the atan function output? - - for(i = 0; i <= fp->symbols_per_tti; i++){ - for(j = 0; j < NrOfNonZeroValues; j=j+2){ - - symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] - - data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); - data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); - // use memset? - } - - } - -/* -memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], - 0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t)); - } - */ + for(i=0; isymbols_per_tti; i++) { + // Do compression of the two parts and generate data blocks + + symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] + data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); + data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); + + // Set data blocks and update subframe no./other information to generated packet + + + // Write the packet(s) to the fronthaul + + } + } -void recv_IF4( ) { +void recv_IF4( /* ADD INFO and data_block pointer */ ) { + + // Read packet(s) from the fronthaul + + // Apply reverse processing - decompression + + // Generate and return the OFDM symbols (txdataF) } -IF4_dl_packet gen_IF4_dl_packet( ) { - +IF4_dl_packet gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ) { IF4_dl_packet dl_packet; + // Set destination and source address + + // Set Type and Sub-Type + dl_packet.type = ; //08_0A ? + dl_packet.sub_type = 0x0020; + + // Leave reserved as it is + //dl_packet.rsvd = ; + + // Set frame status + dl_packet.frame_status.ant_num = ; + dl_packet.frame_status.ant_start = ; + dl_packet.frame_status.rf_num = ; + dl_packet.frame_status.sf_num = ; + dl_packet.frame_status.sym_num = ; + //dl_packet.frame_status.rsvd = ; + + // Set data blocks if sent + if (data_block != NULL) { + + } else { + + } + + // Set frame check sequence + dl_packet.fcs = ; + return dl_packet; } -IF4_ul_packet gen_IF4_ul_packet( ) { - +IF4_ul_packet gen_IF4_ul_packet( /* ADD INFO and data_block pointer */ ) { IF4_ul_packet ul_packet; + + // Set destination and source address + + // Set Type and Sub-Type + ul_packet.type = ; //08_0A ? + ul_packet.sub_type = 0x0019; + + // Leave reserved as it is + //ul_packet.rsvd = ; + + // Set frame status + ul_packet.frame_status.ant_num = ; + ul_packet.frame_status.ant_start = ; + ul_packet.frame_status.rf_num = ; + ul_packet.frame_status.sf_num = ; + ul_packet.frame_status.sym_num = ; + //ul_packet.frame_status.rsvd = ; + + // Set antenna specific gain + ul_packet.gain0.exponent = ; + //ul_packet.gain0.rsvd = ; + + // Set data blocks if sent + if (data_block != NULL) { + + } else { + + } + + // Set frame check sequence + ul_packet.fcs = ; return ul_packet; } -IF4_prach_packet gen_IF4_prach_packet( ) { - +IF4_prach_packet gen_IF4_prach_packet( /* ADD INFO and data_block pointer */ ) { IF4_prach_packet prach_packet; + + // Set destination and source address + + // Set Type and Sub-Type + prach_packet.type = ; //08_0A ? + prach_packet.sub_type = 0x0021; + + // Leave reserved as it is + //prach_packet.rsvd = ; + + // Set LTE Prach configuration + //prach_packet.prach_conf.rsvd = ; + prach_packet.prach_conf.ant = ; + prach_packet.prach_conf.rf_num = ; + prach_packet.prach_conf.sf_num = ; + prach_packet.prach_conf.exponent = ; + + // Set data blocks if sent + if (data_block != NULL) { + + } else { + + } + + // Set frame check sequence + prach_packet.fcs = ; return prach_packet; } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 363dbf444d..3b25e82c6a 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -56,7 +56,7 @@ struct IF4_frame_status { uint32_t rsvd:2; }; -/// IF4 Antenna Gain +/// IF4 Antenna Gain (16 bits) struct IF4_gain { /// Reserved uint32_t rsvd:10; @@ -151,6 +151,8 @@ struct IF4_prach_packet { uint32_t fcs; }; +// Needs to be checked + IF4_dl_packet gen_IF4_dl_packet(); IF4_ul_packet gen_IF4_ul_packet(); From eea7764acefca644d17b76d8c1d871f882e81689 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 3 Jun 2016 22:57:16 -0700 Subject: [PATCH 030/206] updated oai_L1_L2_procedures.pdf --- targets/DOCS/oai_L1_L2_procedures.pdf | Bin 1652669 -> 269265 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/targets/DOCS/oai_L1_L2_procedures.pdf b/targets/DOCS/oai_L1_L2_procedures.pdf index 0f47195db1c70b27f17b907a3b95174d45e4f292..89ec48595691438ecf418ab54e78041267f880e3 100755 GIT binary patch delta 138261 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%0DhsqMyeWgdBEL54Xx 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 z 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%0DlJl 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 Date: Tue, 7 Jun 2016 17:17:36 +0200 Subject: [PATCH 031/206] added original ALAW compression --- openair1/PHY/TOOLS/ALAW/companders.c | 125 ++++++++++++ openair1/PHY/TOOLS/ALAW/companders.h | 90 +++++++++ openair1/PHY/TOOLS/ALAW/compandit.c | 128 ++++++++++++ openair1/PHY/TOOLS/ALAW/readme-companders.txt | 185 ++++++++++++++++++ 4 files changed, 528 insertions(+) create mode 100644 openair1/PHY/TOOLS/ALAW/companders.c create mode 100644 openair1/PHY/TOOLS/ALAW/companders.h create mode 100644 openair1/PHY/TOOLS/ALAW/compandit.c create mode 100644 openair1/PHY/TOOLS/ALAW/readme-companders.txt diff --git a/openair1/PHY/TOOLS/ALAW/companders.c b/openair1/PHY/TOOLS/ALAW/companders.c new file mode 100644 index 0000000000..b089716977 --- /dev/null +++ b/openair1/PHY/TOOLS/ALAW/companders.c @@ -0,0 +1,125 @@ +/** + * @companders.c - implementation + * + * @copy Copyright (C) <2012> + * @author M A Chatterjee + * @version 1.01 M. A. Chatterjee, cleaned up naming + * + * This file contains integer math compander functions for analog/audio representations on + * embedded systems. Linear2Alaw derived from Mark Spencer, Sun Microsystem and from + * the A Law specification + * + * @license: + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include "companders.h" + +DIO_s8 DIO_LinearToALaw(DIO_s16 sample) +{ + const DIO_s16 cClip = 32635; + const static DIO_s8 LogTable[128] = + { + 1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + }; + + DIO_s32 sign, exponent, mantissa; + DIO_s8 compandedValue; + sample = (sample ==-32768) ? -32767 : sample; + sign = ((~sample) >> 8) & 0x80; + if (!sign) + sample = (short)-sample; + if (sample > cClip) + sample = cClip; + if (sample >= 256) + { + exponent = (int)LogTable[(sample >> 8) & 0x7F]; + mantissa = (sample >> (exponent + 3) ) & 0x0F; + compandedValue = ((exponent << 4) | mantissa); + } + else + { + compandedValue = (unsigned char)(sample >> 4); + } + compandedValue ^= (sign ^ 0x55); + return compandedValue; +} + +DIO_s16 DIO_ALawToLinear(DIO_s8 aLawByte) +{ + const static DIO_s16 ALawDecompTable[256]={ + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848, + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944, + -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136, + -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472, + -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848}; + DIO_s16 addr = ((DIO_s16)aLawByte)+128; // done for compilers with poor expr type enforcement + return ALawDecompTable[addr]; +} + +// see companders.h +// fixed-radix IIR averager implementation supporting arbitrarily chosen windows +DIO_s32 DIO_IIRavgFR (DIO_s32 prevAvg, DIO_u16 windowLen, DIO_s16 newSample, DIO_u8 radix) +{ + DIO_s32 iirAvg=0; + iirAvg = ((prevAvg * (windowLen-1)) + (DIO_I2FR(newSample,radix)))/windowLen; + return iirAvg; +} + +// see companders.h +// fixed-radix IIR averager implementation using power-of-2 sized windows +// and only shift operations for cpu efficiency +DIO_s32 DIO_IIRavgPower2FR (DIO_s32 prevAvg, DIO_u8 windowLenInBits, DIO_s16 newSample, DIO_u8 radix) +{ + DIO_s32 iirAvg=0; + iirAvg = (((prevAvg<>windowLenInBits; + return iirAvg; +} diff --git a/openair1/PHY/TOOLS/ALAW/companders.h b/openair1/PHY/TOOLS/ALAW/companders.h new file mode 100644 index 0000000000..4d1ab33f19 --- /dev/null +++ b/openair1/PHY/TOOLS/ALAW/companders.h @@ -0,0 +1,90 @@ +/** + * @companders.h - header definition file for embedded companding routines + * + * @copy Copyright (C) <2001-2012> + * @author M A Chatterjee + * @version 1.01 M. A. Chatterjee, cleaned up naming + * + * This file contains integer math settable fixed point radix math routines for + * use on systems in which floating point is not desired or unavailable. + * + * @license: + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#ifndef __DIO_Compand_h__ +#define __DIO_Compand_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +//"DIO" prefixes are to assist in prevent name collisions if global namespace is used. + +//typedefs ... change for platform dependant register size +// u/s = unsigned/signed 8/16/32 = num of bits +// keywords "int" and "long" in C/C++ are platform dependant +typedef unsigned char DIO_u8 ; +typedef signed char DIO_s8 ; +typedef unsigned short DIO_u16 ; +typedef signed short DIO_s16 ; +typedef unsigned long DIO_u32 ; +typedef signed long DIO_s32 ; + +// macros for converting from Fixed-Radix to integer, vice-versa +// r represents radix precision in bits, converts to/from integer w truncation +#define DIO_I2FR(x,r) ((x)<<(r)) +#define DIO_FR2I(x,r) ((x)>>(r)) + + +// convert FR to double, this is for debug only and WILL NOT compile under many embedded systems. +// use this in test harnesses. Since this is a macro if its not used it won't expand / link +#define DIO_FR2D(x,r) ((double)(((double)(x))/((double)(1<<(r))))) + +//convert signed linear 16 bit sample to an 8 bit A-Law companded sample +DIO_s8 DIO_LinearToALaw(DIO_s16 sample); + +//convert 8bit Alaw companded representation back to linear 16 bit +DIO_s16 DIO_ALawToLinear(DIO_s8 aLawByte); + + +//DC Offset correction for integer companders +//IIR: y_0=(y_1*(w-1)+x_0)/(w) +//where w is the window length +//below are fixed radix precision IIR averagers which allow runtime tradeoffs for windowLen & precision +//Note that (windowLen)*(1< + * @author M A Chatterjee + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +#include +#include + + +#include "companders.h" + + +//=============================================== +//main program for testing the functions +int main (int argc, char *argv[]) +{ + int ret_val = 0; + int i=0,j=0; + printf("\n============================================================\n"); + printf("compandit library quikie program\n"); + printf("M. A. Chatterjee (c) 2012\n\n"); + printf("These routines were developed for use on embedded projects\n"); + printf("for more info see the accompanying compand.txt\n"); + printf("\n"); + + //uncomment to + //show how linear-->alaw-->linear-->alaw progression / quantization error works + /* + + { + char alaw=0,alaw2; + short rev=0; + + for (i= -32768; i <= 32767; i++) + { + alaw = DIO_LinearToALaw((short)i); + rev = DIO_ALawToLinear(alaw); + alaw2 =DIO_LinearToALaw(rev); + if (alaw != alaw2) + printf("***********"); + printf("%7d %7d %7d %7d\n",i,(int)alaw,(int)rev,(int)alaw2); + } + } + + + // IIR averager examples + //IIR window length of 8 samples, using fractional precision of 4 bits + { + int a3=0, a4=0; + unsigned char rad=4; //4 bits fixed-radix fractional precision + printf(" index wave IIRav(i) IIRav(f) IIRavP2(i) IIRavP2(f)\n"); + for (i=0; i < 300; i++) + { + j=(i&0x3f)-20; // triangle wave with range -20 to + 43 + a3= DIO_IIRavgFR(a3,8,j,rad); + a4= DIO_IIRavgPower2FR(a4,3,j,rad); + printf("%6d %6d %6d %9.4f %6d %9.4f \n",i,j, + DIO_FR2I(a3,rad),DIO_FR2D(a3,rad) ,DIO_FR2I(a4,rad),DIO_FR2D(a4,rad)); + } + } + //IIR window length of 64 samples + { + int a3=0, a4=0; + unsigned char rad=6; //rad is the number of bits of precision + printf(" index wave IIRav(i) IIRav(f) IIRavP2(i) IIRavP2(f)\n"); + for (i=0; i < 300; i++) + { + j=(i&0x3f)-20; // triangle wave with range -20 to + 43 + a3= DIO_IIRavgFR(a3,64,j,rad); + a4= DIO_IIRavgPower2FR(a4,6,j,rad); + printf("%6d %6d %6d %9.4f %6d %9.4f \n",i,j, + DIO_FR2I(a3,rad),DIO_FR2D(a3,rad) ,DIO_FR2I(a4,rad),DIO_FR2D(a4,rad)); + } + } + // */ + //Typical microcontroller application. See readme-companders.txt + // the input here simulates an A/D which has a range 0..3.3V mapped as 12 bits (0..4095) + // with a DC bias of 1.55V ==> (1.55/3.3)*4095 counts = 1923 counts + + //now window length of 256 is used for rejecting the resistor bias. at 8KHz this window + // would be approx 8000/256 ~= 31 Hz (not quite but explaining Z xforms is beyond what + // can be explained in this small space.) + //we seed the DC average at 3.3/2 = 1.65V (we guess its in the middle) and let the long window + //length hone in on the correct value. (1.65V/3.3V) *4095 = 2048 counts + { + int actualDCbias =1923; + int calculatedDCbias =2048; //2048 is our initial estimate as outlined above + unsigned char windowLenPow2InBits = 8; // 8 bit long window = 256 sample long window + unsigned char rad=6; //rad is the number of bits of precision + + calculatedDCbias = DIO_I2FR(calculatedDCbias,rad); + printf(" index wave actDCbias calcDCbias calcDCbias(f) alaw\n"); + for (i=0; i < 1000; i++) // if 8000 hz sample rate this represents the number of samples captured + { + j=(((i&0x3f)<<1)-63)+1923; // triangle wave w range 0..127 with a bias set at actualDCbias + calculatedDCbias = DIO_IIRavgPower2FR(calculatedDCbias,windowLenPow2InBits,j,rad); + printf("%6d %6d %6d %6d %9.4f %3d\n",i,j,actualDCbias, + DIO_FR2I(calculatedDCbias,rad),DIO_FR2D(calculatedDCbias,rad), + (int)(DIO_LinearToALaw(j-DIO_FR2I(calculatedDCbias,rad)) )); + } + } + printf("\n"); + return ret_val; +} + diff --git a/openair1/PHY/TOOLS/ALAW/readme-companders.txt b/openair1/PHY/TOOLS/ALAW/readme-companders.txt new file mode 100644 index 0000000000..dbedc91788 --- /dev/null +++ b/openair1/PHY/TOOLS/ALAW/readme-companders.txt @@ -0,0 +1,185 @@ +/** + * @readme-companders.txt - using compander.c / .h and related functions + * + * @copy Copyright (C) <2001-2012> + * @author M A Chatterjee + * + * This document is a brief overview of the simple compander library with + * a small introductory disucssion about fixed radix math IIRs for microcontrollers + * + * @license: + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +Welcome... + +The accompanying companders.c contains a small set of functions written in C using only integer math for companding operations. I developed this several years ago for use in several embedded interized math projects and this small, slightly cleaned up version is made available for the public here. It worked very well on M*CORE, 80x86 and ARM processors for small embedded systems. + +usage: +#include "companders.h" +no other dependancies are required. +compile and link companders.c + + +*********************** +About companding... + +Companding is a special type of lossy compression in which linear format samples are converted to logarithmic representation in order to preserve dynamic range of the original linear sample at the expense of uniform precision. Companding is an old method and is free of patents (all have expired). + +Theory of how companding works: +Suppose that we have a signed 16 bit linear sample in 2's complement math. The range of this sample can vary from -32768 to + 32767 in integer steps. Now lets put the constraint that we only have 8 bits with which to represent the data not the full 16 bits of the original linear number. A simple way to preserve high order information would be to linearly truncate off the lower 8 bits giving us a signed number from -128 to +127. We could make a mental note to keep track of the fact that we lost the lower 8 bits and so when use this representation we multiply by 8 bits (or 256) to preserve the input range. +so: +-128 * 256 = -32768 +-127 * 256 = -32512 +... + -1 * 256 = -256 + 0 * 256 = 0 + 1 * 256 = 256 + 2 * 256 = 512 +... + 126 * 256 = 32256 + 127 * 256 = 32512 + + Notice that the steps between these linearly rounded off samples are quite large. This truncated 8 bit representation would be very good at representing a linear quantity system such as linear displacement transducer which moves through its whole range as part of normal operation (like a door). but terrible at logarithmic phenomonen such as audio. Audio information tends to be grouped around zero with occaisonaly peaks of loudness. So with linear quantization soft audio would be lost due to the large quanitization steps at low volumes. To address this companders were developed for use in landline telephony for compressing audio data logarithmically instead of linearly. Hence we use more bits for audio samples near zero and less with audio samples near the integer max extremes. + +A-Law and it cousin mu-Law are companders. Rather than represent samples in linear steps the more bits are allocated to samples near zero while larger magnitude (positive or negative) samples are represented with proportionately larger interval sizes. + +Differential encoding (taking the difference of neighboring samples) can greatly help with compressing data to where we "have more bits" as well, provided samples rates are fast enough. Telephony typically operated with 8 bit non-differential (companded) samples at 8KHz. + +In A-Law the following table (in bits) shows how a 13 bit signed linear integer is companded in to A-Law: +(source is Sun microsystems, a similar table is on wikipedia or the G.711 specification). + + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + + + About this library: + + This free library supports A-Law and IIR averages. A-Law is used for the companding while the IIR averagers can be used for for embedded ADCs where the zero point is set loosely. Since the companders are sensitive, and allocate more bits, to values near zero its important to define a good zero. For example a microcontroller has a pin with an ADC which is fed digitized audio signal. The smallest value for the microtroncoller is 0V = 0x00 and the 3.3V = 0x3ff for 10 effective bits of resolution. A resisitive analog divider is used to center the ADC near the half-input range or about 1.6V while the audio is capacitively coupled as shown here: + + +3.3V + | + R + | + uC_ADC_Pin-----------C----audio_input + | + R + | + GND + + However cheap resistors have tolerances 5 to 10%, so the setpoint voltage could easily be anywhere from 1.4 to 1.8V. To address this software should read the ADC before audio is coming in and determine the actual DC bias voltage set by the resistors. Then when audio is coming in this value is subtracted from the ADC input to give a signed number which is fed to the LinearToAlaw encoder. + + If it not easily possible to turn off the analog / audio source then the long term DC average can be inferred by using one of the IIR functions included here with a long window length (perhaps 2000 samples if sampling at 8 KHz or about 1/4 second). These IIR functions are cheap to run in realtime even with reasonably high sample rates as they take little memory and are simple integer-math IIRs. + + About the Fixed Radix (FR) Math IIR averages + +The (Infinite Impulse Reponse) IIR functions included here use fixed radix math to represent fractional parts of an integer. By providing a settable radix (amount of bits devoted to fractional resolution), the programmer can make tradeoffs between resolution and dynamic range. The larger the radix specified the more bits that will be used in the fractional portion of the representation, which for smaller window sizes may not by necessary. There are more comprehensive ways to deal with fractional representation in binary systems (floating point, bigNum / arbitrary length registers, separation of numerator/denomators etc) but these incur much larger compute/code/memory overhead. The simple system used here avoids the need for testing for overflow/underflow which allows for low foot print code/cpu/memory bandwidth. + + To calculate how many bits of fractional part while preventing overflow use the following formulas: + +Nb = number of bits in use = ceiling(log2(highest_number_represented)) + +radix = 32-Nb(sample_resolution)-Nb(WindowLength)-2 + +for example if you have a ADC generating counts from 0 to 1023 then the Nb(ADC-range) = + Nb = ceiling(log2(1023)) = 10 bits + +If you use a DC average window length of 2000 + Nb = ceiling(log2(2000)) = 11 bits + +so the max radix that should be specified is: + radix = 32 - 10 - 11 - 2 = 32 - 23 = 9 bits + +with 9 bits in the radix fractional precision of 512 units per integer (e.g 1/512) is possible. The "2" in for formula comes from reserving bits for the sign bit and the additional operation in averager. + +The function DIO_s32 DIO_IIRavgFR() allows any integer length window size to be used, while the function DIO_IIRavgPower2FR() specifies window lengths in powers of two but all calculations are based on shift operations which can be significantly faster on lower end microprocessors. + + + +Embedded Systems + +Now back to an embedded microcontroller example. It has a ADC which maps the voltage on 1 pin from 0-3.3V in to 0-4095 counts (12 bit). We capacitively couple the input voltage and use the bias resistors to set mid point in the center of the range. Lets say the the our resistors set the bias at 1.55V. This equals our "zero point". Below this point is negative from the incoming capacitively coupled audio and above this is positive. + +Our "guess" as to the bias = both resistors are the same = (3.3V/2) =1.65V = (1.65V)/(4095 counts/3.3V)= 2048 counts + +Resistor actual set bias "zero point" = 1.55V = (1.55V) *(4095 counts/3.3V)) = 1923 counts +We want this to be "zero" we use for the companded A/D process. + +To do this we start our ADC to periodically sample for sometime before we start "recording" audio. We will feed the ADC values in to our IIR average to find the actual zero point. Note that even when we decide not to "record" we still can still run the A/D and IIR averager so its adapting to the real zero point. + + + +//C-like psuedo code + +#include "companders.h" + +static volatile int32 gIIRavg= 2048; // global static var holds DC average +static volatile int gDoSomethingWithCompandedValue=0; +void processAudioSample() //interrupt handler +{ + short adcValue; + char aLawValue; + + //read the raw uncorrected sample + adcValue= inputPin.read_u16(); // read a 16 bit unsigned sample + + // this updates the IIR average everytime the adc returns a sample + gIIRavg = DIO_IIRavgPower2FR(gIIRavg,11,adcValue,8); + + //now compute companded value with DC offset correction + if (gDoSomethingWithCompandedValue) + { + aLawValue = DIO_LinearToALaw(adcValue-DIO_FR2I(gIIRavg)); + doSomethingWithALaw(aLawValue); // store it to a buffer, send it etc + } +} + +main() +{ + gDoSomethingWithCompandedValue=0; + inputPin.attachInterrupt(&processAudioSample,8000); //attach interrupt handler, 8000 Hz sample rate + + // ... somepoint later in the code + + inputPin.start(); // start the averager + + // ... some time later + gDoSomethingWithCompandedValue=1; //now the interrupt routine will call the doSomethingWithALaw() function + + // ... some time later + gDoSomethingWithCompandedValue=0; //we're no longer collecting ALaw companded date, but we're + // still running the IIR averager + + +} + +Finally, it can be in some systems that we can't turn off the audio input source it may be hard wired to some sensor or mic or perhaps the A/D center bias circuit (the 2 resistors) always is on when the audio is on. In this case running the IIR with a long filter length all the time can remove the bias even when the audio is running. For example in an 8KHz sampling system with an IIR length of 1024 is about 1/8 of a second or a cutoff freq well below 10Hz and costs almost nothing to run. + + + From d5d1dd0e8a0a5f94ee041d8188756e16d32de06c Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 7 Jun 2016 18:19:26 +0200 Subject: [PATCH 032/206] fixed packet struct types --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 121 ++++++++++++++----------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 41 ++++----- 2 files changed, 86 insertions(+), 76 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 669b7a6739..a42eae8798 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -38,40 +38,44 @@ * \warning */ +#ifndef USER_MODE +#include "if4_tools.h" +#include +#else #include "PHY/LTE_TRANSPORT/if4_tools.h" +#endif // Define how data blocks are stored and transferred - -void send_IF4(PHY_VARS_eNB *eNB, int subframe){ - eNB_proc_t *proc = &eNB->proc; +//void send_IF4(PHY_VARS_eNB *eNB, int subframe){ + //eNB_proc_t *proc = &eNB->proc; //int frame=proc->frame_tx; //int subframe=proc->subframe_tx; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - uint32_t i,j; - float *data_block = malloc(length*sizeof(long)); + //uint32_t i,j; + //float *data_block = malloc(length*sizeof(long)); // Generate IF4 packet (for now DL) with frame status information - dl_packet = gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ); + //dl_packet = gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ); - for(i=0; isymbols_per_tti; i++) { + //for(i=0; isymbols_per_tti; i++) { // Do compression of the two parts and generate data blocks - symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] - data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); - data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); + //symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] + //data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); + //data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); // Set data blocks and update subframe no./other information to generated packet // Write the packet(s) to the fronthaul - } + //} -} +//} void recv_IF4( /* ADD INFO and data_block pointer */ ) { @@ -83,83 +87,83 @@ void recv_IF4( /* ADD INFO and data_block pointer */ ) { } -IF4_dl_packet gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ) { - IF4_dl_packet dl_packet; +struct IF4_dl_packet gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ) { + struct IF4_dl_packet dl_packet; // Set destination and source address // Set Type and Sub-Type - dl_packet.type = ; //08_0A ? + dl_packet.type = 0x080A; dl_packet.sub_type = 0x0020; // Leave reserved as it is //dl_packet.rsvd = ; // Set frame status - dl_packet.frame_status.ant_num = ; - dl_packet.frame_status.ant_start = ; - dl_packet.frame_status.rf_num = ; - dl_packet.frame_status.sf_num = ; - dl_packet.frame_status.sym_num = ; + dl_packet.frame_status.ant_num = 0; + dl_packet.frame_status.ant_start = 0; + dl_packet.frame_status.rf_num = 0; + dl_packet.frame_status.sf_num = 0; + dl_packet.frame_status.sym_num = 0; //dl_packet.frame_status.rsvd = ; // Set data blocks if sent - if (data_block != NULL) { - - } else { - - } + //if (data_block != NULL) { + // + //} else { + // + //} // Set frame check sequence - dl_packet.fcs = ; + dl_packet.fcs = 0; return dl_packet; } -IF4_ul_packet gen_IF4_ul_packet( /* ADD INFO and data_block pointer */ ) { - IF4_ul_packet ul_packet; +struct IF4_ul_packet gen_IF4_ul_packet( /* ADD INFO and data_block pointer */ ) { + struct IF4_ul_packet ul_packet; // Set destination and source address // Set Type and Sub-Type - ul_packet.type = ; //08_0A ? + ul_packet.type = 0x080A; ul_packet.sub_type = 0x0019; // Leave reserved as it is //ul_packet.rsvd = ; // Set frame status - ul_packet.frame_status.ant_num = ; - ul_packet.frame_status.ant_start = ; - ul_packet.frame_status.rf_num = ; - ul_packet.frame_status.sf_num = ; - ul_packet.frame_status.sym_num = ; + ul_packet.frame_status.ant_num = 0; + ul_packet.frame_status.ant_start = 0; + ul_packet.frame_status.rf_num = 0; + ul_packet.frame_status.sf_num = 0; + ul_packet.frame_status.sym_num = 0; //ul_packet.frame_status.rsvd = ; // Set antenna specific gain - ul_packet.gain0.exponent = ; + ul_packet.gain0.exponent = 0; //ul_packet.gain0.rsvd = ; // Set data blocks if sent - if (data_block != NULL) { - - } else { - - } + //if (data_block != NULL) { + // + //} else { + // + //} // Set frame check sequence - ul_packet.fcs = ; + ul_packet.fcs = 0; return ul_packet; } -IF4_prach_packet gen_IF4_prach_packet( /* ADD INFO and data_block pointer */ ) { - IF4_prach_packet prach_packet; +struct IF4_prach_packet gen_IF4_prach_packet( /* ADD INFO and data_block pointer */ ) { + struct IF4_prach_packet prach_packet; // Set destination and source address // Set Type and Sub-Type - prach_packet.type = ; //08_0A ? + prach_packet.type = 0x080A; prach_packet.sub_type = 0x0021; // Leave reserved as it is @@ -167,20 +171,27 @@ IF4_prach_packet gen_IF4_prach_packet( /* ADD INFO and data_block pointer */ ) { // Set LTE Prach configuration //prach_packet.prach_conf.rsvd = ; - prach_packet.prach_conf.ant = ; - prach_packet.prach_conf.rf_num = ; - prach_packet.prach_conf.sf_num = ; - prach_packet.prach_conf.exponent = ; + prach_packet.prach_conf.ant = 0; + prach_packet.prach_conf.rf_num = 0; + prach_packet.prach_conf.sf_num = 0; + prach_packet.prach_conf.exponent = 0; // Set data blocks if sent - if (data_block != NULL) { - - } else { - - } + //if (data_block != NULL) { + // + //} else { + // + //} // Set frame check sequence - prach_packet.fcs = ; + prach_packet.fcs = 0; return prach_packet; } + +int main(){ + + uint32_t i=0; + + return 0; +} diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 3b25e82c6a..c5bb46576c 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -38,8 +38,6 @@ * \warning */ -#include - /// IF4 Frame Status (32 bits) struct IF4_frame_status { /// Antenna Numbers @@ -59,9 +57,9 @@ struct IF4_frame_status { /// IF4 Antenna Gain (16 bits) struct IF4_gain { /// Reserved - uint32_t rsvd:10; + uint16_t rsvd:10; /// FFT Exponent Output - uint32_t exponent:6; + uint16_t exponent:6; }; /// IF4 LTE PRACH Configuration (32 bits) @@ -77,7 +75,7 @@ struct IF4_lte_prach_conf { /// FFT Exponent Output uint32_t exponent:6; }; - + struct IF4_dl_packet { /// Destination Address @@ -90,13 +88,14 @@ struct IF4_dl_packet { /// Reserved uint32_t rsvd; /// Frame Status - IF4_frame_status frame_status; + struct IF4_frame_status frame_status; /// Data Blocks /// Frame Check Sequence uint32_t fcs; }; + struct IF4_ul_packet { /// Destination Address @@ -109,23 +108,23 @@ struct IF4_ul_packet { /// Reserved uint32_t rsvd; /// Frame Status - IF4_frame_status frame_status; + struct IF4_frame_status frame_status; /// Gain 0 - IF4_gain gain0; + struct IF4_gain gain0; /// Gain 1 - IF4_gain gain1; + struct IF4_gain gain1; /// Gain 2 - IF4_gain gain2; + struct IF4_gain gain2; /// Gain 3 - IF4_gain gain3; + struct IF4_gain gain3; /// Gain 4 - IF4_gain gain4; + struct IF4_gain gain4; /// Gain 5 - IF4_gain gain5; + struct IF4_gain gain5; /// Gain 6 - IF4_gain gain6; + struct IF4_gain gain6; /// Gain 7 - IF4_gain gain7; + struct IF4_gain gain7; /// Data Blocks /// Frame Check Sequence @@ -144,7 +143,7 @@ struct IF4_prach_packet { /// Reserved uint32_t rsvd; /// LTE Prach Configuration - IF4_lte_prach_conf prach_conf; + struct IF4_lte_prach_conf prach_conf; /// Prach Data Block (one antenna) /// Frame Check Sequence @@ -153,12 +152,12 @@ struct IF4_prach_packet { // Needs to be checked -IF4_dl_packet gen_IF4_dl_packet(); +struct IF4_dl_packet gen_IF4_dl_packet(); -IF4_ul_packet gen_IF4_ul_packet(); +struct IF4_ul_packet gen_IF4_ul_packet(); -IF4_prach_packet gen_IF4_prach_packet(); +struct IF4_prach_packet gen_IF4_prach_packet(); -void send_IF4(PHY_VARS_eNB *eNB, int subframe); +void send_IF4( /* ADD INFO */ ); -void recv_IF4(PHY_VARS_eNB *eNB, int subframe); +void recv_IF4( /* ADD INFO */ ); From 1654af9a63c9071d7208738535a1602000933ec5 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 8 Jun 2016 00:28:16 +0200 Subject: [PATCH 033/206] removed some traces that flooded the screen. Added UE information in PHY/MAC/RRC to indicate status of active/failing UEs every 10.24 seconds. --- openair1/SCHED/phy_procedures_lte_eNb.c | 23 +++++++++++++---------- openair2/LAYER2/MAC/eNB_scheduler.c | 8 +++++--- openair2/RRC/LITE/rrc_common.c | 13 +++++++++++++ openair2/RRC/LITE/rrc_eNB.c | 3 ++- targets/RT/USER/lte-enb.c | 3 ++- targets/RT/USER/lte-softmodem.c | 2 +- 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 619a5d6329..4601781e68 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -159,12 +159,11 @@ int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB) { uint8_t i; -#ifdef DEBUG_PHY_PROC - LOG_I(PHY,"[eNB %d/%d] Adding UE with rnti %x\n", + + LOG_D(PHY,"[eNB %d/%d] Adding UE with rnti %x\n", eNB->Mod_id, eNB->CC_id, (uint16_t)rnti); -#endif for (i=0; idlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) { @@ -209,9 +208,9 @@ int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) { } else { if (eNB->UE_stats[i].crnti==rntiP) { MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP); -#ifdef DEBUG_PHY_PROC - LOG_I(PHY,"eNB %d removing UE %d with rnti %x\n",eNB->Mod_id,i,rnti); -#endif + + LOG_D(PHY,"eNB %d removing UE %d with rnti %x\n",eNB->Mod_id,i,rntiP); + //LOG_D(PHY,("[PHY] UE_id %d\n",i); clean_eNb_dlsch(eNB->dlsch[i][0]); clean_eNb_ulsch(eNB->ulsch[i]); @@ -841,7 +840,7 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC int frame = proc->frame_tx; int subframe = proc->subframe_tx; - LOG_I(PHY, + LOG_D(PHY, "[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8"), aggregation %d\n", eNB->Mod_id, subframe2harq_pid(fp, @@ -1137,7 +1136,11 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, for (i=0; iUE_stats[i].crnti > 0) { + LOG_I(PHY,"UE %d : rnti %x\n",i,eNB->UE_stats[i].crnti); + } + } if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) { LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n", eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors); @@ -1947,7 +1950,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits eNB->UE_stats[(uint32_t)UE_id].sector = 0; - LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", + LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, frame, @@ -2616,7 +2619,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const { //RX processing for ue-specific resources (i UNUSED(r_type); - uint32_t l, ret=0,i,j,k; + uint32_t ret=0,i,j,k; uint32_t harq_pid, harq_idx, round; uint8_t nPRS; int sync_pos; diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 65098e975f..4167db00fd 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -119,8 +119,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, while (i>=0) { rnti = UE_RNTI(module_idP, i); CC_id = UE_PCCID(module_idP, i); - LOG_D(MAC,"UE %d: rnti %x (%p)\n", i, rnti, - mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti)); + if ((frameP==0)&&(subframeP==0)) + LOG_I(MAC,"UE rnti %x : %s\n", rnti, + UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync"); + next_i= UE_list->next[i]; PHY_vars_eNB_g[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]=-63; @@ -317,7 +319,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, //if (subframeP%5 == 0) //#ifdef EXMIMO - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, 0,module_idP); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP); pdcp_run(&ctxt); //#endif diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c index 2092317647..e05e957e36 100644 --- a/openair2/RRC/LITE/rrc_common.c +++ b/openair2/RRC/LITE/rrc_common.c @@ -525,6 +525,19 @@ rrc_rx_tx( // check for UL failure RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head)) { + if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) { + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { + LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n", + ue_context_p->ue_context.rnti, + ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, + ue_context_p->ue_context.ul_failure_timer); + } + else { + LOG_I(RRC,"UE rnti %x failure timer %d/20000\n", + ue_context_p->ue_context.rnti, + ue_context_p->ue_context.ul_failure_timer); + } + } if (ue_context_p->ue_context.ul_failure_timer>0) { ue_context_p->ue_context.ul_failure_timer++; if (ue_context_p->ue_context.ul_failure_timer >= 20000) { diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index dcc3264828..b0ee647fc8 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -3742,12 +3742,13 @@ rrc_eNB_decode_ccch( if ((ue_context_p = rrc_eNB_ue_context_stmsi_exist(ctxt_pP, mme_code, m_tmsi))) { //#warning "TODO: stmsi_exist: remove UE from MAC/PHY (how?)" - LOG_I(RRC," S-TMSI exists, ue_context_p %p, old rnti %x => %x\n",ue_context_p,ue_context_p->ue_context.rnti); + LOG_I(RRC," S-TMSI exists, ue_context_p %p, old rnti %x => %x\n",ue_context_p,ue_context_p->ue_context.rnti,ctxt_pP->rnti); stmsi_received=1; ue_context_p->ue_context.rnti = ctxt_pP->rnti; // AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); // ue_context_p = NULL; } else { + LOG_I(RRC," S-TMSI doesn't exist, setting Initialue_identity_s_TMSI.m_tmsi to %x => %x\n",ue_context_p,m_tmsi); ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY); ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = TRUE; ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = mme_code; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index daeca00f42..373a13e150 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -741,7 +741,8 @@ static void* eNB_thread_rx_common( void* param ) #if defined(ENABLE_ITTI) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif - + if (openair0.trx_start_func(&openair0) != 0 ) + LOG_E(HW,"Could not start the device\n"); // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 26c4a9ae88..70769c6957 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1762,7 +1762,7 @@ int main( int argc, char **argv ) #ifndef USRP_DEBUG - if (mode!=loop_through_memory) + if ((UE_flag==1) && (mode!=loop_through_memory)) if (openair0.trx_start_func(&openair0) != 0 ) LOG_E(HW,"Could not start the device\n"); From d51d5deeaca2378cea73758a1e05d6aa519eabf0 Mon Sep 17 00:00:00 2001 From: "S. Sandeep Kumar" Date: Wed, 8 Jun 2016 04:00:13 +0530 Subject: [PATCH 034/206] fix some structures and add more details to if4 functions --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 211 +++++++++++-------------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 55 ++++--- 2 files changed, 130 insertions(+), 136 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index a42eae8798..e75a8675e9 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -45,153 +45,132 @@ #include "PHY/LTE_TRANSPORT/if4_tools.h" #endif -// Define how data blocks are stored and transferred - -//void send_IF4(PHY_VARS_eNB *eNB, int subframe){ - //eNB_proc_t *proc = &eNB->proc; - //int frame=proc->frame_tx; - //int subframe=proc->subframe_tx; - - //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - - //uint32_t i,j; - //float *data_block = malloc(length*sizeof(long)); - - // Generate IF4 packet (for now DL) with frame status information - //dl_packet = gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ); +void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { + int frame = proc->frame_tx; + int subframe = proc->subframe_tx; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - //for(i=0; isymbols_per_tti; i++) { - - // Do compression of the two parts and generate data blocks - - //symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] - //data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); - //data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); - - // Set data blocks and update subframe no./other information to generated packet - - - // Write the packet(s) to the fronthaul - - //} - -//} + uint16_t i; -void recv_IF4( /* ADD INFO and data_block pointer */ ) { + float_t data_block_length = 1200*(fp->ofdm_symbol_size/2048); + uint16_t *data_block = (uint16_t*)malloc(data_block_length*sizeof(uint16_t)); + + // Caller: RCC - DL *** handle RRU case - UL and PRACH *** + if (eNB->node_function == NGFI_RCC_IF4) { + IF4_dl_packet_t *dl_packet = (IF4_dl_packet_t*)malloc(sizeof_IF4_dl_packet_t); + gen_IF4_dl_packet(dl_packet, proc); + + dl_packet->data_block = data_block; + + for(i=0; isymbols_per_tti; i++) { + + //Do compression of the two parts and generate data blocks + + //symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] + //data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); + //data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); + + // Update information in generated packet + dl_packet->frame_status.sym_num = i; + + // Write the packet(s) to the fronthaul + + } + }else { + IF4_ul_packet_t *ul_packet = (IF4_ul_packet_t*)malloc(sizeof_IF4_ul_packet_t); + gen_IF4_ul_packet(ul_packet, proc); + + ul_packet->data_block = data_block; + + for(i=0; isymbols_per_tti; i++) { + + //Do compression of the two parts and generate data blocks + + //symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] + //data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); + //data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); + + // Update information in generated packet + ul_packet->frame_status.sym_num = i; + + // Write the packet(s) to the fronthaul + + } + } + +} + +void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { // Read packet(s) from the fronthaul // Apply reverse processing - decompression // Generate and return the OFDM symbols (txdataF) - + + // Caller: RRU - DL *** handle RCC case - UL and PRACH *** + } -struct IF4_dl_packet gen_IF4_dl_packet( /* ADD INFO and data_block pointer */ ) { - struct IF4_dl_packet dl_packet; - - // Set destination and source address - +void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type - dl_packet.type = 0x080A; - dl_packet.sub_type = 0x0020; + dl_packet->type = 0x080A; + dl_packet->sub_type = 0x0020; // Leave reserved as it is - //dl_packet.rsvd = ; + dl_packet->rsvd = 0; // Set frame status - dl_packet.frame_status.ant_num = 0; - dl_packet.frame_status.ant_start = 0; - dl_packet.frame_status.rf_num = 0; - dl_packet.frame_status.sf_num = 0; - dl_packet.frame_status.sym_num = 0; - //dl_packet.frame_status.rsvd = ; - - // Set data blocks if sent - //if (data_block != NULL) { - // - //} else { - // - //} - + dl_packet->frame_status.ant_num = 0; + dl_packet->frame_status.ant_start = 0; + dl_packet->frame_status.rf_num = proc->frame_tx; + dl_packet->frame_status.sf_num = proc->subframe_tx; + dl_packet->frame_status.sym_num = 0; + dl_packet->frame_status.rsvd = 0; + // Set frame check sequence - dl_packet.fcs = 0; - - return dl_packet; + dl_packet->fcs = 0; } -struct IF4_ul_packet gen_IF4_ul_packet( /* ADD INFO and data_block pointer */ ) { - struct IF4_ul_packet ul_packet; - - // Set destination and source address - +void gen_IF4_ul_packet(IF4_ul_packet_t *ul_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type - ul_packet.type = 0x080A; - ul_packet.sub_type = 0x0019; + ul_packet->type = 0x080A; + ul_packet->sub_type = 0x0019; // Leave reserved as it is - //ul_packet.rsvd = ; + ul_packet->rsvd = 0; // Set frame status - ul_packet.frame_status.ant_num = 0; - ul_packet.frame_status.ant_start = 0; - ul_packet.frame_status.rf_num = 0; - ul_packet.frame_status.sf_num = 0; - ul_packet.frame_status.sym_num = 0; - //ul_packet.frame_status.rsvd = ; + ul_packet->frame_status.ant_num = 0; + ul_packet->frame_status.ant_start = 0; + ul_packet->frame_status.rf_num = proc->frame_rx; + ul_packet->frame_status.sf_num = proc->subframe_rx; + ul_packet->frame_status.sym_num = 0; + ul_packet->frame_status.rsvd = 0; + + // Set antenna specific gain *** set other antenna gain *** + ul_packet->gain0.exponent = 0; + ul_packet->gain0.rsvd = 0; - // Set antenna specific gain - ul_packet.gain0.exponent = 0; - //ul_packet.gain0.rsvd = ; - - // Set data blocks if sent - //if (data_block != NULL) { - // - //} else { - // - //} - // Set frame check sequence - ul_packet.fcs = 0; - - return ul_packet; + ul_packet->fcs = 0; } -struct IF4_prach_packet gen_IF4_prach_packet( /* ADD INFO and data_block pointer */ ) { - struct IF4_prach_packet prach_packet; - - // Set destination and source address - +void gen_IF4_prach_packet(IF4_prach_packet_t *prach_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type - prach_packet.type = 0x080A; - prach_packet.sub_type = 0x0021; + prach_packet->type = 0x080A; + prach_packet->sub_type = 0x0021; // Leave reserved as it is - //prach_packet.rsvd = ; + prach_packet->rsvd = 0; // Set LTE Prach configuration - //prach_packet.prach_conf.rsvd = ; - prach_packet.prach_conf.ant = 0; - prach_packet.prach_conf.rf_num = 0; - prach_packet.prach_conf.sf_num = 0; - prach_packet.prach_conf.exponent = 0; - - // Set data blocks if sent - //if (data_block != NULL) { - // - //} else { - // - //} - + prach_packet->prach_conf.rsvd = 0; + prach_packet->prach_conf.ant = 0; + prach_packet->prach_conf.rf_num = proc->frame_rx; + prach_packet->prach_conf.sf_num = proc->subframe_rx; + prach_packet->prach_conf.exponent = 0; + // Set frame check sequence - prach_packet.fcs = 0; - - return prach_packet; + prach_packet->fcs = 0; } - -int main(){ - - uint32_t i=0; - - return 0; -} diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index c5bb46576c..819aca58d6 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -54,6 +54,9 @@ struct IF4_frame_status { uint32_t rsvd:2; }; +typedef struct IF4_frame_status IF4_frame_status_t; +#define sizeof_IF4_frame_status_t 4 + /// IF4 Antenna Gain (16 bits) struct IF4_gain { /// Reserved @@ -62,6 +65,9 @@ struct IF4_gain { uint16_t exponent:6; }; +typedef struct IF4_gain IF4_gain_t; +#define sizeof_IF_gain_t 2 + /// IF4 LTE PRACH Configuration (32 bits) struct IF4_lte_prach_conf { /// Reserved @@ -76,6 +82,9 @@ struct IF4_lte_prach_conf { uint32_t exponent:6; }; +typedef struct IF4_lte_prach_conf IF4_lte_prach_conf_t; +#define sizeof_IF4_lte_prach_conf_t 4 + struct IF4_dl_packet { /// Destination Address @@ -88,13 +97,15 @@ struct IF4_dl_packet { /// Reserved uint32_t rsvd; /// Frame Status - struct IF4_frame_status frame_status; + IF4_frame_status_t frame_status; /// Data Blocks - + uint16_t *data_block; /// Frame Check Sequence uint32_t fcs; }; +typedef struct IF4_dl_packet IF4_dl_packet_t; +#define sizeof_IF4_dl_packet_t 18 struct IF4_ul_packet { /// Destination Address @@ -108,29 +119,32 @@ struct IF4_ul_packet { /// Reserved uint32_t rsvd; /// Frame Status - struct IF4_frame_status frame_status; + IF4_frame_status_t frame_status; /// Gain 0 - struct IF4_gain gain0; + IF4_gain_t gain0; /// Gain 1 - struct IF4_gain gain1; + IF4_gain_t gain1; /// Gain 2 - struct IF4_gain gain2; + IF4_gain_t gain2; /// Gain 3 - struct IF4_gain gain3; + IF4_gain_t gain3; /// Gain 4 - struct IF4_gain gain4; + IF4_gain_t gain4; /// Gain 5 - struct IF4_gain gain5; + IF4_gain_t gain5; /// Gain 6 - struct IF4_gain gain6; + IF4_gain_t gain6; /// Gain 7 - struct IF4_gain gain7; + IF4_gain_t gain7; /// Data Blocks - + uint16_t *data_block; /// Frame Check Sequence uint32_t fcs; }; +typedef struct IF4_ul_packet IF4_ul_packet_t; +#define sizeof_IF4_ul_packet_t 34 + struct IF4_prach_packet { /// Destination Address @@ -143,21 +157,22 @@ struct IF4_prach_packet { /// Reserved uint32_t rsvd; /// LTE Prach Configuration - struct IF4_lte_prach_conf prach_conf; + IF4_lte_prach_conf_t prach_conf; /// Prach Data Block (one antenna) - + uint16_t *data_block; /// Frame Check Sequence uint32_t fcs; }; -// Needs to be checked +typedef struct IF4_prach_packet IF4_prach_packet_t; +#define sizeof_IF4_prach_packet_t 18 -struct IF4_dl_packet gen_IF4_dl_packet(); +void gen_IF4_dl_packet(IF4_dl_packet_t*, eNB_rxtx_proc_t*); -struct IF4_ul_packet gen_IF4_ul_packet(); +void gen_IF4_ul_packet(IF4_ul_packet_t*, eNB_rxtx_proc_t*); -struct IF4_prach_packet gen_IF4_prach_packet(); +void gen_IF4_prach_packet(IF4_prach_packet_t*, eNB_rxtx_proc_t*); -void send_IF4( /* ADD INFO */ ); +void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*); -void recv_IF4( /* ADD INFO */ ); +void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*); From 89eba068aa3fbc353ef2bf2eaddb3c5203a01767 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 8 Jun 2016 11:41:14 +0200 Subject: [PATCH 035/206] added comments on IF# split point phy_TX --- openair1/SCHED/phy_procedures_lte_eNb.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 4601781e68..c0165bc2e6 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1412,7 +1412,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #endif #if !(defined(EXMIMO) || defined(OAI_USRP) || defined (CPRIGW)) - + if (abstraction_flag==0) { start_meas(&eNB->ofdm_mod_stats); @@ -1429,10 +1429,27 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #endif + // Clean up split point *** RRU only function to recv and do_OFDM_mod *** + if (eNB->node_function == eNodeB_3GPP) { + // Add above to IF4 split + // do_OFDM_mod + + }else if (eNB->node_function == NGFI_RCC_IF4) { + //send_IF4(eNB,subframe<<1); + //send_IF4(eNB,(subframe<<1)+1); + + }else if (eNB->node_function == NGFI_RRU_IF4) { // => acquisition from RCC (IF4) + // get frame/subframe information from IF4 interface + + //recv_IF4(eNB,subframe<<1); + //recv_IF4(eNB,1+(subframe<<1)); + + //do_OFDM_mod + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,0); stop_meas(&eNB->phy_proc_tx); - - + } void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid) From f7b6d16c4ec6845c23df2d266de7de7c24a30210 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 8 Jun 2016 19:27:11 +0200 Subject: [PATCH 036/206] initializations for LMSSDR --- openair1/SCHED/phy_procedures_lte_eNb.c | 4 +++- targets/RT/USER/lte-enb.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 4601781e68..de44777c33 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2512,12 +2512,14 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl fp->nb_antennas_rx); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + /* printf("Frame %d, subframe %d : TS %lu => %d,%d (rxs %d)\n", + frame,subframe,proc->timestamp_rx,proc->frame_rx,proc->subframe_rx,rxs);*/ if (proc->first_rx == 0) { AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)",proc->subframe_rx,subframe); AssertFatal(proc->frame_rx == frame, "Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)",proc->frame_rx,frame); } else - proc->first_rx = 0; + proc->first_rx--;// = 0; // printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 373a13e150..7ab31098d2 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1045,7 +1045,7 @@ void init_eNB_proc(void) proc->instance_cnt_prach = -1; proc->CC_id = CC_id; - proc->first_rx=1; + proc->first_rx=4; pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); From a2e7ddee8621dfa15fd53aad2d18033072c39115 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 12 Jun 2016 04:56:16 -0700 Subject: [PATCH 037/206] fixed AVX2 issue in 3gpplte_sse.c --- openair1/PHY/CODING/3gpplte_sse.c | 12 ++- openair1/PHY/CODING/lte_segmentation.c | 2 +- openair1/PHY/INIT/lte_param_init.c | 3 +- openair1/PHY/LTE_ESTIMATION/defs.h | 1 + .../lte_ul_channel_estimation.c | 5 +- openair1/PHY/LTE_TRANSPORT/drs_modulation.c | 84 ++----------------- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 28 +++---- openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c | 2 +- openair1/PHY/TOOLS/ALAW/companders.c | 18 +++- openair1/SIMULATION/LTE_PHY/ulsim.c | 41 +++++---- 10 files changed, 75 insertions(+), 121 deletions(-) diff --git a/openair1/PHY/CODING/3gpplte_sse.c b/openair1/PHY/CODING/3gpplte_sse.c index 6806967921..99afa1cf5a 100755 --- a/openair1/PHY/CODING/3gpplte_sse.c +++ b/openair1/PHY/CODING/3gpplte_sse.c @@ -233,7 +233,7 @@ char interleave_compact_byte(short * base_interleaver,unsigned char * input, uns loop++; #endif - + for (i=0; i>1; + int input_length_words=1+((n-1)>>1); #else - int input_length_words=n>>2; + int input_length_words=1+((n-1)>>2); #endif + for ( i=0; i< input_length_words ; i ++ ) { + #if defined(__x86_64__) || defined(__i386__) #ifndef __AVX2__ tmp=_mm_insert_epi8(tmp,expandInput[*ptr_intl++],7); @@ -571,6 +573,7 @@ void threegpplte_turbo_encoder(unsigned char *input, unsigned char systematic2[768] __attribute__((aligned(32))); + interleave_compact_byte(base_interleaver,input,systematic2,input_length_bytes); #if defined(__x86_64__) || defined(__i386__) @@ -584,7 +587,7 @@ void threegpplte_turbo_encoder(unsigned char *input, for ( state0=state1=i=0 ; i>3)) { output_buffers[r][k] = input_buffer[s]; - // printf("encoding segment %d : byte %d => %d\n",r,k,input_buffer[s]); + // printf("encoding segment %d : byte %d (%d) => %d\n",r,k,Kr>>3,input_buffer[s]); k++; s++; } diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c index 0e18537965..a32a2441c7 100644 --- a/openair1/PHY/INIT/lte_param_init.c +++ b/openair1/PHY/INIT/lte_param_init.c @@ -28,10 +28,11 @@ void lte_param_init(unsigned char N_tx, LTE_DL_FRAME_PARMS *frame_parms; int i; - printf("Start lte_param_init\n"); eNB = malloc(sizeof(PHY_VARS_eNB)); UE = malloc(sizeof(PHY_VARS_UE)); + memset((void*)eNB,0,sizeof(PHY_VARS_eNB)); + memset((void*)UE,0,sizeof(PHY_VARS_UE)); //PHY_config = malloc(sizeof(PHY_CONFIG)); mac_xface = malloc(sizeof(MAC_xface)); diff --git a/openair1/PHY/LTE_ESTIMATION/defs.h b/openair1/PHY/LTE_ESTIMATION/defs.h index ebba52670d..c01b1435d9 100644 --- a/openair1/PHY/LTE_ESTIMATION/defs.h +++ b/openair1/PHY/LTE_ESTIMATION/defs.h @@ -217,6 +217,7 @@ void phy_adjust_gain (PHY_VARS_UE *phy_vars_ue, unsigned char eNB_id); int lte_ul_channel_estimation(PHY_VARS_eNB *phy_vars_eNB, + eNB_rxtx_proc_t *proc, module_id_t eNB_id, module_id_t UE_id, uint8_t l, diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 84975c1deb..8434d2a72c 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -53,6 +53,7 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32 #define SCALE 0x3FFF int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, uint8_t eNB_id, uint8_t UE_id, unsigned char l, @@ -67,8 +68,8 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, int32_t **ul_ch_estimates_0= pusch_vars->drs_ch_estimates_0[eNB_id]; int32_t **ul_ch_estimates_1= pusch_vars->drs_ch_estimates_1[eNB_id]; int32_t **rxdataF_ext= pusch_vars->rxdataF_ext[eNB_id]; - int subframe = eNB->proc.subframe_rx; - uint8_t harq_pid = subframe2harq_pid(frame_parms,eNB->proc.frame_rx,subframe); + int subframe = proc->subframe_rx; + uint8_t harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe); int16_t delta_phase = 0; int16_t *ru1 = ru_90; int16_t *ru2 = ru_90; diff --git a/openair1/PHY/LTE_TRANSPORT/drs_modulation.c b/openair1/PHY/LTE_TRANSPORT/drs_modulation.c index 2d3b9d3b23..8ccfc72d20 100644 --- a/openair1/PHY/LTE_TRANSPORT/drs_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/drs_modulation.c @@ -94,7 +94,7 @@ int generate_drs_pusch(PHY_VARS_UE *ue, if (Msc_idx_ptr) Msc_RS_idx = Msc_idx_ptr - dftsizes; else { - msg("generate_drs_pusch: index for Msc_RS=%d not found\n",Msc_RS); + printf("generate_drs_pusch: index for Msc_RS=%d not found\n",Msc_RS); return(-1); } @@ -107,7 +107,7 @@ int generate_drs_pusch(PHY_VARS_UE *ue, #endif #ifdef DEBUG_DRS - msg("[PHY] drs_modulation: Msc_RS = %d, Msc_RS_idx = %d,cyclic_shift %d, u0 %d, v0 %d, u1 %d, v1 %d,cshift0 %d,cshift1 %d\n",Msc_RS, Msc_RS_idx,cyclic_shift,u0,v0,u1,v1,cyclic_shift0,cyclic_shift1); + printf("[PHY] drs_modulation: Msc_RS = %d, Msc_RS_idx = %d,cyclic_shift %d, u0 %d, v0 %d, u1 %d, v1 %d,cshift0 %d,cshift1 %d\n",Msc_RS, Msc_RS_idx,cyclic_shift,u0,v0,u1,v1,cyclic_shift0,cyclic_shift1); #endif @@ -116,21 +116,17 @@ int generate_drs_pusch(PHY_VARS_UE *ue, lsymbols_per_tti; l += (7 - frame_parms->Ncp),u=u1,v=v1,cyclic_shift=cyclic_shift1) { - drs_offset = 0; // msg("drs_modulation: Msc_RS = %d, Msc_RS_idx = %d\n",Msc_RS, Msc_RS_idx); + drs_offset = 0; // printf("drs_modulation: Msc_RS = %d, Msc_RS_idx = %d\n",Msc_RS, Msc_RS_idx); + -#ifdef IFFT_FPGA_UE - re_offset = frame_parms->N_RB_DL*12/2; - subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->N_RB_UL*12; - symbol_offset = subframe_offset + frame_parms->N_RB_UL*12*l; -#else re_offset = frame_parms->first_carrier_offset; subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->ofdm_symbol_size; symbol_offset = subframe_offset + frame_parms->ofdm_symbol_size*l; -#endif + #ifdef DEBUG_DRS - msg("generate_drs_pusch: symbol_offset %d, subframe offset %d, cyclic shift %d\n",symbol_offset,subframe_offset,cyclic_shift); + printf("generate_drs_pusch: symbol_offset %d, subframe offset %d, cyclic shift %d\n",symbol_offset,subframe_offset,cyclic_shift); #endif alpha_ind = 0; @@ -139,60 +135,9 @@ int generate_drs_pusch(PHY_VARS_UE *ue, if ((rb >= first_rb) && (rb<(first_rb+nb_rb))) { #ifdef DEBUG_DRS - msg("generate_drs_pusch: doing RB %d, re_offset=%d, drs_offset=%d,cyclic shift %d\n",rb,re_offset,drs_offset,cyclic_shift); + printf("generate_drs_pusch: doing RB %d, re_offset=%d, drs_offset=%d,cyclic shift %d\n",rb,re_offset,drs_offset,cyclic_shift); #endif -#ifdef IFFT_FPGA_UE - - if (cyclic_shift == 0) { - for (k=0; k<12; k++) { - if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] >= 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] >= 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 1; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] >= 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] < 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 2; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] < 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] >= 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 3; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] < 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] < 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 4; - - re_offset++; - drs_offset++; - - if (re_offset >= frame_parms->N_RB_UL*12) - re_offset=0; - } - } else if(cyclic_shift == 6 ) { - for (k=0; k<12; k++) { - if(k%2 == 0) { - if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] >= 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] >= 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 4; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] >= 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] < 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 3; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] < 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] >= 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 2; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] < 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] < 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 1; - } else { - if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] >= 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] >= 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 1; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] >= 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] < 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 2; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] < 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] >= 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 3; - else if ((ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1] < 0) && (ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1] < 0)) - txdataF[symbol_offset+re_offset] = (int32_t) 4; - } - - re_offset++; - drs_offset++; - - if (re_offset >= frame_parms->N_RB_UL*12) - re_offset=0; - } - } - -#else //IFFT_FPGA_UE - for (k=0; k<12; k++) { ref_re = (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1]; ref_im = (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1]; @@ -211,7 +156,7 @@ int generate_drs_pusch(PHY_VARS_UE *ue, alpha_ind-=12; #ifdef DEBUG_DRS - msg("symbol_offset %d, alpha_ind %d , re_offset %d : (%d,%d)\n", + printf("symbol_offset %d, alpha_ind %d , re_offset %d : (%d,%d)\n", symbol_offset, alpha_ind, re_offset, @@ -226,21 +171,10 @@ int generate_drs_pusch(PHY_VARS_UE *ue, re_offset = 0; } -#endif // IFFT_FPGA_UE } else { re_offset+=12; // go to next RB // check if we crossed the symbol boundary and skip DC -#ifdef IFFT_FPGA_UE - - if (re_offset >= frame_parms->N_RB_DL*12) { - if (frame_parms->N_RB_DL&1) // odd number of RBs - re_offset=6; - else // even number of RBs (doesn't straddle DC) - re_offset=0; - } - -#else if (re_offset >= frame_parms->ofdm_symbol_size) { if (frame_parms->N_RB_DL&1) // odd number of RBs @@ -249,7 +183,7 @@ int generate_drs_pusch(PHY_VARS_UE *ue, re_offset=0; } -#endif + } } } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 59cf11a06c..25ba06077f 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -739,7 +739,7 @@ void ulsch_extract_rbs_single(int32_t **rxdataF, nb_rb2 = 2*nb_rb - nb_rb1; // 2 times no. RBs after the DC #ifdef DEBUG_ULSCH - msg("ulsch_extract_rbs_single: 2*nb_rb1 = %d, 2*nb_rb2 = %d\n",nb_rb1,nb_rb2); + printf("ulsch_extract_rbs_single: 2*nb_rb1 = %d, 2*nb_rb2 = %d\n",nb_rb1,nb_rb2); #endif rxF_ext = &rxdataF_ext[aarx][(symbol*frame_parms->N_RB_UL*12)]; @@ -1608,7 +1608,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe); Qm = get_Qm_ul(ulsch[UE_id]->harq_processes[harq_pid]->mcs); #ifdef DEBUG_ULSCH - msg("rx_ulsch: eNB_id %d, harq_pid %d, nb_rb %d first_rb %d, cooperation %d\n",eNB_id,harq_pid,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,ulsch[UE_id]->harq_processes[harq_pid]->first_rb, + printf("rx_ulsch: eNB_id %d, harq_pid %d, nb_rb %d first_rb %d, cooperation %d\n",eNB_id,harq_pid,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,ulsch[UE_id]->harq_processes[harq_pid]->first_rb, cooperation_flag); #endif //DEBUG_ULSCH @@ -1622,7 +1622,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, for (l=0; l<(frame_parms->symbols_per_tti-ulsch[UE_id]->harq_processes[harq_pid]->srs_active); l++) { #ifdef DEBUG_ULSCH - msg("rx_ulsch : symbol %d (first_rb %d,nb_rb %d), rxdataF %p, rxdataF_ext %p\n",l, + printf("rx_ulsch : symbol %d (first_rb %d,nb_rb %d), rxdataF %p, rxdataF_ext %p\n",l, ulsch[UE_id]->harq_processes[harq_pid]->first_rb, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, common_vars->rxdataF[eNB_id], @@ -1637,7 +1637,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, l/(frame_parms->symbols_per_tti/2), frame_parms); - lte_ul_channel_estimation(eNB, + lte_ul_channel_estimation(eNB,proc, eNB_id, UE_id, l%(frame_parms->symbols_per_tti/2), @@ -1681,7 +1681,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, avgU_0, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); - // msg("[ULSCH] avg_0[0] %d\n",avgU_0[0]); + // printf("[ULSCH] avg_0[0] %d\n",avgU_0[0]); avgs_0 = 0; @@ -1691,7 +1691,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, log2_maxh_0 = (log2_approx(avgs_0)/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+3; #ifdef DEBUG_ULSCH - msg("[ULSCH] log2_maxh_0 = %d (%d,%d)\n",log2_maxh_0,avgU_0[0],avgs_0); + printf("[ULSCH] log2_maxh_0 = %d (%d,%d)\n",log2_maxh_0,avgU_0[0],avgs_0); #endif ulsch_channel_level(pusch_vars->drs_ch_estimates_1[eNB_id], @@ -1699,7 +1699,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, avgU_1, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); - // msg("[ULSCH] avg_1[0] %d\n",avgU_1[0]); + // printf("[ULSCH] avg_1[0] %d\n",avgU_1[0]); avgs_1 = 0; @@ -1709,7 +1709,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, log2_maxh_1 = (log2_approx(avgs_1)/2) + log2_approx(frame_parms->nb_antennas_rx-1)+3; #ifdef DEBUG_ULSCH - msg("[ULSCH] log2_maxh_1 = %d (%d,%d)\n",log2_maxh_1,avgU_1[0],avgs_1); + printf("[ULSCH] log2_maxh_1 = %d (%d,%d)\n",log2_maxh_1,avgU_1[0],avgs_1); #endif log2_maxh = max(log2_maxh_0,log2_maxh_1); } else { @@ -1718,7 +1718,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, avgU, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb); - // msg("[ULSCH] avg[0] %d\n",avgU[0]); + // printf("[ULSCH] avg[0] %d\n",avgU[0]); avgs = 0; @@ -1731,7 +1731,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, log2_maxh = (log2_approx(avgs)/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+4; #ifdef DEBUG_ULSCH - msg("[ULSCH] log2_maxh = %d (%d,%d)\n",log2_maxh,avgU[0],avgs); + printf("[ULSCH] log2_maxh = %d (%d,%d)\n",log2_maxh,avgU[0],avgs); #endif } @@ -1827,11 +1827,11 @@ void rx_ulsch(PHY_VARS_eNB *eNB, //#ifdef DEBUG_ULSCH // Inverse-Transform equalized outputs - // msg("Doing IDFTs\n"); + // printf("Doing IDFTs\n"); lte_idft(frame_parms, (uint32_t*)pusch_vars->rxdataF_comp[eNB_id][0], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); - // msg("Done\n"); + // printf("Done\n"); //#endif //DEBUG_ULSCH #endif @@ -1877,7 +1877,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, default: #ifdef DEBUG_ULSCH - msg("ulsch_demodulation.c (rx_ulsch): Unknown Qm!!!!\n"); + printf("ulsch_demodulation.c (rx_ulsch): Unknown Qm!!!!\n"); #endif //DEBUG_ULSCH break; } @@ -1890,7 +1890,7 @@ void rx_ulsch_emul(PHY_VARS_eNB *eNB, uint8_t sect_id, uint8_t UE_index) { - msg("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",eNB->Mod_id,proc->subframe_rx,sect_id,UE_index); + printf("[PHY] EMUL eNB %d rx_ulsch_emul : subframe %d, sect_id %d, UE_index %d\n",eNB->Mod_id,proc->subframe_rx,sect_id,UE_index); eNB->pusch_vars[UE_index]->ulsch_power[0] = 31622; //=45dB; eNB->pusch_vars[UE_index]->ulsch_power[1] = 31622; //=45dB; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c index 32d3f3e34d..a60e27908b 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c @@ -754,7 +754,7 @@ void ulsch_modulation(int32_t **txdataF, re_offset = re_offset0; symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe*nsymb)); #ifdef DEBUG_ULSCH_MODULATION - printf("ulsch_mod (OFDMA) symbol %d (subframe %d): symbol_offset %d\n",l,subframe,symbol_offset); + printf("ulsch_mod (SC-FDMA) symbol %d (subframe %d): symbol_offset %d\n",l,subframe,symbol_offset); #endif txptr = &txdataF[0][symbol_offset]; diff --git a/openair1/PHY/TOOLS/ALAW/companders.c b/openair1/PHY/TOOLS/ALAW/companders.c index b089716977..566c7d6cf3 100644 --- a/openair1/PHY/TOOLS/ALAW/companders.c +++ b/openair1/PHY/TOOLS/ALAW/companders.c @@ -45,8 +45,9 @@ DIO_s8 DIO_LinearToALaw(DIO_s16 sample) }; DIO_s32 sign, exponent, mantissa; - DIO_s8 compandedValue; - sample = (sample ==-32768) ? -32767 : sample; + DIO_s8 compandedValue; + + sample = (sample ==-32768) ? -32767 : sample; sign = ((~sample) >> 8) & 0x80; if (!sign) sample = (short)-sample; @@ -123,3 +124,16 @@ DIO_s32 DIO_IIRavgPower2FR (DIO_s32 prevAvg, DIO_u8 windowLenInBits, DIO_s16 new iirAvg = (((prevAvg<>windowLenInBits; return iirAvg; } + + +#ifdef MAIN + +int main(int argc, char* argv[]) +{ + + + + return 0; +} + +#endif diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 96c0083f94..135ad59037 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -668,7 +668,7 @@ int main(int argc, char **argv) if (eNB->frame_parms.frame_type == TDD) { ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; @@ -678,7 +678,7 @@ int main(int argc, char **argv) } else { ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->type = 0; ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; @@ -692,7 +692,7 @@ int main(int argc, char **argv) if (eNB->frame_parms.frame_type == TDD) { ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; @@ -702,7 +702,7 @@ int main(int argc, char **argv) } else { ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->type = 0; ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); + //printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; @@ -754,16 +754,15 @@ int main(int argc, char **argv) eNB->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + eNB_rxtx_proc_t *proc_rxtx = &eNB->proc.proc_rxtx[subframe&1]; + proc_rxtx->frame_rx=1; + proc_rxtx->subframe_rx=subframe; + proc_rxtx->frame_tx=pdcch_alloc2ul_frame(&eNB->frame_parms,1,subframe); + proc_rxtx->subframe_tx=pdcch_alloc2ul_subframe(&eNB->frame_parms,subframe); - eNB->proc.frame_rx=1; - eNB->proc.subframe_rx=subframe; - - eNB->proc.frame_tx=pdcch_alloc2ul_frame(&eNB->frame_parms,1,subframe); - eNB->proc.subframe_tx=pdcch_alloc2ul_subframe(&eNB->frame_parms,subframe); - - UE->frame_tx = eNB->proc.frame_rx; - UE->frame_rx = eNB->proc.frame_tx; + UE->frame_tx = proc_rxtx->frame_rx; + UE->frame_rx = proc_rxtx->frame_tx; printf("Init UL hopping UE\n"); init_ul_hopping(&UE->frame_parms); @@ -773,11 +772,11 @@ int main(int argc, char **argv) UE->dlsch[0][0]->harq_ack[ul_subframe2pdcch_alloc_subframe(&eNB->frame_parms,subframe)].send_harq_status = 1; - - + UE->ulsch_Msg3_active[eNB_id] = 0; + UE->ul_power_control_dedicated[eNB_id].accumulationEnabled=1; generate_ue_ulsch_params_from_dci((void *)&UL_alloc_pdu, 14, - eNB->proc.subframe_tx, + proc_rxtx->subframe_tx, format0, UE, SI_RNTI, @@ -789,7 +788,7 @@ int main(int argc, char **argv) // printf("RIV %d\n",UL_alloc_pdu.rballoc); - generate_eNB_ulsch_params_from_dci(eNB, + generate_eNB_ulsch_params_from_dci(eNB,proc_rxtx, (void *)&UL_alloc_pdu, 14, format0, @@ -848,7 +847,7 @@ int main(int argc, char **argv) harq_pid = subframe2harq_pid(&UE->frame_parms,UE->frame_tx,subframe); input_buffer_length = UE->ulsch[0]->harq_processes[harq_pid]->TBS/8; - input_buffer = (unsigned char *)malloc(input_buffer_length+4); + input_buffer = (unsigned char *)memalign(32,input_buffer_length+64); // printf("UL frame %d/subframe %d, harq_pid %d\n",UE->frame,subframe,harq_pid); if (input_fdUL == NULL) { @@ -1230,7 +1229,7 @@ int main(int argc, char **argv) */ start_meas(&eNB->ulsch_demodulation_stats); - rx_ulsch(eNB, + rx_ulsch(eNB,proc_rxtx, 0, // this is the effective sector id 0, // this is the UE_id eNB->ulsch, @@ -1253,7 +1252,7 @@ int main(int argc, char **argv) start_meas(&eNB->ulsch_decoding_stats); - ret= ulsch_decoding(eNB, + ret= ulsch_decoding(eNB,proc_rxtx, 0, // UE_id control_only_flag, 1, // Nbundled @@ -1303,7 +1302,7 @@ int main(int argc, char **argv) print_CQI(eNB->ulsch[0]->harq_processes[harq_pid]->o, eNB->ulsch[0]->harq_processes[harq_pid]->uci_format,0,eNB->frame_parms.N_RB_DL); - dump_ulsch(eNB,0); + dump_ulsch(eNB,proc_rxtx,0); exit(-1); } @@ -1332,7 +1331,7 @@ int main(int argc, char **argv) eNB->ulsch[0]->harq_processes[harq_pid]->c[s][i]^UE->ulsch[0]->harq_processes[harq_pid]->c[s][i]); } - dump_ulsch(eNB,0); + dump_ulsch(eNB,proc_rxtx,0); exit(-1); } From 9c159229d52b3f10467ab752ee21ca14443001f3 Mon Sep 17 00:00:00 2001 From: "S. Sandeep Kumar" Date: Mon, 13 Jun 2016 02:48:05 +0530 Subject: [PATCH 038/206] added rcc rx recv_IF4 logic --- openair1/PHY/LTE_TRANSPORT/prach.c | 5 +++-- openair1/SCHED/phy_procedures_lte_eNb.c | 28 +++++++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 15c7bda045..0f806e2ea1 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1272,9 +1272,10 @@ void rx_prach(PHY_VARS_eNB *eNB, //send prachF to RCC return; } - else if (eNB->node_function == NGFI_RCC_IF4) { + // in case of RCC and prach received rx_thread wakes up prach + //else if (eNB->node_function == NGFI_RCC_IF4) { //wait for prachF from RRU and continue with PRACH processing - } + //} diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index c0165bc2e6..785001e8f4 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2498,7 +2498,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; - + int symbol_number, symbol_mask, symbol_mask_full, prach_rx; if (subframe==9) { subframe=0; @@ -2577,10 +2577,30 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } else if (eNB->node_function == NGFI_RCC_IF4) { // => acquisition from RRU (IF4) - // get frame/subframe information from IF4 interface + // get frame/subframe information from IF4 interface + // timed loop (200 us) + + symbol_mask = 0; + symbol_mask_full = (1<symbols_per_tti)-1; + if (is_prach_subframe(fp,frame,subframe)>0) + prach_rx = 0; + else + prach_rx = 1; + + do { + recv_IF4(eNB, proc, &packet_type, &symbol_number); + if (is_prach_subframe(fp,frame,subframe)>0 && packet_type == PRACH) { + // wake up prach_rx + prach_rx = 1; + } + if (packet_type == PULFFT) + symbol_mask = symbol_mask | (1< Date: Sun, 12 Jun 2016 21:44:40 -0700 Subject: [PATCH 039/206] fixed unitary simulators --- openair1/SIMULATION/LTE_PHY/pbchsim.c | 342 ++++++++++++------------- openair1/SIMULATION/LTE_PHY/pdcchsim.c | 15 +- 2 files changed, 175 insertions(+), 182 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/pbchsim.c b/openair1/SIMULATION/LTE_PHY/pbchsim.c index 4a2b3f9351..624ce7ad3e 100644 --- a/openair1/SIMULATION/LTE_PHY/pbchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pbchsim.c @@ -52,8 +52,10 @@ #include "OCG_vars.h" -PHY_VARS_eNB *PHY_vars_eNB,*PHY_vars_eNB1,*PHY_vars_eNB2; -PHY_VARS_UE *PHY_vars_UE; +#include "unitary_defs.h" + +PHY_VARS_eNB *eNB,*eNB1,*eNB2; +PHY_VARS_UE *UE; #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 @@ -123,17 +125,7 @@ int main(int argc, char **argv) logInit(); number_of_cards = 1; - openair_daq_vars.rx_rf_mode = 1; - /* - rxdataF = (int **)malloc16(2*sizeof(int*)); - rxdataF[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdataF[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - - rxdata = (int **)malloc16(2*sizeof(int*)); - rxdata[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - rxdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - */ while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:N:F:GR:O:dP:")) != -1) { switch (c) { case 'f': @@ -340,29 +332,29 @@ int main(int argc, char **argv) if (transmission_mode>=2) n_tx=2; - lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,N_RB_DL,osf); + lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,3,N_RB_DL,0,osf,0); - PHY_vars_eNB1 = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_eNB2 = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_UE->PHY_measurements.n_adj_cells=2; - PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; - PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; + eNB1 = malloc(sizeof(PHY_VARS_eNB)); + eNB2 = malloc(sizeof(PHY_VARS_eNB)); + UE->measurements.n_adj_cells=2; + UE->measurements.adj_cell_id[0] = Nid_cell+1; + UE->measurements.adj_cell_id[1] = Nid_cell+2; for (i=0; i<3; i++) - lte_gold(&PHY_vars_eNB->lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); + lte_gold(&eNB->frame_parms,UE->lte_gold_table[i],Nid_cell+i); - memcpy((void*)&PHY_vars_eNB1->lte_frame_parms,(void*)&PHY_vars_eNB->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNB1->lte_frame_parms.Nid_cell=Nid_cell+1; - PHY_vars_eNB1->lte_frame_parms.nushift=(Nid_cell+1)%6; - PHY_vars_eNB1->Mod_id=1; + memcpy((void*)&eNB1->frame_parms,(void*)&eNB->frame_parms,sizeof(LTE_DL_FRAME_PARMS)); + eNB1->frame_parms.Nid_cell=Nid_cell+1; + eNB1->frame_parms.nushift=(Nid_cell+1)%6; + eNB1->Mod_id=1; - memcpy((void*)&PHY_vars_eNB2->lte_frame_parms,(void*)&PHY_vars_eNB->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNB2->lte_frame_parms.Nid_cell=Nid_cell+2; - PHY_vars_eNB2->lte_frame_parms.nushift=(Nid_cell+2)%6; - PHY_vars_eNB2->Mod_id=2; + memcpy((void*)&eNB2->frame_parms,(void*)&eNB->frame_parms,sizeof(LTE_DL_FRAME_PARMS)); + eNB2->frame_parms.Nid_cell=Nid_cell+2; + eNB2->frame_parms.nushift=(Nid_cell+2)%6; + eNB2->Mod_id=2; - phy_init_lte_eNB(PHY_vars_eNB1,0,0,0); - phy_init_lte_eNB(PHY_vars_eNB2,0,0,0); + phy_init_lte_eNB(eNB1,0,0,0); + phy_init_lte_eNB(eNB2,0,0,0); #ifdef XFORMS fl_initialize (&argc, argv, NULL, 0, 0); @@ -380,13 +372,13 @@ int main(int argc, char **argv) printf("SNR0 %f, SNR1 %f\n",snr0,snr1); - frame_parms = &PHY_vars_eNB->lte_frame_parms; + frame_parms = &eNB->frame_parms; - txdata = PHY_vars_eNB->lte_eNB_common_vars.txdata[0]; - txdata1 = PHY_vars_eNB1->lte_eNB_common_vars.txdata[0]; - txdata2 = PHY_vars_eNB2->lte_eNB_common_vars.txdata[0]; + txdata = eNB->common_vars.txdata[0]; + txdata1 = eNB1->common_vars.txdata[0]; + txdata2 = eNB2->common_vars.txdata[0]; s_re = malloc(2*sizeof(double*)); @@ -407,8 +399,8 @@ int main(int argc, char **argv) printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Symbols per subframe %d, interf (%d,%d)\n",NUMBER_OF_OFDM_CARRIERS, frame_parms->Ncp,frame_parms->samples_per_tti,nsymb,interf1,interf2); - printf("PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0] = %p\n", - PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0]); + printf("eNB1->common_vars.txdataF[0][0] = %p\n", + eNB1->common_vars.txdataF[0][0]); DLSCH_alloc_pdu2.rah = 0; @@ -423,31 +415,31 @@ int main(int argc, char **argv) // Forget second codeword DLSCH_alloc_pdu2.tpmi = (transmission_mode==6 ? 5 : 0) ; // precoding - eNB2UE = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 0, 0); if (interf1>-20) - eNB2UE1 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + eNB2UE1 = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 4, 0); if (interf2>-20) - eNB2UE2 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + eNB2UE2 = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 8, 0); @@ -511,47 +503,47 @@ int main(int argc, char **argv) pbch_pdu[1]=1; pbch_pdu[2]=0; - if (PHY_vars_eNB->lte_frame_parms.frame_type == 0) { - generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + if (eNB->frame_parms.frame_type == 0) { + generate_pss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, - (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, + &eNB->frame_parms, + (eNB->frame_parms.Ncp==0) ? 6 : 5, 0); - generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_sss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, - (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4, + &eNB->frame_parms, + (eNB->frame_parms.Ncp==0) ? 5 : 4, 0); - generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_pss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, - (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, + &eNB->frame_parms, + (eNB->frame_parms.Ncp==0) ? 6 : 5, 10); - generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_sss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, - (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4, + &eNB->frame_parms, + (eNB->frame_parms.Ncp==0) ? 5 : 4, 10); } else { - generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_sss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, - (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, + &eNB->frame_parms, + (eNB->frame_parms.Ncp==0) ? 6 : 5, 1); - generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_pss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, 2, 2); - generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_sss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, - (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, + &eNB->frame_parms, + (eNB->frame_parms.Ncp==0) ? 6 : 5, 11); - generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_pss(eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, 2, 12); @@ -570,11 +562,11 @@ int main(int argc, char **argv) dci_alloc[1].rnti = 0x1234; */ - printf("Generating PBCH for mode1_flag = %d\n", PHY_vars_eNB->lte_frame_parms.mode1_flag); + printf("Generating PBCH for mode1_flag = %d\n", eNB->frame_parms.mode1_flag); - generate_pilots(PHY_vars_eNB, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_pilots(eNB, + eNB->common_vars.txdataF[0], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); @@ -585,8 +577,8 @@ int main(int argc, char **argv) dci_alloc, 0, 1024, - &PHY_vars_eNB->lte_frame_parms, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + &eNB->frame_parms, + eNB->common_vars.txdataF[0], 0); */ @@ -601,47 +593,47 @@ int main(int argc, char **argv) dummybuf[1] = dummy1; dummybuf[2] = dummy2; dummybuf[3] = dummy3; - generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, + generate_pbch(&eNB->pbch, (int32_t**)dummybuf, AMP, - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, pbch_pdu, 0); } - generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_pbch(&eNB->pbch, + eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, pbch_pdu, pbch_phase); /* - generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, - PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], + generate_pbch(&eNB->pbch, + eNB->common_vars.txdataF[0], AMP, - &PHY_vars_eNB->lte_frame_parms, + &eNB->frame_parms, pbch_pdu, 1); */ if (interf1>-20) { /* - generate_pss(PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0], + generate_pss(eNB1->common_vars.txdataF[0], AMP, - &PHY_vars_eNB1->lte_frame_parms, - (PHY_vars_eNB1->lte_frame_parms.Ncp==0)?6:5, + &eNB1->frame_parms, + (eNB1->frame_parms.Ncp==0)?6:5, 0); */ - generate_pilots(PHY_vars_eNB1, - PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0], + generate_pilots(eNB1, + eNB1->common_vars.txdataF[0], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); - generate_pbch(&PHY_vars_eNB1->lte_eNB_pbch, - PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0], + generate_pbch(&eNB1->pbch, + eNB1->common_vars.txdataF[0], AMP, - &PHY_vars_eNB1->lte_frame_parms, + &eNB1->frame_parms, pbch_pdu, 0); @@ -649,38 +641,38 @@ int main(int argc, char **argv) if (interf2>-20) { /* - generate_pss(PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0], + generate_pss(eNB2->common_vars.txdataF[0], AMP, - &PHY_vars_eNB2->lte_frame_parms, - (PHY_vars_eNB2->lte_frame_parms.Ncp==0)?6:5, + &eNB2->frame_parms, + (eNB2->frame_parms.Ncp==0)?6:5, 0); */ - generate_pilots(PHY_vars_eNB2, - PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0], + generate_pilots(eNB2, + eNB2->common_vars.txdataF[0], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); - generate_pbch(&PHY_vars_eNB2->lte_eNB_pbch, - PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0], + generate_pbch(&eNB2->pbch, + eNB2->common_vars.txdataF[0], AMP, - &PHY_vars_eNB2->lte_frame_parms, + &eNB2->frame_parms, pbch_pdu, 0); } - // write_output("pilotsF.m","rsF",txdataF[0],lte_frame_parms->ofdm_symbol_size,1,1); + // write_output("pilotsF.m","rsF",txdataF[0],frame_parms->ofdm_symbol_size,1,1); - write_output("txsigF0.m","txsF0", PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0.m","txsF0", eNB->common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1.m","txsF1", PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (eNB->frame_parms.nb_antennas_tx>1) + write_output("txsigF1.m","txsF1", eNB->common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); tx_lev = 0; tx_lev1 = 0; @@ -689,16 +681,16 @@ int main(int argc, char **argv) - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][aa], // input, + PHY_ofdm_mod(eNB->common_vars.txdataF[0][aa], // input, txdata[aa], // output frame_parms->ofdm_symbol_size, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][aa], + normal_prefix_mod(eNB->common_vars.txdataF[0][aa], txdata[aa], LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, frame_parms); @@ -709,17 +701,17 @@ int main(int argc, char **argv) } if (interf1>-20) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][aa], // input, - PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][aa], // output + PHY_ofdm_mod(eNB1->common_vars.txdataF[0][aa], // input, + eNB1->common_vars.txdata[0][aa], // output frame_parms->ofdm_symbol_size, 2*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][aa], - PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][aa], + normal_prefix_mod(eNB1->common_vars.txdataF[0][aa], + eNB1->common_vars.txdata[0][aa], 2*nsymb, frame_parms); } @@ -728,24 +720,24 @@ int main(int argc, char **argv) OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES); } - write_output("txsigF0_1.m","txsF0_1", PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0_1.m","txsF0_1", eNB1->common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNB1->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1_1.m","txsF1_1", PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (eNB1->frame_parms.nb_antennas_tx>1) + write_output("txsigF1_1.m","txsF1_1", eNB1->common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); } if (interf2>-20) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][aa], // input, - PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][aa], // output + PHY_ofdm_mod(eNB2->common_vars.txdataF[0][aa], // input, + eNB2->common_vars.txdata[0][aa], // output frame_parms->ofdm_symbol_size, 2*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][aa], - PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][aa], + normal_prefix_mod(eNB2->common_vars.txdataF[0][aa], + eNB2->common_vars.txdata[0][aa], 2*nsymb, frame_parms); } @@ -754,10 +746,10 @@ int main(int argc, char **argv) OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES); } - write_output("txsigF0_2.m","txsF0_2", PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0_2.m","txsF0_2", eNB2->common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNB2->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1_2.m","txsF1_2", PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (eNB2->frame_parms.nb_antennas_tx>1) + write_output("txsigF1_2.m","txsF1_2", eNB2->common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); } // tx_lev_dB = (unsigned int) dB_fixed(tx_lev); @@ -767,15 +759,15 @@ int main(int argc, char **argv) if (frame_parms->nb_antennas_tx>1) write_output("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); - write_output("txsig0_1.m","txs0_1", PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig0_1.m","txs0_1", eNB1->common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); if (frame_parms->nb_antennas_tx>1) - write_output("txsig1_1.m","txs1_1", PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig1_1.m","txs1_1", eNB1->common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); - write_output("txsig0_2.m","txs0_2", PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig0_2.m","txs0_2", eNB2->common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); if (frame_parms->nb_antennas_tx>1) - write_output("txsig1_2.m","txs1_2", PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig1_2.m","txs1_2", eNB2->common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); } else { //read in from file i=0; @@ -811,7 +803,7 @@ int main(int argc, char **argv) // multipath channel for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { s_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); s_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); @@ -872,7 +864,7 @@ int main(int argc, char **argv) } } - sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(double)(12*NB_RB)) - SNR; + sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(12*NB_RB)) - SNR; if (n_frames==1) printf("sigma2_dB %f (SNR %f dB) tx_lev_dB %f,%f,%f\n",sigma2_dB,SNR, @@ -894,20 +886,20 @@ int main(int argc, char **argv) for (n_trials=0; n_trialslte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { if (n_trials==0) { r_re[aa][i] += (pow(10.0,.05*interf1)*r_re1[aa][i] + pow(10.0,.05*interf2)*r_re2[aa][i]); r_im[aa][i] += (pow(10.0,.05*interf1)*r_im1[aa][i] + pow(10.0,.05*interf2)*r_im2[aa][i]); } - ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[2*i] = (short) (.167*(r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[2*i+1] = (short) (.167*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) UE->common_vars.rxdata[aa])[2*i] = (short) (.167*(r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) (.167*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } } if (n_frames==1) { printf("rx_level data symbol %f\n", - 10*log10(signal_energy(&PHY_vars_UE->lte_ue_common_vars.rxdata[0][frame_parms->samples_per_tti/2],4*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES))); + 10*log10(signal_energy(&UE->common_vars.rxdata[0][frame_parms->samples_per_tti/2],4*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES))); } @@ -919,10 +911,10 @@ int main(int argc, char **argv) exit(0); } - result = fread((void *)PHY_vars_UE->lte_ue_common_vars.rxdata[0],4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file); + result = fread((void *)UE->common_vars.rxdata[0],4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file); printf("Read %d bytes\n",result); - if (PHY_vars_UE->lte_frame_parms.nb_antennas_rx>1) { - result = fread((void *)PHY_vars_UE->lte_ue_common_vars.rxdata[1],4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file); + if (UE->frame_parms.nb_antennas_rx>1) { + result = fread((void *)UE->common_vars.rxdata[1],4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file); printf("Read %d bytes\n",result); } @@ -930,21 +922,21 @@ int main(int argc, char **argv) */ - for (l=0; llte_frame_parms.symbols_per_tti; l++) { + for (l=0; lframe_parms.symbols_per_tti; l++) { - // subframe_offset = (l/PHY_vars_eNB->lte_frame_parms.symbols_per_tti)*PHY_vars_eNB->lte_frame_parms.samples_per_tti; + // subframe_offset = (l/eNB->frame_parms.symbols_per_tti)*eNB->frame_parms.samples_per_tti; // printf("subframe_offset = %d\n",subframe_offset); - slot_fep(PHY_vars_UE, - l%(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2), - l/(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2), + slot_fep(UE, + l%(eNB->frame_parms.symbols_per_tti/2), + l/(eNB->frame_parms.symbols_per_tti/2), 0, 0, 0); if (l==0) { - lte_ue_measurements(PHY_vars_UE, + lte_ue_measurements(UE, 0, 1, 0); @@ -952,19 +944,19 @@ int main(int argc, char **argv) if (trial%100 == 0) { msg("[PHY_PROCEDURES_LTE] frame %d, RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), RX gain %d dB\n", trial, - PHY_vars_UE->PHY_measurements.rx_rssi_dBm[0], - PHY_vars_UE->PHY_measurements.rx_power_dB[0][0], - PHY_vars_UE->PHY_measurements.rx_power_dB[0][1], - PHY_vars_UE->PHY_measurements.rx_power[0][0], - PHY_vars_UE->PHY_measurements.rx_power[0][1], - PHY_vars_UE->rx_total_gain_dB); + UE->measurements.rx_rssi_dBm[0], + UE->measurements.rx_power_dB[0][0], + UE->measurements.rx_power_dB[0][1], + UE->measurements.rx_power[0][0], + UE->measurements.rx_power[0][1], + UE->rx_total_gain_dB); msg("[PHY_PROCEDURES_LTE] frame %d, N0 digital (%d, %d) dB, linear (%d, %d)\n", trial, - PHY_vars_UE->PHY_measurements.n0_power_dB[0], - PHY_vars_UE->PHY_measurements.n0_power_dB[1], - PHY_vars_UE->PHY_measurements.n0_power[0], - PHY_vars_UE->PHY_measurements.n0_power[1]); + UE->measurements.n0_power_dB[0], + UE->measurements.n0_power_dB[1], + UE->measurements.n0_power[0], + UE->measurements.n0_power[1]); msg("[PHY_PROCEDURES_LTE] frame %d, freq_offset_filt = %d\n", trial, freq_offset); @@ -973,47 +965,47 @@ int main(int argc, char **argv) */ } - if (l==((PHY_vars_eNB->lte_frame_parms.Ncp==0)?4:3)) { + if (l==((eNB->frame_parms.Ncp==0)?4:3)) { //sprintf(fname,"dl_ch00_%d.m",l); //sprintf(vname,"dl_ch00_%d",l); - //write_output(fname,vname,&(lte_ue_common_vars->dl_ch_estimates[0][lte_frame_parms->ofdm_symbol_size*(l%6)]),lte_frame_parms->ofdm_symbol_size,1,1); + //write_output(fname,vname,&(common_vars->dl_ch_estimates[0][frame_parms->ofdm_symbol_size*(l%6)]),frame_parms->ofdm_symbol_size,1,1); - lte_est_freq_offset(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0], - &PHY_vars_UE->lte_frame_parms, + lte_est_freq_offset(UE->common_vars.dl_ch_estimates[0], + &UE->frame_parms, l, &freq_offset, 1); } - if (l==((PHY_vars_eNB->lte_frame_parms.Ncp==0)?10:9)) { + if (l==((eNB->frame_parms.Ncp==0)?10:9)) { for (frame_mod4=0; frame_mod4<4; frame_mod4++) { - pbch_tx_ant = rx_pbch(&PHY_vars_UE->lte_ue_common_vars, - PHY_vars_UE->lte_ue_pbch_vars[0], - &PHY_vars_UE->lte_frame_parms, + pbch_tx_ant = rx_pbch(&UE->common_vars, + UE->pbch_vars[0], + &UE->frame_parms, 0, SISO, - PHY_vars_UE->high_speed_flag, + UE->high_speed_flag, frame_mod4); if ((pbch_tx_ant>0) && (pbch_tx_ant<4)) { - PHY_vars_UE->lte_frame_parms.mode1_flag = 1; + UE->frame_parms.mode1_flag = 1; break; if (pbch_phase != frame_mod4) printf("pbch_phase different!!!\n"); } - pbch_tx_ant = rx_pbch(&PHY_vars_UE->lte_ue_common_vars, - PHY_vars_UE->lte_ue_pbch_vars[0], - &PHY_vars_eNB->lte_frame_parms, + pbch_tx_ant = rx_pbch(&UE->common_vars, + UE->pbch_vars[0], + &eNB->frame_parms, 0, ALAMOUTI, - PHY_vars_UE->high_speed_flag, + UE->high_speed_flag, frame_mod4); if ((pbch_tx_ant>0) && (pbch_tx_ant<4)) { - PHY_vars_UE->lte_frame_parms.mode1_flag = 0; + UE->frame_parms.mode1_flag = 0; n_alamouti++; break; } @@ -1023,7 +1015,7 @@ int main(int argc, char **argv) if ((pbch_tx_ant>0) && (pbch_tx_ant<4)) { if (n_frames==1) msg("pbch decoded sucessfully mode1_flag %d, frame_mod4 %d, tx_ant %d!\n", - PHY_vars_UE->lte_frame_parms.mode1_flag,frame_mod4,pbch_tx_ant); + UE->frame_parms.mode1_flag,frame_mod4,pbch_tx_ant); } else { n_errors++; n_errors2++; @@ -1036,7 +1028,7 @@ int main(int argc, char **argv) #ifdef XFORMS phy_scope_UE(form_ue, - PHY_vars_UE, + UE, 0,0,1); #endif @@ -1066,16 +1058,16 @@ int main(int argc, char **argv) if (n_frames==1) { - write_output("H00.m","h00",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size),1,1); + write_output("H00.m","h00",&(UE->common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(eNB->frame_parms.ofdm_symbol_size),1,1); if (n_tx==2) - write_output("H10.m","h10",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][2][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size),1,1); + write_output("H10.m","h10",&(UE->common_vars.dl_ch_estimates[0][2][0]),((frame_parms->Ncp==0)?7:6)*(eNB->frame_parms.ofdm_symbol_size),1,1); - write_output("rxsig0.m","rxs0", PHY_vars_UE->lte_ue_common_vars.rxdata[0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); - write_output("rxsigF0.m","rxsF0", PHY_vars_UE->lte_ue_common_vars.rxdataF[0],NUMBER_OF_OFDM_CARRIERS*2*((frame_parms->Ncp==0)?14:12),2,1); - write_output("PBCH_rxF0_ext.m","pbch0_ext",PHY_vars_UE->lte_ue_pbch_vars[0]->rxdataF_ext[0],12*4*6,1,1); - write_output("PBCH_rxF0_comp.m","pbch0_comp",PHY_vars_UE->lte_ue_pbch_vars[0]->rxdataF_comp[0],12*4*6,1,1); - write_output("PBCH_rxF_llr.m","pbch_llr",PHY_vars_UE->lte_ue_pbch_vars[0]->llr,(frame_parms->Ncp==0) ? 1920 : 1728,1,4); + write_output("rxsig0.m","rxs0", UE->common_vars.rxdata[0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("rxsigF0.m","rxsF0", UE->common_vars.rxdataF[0],NUMBER_OF_OFDM_CARRIERS*2*((frame_parms->Ncp==0)?14:12),2,1); + write_output("PBCH_rxF0_ext.m","pbch0_ext",UE->pbch_vars[0]->rxdataF_ext[0],12*4*6,1,1); + write_output("PBCH_rxF0_comp.m","pbch0_comp",UE->pbch_vars[0]->rxdataF_comp[0],12*4*6,1,1); + write_output("PBCH_rxF_llr.m","pbch_llr",UE->pbch_vars[0]->llr,(frame_parms->Ncp==0) ? 1920 : 1728,1,4); } diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c index 73da52085f..d14f13f60f 100644 --- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c @@ -759,13 +759,14 @@ int main(int argc, char **argv) + eNB_rxtx_proc_t *proc_rxtx = &eNB->proc.proc_rxtx[subframe&1]; eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,N_RB_DL,0); UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); - eNB->proc.frame_tx = 0; - eNB->proc.subframe_tx = subframe; + proc_rxtx->frame_tx = 0; + proc_rxtx->subframe_tx = subframe; if (input_fd==NULL) { msg("No input file, so starting TX\n"); @@ -932,7 +933,7 @@ int main(int argc, char **argv) if (n_frames==1) printf("generating PHICH\n"); - harq_pid = phich_subframe_to_harq_pid(&eNB->frame_parms, eNB->proc.frame_tx, subframe); + harq_pid = phich_subframe_to_harq_pid(&eNB->frame_parms, proc_rxtx->frame_tx, subframe); phich_ACK = taus()&1; eNB->ulsch[0]->harq_processes[harq_pid]->phich_active = 1; @@ -944,23 +945,23 @@ int main(int argc, char **argv) UE->ulsch[0]->harq_processes[harq_pid]->first_rb = 0; UE->ulsch[0]->harq_processes[harq_pid]->n_DMRS = 0; - generate_phich_top(eNB,AMP,0,0); + generate_phich_top(eNB,proc_rxtx,AMP,0,0); // generate 3 interfering PHICH if (num_phich_interf>0) { eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 4; - generate_phich_top(eNB,1024,0,0); + generate_phich_top(eNB,proc_rxtx,1024,0,0); } if (num_phich_interf>1) { eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 8; eNB->ulsch[0]->harq_processes[harq_pid]->n_DMRS = 1; - generate_phich_top(eNB,1024,0,0); + generate_phich_top(eNB,proc_rxtx,1024,0,0); } if (num_phich_interf>2) { eNB->ulsch[0]->harq_processes[harq_pid]->first_rb = 12; eNB->ulsch[0]->harq_processes[harq_pid]->n_DMRS = 1; - generate_phich_top(eNB,1024,0,0); + generate_phich_top(eNB,proc_rxtx,1024,0,0); } From 2cc779b9302e3ba3ea3b0a25b7ac2ddfd4aee74e Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 13 Jun 2016 18:27:42 +0200 Subject: [PATCH 040/206] added macros for packet_type --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 50 +++++++++++++++++++------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 6 +++- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index e75a8675e9..cf41812c19 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -45,6 +45,7 @@ #include "PHY/LTE_TRANSPORT/if4_tools.h" #endif +// Get device information void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { int frame = proc->frame_tx; int subframe = proc->subframe_tx; @@ -73,8 +74,15 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { // Update information in generated packet dl_packet->frame_status.sym_num = i; - // Write the packet(s) to the fronthaul - + // Write the packet(s) to the fronthaul + //if ((bytes_sent = dev->eth_dev.trx_write_func (&dev->eth_dev, + // timestamp_rx, + // rx_eNB, + // spp_eth, + // dev->eth_dev.openair0_cfg->rx_num_channels, + // 0)) < 0) { + // perror("RCC : ETHERNET write"); + //} } }else { IF4_ul_packet_t *ul_packet = (IF4_ul_packet_t*)malloc(sizeof_IF4_ul_packet_t); @@ -102,20 +110,38 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { - // Read packet(s) from the fronthaul - - // Apply reverse processing - decompression - - // Generate and return the OFDM symbols (txdataF) - // Caller: RRU - DL *** handle RCC case - UL and PRACH *** - + + if (eNB->node_function == NGFI_RRU_IF4) { + + + + for(i=0; isymbols_per_tti; i++) { + // Read packet(s) from the fronthaul + if (dev->eth_dev.trx_read_func (&dev->eth_dev, + timestamp_rx, + rx_eNB, + spp_eth, + dev->eth_dev.openair0_cfg->rx_num_channels + ) < 0) { + perror("RRU : ETHERNET read"); + } + + // Apply reverse processing - decompression + // txAlawtolinear( Datablock ) + + // Generate and return the OFDM symbols (txdataF) + txDataF + } + }else { + + } } void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type dl_packet->type = 0x080A; - dl_packet->sub_type = 0x0020; + dl_packet->sub_type = IF4_PDLFFT; // Leave reserved as it is dl_packet->rsvd = 0; @@ -135,7 +161,7 @@ void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { void gen_IF4_ul_packet(IF4_ul_packet_t *ul_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type ul_packet->type = 0x080A; - ul_packet->sub_type = 0x0019; + ul_packet->sub_type = IF4_PULFFT; // Leave reserved as it is ul_packet->rsvd = 0; @@ -159,7 +185,7 @@ void gen_IF4_ul_packet(IF4_ul_packet_t *ul_packet, eNB_rxtx_proc_t *proc) { void gen_IF4_prach_packet(IF4_prach_packet_t *prach_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type prach_packet->type = 0x080A; - prach_packet->sub_type = 0x0021; + prach_packet->sub_type = IF4_PRACH; // Leave reserved as it is prach_packet->rsvd = 0; diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 819aca58d6..91a9e93d79 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -38,6 +38,10 @@ * \warning */ +#define IF4_PULFFT 0x0019 +#define IF4_PDLFFT 0x0020 +#define IF4_PRACH 0x0021 + /// IF4 Frame Status (32 bits) struct IF4_frame_status { /// Antenna Numbers @@ -175,4 +179,4 @@ void gen_IF4_prach_packet(IF4_prach_packet_t*, eNB_rxtx_proc_t*); void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*); -void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*); +void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, int*, int*); From 2cd848908646746dc8d76fabc5872ed16e3b0428 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 13 Jun 2016 18:50:05 +0200 Subject: [PATCH 041/206] starting to add run options for node_function --- openair1/SCHED/phy_procedures_lte_eNb.c | 32 ++++----- targets/RT/USER/lte-softmodem.c | 92 ++++++++++++++++++++----- 2 files changed, 92 insertions(+), 32 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 785001e8f4..0e1685d266 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2498,7 +2498,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; - int symbol_number, symbol_mask, symbol_mask_full, prach_rx; + int symbol_number, symbol_mask, symbol_mask_full, prach_rx, packet_type; if (subframe==9) { subframe=0; @@ -2580,23 +2580,23 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl // get frame/subframe information from IF4 interface // timed loop (200 us) - symbol_mask = 0; - symbol_mask_full = (1<symbols_per_tti)-1; - if (is_prach_subframe(fp,frame,subframe)>0) - prach_rx = 0; - else - prach_rx = 1; + //symbol_mask = 0; + //symbol_mask_full = (1<symbols_per_tti)-1; + //if (is_prach_subframe(fp,frame,subframe)>0) + //prach_rx = 0; + //else + //prach_rx = 1; - do { - recv_IF4(eNB, proc, &packet_type, &symbol_number); - if (is_prach_subframe(fp,frame,subframe)>0 && packet_type == PRACH) { - // wake up prach_rx - prach_rx = 1; - } - if (packet_type == PULFFT) - symbol_mask = symbol_mask | (1<0 && packet_type == PRACH) { + //// wake up prach_rx + //prach_rx = 1; + //} + //if (packet_type == IF4_PULFFT) + //symbol_mask = symbol_mask | (1<properties[i]->rrh_gw_config[j].active == 1 ) { local_remote_radio = BBU_REMOTE_RADIO_HEAD; - eth_params = (eth_params_t*)malloc(sizeof(eth_params_t)); + eth_params = (eth_params_t*)malloc(sizeof(eth_params_t)); memset(eth_params, 0, sizeof(eth_params_t)); eth_params->local_if_name = enb_properties->properties[i]->rrh_gw_if_name; @@ -1120,7 +1141,6 @@ int main( int argc, char **argv ) uint16_t Nid_cell = 0; uint8_t cooperation_flag=0, abstraction_flag=0; uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; - eNB_func_t node_function=eNodeB_3GPP; #if defined (XFORMS) int ret; @@ -1458,13 +1478,20 @@ int main( int argc, char **argv ) else //FDD openair0_cfg[card].duplex_mode = duplex_mode_FDD; - + if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) { openair0_cfg[card].remote_addr = eth_params->remote_addr; openair0_cfg[card].remote_port = eth_params->remote_port; openair0_cfg[card].my_addr = eth_params->my_addr; openair0_cfg[card].my_port = eth_params->my_port; - } + } + + //if (node_function == NGFI_RCC_IF4 || node_function == NGFI_RRU_IF4) { + //openair0_cfg[card].remote_addr = eth_params->remote_addr; + //openair0_cfg[card].remote_port = eth_params->remote_port; + //openair0_cfg[card].my_addr = eth_params->my_addr; + //openair0_cfg[card].my_port = eth_params->my_port; + //} printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx), @@ -1562,35 +1589,68 @@ int main( int argc, char **argv ) /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ openair0.transp_type = NONE_TP; openair0_cfg[0].log_level = glog_level; - + + // Legacy BBU - RRH init + //int returns=-1; + ///* BBU can have either a local or a remote radio head */ + //if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active - load library of radio head and initiate it + //if (mode!=loop_through_memory) { + //returns=openair0_device_load(&openair0, &openair0_cfg[0]); + //printf("openair0_device_init returns %d\n",returns); + //if (returns<0) { + //printf("Exiting, cannot initialize device\n"); + //exit(-1); + //} + //} + //else if (mode==loop_through_memory) { + //} + //} else { //remote radio head active - load library of transport protocol and initiate it + //if (mode!=loop_through_memory) { + //returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params); + //printf("openair0_transport_init returns %d\n",returns); + //if (returns<0) { + //printf("Exiting, cannot initialize transport protocol\n"); + //exit(-1); + //} + //} + //else if (mode==loop_through_memory) { + //} + //} + + //printf("Done\n"); + int returns=-1; - /* BBU can have either a local or a remote radio head */ - if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active - load library of radio head and initiate it + + // Load RF device and initialize + if (node_function == eNodeB_3GPP || node_function == NGFI_RRU_IF4) { if (mode!=loop_through_memory) { returns=openair0_device_load(&openair0, &openair0_cfg[0]); printf("openair0_device_init returns %d\n",returns); if (returns<0) { - printf("Exiting, cannot initialize device\n"); - exit(-1); + printf("Exiting, cannot initialize device\n"); + exit(-1); } } else if (mode==loop_through_memory) { } - } else { //remote radio head active - load library of transport protocol and initiate it + } + + // Load transport protocol and initialize + if (node_function == NGFI_RCC_IF4 || node_function == NGFI_RRU_IF4){ if (mode!=loop_through_memory) { returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params); printf("openair0_transport_init returns %d\n",returns); if (returns<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); } } else if (mode==loop_through_memory) { } } - - printf("Done\n"); + printf("Done\n"); + mac_xface = malloc(sizeof(MAC_xface)); int eMBMS_active=0; From e48a34f68fc50c987a39bfb4f63a78abdbcbdbd7 Mon Sep 17 00:00:00 2001 From: "S. Sandeep Kumar" Date: Tue, 14 Jun 2016 05:07:16 +0530 Subject: [PATCH 042/206] added alaw lut for +-16/+8/+-16 --- openair1/PHY/TOOLS/ALAW/alaw_lut.h | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 openair1/PHY/TOOLS/ALAW/alaw_lut.h diff --git a/openair1/PHY/TOOLS/ALAW/alaw_lut.h b/openair1/PHY/TOOLS/ALAW/alaw_lut.h new file mode 100644 index 0000000000..bcb9bea790 --- /dev/null +++ b/openair1/PHY/TOOLS/ALAW/alaw_lut.h @@ -0,0 +1,47 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/*! \file PHY/TOOLS/ALAW/alaw_lut.h +* \brief +* \author S. Sandeep Kumar, Raymond Knopp +* \date 2016 +* \version 0.1 +* \company Eurecom +* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr +* \note +* \warning +*/ + +// Linear to ALaw +// 16 bit signed integer to 8 bit unsigned integer +const uint8_t lin2alaw[65536] = {42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170}; + +// ALaw to Linear +// 8 bit unsigned integer to 16 bit signed integer +const int16_t alaw2lin[256] = {-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; From a33bb694216a8073f03b3422bc9b568caba56e0e Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 14 Jun 2016 11:18:47 +0200 Subject: [PATCH 043/206] added multiple eth_params read --- targets/RT/USER/lte-softmodem.c | 61 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index b8adf5b405..c92f28b332 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1009,39 +1009,38 @@ static void get_options (int argc, char **argv) AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc, "lte-softmodem compiled with MAX_NUM_CCs=%d, but only %d CCs configured for eNB %d!", MAX_NUM_CCs, enb_properties->properties[i]->nb_cc, i); + eth_params = (eth_params_t*)malloc(enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); + memset(eth_params, 0, enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); for (j=0; jproperties[i]->nb_rrh_gw; j++) { - - if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) { - local_remote_radio = BBU_REMOTE_RADIO_HEAD; - eth_params = (eth_params_t*)malloc(sizeof(eth_params_t)); - memset(eth_params, 0, sizeof(eth_params_t)); - - eth_params->local_if_name = enb_properties->properties[i]->rrh_gw_if_name; - eth_params->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address; - eth_params->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; - eth_params->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; - eth_params->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; - eth_params->transp_preference = enb_properties->properties[i]->rrh_gw_config[j].raw; - eth_params->iq_txshift = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift; - eth_params->tx_sample_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance; - eth_params->tx_scheduling_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance; - if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) { - eth_params->rf_preference = EXMIMO_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) { - eth_params->rf_preference = USRP_B200_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) { - eth_params->rf_preference = USRP_X300_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) { - eth_params->rf_preference = BLADERF_DEV; - } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) { - //eth_params->rf_preference = LMSSDR_DEV; - } else { - eth_params->rf_preference = 0; - } - } else { - local_remote_radio = BBU_LOCAL_RADIO_HEAD; - } + + if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) { + local_remote_radio = BBU_REMOTE_RADIO_HEAD; + (eth_params+j)->local_if_name = enb_properties->properties[i]->rrh_gw_if_name; + (eth_params+j)->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address; + (eth_params+j)->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; + (eth_params+j)->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; + (eth_params+j)->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; + (eth_params+j)->transp_preference = enb_properties->properties[i]->rrh_gw_config[j].raw; + (eth_params+j)->iq_txshift = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift; + (eth_params+j)->tx_sample_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance; + (eth_params+j)->tx_scheduling_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance; + if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) { + (eth_params+j)->rf_preference = EXMIMO_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) { + (eth_params+j)->rf_preference = USRP_B200_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) { + (eth_params+j)->rf_preference = USRP_X300_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) { + (eth_params+j)->rf_preference = BLADERF_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) { + //(eth_params+j)->rf_preference = LMSSDR_DEV; + } else { + (eth_params+j)->rf_preference = 0; + } + } else { + local_remote_radio = BBU_LOCAL_RADIO_HEAD; + } } From 981655ccb1b96a94051ab236ba3f7e69d7829621 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 14 Jun 2016 17:05:07 +0200 Subject: [PATCH 044/206] integrate send_IF4 with alaw lut --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 69 +++++++++++++++----------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 4 +- 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index cf41812c19..9c521f10ff 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -29,7 +29,7 @@ /*! \file PHY/LTE_TRANSPORT/if4_tools.c * \brief -* \author Mauricio Gunther, S. Sandeep Kumar, Raymond Knopp +* \author Fredrik Skretteberg, Tobias Schuster, Mauricio Gunther, S. Sandeep Kumar, Raymond Knopp * \date 2016 * \version 0.1 * \company Eurecom @@ -43,6 +43,7 @@ #include #else #include "PHY/LTE_TRANSPORT/if4_tools.h" +#include "PHY/TOOLS/ALAW/alaw_lut.h" #endif // Get device information @@ -50,11 +51,15 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { int frame = proc->frame_tx; int subframe = proc->subframe_tx; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - - uint16_t i; - - float_t data_block_length = 1200*(fp->ofdm_symbol_size/2048); - uint16_t *data_block = (uint16_t*)malloc(data_block_length*sizeof(uint16_t)); + int32_t **txdataF = eNB->common_vars.txdataF[0]; + + uint16_t symbol_id, element_id; + uint16_t db_fulllength = 12*fp->N_RB_DL; + uint16_t db_halflength = db_fulllength>>1; + int slotoffsetF = (subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + int blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; + + int16_t *data_block = (int16_t*)malloc(db_fulllength*sizeof(int16_t)); // Caller: RCC - DL *** handle RRU case - UL and PRACH *** if (eNB->node_function == NGFI_RCC_IF4) { @@ -63,14 +68,17 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { dl_packet->data_block = data_block; - for(i=0; isymbols_per_tti; i++) { - - //Do compression of the two parts and generate data blocks + for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - //symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] - //data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); - //data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); - + // Do compression of the two parts and generate data blocks + for (element_id=0; element_id>16 + 32768 ]<<8; + + data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id])&0xffff + 32768 ]; + data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id])>>16 + 32768 ]<<8; + } + // Update information in generated packet dl_packet->frame_status.sym_num = i; @@ -82,7 +90,10 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { // dev->eth_dev.openair0_cfg->rx_num_channels, // 0)) < 0) { // perror("RCC : ETHERNET write"); - //} + //} + + slotoffsetF += fp->ofdm_symbol_size; + blockoffsetF += fp->ofdm_symbol_size; } }else { IF4_ul_packet_t *ul_packet = (IF4_ul_packet_t*)malloc(sizeof_IF4_ul_packet_t); @@ -90,32 +101,34 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { ul_packet->data_block = data_block; - for(i=0; isymbols_per_tti; i++) { - - //Do compression of the two parts and generate data blocks + for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - //symbol = eNB->common_vars.txdataF[0][0 /*antenna number*/][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)] - //data_block[j] = Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j -1])<<16 + Atan(symbol[fp->ofmd_symbol_size - NrOfNonZeroValues + j]); - //data_block[j+NrOfNonZeroValues] = Atan(subframe[i][j+1])<<16 + Atan(subframe[i][j+2]); - + // Do compression of the two parts and generate data blocks + for (element_id=0; element_id>16 + 32768 ]<<8; + + data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id])&0xffff + 32768 ]; + data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id])>>16 + 32768 ]<<8; + } + // Update information in generated packet ul_packet->frame_status.sym_num = i; // Write the packet(s) to the fronthaul + slotoffsetF += fp->ofdm_symbol_size; + blockoffsetF += fp->ofdm_symbol_size; } } } -void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { +void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, uint32_t *symbol_number) { // Caller: RRU - DL *** handle RCC case - UL and PRACH *** - if (eNB->node_function == NGFI_RRU_IF4) { - - for(i=0; isymbols_per_tti; i++) { // Read packet(s) from the fronthaul if (dev->eth_dev.trx_read_func (&dev->eth_dev, @@ -140,7 +153,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type - dl_packet->type = 0x080A; + dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; // Leave reserved as it is @@ -160,7 +173,7 @@ void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { void gen_IF4_ul_packet(IF4_ul_packet_t *ul_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type - ul_packet->type = 0x080A; + ul_packet->type = IF4_PACKET_TYPE; ul_packet->sub_type = IF4_PULFFT; // Leave reserved as it is @@ -184,7 +197,7 @@ void gen_IF4_ul_packet(IF4_ul_packet_t *ul_packet, eNB_rxtx_proc_t *proc) { void gen_IF4_prach_packet(IF4_prach_packet_t *prach_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type - prach_packet->type = 0x080A; + prach_packet->type = IF4_PACKET_TYPE; prach_packet->sub_type = IF4_PRACH; // Leave reserved as it is diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 91a9e93d79..cadcb2f8c2 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -38,6 +38,8 @@ * \warning */ +/// Macro for IF4 packet type +#define IF4_PACKET_TYPE 0x080A #define IF4_PULFFT 0x0019 #define IF4_PDLFFT 0x0020 #define IF4_PRACH 0x0021 @@ -179,4 +181,4 @@ void gen_IF4_prach_packet(IF4_prach_packet_t*, eNB_rxtx_proc_t*); void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*); -void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, int*, int*); +void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t*, uint32_t*); From b70b2ac4c49a3af0b8ac3dbc08c56d1346c1f703 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 16 Jun 2016 11:32:48 +0200 Subject: [PATCH 045/206] add openair0 device to eNB struct and per CC_id changes --- openair1/PHY/defs.h | 7 ++++ targets/RT/USER/lte-softmodem.c | 74 ++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 89fc1cd7ed..ed3ca5c251 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -139,6 +139,8 @@ static inline void* malloc16_clear( size_t size ) #include "PHY/LTE_TRANSPORT/defs.h" #include +#include "targets/ARCH/COMMON/common_lib.h" + #define NUM_DCI_MAX 32 #define NUMBER_OF_eNB_SECTORS_MAX 3 @@ -456,6 +458,11 @@ typedef struct PHY_VARS_eNB_s { SLIST_HEAD(ral_thresholds_gen_poll_enb_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX]; SLIST_HEAD(ral_thresholds_lte_poll_enb_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; #endif + + /// RF and Interface devices per CC + openair0_device rfdevice; + openair0_device ifdevice; + // *** Handle spatially distributed MIMO antenna ports } PHY_VARS_eNB; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index c92f28b332..8a2d8d9360 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -152,8 +152,6 @@ int sync_var=-1; //!< protected by mutex \ref sync_mutex. static pthread_t forms_thread; //xforms #endif -openair0_device openair0; - uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] @@ -1580,15 +1578,27 @@ int main( int argc, char **argv ) } LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity); #endif - - /* device host type is set*/ - openair0.host_type = BBU_HOST; - /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ - openair0.type = NONE_DEV; - /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ - openair0.transp_type = NONE_TP; + openair0_cfg[0].log_level = glog_level; + for (CC_id=0; CC_idrfdevice.host_type = BBU_HOST; + PHY_vars_eNB_g[0][CC_id]->rfdevice.type = NONE_DEV; + PHY_vars_eNB_g[0][CC_id]->rfdevice.transp_type = NONE_TP; + + PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = BBU_HOST; + PHY_vars_eNB_g[0][CC_id]->ifdevice.type = NONE_DEV; + PHY_vars_eNB_g[0][CC_id]->ifdevice.transp_type = NONE_TP; + } + + /* device host type is set*/ + //openair0.host_type = BBU_HOST; + /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ + //openair0.type = NONE_DEV; + /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ + //openair0.transp_type = NONE_TP; + //openair0_cfg[0].log_level = glog_level; + // Legacy BBU - RRH init //int returns=-1; ///* BBU can have either a local or a remote radio head */ @@ -1619,36 +1629,40 @@ int main( int argc, char **argv ) //printf("Done\n"); int returns=-1; - + + // Handle spatially distributed MIMO antenna ports // Load RF device and initialize if (node_function == eNodeB_3GPP || node_function == NGFI_RRU_IF4) { - if (mode!=loop_through_memory) { - returns=openair0_device_load(&openair0, &openair0_cfg[0]); - printf("openair0_device_init returns %d\n",returns); - if (returns<0) { - printf("Exiting, cannot initialize device\n"); - exit(-1); + for (CC_id=0; CC_idrfdevice), &openair0_cfg[0]); + printf("openair0_device_init returns %d for CC_id %d\n",returns,CC_id); + if (returns<0) { + printf("Exiting, cannot initialize device\n"); + exit(-1); + } } - } - else if (mode==loop_through_memory) { + else if (mode==loop_through_memory) { + } } } // Load transport protocol and initialize if (node_function == NGFI_RCC_IF4 || node_function == NGFI_RRU_IF4){ - if (mode!=loop_through_memory) { - returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params); - printf("openair0_transport_init returns %d\n",returns); - if (returns<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); + for (CC_id=0; CC_idifdevice), &openair0_cfg[0], (eth_params+CC_id)); + printf("openair0_transport_init returns %d for CC_id %d\n",returns,CC_id); + if (returns<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } } + else if (mode==loop_through_memory) { + } } - else if (mode==loop_through_memory) { - } - } - printf("Done\n"); + printf("Done initializing RF and IF devices\n"); mac_xface = malloc(sizeof(MAC_xface)); @@ -1819,7 +1833,7 @@ int main( int argc, char **argv ) - +// *** Handle per CC_id openair0 #ifndef USRP_DEBUG if ((UE_flag==1) && (mode!=loop_through_memory)) if (openair0.trx_start_func(&openair0) != 0 ) @@ -1889,7 +1903,7 @@ int main( int argc, char **argv ) pthread_cond_destroy(&sync_cond); pthread_mutex_destroy(&sync_mutex); - + // *** Handle per CC_id openair0 openair0.trx_end_func(&openair0); if (ouput_vcd) From dd6e1f9d87020e31222abf4e55da441cd5bc19ab Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 16 Jun 2016 12:45:08 +0200 Subject: [PATCH 046/206] fixes for if4_tools for compilation --- cmake_targets/CMakeLists.txt | 3 +- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 49 +++++++++++++------------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 8 +++-- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 5eca2e8d41..2101009016 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -138,7 +138,7 @@ else (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mavx2") endif() if (CPUINFO MATCHES "sse4_1") - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1 -mavx2") + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1") endif() if (CPUINFO MATCHES "ssse3") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mssse3") @@ -959,6 +959,7 @@ add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????") ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/rar_tools.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/print_stats.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/initial_sync.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c ${OPENAIR1_DIR}/PHY/MODULATION/ofdm_mod.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_mbsfn.c diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 9c521f10ff..06e057cdf0 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -42,21 +42,22 @@ #include "if4_tools.h" #include #else +#include +#include "PHY/defs.h" + #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/TOOLS/ALAW/alaw_lut.h" #endif // Get device information void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { - int frame = proc->frame_tx; - int subframe = proc->subframe_tx; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; uint16_t symbol_id, element_id; uint16_t db_fulllength = 12*fp->N_RB_DL; uint16_t db_halflength = db_fulllength>>1; - int slotoffsetF = (subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + int slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; int blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; int16_t *data_block = (int16_t*)malloc(db_fulllength*sizeof(int16_t)); @@ -72,15 +73,15 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { // Do compression of the two parts and generate data blocks for (element_id=0; element_id>16 + 32768 ]<<8; + data_block[element_id] = lin2alaw[ (txdataF[0][blockoffsetF+element_id] & 0xffff) + 32768 ]; + data_block[element_id] |= lin2alaw[ (txdataF[0][blockoffsetF+element_id]>>16) + 32768 ]<<8; - data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id])&0xffff + 32768 ]; - data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id])>>16 + 32768 ]<<8; + data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; + data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; } // Update information in generated packet - dl_packet->frame_status.sym_num = i; + dl_packet->frame_status.sym_num = symbol_id; // Write the packet(s) to the fronthaul //if ((bytes_sent = dev->eth_dev.trx_write_func (&dev->eth_dev, @@ -105,15 +106,15 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { // Do compression of the two parts and generate data blocks for (element_id=0; element_id>16 + 32768 ]<<8; + data_block[element_id] = lin2alaw[ (txdataF[0][blockoffsetF+element_id] & 0xffff) + 32768 ]; + data_block[element_id] |= lin2alaw[ (txdataF[0][blockoffsetF+element_id]>>16) + 32768 ]<<8; - data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id])&0xffff + 32768 ]; - data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id])>>16 + 32768 ]<<8; + data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; + data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; } // Update information in generated packet - ul_packet->frame_status.sym_num = i; + ul_packet->frame_status.sym_num = symbol_id; // Write the packet(s) to the fronthaul @@ -129,23 +130,23 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u // Caller: RRU - DL *** handle RCC case - UL and PRACH *** if (eNB->node_function == NGFI_RRU_IF4) { - for(i=0; isymbols_per_tti; i++) { +// for(i=0; isymbols_per_tti; i++) { // Read packet(s) from the fronthaul - if (dev->eth_dev.trx_read_func (&dev->eth_dev, - timestamp_rx, - rx_eNB, - spp_eth, - dev->eth_dev.openair0_cfg->rx_num_channels - ) < 0) { - perror("RRU : ETHERNET read"); - } +// if (dev->eth_dev.trx_read_func (&dev->eth_dev, +// timestamp_rx, +// rx_eNB, +// spp_eth, +// dev->eth_dev.openair0_cfg->rx_num_channels +// ) < 0) { +// perror("RRU : ETHERNET read"); +// } // Apply reverse processing - decompression // txAlawtolinear( Datablock ) // Generate and return the OFDM symbols (txdataF) - txDataF - } + //txDataF + //} }else { } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index cadcb2f8c2..d7a0461169 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -38,6 +38,8 @@ * \warning */ +#include + /// Macro for IF4 packet type #define IF4_PACKET_TYPE 0x080A #define IF4_PULFFT 0x0019 @@ -105,7 +107,7 @@ struct IF4_dl_packet { /// Frame Status IF4_frame_status_t frame_status; /// Data Blocks - uint16_t *data_block; + int16_t *data_block; /// Frame Check Sequence uint32_t fcs; }; @@ -143,7 +145,7 @@ struct IF4_ul_packet { /// Gain 7 IF4_gain_t gain7; /// Data Blocks - uint16_t *data_block; + int16_t *data_block; /// Frame Check Sequence uint32_t fcs; }; @@ -165,7 +167,7 @@ struct IF4_prach_packet { /// LTE Prach Configuration IF4_lte_prach_conf_t prach_conf; /// Prach Data Block (one antenna) - uint16_t *data_block; + int16_t *data_block; /// Frame Check Sequence uint32_t fcs; }; From c76951a31904fbe73d04366cc3457f9ee13fd450 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 16 Jun 2016 12:49:15 +0200 Subject: [PATCH 047/206] handle per cc device for some tx/rx cases --- openair1/SCHED/phy_procedures_lte_eNb.c | 5 +++-- targets/RT/USER/lte-enb.c | 21 ++++++++++++++++----- targets/RT/USER/lte-softmodem.c | 10 +++++++--- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 0e1685d266..a42d01fd32 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -73,7 +73,8 @@ void exit_fun(const char* s); extern int exit_openair; -extern openair0_device openair0; +// Fix per CC openair rf/if device update +// extern openair0_device openair0; unsigned char dlsch_input_buffer[2700] __attribute__ ((aligned(32))); int eNB_sync_buffer0[640*6] __attribute__ ((aligned(32))); @@ -2522,7 +2523,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - rxs = openair0.trx_read_func(&openair0, + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, &proc->timestamp_rx, rxp, fp->samples_per_tti, diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 373a13e150..aa30f0874b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -120,8 +120,8 @@ struct timing_info_t { unsigned int n_samples; } timing_info; - -extern openair0_device openair0; +// Fix per CC openair rf/if device update +// extern openair0_device openair0; #if defined(ENABLE_ITTI) extern volatile int start_eNB; @@ -524,7 +524,7 @@ static void* eNB_thread_rxtx( void* param ) for (i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; // if symb_written < spp ==> error - openair0.trx_write_func(&openair0, + PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), txp, PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, @@ -741,8 +741,19 @@ static void* eNB_thread_rx_common( void* param ) #if defined(ENABLE_ITTI) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif - if (openair0.trx_start_func(&openair0) != 0 ) - LOG_E(HW,"Could not start the device\n"); + + // Start RF device for this CC + if (eNB->node_function == eNodeB_3GPP || eNB->node_function == NGFI_RRU_IF4) { + if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) + LOG_E(HW,"Could not start the RF device\n"); + } + + // Start IF device for this CC + if (eNB->node_function == NGFI_RCC_IF4 || eNB->node_function == NGFI_RRU_IF4) { + if (eNB->ifdevice.trx_start_func(&eNB->ifdevice) != 0 ) + LOG_E(HW,"Could not start the IF device\n"); + } + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 8a2d8d9360..97feaed919 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -280,6 +280,9 @@ eth_params_t *eth_params; openair0_config_t openair0_cfg[MAX_CARDS]; +// Change to openair_global to handle UE +openair0_device openair0; + double cpuf; char uecap_xer[1024],uecap_xer_in=0; @@ -1592,11 +1595,11 @@ int main( int argc, char **argv ) } /* device host type is set*/ - //openair0.host_type = BBU_HOST; + openair0.host_type = BBU_HOST; /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ - //openair0.type = NONE_DEV; + openair0.type = NONE_DEV; /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ - //openair0.transp_type = NONE_TP; + openair0.transp_type = NONE_TP; //openair0_cfg[0].log_level = glog_level; // Legacy BBU - RRH init @@ -1661,6 +1664,7 @@ int main( int argc, char **argv ) else if (mode==loop_through_memory) { } } + } printf("Done initializing RF and IF devices\n"); From c5745c16226385fa4771eb3e60daa6cd5d6ea43b Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 16 Jun 2016 17:44:05 +0200 Subject: [PATCH 048/206] highlight send/recv if4 - midsave to swich pc --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 33 +++++---- openair1/PHY/LTE_TRANSPORT/prach.c | 6 +- openair1/SCHED/phy_procedures_lte_eNb.c | 32 ++------- targets/RT/USER/lte-enb.c | 89 ++++++++++++++----------- targets/RT/USER/lte-softmodem.c | 4 +- 5 files changed, 78 insertions(+), 86 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 06e057cdf0..a8a27b2c09 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -38,16 +38,11 @@ * \warning */ -#ifndef USER_MODE -#include "if4_tools.h" #include -#else -#include -#include "PHY/defs.h" +#include "PHY/defs.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/TOOLS/ALAW/alaw_lut.h" -#endif // Get device information void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { @@ -70,6 +65,8 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { dl_packet->data_block = data_block; for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { + + printf("\n Send IF4 for frame %d, subframe %d and symbol %d\n", proc->frame_tx, proc->subframe_tx, symbol_id); // Do compression of the two parts and generate data blocks for (element_id=0; element_idframe_status.sym_num = symbol_id; // Write the packet(s) to the fronthaul - //if ((bytes_sent = dev->eth_dev.trx_write_func (&dev->eth_dev, - // timestamp_rx, - // rx_eNB, - // spp_eth, - // dev->eth_dev.openair0_cfg->rx_num_channels, - // 0)) < 0) { - // perror("RCC : ETHERNET write"); - //} + // if ((bytes_sent = eNB->ifdevice.trx_write_func(&eNB->ifdevice, + // (proc->timestamp_tx-eNB->ifdevice.openair0_cfg.tx_sample_advance), + // dl_packet, + // eNB->frame_parms.samples_per_tti, + // eNB->frame_parms.nb_antennas_tx, + // 0)) < 0) { + // perror("RCC : ETHERNET write"); + //} slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; @@ -104,10 +101,10 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - // Do compression of the two parts and generate data blocks + // Do compression of the two parts and generate data blocks - rxdataF for (element_id=0; element_id>16) + 32768 ]<<8; + data_block[element_id] = lin2alaw[ (rxdataF[0][blockoffsetF+element_id] & 0xffff) + 32768 ]; + data_block[element_id] |= lin2alaw[ (rxdataF[0][blockoffsetF+element_id]>>16) + 32768 ]<<8; data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; @@ -130,6 +127,8 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u // Caller: RRU - DL *** handle RCC case - UL and PRACH *** if (eNB->node_function == NGFI_RRU_IF4) { + printf("\n Recv IF4 for frame %d, subframe %d and symbol %d\n", proc->frame_tx, proc->subframe_tx, symbol_id); + // for(i=0; isymbols_per_tti; i++) { // Read packet(s) from the fronthaul // if (dev->eth_dev.trx_read_func (&dev->eth_dev, diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 0f806e2ea1..555685b23e 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1269,16 +1269,16 @@ void rx_prach(PHY_VARS_eNB *eNB, } if (eNB->node_function == NGFI_RRU_IF4) { - //send prachF to RCC + /// **** send_IF4 of prachF to RCC **** /// return; } + // in case of RCC and prach received rx_thread wakes up prach //else if (eNB->node_function == NGFI_RCC_IF4) { - //wait for prachF from RRU and continue with PRACH processing + // wait for prachF from RRU and continue with PRACH processing //} - // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4 preamble_offset_old = 99; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index a42d01fd32..087404d10a 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1430,24 +1430,6 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #endif - // Clean up split point *** RRU only function to recv and do_OFDM_mod *** - if (eNB->node_function == eNodeB_3GPP) { - // Add above to IF4 split - // do_OFDM_mod - - }else if (eNB->node_function == NGFI_RCC_IF4) { - //send_IF4(eNB,subframe<<1); - //send_IF4(eNB,(subframe<<1)+1); - - }else if (eNB->node_function == NGFI_RRU_IF4) { // => acquisition from RCC (IF4) - // get frame/subframe information from IF4 interface - - //recv_IF4(eNB,subframe<<1); - //recv_IF4(eNB,1+(subframe<<1)); - - //do_OFDM_mod - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,0); stop_meas(&eNB->phy_proc_tx); @@ -2572,12 +2554,14 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); if (eNB->node_function == NGFI_RRU_IF4) { - //send_IF4(eNB,subframe<<1); - //send_IF4(eNB,(subframe<<1)+1); + /// **** send_IF4 of rxdataF to RCC **** /// + /// Handle routing to prach thread for sending prach } } - else if (eNB->node_function == NGFI_RCC_IF4) { // => acquisition from RRU (IF4) + else if (eNB->node_function == NGFI_RCC_IF4) { + /// **** recv_IF4 of rxdataF from RRU **** /// + /// **** recv_IF4 of prachF from RRU **** /// // get frame/subframe information from IF4 interface // timed loop (200 us) @@ -2598,11 +2582,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl //symbol_mask = symbol_mask | (1<CC_id]->node_function != NGFI_RCC_IF4) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); - do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); - /* - short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; - int i; - for (i=0;iCC_id]->frame_parms.samples_per_tti*2;i+=8) { - txdata[i] = 2047; - txdata[i+1] = 0; - txdata[i+2] = 0; - txdata[i+3] = 2047; - txdata[i+4] = -2047; - txdata[i+5] = 0; - txdata[i+6] = 0; - txdata[i+7] = -2047; } - */ + // eNodeB_3GPP and RRU create txdata and write to RF device + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RCC_IF4) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); + do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); + /* + short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; + int i; + for (i=0;iCC_id]->frame_parms.samples_per_tti*2;i+=8) { + txdata[i] = 2047; + txdata[i+1] = 0; + txdata[i+2] = 0; + txdata[i+3] = 2047; + txdata[i+4] = -2047; + txdata[i+5] = 0; + txdata[i+6] = 0; + txdata[i+7] = -2047; } + */ - // Transmit TX buffer based on timestamp from RX + // Transmit TX buffer based on timestamp from RX + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + int i; + for (i=0; iframe_parms.nb_antennas_tx; i++) + txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; + // if symb_written < spp ==> error + PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, + (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), + txp, + PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, + PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, + 1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - int i; - for (i=0; iframe_parms.nb_antennas_tx; i++) - txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; - // if symb_written < spp ==> error - PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, - (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), - txp, - PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, - PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, - 1); - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - } + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + + } else { // RCC sends the txdataF using send_IF4 function + + /// **** send_IF4 of txdataF to RRU **** /// + //send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc); + + } if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n"); @@ -743,13 +756,13 @@ static void* eNB_thread_rx_common( void* param ) #endif // Start RF device for this CC - if (eNB->node_function == eNodeB_3GPP || eNB->node_function == NGFI_RRU_IF4) { + if (eNB->node_function != NGFI_RCC_IF4) { if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) LOG_E(HW,"Could not start the RF device\n"); } // Start IF device for this CC - if (eNB->node_function == NGFI_RCC_IF4 || eNB->node_function == NGFI_RRU_IF4) { + if (eNB->node_function != eNodeB_3GPP) { if (eNB->ifdevice.trx_start_func(&eNB->ifdevice) != 0 ) LOG_E(HW,"Could not start the IF device\n"); } @@ -769,7 +782,7 @@ static void* eNB_thread_rx_common( void* param ) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); // this spawns the prach inside and updates the frame and subframe counters phy_procedures_eNB_common_RX(eNB, 0); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 97feaed919..efc2291dde 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1635,7 +1635,7 @@ int main( int argc, char **argv ) // Handle spatially distributed MIMO antenna ports // Load RF device and initialize - if (node_function == eNodeB_3GPP || node_function == NGFI_RRU_IF4) { + if (node_function != NGFI_RCC_IF4) { for (CC_id=0; CC_idrfdevice), &openair0_cfg[0]); @@ -1651,7 +1651,7 @@ int main( int argc, char **argv ) } // Load transport protocol and initialize - if (node_function == NGFI_RCC_IF4 || node_function == NGFI_RRU_IF4){ + if (node_function != eNodeB_3GPP){ for (CC_id=0; CC_idifdevice), &openair0_cfg[0], (eth_params+CC_id)); From d7781f7a315e2d3558329f095597bd8d94b2f13e Mon Sep 17 00:00:00 2001 From: "S. Sandeep Kumar" Date: Fri, 17 Jun 2016 01:47:42 +0530 Subject: [PATCH 049/206] asthetic fixes for lte-enb.c --- targets/RT/USER/lte-enb.c | 632 +++++++++++++++++--------------------- 1 file changed, 285 insertions(+), 347 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 3afdb15ef1..918c1f82ee 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -108,10 +108,6 @@ unsigned short config_frames[4] = {2,9,11,13}; # endif #endif - - - - //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -158,15 +154,14 @@ static struct { volatile uint8_t phy_proc_CC_id; } sync_phy_proc; - void exit_fun(const char* s); void init_eNB(eNB_func_t node_function); void stop_eNB(void); -void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) -{ +void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { + unsigned int aa,slot_offset, slot_offset_F; int dummy_tx_b[7680*4] __attribute__((aligned(32))); int i,j, tx_offset; @@ -183,7 +178,6 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_S))) { // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (phy_vars_eNB->frame_parms.Ncp == EXTENDED) { PHY_ofdm_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F], @@ -204,7 +198,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) 7, &(phy_vars_eNB->frame_parms)); // if S-subframe generate first slot only - if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) + if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) normal_prefix_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], dummy_tx_b+(phy_vars_eNB->frame_parms.samples_per_tti>>1), 7, @@ -237,9 +231,8 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) txdata[j++] = ((int16_t*)dummy_tx_b)[i]<(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) { - tx_offset = (int)slot_offset+time_offset[aa]; txdata = (int16_t*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset]; len2 = -tx_offset+LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; @@ -260,7 +253,6 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) } } - // if S-subframe switch to RX in second subframe /* if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S) { @@ -270,34 +262,35 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) } */ if ((((phy_vars_eNB->frame_parms.tdd_config==0) || - (phy_vars_eNB->frame_parms.tdd_config==1) || - (phy_vars_eNB->frame_parms.tdd_config==2) || - (phy_vars_eNB->frame_parms.tdd_config==6)) && - (subframe==0)) || (subframe==5)) { + (phy_vars_eNB->frame_parms.tdd_config==1) || + (phy_vars_eNB->frame_parms.tdd_config==2) || + (phy_vars_eNB->frame_parms.tdd_config==6)) && + (subframe==0)) || (subframe==5)) { // turn on tx switch N_TA_offset before //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset); for (i=0; iN_TA_offset; i++) { - tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset/2; - if (tx_offset<0) - tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; + tx_offset = (int)slot_offset+time_offset[aa]+i-phy_vars_eNB->N_TA_offset/2; + if (tx_offset<0) + tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; + if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) + tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti; - phy_vars_eNB->common_vars.txdata[0][aa][tx_offset] = 0x00000000; + phy_vars_eNB->common_vars.txdata[0][aa][tx_offset] = 0x00000000; } } } } } + /*! * \brief The RX UE-specific and TX thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_rxtx( void* param ) -{ +static void* eNB_thread_rxtx( void* param ) { + static int eNB_thread_rxtx_status; eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param; @@ -365,56 +358,47 @@ static void* eNB_thread_rxtx( void* param ) #endif //CPU_AFFINITY /* Check the actual affinity mask assigned to the thread */ - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { + if (s != 0) { perror( "pthread_getaffinity_np"); exit_fun("Error getting processor affinity "); } memset(cpu_affinity,0,sizeof(cpu_affinity)); for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } + if (CPU_ISSET(j, &cpuset)) { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } - memset(&sparam, 0 , sizeof (sparam)); + memset(&sparam, 0, sizeof(sparam)); sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; policy = SCHED_FIFO ; s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } + if (s != 0) { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); + if (s != 0) { + perror("pthread_getschedparam : "); + exit_fun("Error getting thread priority"); + } - } - - LOG_I( HW, "[SCHED][eNB] TX thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), + LOG_I(HW, "[SCHED][eNB] TX thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : "???", sparam.sched_priority, cpu_affinity ); - #endif //LOW_LATENCY - mlockall(MCL_CURRENT | MCL_FUTURE); - while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { @@ -462,6 +446,7 @@ static void* eNB_thread_rxtx( void* param ) exit_fun("nothing to add"); break; } + // wait for our turn or oai_exit while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) { pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx, @@ -473,28 +458,27 @@ static void* eNB_thread_rxtx( void* param ) exit_fun("nothing to add"); } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_ENB, proc->subframe_tx ); - if (oai_exit) - break; + + if (oai_exit) break; + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { - phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay, NULL ); - - /* we're done, let the next one proceed */ - if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; - } - sync_phy_proc.phy_proc_CC_id++; - sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs; - pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); - if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; + phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay, NULL ); + + /* we're done, let the next one proceed */ + if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n"); + exit_fun("nothing to add"); + break; + } + sync_phy_proc.phy_proc_CC_id++; + sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs; + pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); + if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n"); + exit_fun("nothing to add"); + break; } } else { @@ -504,53 +488,51 @@ static void* eNB_thread_rxtx( void* param ) } } - // eNodeB_3GPP and RRU create txdata and write to RF device - if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RCC_IF4) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); - do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); - /* - short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; - int i; - for (i=0;iCC_id]->frame_parms.samples_per_tti*2;i+=8) { - txdata[i] = 2047; - txdata[i+1] = 0; - txdata[i+2] = 0; - txdata[i+3] = 2047; - txdata[i+4] = -2047; - txdata[i+5] = 0; - txdata[i+6] = 0; - txdata[i+7] = -2047; } - */ - - - // Transmit TX buffer based on timestamp from RX + // eNodeB_3GPP and RRU create txdata and write to RF device + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RCC_IF4) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); + do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - int i; - for (i=0; iframe_parms.nb_antennas_tx; i++) - txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; - // if symb_written < spp ==> error - PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, - (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), - txp, - PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, - PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, - 1); + /* + short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; + int i; + for (i=0;iCC_id]->frame_parms.samples_per_tti*2;i+=8) { + txdata[i] = 2047; + txdata[i+1] = 0; + txdata[i+2] = 0; + txdata[i+3] = 2047; + txdata[i+4] = -2047; + txdata[i+5] = 0; + txdata[i+6] = 0; + txdata[i+7] = -2047; } + */ + + // Transmit TX buffer based on timestamp from RX + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + int i; + for (i=0; iframe_parms.nb_antennas_tx; i++) + txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; + // if symb_written < spp ==> error + PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, + (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), + txp, + PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, + PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, + 1); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + } else { + + /// **** send_IF4 of txdataF to RRU **** /// + //send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); - - } else { // RCC sends the txdataF using send_IF4 function - - /// **** send_IF4 of txdataF to RRU **** /// - //send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc); - - } + } if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n"); @@ -567,19 +549,18 @@ static void* eNB_thread_rxtx( void* param ) } stop_meas( &softmodem_stats_rxtx_sf ); + #ifdef LOWLATENCY - if (opp_enabled){ - if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); + if (opp_enabled) { + if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); } } #endif + print_meas_now(&softmodem_stats_rxtx_sf,"eNB_TX_SF",tx_time_file); - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); #ifdef DEBUG_THREADS @@ -591,13 +572,11 @@ static void* eNB_thread_rxtx( void* param ) } #if defined(ENABLE_ITTI) -static void wait_system_ready (char *message, volatile int *start_flag) - - /* Wait for eNB application initialization to be complete (eNB registration to MME) */ -{ +/* Wait for eNB application initialization to be complete (eNB registration to MME) */ +static void wait_system_ready (char *message, volatile int *start_flag) { + static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", - " ....", " ...", " ..", " .", " " - }; + " ....", " ...", " ..", " .", " "}; int i = 0; while ((!oai_exit) && (*start_flag == 0)) { @@ -609,16 +588,16 @@ static void wait_system_ready (char *message, volatile int *start_flag) LOG_D(EMU,"\n"); } - #endif + /*! * \brief The RX common thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_rx_common( void* param ) -{ +static void* eNB_thread_rx_common( void* param ) { + static int eNB_thread_rx_status; eNB_proc_t *proc = (eNB_proc_t*)param; @@ -629,7 +608,7 @@ static void* eNB_thread_rx_common( void* param ) char rx_time_name[101]; //int i; - if (opp_enabled == 1){ + if (opp_enabled == 1) { snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB"); rx_time_file = fopen(rx_time_name,"w"); } @@ -674,14 +653,12 @@ static void* eNB_thread_rx_common( void* param ) /* Set CPU Affinity only if number of CPUs >2 */ CPU_ZERO(&cpuset); #ifdef CPU_AFFINITY - if (get_nprocs() >2) - { + if (get_nprocs() >2) { for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); + CPU_SET(j, &cpuset); s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { + if (s != 0) { perror( "pthread_setaffinity_np"); exit_fun (" Error setting processor affinity :"); } @@ -690,66 +667,58 @@ static void* eNB_thread_rx_common( void* param ) /* Check the actual affinity mask assigned to the thread */ s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); + if (s != 0) { + perror ("pthread_getaffinity_np"); + exit_fun (" Error getting processor affinity :"); } memset(cpu_affinity,0, sizeof(cpu_affinity)); for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - + if (CPU_ISSET(j, &cpuset)) { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } memset(&sparam, 0 , sizeof (sparam)); sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); policy = SCHED_FIFO ; s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } + if (s != 0) { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } memset(&sparam, 0 , sizeof (sparam)); s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } + if (s != 0) { + perror("pthread_getschedparam"); + exit_fun("Error getting thread priority"); + } - - LOG_I( HW, "[SCHED][eNB] RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + LOG_I(HW, "[SCHED][eNB] RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : "???", sparam.sched_priority, cpu_affinity); - - + #endif // LOWLATENCY - mlockall(MCL_CURRENT | MCL_FUTURE); + mlockall(MCL_CURRENT | MCL_FUTURE); + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe of TX and RX threads + printf( "waiting for sync (eNB_thread_rx_common)\n"); + pthread_mutex_lock( &sync_mutex ); - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe of TX and RX threads - printf( "waiting for sync (eNB_thread_rx_common)\n"); - pthread_mutex_lock( &sync_mutex ); - - while (sync_var<0) - pthread_cond_wait( &sync_cond, &sync_mutex ); + while (sync_var<0) + pthread_cond_wait( &sync_cond, &sync_mutex ); - pthread_mutex_unlock(&sync_mutex); + pthread_mutex_unlock(&sync_mutex); - printf( "got sync (eNB_thread)\n" ); + printf( "got sync (eNB_thread)\n" ); #if defined(ENABLE_ITTI) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); @@ -767,96 +736,90 @@ static void* eNB_thread_rx_common( void* param ) LOG_E(HW,"Could not start the IF device\n"); } - // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices - while (!oai_exit) { + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); + start_meas( &softmodem_stats_rx_sf ); + if (oai_exit) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); - start_meas( &softmodem_stats_rx_sf ); - - if (oai_exit) break; - - if ((((fp->frame_type == TDD )&&(subframe_select(fp,proc->subframe_rx)==SF_UL)) || - (fp->frame_type == FDD))) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); - // this spawns the prach inside and updates the frame and subframe counters - phy_procedures_eNB_common_RX(eNB, 0); - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); - } + if ((((fp->frame_type == TDD )&&(subframe_select(fp,proc->subframe_rx)==SF_UL)) || + (fp->frame_type == FDD))) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); + // this spawns the prach inside and updates the frame and subframe counters + phy_procedures_eNB_common_RX(eNB, 0); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); + } - // choose even or odd thread for RXn-TXnp4 processing - eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[proc->subframe_rx&1]; + // choose even or odd thread for RXn-TXnp4 processing + eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[proc->subframe_rx&1]; - // wake up TX for subframe n+4 - // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_lock(&proc_rxtx->mutex_rxtx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc_rxtx->instance_cnt_rxtx ); - exit_fun( "error locking mutex_rxtx" ); - break; - } - int cnt_rxtx = ++proc_rxtx->instance_cnt_rxtx; - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_pexr_frame) was n*samples_per_tti, - // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, - // and proc->subframe_tx = proc->subframe_rx+3 - proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); - proc_rxtx->frame_rx = proc->frame_rx; - proc_rxtx->subframe_rx = proc->subframe_rx; - proc_rxtx->frame_tx = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx; - proc_rxtx->subframe_tx = (proc_rxtx->subframe_rx + 4)%10; + // wake up TX for subframe n+4 + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_lock(&proc_rxtx->mutex_rxtx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc_rxtx->instance_cnt_rxtx ); + exit_fun( "error locking mutex_rxtx" ); + break; + } + int cnt_rxtx = ++proc_rxtx->instance_cnt_rxtx; + // We have just received and processed the common part of a subframe, say n. + // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired + // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_pexr_frame) was n*samples_per_tti, + // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+3 + proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); + proc_rxtx->frame_rx = proc->frame_rx; + proc_rxtx->subframe_rx = proc->subframe_rx; + proc_rxtx->frame_tx = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx; + proc_rxtx->subframe_tx = (proc_rxtx->subframe_rx + 4)%10; - pthread_mutex_unlock( &proc_rxtx->mutex_rxtx ); + pthread_mutex_unlock( &proc_rxtx->mutex_rxtx ); - if (cnt_rxtx == 0){ - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, cnt_rxtx ); - exit_fun( "TX thread busy" ); - break; - } + if (cnt_rxtx == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + break; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, cnt_rxtx ); + exit_fun( "TX thread busy" ); + break; + } - stop_meas( &softmodem_stats_rxtx_sf ); + stop_meas( &softmodem_stats_rxtx_sf ); + #ifdef LOWLATENCY - if (opp_enabled){ - if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); - } - } + if (opp_enabled){ + if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); + } + } #endif // LOWLATENCY - print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - - } - + print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); + } #ifdef DEBUG_THREADS - printf( "Exiting eNB thread RXn-TXnp4\n"); + printf( "Exiting eNB thread RXn-TXnp4\n"); #endif - eNB_thread_rx_status = 0; - return &eNB_thread_rx_status; + eNB_thread_rx_status = 0; + return &eNB_thread_rx_status; } - /*! * \brief The prach receive thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_prach( void* param ) -{ +static void* eNB_thread_prach( void* param ) { static int eNB_thread_prach_status; eNB_proc_t *proc = (eNB_proc_t*)param; @@ -865,7 +828,6 @@ static void* eNB_thread_prach( void* param ) eNB_thread_prach_status = 0; MSC_START_USE(); - #ifdef LOWLATENCY struct sched_attr attr; @@ -903,113 +865,102 @@ static void* eNB_thread_prach( void* param ) /* Set CPU Affinity only if number of CPUs >2 */ CPU_ZERO(&cpuset); #ifdef CPU_AFFINITY - if (get_nprocs() >2) - { + if (get_nprocs() >2) { for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); + CPU_SET(j, &cpuset); s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { + if (s != 0) { perror( "pthread_setaffinity_np"); exit_fun (" Error setting processor affinity :"); } } #endif //CPU_AFFINITY - /* Check the actual affinity mask assigned to the thread */ + /* Check the actual affinity mask assigned to the thread */ s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); + if (s != 0) { + perror ("pthread_getaffinity_np"); + exit_fun (" Error getting processor affinity :"); } memset(cpu_affinity,0, sizeof(cpu_affinity)); for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - + if (CPU_ISSET(j, &cpuset)) { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } memset(&sparam, 0 , sizeof (sparam)); sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-2; policy = SCHED_FIFO ; s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } + if (s != 0) { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } memset(&sparam, 0 , sizeof (sparam)); s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } + if (s != 0) { + perror("pthread_getschedparam"); + exit_fun("Error getting thread priority"); + } - - LOG_I( HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + LOG_I(HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : "???", sparam.sched_priority, cpu_affinity); - - + #endif // LOWLATENCY - mlockall(MCL_CURRENT | MCL_FUTURE); + mlockall(MCL_CURRENT | MCL_FUTURE); - - while (!oai_exit) { - - - if (oai_exit) break; - - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n"); - exit_fun( "error locking mutex" ); - break; - } - - while (proc->instance_cnt_prach < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_prach is -1 - pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH\n"); - exit_fun( "error unlocking mutex" ); - break; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); - prach_procedures(eNB,0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); + while (!oai_exit) { - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); - exit_fun( "error locking mutex" ); - break; - } + if (oai_exit) break; + + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n"); + exit_fun( "error locking mutex" ); + break; + } + + while (proc->instance_cnt_prach < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_prach is -1 + pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_rxtx while waiting and then locks it again + } + + if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH\n"); + exit_fun( "error unlocking mutex" ); + break; + } - proc->instance_cnt_prach--; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); + prach_procedures(eNB,0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); + + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); + exit_fun( "error locking mutex" ); + break; + } - if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n"); - exit_fun( "error unlocking mutex" ); - break; - } - } + proc->instance_cnt_prach--; + + if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n"); + exit_fun( "error unlocking mutex" ); + break; + } + } #ifdef DEBUG_THREADS printf( "Exiting eNB thread PRACH\n"); @@ -1020,10 +971,8 @@ static void* eNB_thread_prach( void* param ) } - - -void init_eNB_proc(void) -{ +void init_eNB_proc(void) { + int i; int CC_id; PHY_VARS_eNB *eNB; @@ -1033,7 +982,6 @@ void init_eNB_proc(void) for (CC_id=0; CC_idproc; proc_rxtx = proc->proc_rxtx; #ifndef LOWLATENCY @@ -1097,7 +1045,6 @@ void init_eNB_proc(void) pthread_setname_np( proc->pthread_rx, name ); } - /* setup PHY proc TX sync mechanism */ pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); @@ -1108,8 +1055,8 @@ void init_eNB_proc(void) /*! * \brief Terminate eNB TX and RX threads. */ -void kill_eNB_proc(void) -{ +void kill_eNB_proc(void) { + int *status; PHY_VARS_eNB *eNB; eNB_proc_t *proc; @@ -1133,6 +1080,7 @@ void kill_eNB_proc(void) #ifdef DEBUG_THREADS printf( "Joining eNB TX CC_id %d thread\n", CC_id); #endif + int result,i; for (i=0;i<1;i++) { pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status ); @@ -1148,16 +1096,14 @@ void kill_eNB_proc(void) printf( "The thread was killed. No status available.\n" ); } } - #else UNUSED(result); #endif pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx ); pthread_cond_destroy( &proc_rxtx[i].cond_rxtx ); - - } + #ifdef DEBUG_THREADS printf( "Killing RX CC_id %d thread\n", CC_id); #endif @@ -1165,10 +1111,10 @@ void kill_eNB_proc(void) #ifdef DEBUG_THREADS printf( "Joining eNB RX CC_id %d thread ...\n", CC_id); #endif + result = pthread_join( proc->pthread_rx, (void**)&status ); -#ifdef DEBUG_THREADS - +#ifdef DEBUG_THREADS if (result != 0) { printf( "Error joining thread.\n" ); } else { @@ -1177,8 +1123,7 @@ void kill_eNB_proc(void) } else { printf( "The thread was killed. No status available.\n" ); } - } - + } #else UNUSED(result); #endif @@ -1193,17 +1138,17 @@ void kill_eNB_proc(void) Each rf chain is is addressed by the card number and the chain on the card. The rf_map specifies for each CC, on which rf chain the mapping should start. Multiple antennas are mapped to successive RF chains on the same card. */ -int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) -{ +int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) { int i, CC_id; + #ifndef EXMIMO uint16_t N_TA_offset = 0; #else int j; #endif - LTE_DL_FRAME_PARMS *frame_parms; + LTE_DL_FRAME_PARMS *frame_parms; for (CC_id=0; CC_idframe_type == TDD) { - if (frame_parms->N_RB_DL == 100) - N_TA_offset = 624; - else if (frame_parms->N_RB_DL == 50) - N_TA_offset = 624/2; - else if (frame_parms->N_RB_DL == 25) - N_TA_offset = 624/4; - } - + if (frame_parms->frame_type == TDD) { + if (frame_parms->N_RB_DL == 100) + N_TA_offset = 624; + else if (frame_parms->N_RB_DL == 50) + N_TA_offset = 624/2; + else if (frame_parms->N_RB_DL == 25) + N_TA_offset = 624/4; + } #endif // replace RX signal buffers with mmaped HW versions @@ -1285,8 +1227,7 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); - printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset); - + printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset); } for (i=0; inb_antennas_tx; i++) { @@ -1295,19 +1236,17 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i]; memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); - } - #endif + } return(0); } - - void reset_opp_meas(void) { + int sfn; reset_meas(&softmodem_stats_mt); reset_meas(&softmodem_stats_hw); @@ -1318,6 +1257,7 @@ void reset_opp_meas(void) { } } + void print_opp_meas(void) { int sfn=0; @@ -1333,7 +1273,6 @@ void print_opp_meas(void) { void init_eNB(eNB_func_t node_function) { - int CC_id; for (CC_id=0;CC_id Date: Fri, 17 Jun 2016 04:14:41 +0530 Subject: [PATCH 050/206] handle prach rx for enb node functions --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 53 +++-- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 266 +++++++++++++----------- targets/RT/USER/lte-enb.c | 2 +- 4 files changed, 182 insertions(+), 141 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index a8a27b2c09..24b338f5a4 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -45,11 +45,11 @@ #include "PHY/TOOLS/ALAW/alaw_lut.h" // Get device information -void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { - LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - int32_t **txdataF = eNB->common_vars.txdataF[0]; +void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + int32_t **txdataF = eNB->common_vars.txdataF[0]; - uint16_t symbol_id, element_id; + uint16_t symbol_id, element_id; uint16_t db_fulllength = 12*fp->N_RB_DL; uint16_t db_halflength = db_fulllength>>1; int slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; @@ -58,7 +58,7 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { int16_t *data_block = (int16_t*)malloc(db_fulllength*sizeof(int16_t)); // Caller: RCC - DL *** handle RRU case - UL and PRACH *** - if (eNB->node_function == NGFI_RCC_IF4) { + if (packet_type == IF4_PDLFFT) { IF4_dl_packet_t *dl_packet = (IF4_dl_packet_t*)malloc(sizeof_IF4_dl_packet_t); gen_IF4_dl_packet(dl_packet, proc); @@ -93,7 +93,7 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } - }else { + } else if (packet_type == IF4_PULFFT) { IF4_ul_packet_t *ul_packet = (IF4_ul_packet_t*)malloc(sizeof_IF4_ul_packet_t); gen_IF4_ul_packet(ul_packet, proc); @@ -101,7 +101,7 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - // Do compression of the two parts and generate data blocks - rxdataF + // Do compression of the two parts and generate data blocks - rxdataF for (element_id=0; element_id>16) + 32768 ]<<8; @@ -118,19 +118,23 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc) { slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } - } - + } else if (packet_type == IF4_PRACH) { + + + } else { + AssertFatal(1==0, "send_IF4 - Unknown packet_type %x", packet_type); + } + + return; } void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, uint32_t *symbol_number) { - // Caller: RRU - DL *** handle RCC case - UL and PRACH *** - if (eNB->node_function == NGFI_RRU_IF4) { - - printf("\n Recv IF4 for frame %d, subframe %d and symbol %d\n", proc->frame_tx, proc->subframe_tx, symbol_id); - + *packet_type = 0; + int16_t *data_block=NULL; + + // Read packet(s) from the fronthaul // for(i=0; isymbols_per_tti; i++) { - // Read packet(s) from the fronthaul // if (dev->eth_dev.trx_read_func (&dev->eth_dev, // timestamp_rx, // rx_eNB, @@ -139,16 +143,27 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u // ) < 0) { // perror("RRU : ETHERNET read"); // } +// printf("\n Recv IF4 for frame %d, subframe %d and symbol %d\n", proc->frame_tx, proc->subframe_tx, symbol_id); + + //*packet_type = ; + + if (*packet_type == IF4_PDLFFT) { // Apply reverse processing - decompression // txAlawtolinear( Datablock ) // Generate and return the OFDM symbols (txdataF) - //txDataF - //} - }else { + // txDataF - } + } else if (*packet_type == IF4_PULFFT) { + + } else if (*packet_type == IF4_PRACH) { + + } else { + AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type); + } + + return; } void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index d7a0461169..a6ca7eb5c0 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -181,6 +181,6 @@ void gen_IF4_ul_packet(IF4_ul_packet_t*, eNB_rxtx_proc_t*); void gen_IF4_prach_packet(IF4_prach_packet_t*, eNB_rxtx_proc_t*); -void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*); +void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t); void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t*, uint32_t*); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 087404d10a..ae6627939c 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -44,6 +44,8 @@ #include "SCHED/defs.h" #include "SCHED/extern.h" +#include "PHY/LTE_TRANSPORT/if4_tools.h" + #ifdef EMOS #include "SCHED/phy_procedures_emos.h" #endif @@ -2471,7 +2473,6 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p } - void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { int i,l; @@ -2481,158 +2482,183 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; - int symbol_number, symbol_mask, symbol_mask_full, prach_rx, packet_type; + + int prach_rx; + + uint16_t packet_type; + uint32_t symbol_number; + uint32_t symbol_mask, symbol_mask_full; if (subframe==9) { subframe=0; frame++; frame&=1023; + } else { + subframe++; } - else subframe++; - + // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_COMMON_RX,1); start_meas(&eNB->phy_proc_rx); + #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); #endif if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) - + + if ((eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF and front-end processing - if ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF and front-end processing - for (i=0; inb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; + for (i=0; inb_antennas_rx; i++) + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, - &proc->timestamp_rx, - rxp, - fp->samples_per_tti, - fp->nb_antennas_rx); - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; - proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - if (proc->first_rx == 0) { - AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)",proc->subframe_rx,subframe); - AssertFatal(proc->frame_rx == frame, "Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)",proc->frame_rx,frame); - } - else - proc->first_rx = 0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, + &proc->timestamp_rx, + rxp, + fp->samples_per_tti, + fp->nb_antennas_rx); + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - // printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + if (proc->first_rx == 0) { + AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)",proc->subframe_rx,subframe); + AssertFatal(proc->frame_rx == frame, "Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)",proc->frame_rx,frame); + } else { + proc->first_rx = 0; + } - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, frame ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, subframe ); + //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, frame ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, subframe ); - if (rxs != fp->samples_per_tti) - exit_fun( "problem receiving samples" ); + if (rxs != fp->samples_per_tti) + exit_fun( "problem receiving samples" ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - // now do common RX processing for first slot in subframe - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); - remove_7_5_kHz(eNB,subframe<<1); - remove_7_5_kHz(eNB,1+(subframe<<1)); - for (l=0; lsymbols_per_tti/2; l++) { - slot_fep_ul(fp, - &eNB->common_vars, - l, - subframe<<1, - 0, - 0 - ); - slot_fep_ul(fp, - &eNB->common_vars, - l, - 1+(subframe<<1), - 0, - 0 - ); - } + // now do common RX processing for first slot in subframe + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); + remove_7_5_kHz(eNB,subframe<<1); + remove_7_5_kHz(eNB,1+(subframe<<1)); + for (l=0; lsymbols_per_tti/2; l++) { + slot_fep_ul(fp, + &eNB->common_vars, + l, + subframe<<1, + 0, + 0 + ); + slot_fep_ul(fp, + &eNB->common_vars, + l, + 1+(subframe<<1), + 0, + 0 + ); + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); - if (eNB->node_function == NGFI_RRU_IF4) { - /// **** send_IF4 of rxdataF to RCC **** /// - /// Handle routing to prach thread for sending prach - } + if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, frame, subframe)<=0) { - } - else if (eNB->node_function == NGFI_RCC_IF4) { - /// **** recv_IF4 of rxdataF from RRU **** /// - /// **** recv_IF4 of prachF from RRU **** /// - // get frame/subframe information from IF4 interface - // timed loop (200 us) - - //symbol_mask = 0; - //symbol_mask_full = (1<symbols_per_tti)-1; - //if (is_prach_subframe(fp,frame,subframe)>0) - //prach_rx = 0; - //else - //prach_rx = 1; - - //do { - //recv_IF4(eNB, proc, &packet_type, &symbol_number); - //if (is_prach_subframe(fp,frame,subframe)>0 && packet_type == PRACH) { - //// wake up prach_rx - //prach_rx = 1; - //} - //if (packet_type == IF4_PULFFT) - //symbol_mask = symbol_mask | (1<node_function %d",eNB->node_function); - } - - - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); - exit_fun( "error locking mutex_prach" ); - return; - } - - int cnt_prach = ++proc->instance_cnt_prach; - // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; - - pthread_mutex_unlock( &proc->mutex_prach ); - - if (cnt_prach == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame); - exit_fun( "PRACH thread busy" ); - return; + /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// } + /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) + // check if we have to detect PRACH first + if (is_prach_subframe(fp,frame,subframe)>0) { + // wake up thread for PRACH RX + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); + exit_fun( "error locking mutex_prach" ); + return; + } + + int cnt_prach = ++proc->instance_cnt_prach; + // set timing for prach thread + proc->frame_prach = frame; + proc->subframe_prach = subframe; + pthread_mutex_unlock( &proc->mutex_prach ); + + if (cnt_prach == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame); + exit_fun( "PRACH thread busy" ); + return; + } + } + + } else if (eNB->node_function == NGFI_RCC_IF4) { + /// **** recv_IF4 of rxdataF from RRU **** /// + /// **** recv_IF4 of prachF from RRU **** /// + // get frame/subframe information from IF4 interface + // timed loop (200 us) + + symbol_mask = 0; + symbol_mask_full = (1<symbols_per_tti)-1; + prach_rx = 0; + + do { + //recv_IF4(eNB, proc, &packet_type, &symbol_number); + + if (packet_type == IF4_PULFFT) { + symbol_mask = symbol_mask | (1<0 && packet_type == PRACH) { + // wake up thread for PRACH RX + prach_rx = 1; + + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); + exit_fun( "error locking mutex_prach" ); + return; + } + + int cnt_prach = ++proc->instance_cnt_prach; + // set timing for prach thread + proc->frame_prach = frame; + proc->subframe_prach = subframe; + + pthread_mutex_unlock( &proc->mutex_prach ); + + if (cnt_prach == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame); + exit_fun( "PRACH thread busy" ); + return; + } + } + + } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); + + // Tobi aka mr monaco: ETH + + } else { // should not get here + AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); } - - - } - - else { // grab transport channel information from network interface + } else { // grab transport channel information from network interface } + } + void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const uint8_t abstraction_flag,const relaying_type_t r_type) { //RX processing for ue-specific resources (i diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 918c1f82ee..3a836d6bdb 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -483,7 +483,7 @@ static void* eNB_thread_rxtx( void* param ) { } else { /// **** recv_IF4 of txdataF from RCC **** /// - //recv_IF4( eNB, proc, packet_type, symbol_number); + //recv_IF4(eNB, proc, packet_type, symbol_number); } } From e38dc81c16d7c132ac5ab721b079e94e7d7f670f Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 17 Jun 2016 12:19:36 +0200 Subject: [PATCH 051/206] just testing node function --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 8 ++++---- openair1/SCHED/phy_procedures_lte_eNb.c | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 24b338f5a4..15e98c36f6 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -103,11 +103,11 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { // Do compression of the two parts and generate data blocks - rxdataF for (element_id=0; element_id>16) + 32768 ]<<8; + //data_block[element_id] = lin2alaw[ (rxdataF[0][blockoffsetF+element_id] & 0xffff) + 32768 ]; + //data_block[element_id] |= lin2alaw[ (rxdataF[0][blockoffsetF+element_id]>>16) + 32768 ]<<8; - data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; - data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; + //data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; + //data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; } // Update information in generated packet diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index ae6627939c..87153a3b10 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2607,9 +2607,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl symbol_mask_full = (1<symbols_per_tti)-1; prach_rx = 0; + // Block from loop while testing + symbol_mask = symbol_mask_full; do { //recv_IF4(eNB, proc, &packet_type, &symbol_number); - + if (packet_type == IF4_PULFFT) { symbol_mask = symbol_mask | (1< Date: Fri, 17 Jun 2016 15:39:24 +0200 Subject: [PATCH 052/206] add vcd logging for send, recv if4 and delay for testing without recv --- openair1/PHY/LTE_TRANSPORT/prach.c | 7 +++++-- openair1/SCHED/phy_procedures_lte_eNb.c | 19 +++++++++++++++++-- openair2/UTIL/LOG/vcd_signal_dumper.c | 6 +++++- openair2/UTIL/LOG/vcd_signal_dumper.h | 5 +++++ targets/RT/USER/lte-enb.c | 12 +++++++++--- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 555685b23e..85330b5a18 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1269,7 +1269,11 @@ void rx_prach(PHY_VARS_eNB *eNB, } if (eNB->node_function == NGFI_RRU_IF4) { - /// **** send_IF4 of prachF to RCC **** /// + /// **** send_IF4 of prachF to RCC **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); + // send_IF4(); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + return; } @@ -1278,7 +1282,6 @@ void rx_prach(PHY_VARS_eNB *eNB, // wait for prachF from RRU and continue with PRACH processing //} - // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4 preamble_offset_old = 99; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 87153a3b10..92392070af 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -61,6 +61,8 @@ #include "assertions.h" #include "msc.h" +#include + #if defined(ENABLE_ITTI) # include "intertask_interface.h" #endif @@ -2488,7 +2490,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl uint16_t packet_type; uint32_t symbol_number; uint32_t symbol_mask, symbol_mask_full; - + + struct timespec time_req, time_rem; + time_req.tv_sec = 0; + time_req.tv_nsec = 300000; + if (subframe==9) { subframe=0; frame++; @@ -2564,6 +2570,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, frame, subframe)<=0) { /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); + // send_IF4(); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + } /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) @@ -2608,9 +2619,13 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl prach_rx = 0; // Block from loop while testing - symbol_mask = symbol_mask_full; + symbol_mask = symbol_mask_full; + nanosleep(&time_req, &time_rem); + do { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); //recv_IF4(eNB, proc, &packet_type, &symbol_number); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); if (packet_type == IF4_PULFFT) { symbol_mask = symbol_mask | (1<CC_id], proc); + /// **** send_IF4 of txdataF to RRU **** /// + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); + //send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc, 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); } From f91457d8d29f9d8d34e8f7672b00eb7ad94cda95 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 18 Jun 2016 03:48:23 -0700 Subject: [PATCH 053/206] added common acquisition interfaces for ExpressMIMO2 --- cmake_targets/CMakeLists.txt | 12 +- cmake_targets/build_oai | 4 +- openair1/PHY/LTE_ESTIMATION/adjust_gain.c | 81 ----- openair1/PHY/TOOLS/lte_dfts.c | 33 +- targets/ARCH/COMMON/common_lib.h | 23 +- .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 321 +++++++++++++++++- .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h | 23 ++ targets/RT/USER/lte-enb.c | 19 +- targets/RT/USER/lte-ue.c | 1 + 9 files changed, 385 insertions(+), 132 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 5f5f09dfab..46fd189952 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -494,7 +494,7 @@ include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/") #set (option_HWEXMIMOLIB_lib "-l ") set(HWLIB_EXMIMO_SOURCE ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c - ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c +# ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c ) add_library(oai_exmimodevif MODULE ${HWLIB_EXMIMO_SOURCE} ) @@ -535,8 +535,8 @@ if (${RF_BOARD} STREQUAL "EXMIMO") include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/") include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/") set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c - ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c) + ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c) +# ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c) set(option_HW_lib "-rdynamic -ldl") elseif (${RF_BOARD} STREQUAL "OAI_USRP") @@ -1478,9 +1478,9 @@ add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????") ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/pgm_link.c ) - add_library(OPENAIR0_LIB - ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c - ) +# add_library(OPENAIR0_LIB +# ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +# ) # System packages that are required # We use either the cmake buildin, in ubuntu are in: /usr/share/cmake*/Modules/ diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 96adfa0040..a289677373 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -692,7 +692,9 @@ function main() { #add exmimo compilation #TODO EXMIMO library support - + compilations \ + $build_dir oai_exmimodevif \ + liboai_exmimodevif.so $dbin/liboai_exmimodevif.so.$REL echo_info "liboai_device.so is linked to EXMIMO device library" elif [ "$HW" == "OAI_USRP" ] ; then if [ -d "/usr/include/uhd" ] ; then diff --git a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c index 48339de4cd..da07687a9e 100644 --- a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c +++ b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c @@ -30,20 +30,10 @@ #include "PHY/defs.h" #include "PHY/extern.h" -#ifdef EXMIMO -#include "openair0_lib.h" -extern int card; -#endif - void phy_adjust_gain (PHY_VARS_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id) { -#ifdef EXMIMO - exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr; - uint16_t i; -#endif - LOG_D(PHY,"Gain control: rssi %d (%d,%d)\n", rx_power_fil_dB, ue->measurements.rssi, @@ -80,77 +70,6 @@ phy_adjust_gain (PHY_VARS_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id) LOG_D(PHY,"Gain control: rx_total_gain_dB = %d (max %d,rxpf %d)\n",ue->rx_total_gain_dB,MAX_RF_GAIN,rx_power_fil_dB); -#ifdef EXMIMO - - if (ue->rx_total_gain_dB>ue->rx_gain_max[0]) { - ue->rx_total_gain_dB = ue->rx_gain_max[0]; - - for (i=0; iframe_parms.nb_antennas_rx; i++) { - p_exmimo_config->rf.rx_gain[i][0] = 30; - } - - } else if (ue->rx_total_gain_dB<(ue->rx_gain_max[0]-30)) { - // for the moment we stay in max gain mode - ue->rx_total_gain_dB = ue->rx_gain_max[0] - 30; - - for (i=0; iframe_parms.nb_antennas_rx; i++) { - p_exmimo_config->rf.rx_gain[i][0] = 0; - } - - /* - ue->rx_gain_mode[0] = byp; - ue->rx_gain_mode[1] = byp; - exmimo_pci_interface->rf.rf_mode0 = 22991; //bypass - exmimo_pci_interface->rf.rf_mode1 = 22991; //bypass - - if (ue->rx_total_gain_dB<(ue->rx_gain_byp[0]-50)) { - exmimo_pci_interface->rf.rx_gain00 = 0; - exmimo_pci_interface->rf.rx_gain10 = 0; - } - */ - } else { - - for (i=0; iframe_parms.nb_antennas_rx; i++) { - p_exmimo_config->rf.rx_gain[i][0] = 30 - ue->rx_gain_max[0] + ue->rx_total_gain_dB; - } - } - - /* - break; - case med_gain: - case byp_gain: - if (ue->rx_total_gain_dB>ue->rx_gain_byp[0]) { - ue->rx_gain_mode[0] = max_gain; - ue->rx_gain_mode[1] = max_gain; - exmimo_pci_interface->rf.rf_mode0 = 55759; //max gain - exmimo_pci_interface->rf.rf_mode1 = 55759; //max gain - - if (ue->rx_total_gain_dB>ue->rx_gain_max[0]) { - exmimo_pci_interface->rf.rx_gain00 = 50; - exmimo_pci_interface->rf.rx_gain10 = 50; - } - else { - exmimo_pci_interface->rf.rx_gain00 = 50 - ue->rx_gain_max[0] + ue->rx_total_gain_dB; - exmimo_pci_interface->rf.rx_gain10 = 50 - ue->rx_gain_max[1] + ue->rx_total_gain_dB; - } - } - else if (ue->rx_total_gain_dB<(ue->rx_gain_byp[0]-50)) { - exmimo_pci_interface->rf.rx_gain00 = 0; - exmimo_pci_interface->rf.rx_gain10 = 0; - } - else { - exmimo_pci_interface->rf.rx_gain00 = 50 - ue->rx_gain_byp[0] + ue->rx_total_gain_dB; - exmimo_pci_interface->rf.rx_gain10 = 50 - ue->rx_gain_byp[1] + ue->rx_total_gain_dB; - } - break; - default: - exmimo_pci_interface->rf.rx_gain00 = 50; - exmimo_pci_interface->rf.rx_gain10 = 50; - break; - } - */ -#endif - #ifdef DEBUG_PHY /* if ((ue->frame%100==0) || (ue->frame < 10)) msg("[PHY][ADJUST_GAIN] frame %d, rx_power = %d, rx_power_fil = %d, rx_power_fil_dB = %d, coef=%d, ncoef=%d, rx_total_gain_dB = %d (%d,%d,%d)\n", diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/lte_dfts.c index 375ea418d7..4fc332704b 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/lte_dfts.c @@ -6817,6 +6817,7 @@ void dft60(int16_t *x,int16_t *y,unsigned char scale) for (i=0; i<60; i++) { y128[i] = mulhi_int16(y128[i],norm128); + printf("y[%d] = (%d,%d)\n",i,((int16_t*)&y128[i])[0],((int16_t*)&y128[i])[1]); } } @@ -18553,6 +18554,7 @@ int main(int argc, char**argv) simd_q15_t x[4096],y[4096],tw0,tw1,tw2,tw3; #endif int i; + simd_q15_t *x128=x,*y128=y; set_taus_seed(0); opp_enabled = 1; @@ -18592,17 +18594,22 @@ int main(int argc, char**argv) ((int16_t *)&tw3)[5] = 0; ((int16_t *)&tw3)[6] = 32767; ((int16_t *)&tw3)[7] = 0; - + */ for (i=0;i<300;i++) { #if defined(__x86_64__) || defined(__i386__) +#ifndef __AVX2__ x[i] = _mm_set1_epi32(taus()); x[i] = _mm_srai_epi16(x[i],4); +#else + x[i] = _mm256_set1_epi32(taus()); + x[i] = _mm256_srai_epi16(x[i],4); +#endif #elif defined(__arm__) x[i] = (int16x8_t)vdupq_n_s32(taus()); x[i] = vshrq_n_s16(x[i],4); #endif } - + /* bfly2_tw1(x,x+1,y,y+1); printf("(%d,%d) (%d,%d) => (%d,%d) (%d,%d)\n",((int16_t*)&x[0])[0],((int16_t*)&x[0])[1],((int16_t*)&x[1])[0],((int16_t*)&x[1])[1],((int16_t*)&y[0])[0],((int16_t*)&y[0])[1],((int16_t*)&y[1])[0],((int16_t*)&y[1])[1]); printf("(%d,%d) (%d,%d) => (%d,%d) (%d,%d)\n",((int16_t*)&x[0])[0],((int16_t*)&x[0])[1],((int16_t*)&x[1])[0],((int16_t*)&x[1])[1],((int16_t*)&y[0])[2],((int16_t*)&y[0])[3],((int16_t*)&y[1])[2],((int16_t*)&y[1])[3]); @@ -18743,27 +18750,27 @@ int main(int argc, char**argv) for (i=0;i<48;i++) printf("%d,%d,",((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]); printf("\n"); - + */ dft60((int16_t *)x,(int16_t *)y,1); printf("\n\n60-point\n"); printf("X: "); for (i=0;i<60;i++) - printf("%d,%d,",((int16_t*)(&x[i]))[0],((int16_t *)(&x[i]))[1]); + printf("%d,%d,",((int16_t*)(&x128[i]))[0],((int16_t *)(&x128[i]))[1]); printf("\nY:"); for (i=0;i<60;i++) - printf("%d,%d,",((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]); + printf("%d,%d,",((int16_t*)(&y128[i]))[0],((int16_t *)(&y128[i]))[1]); printf("\n"); - + dft72((int16_t *)x,(int16_t *)y,1); printf("\n\n72-point\n"); printf("X: "); for (i=0;i<72;i++) - printf("%d,%d,",((int16_t*)(&x[i]))[0],((int16_t *)(&x[i]))[1]); + printf("%d,%d,",((int16_t*)(&x128[i]))[0],((int16_t *)(&x128[i]))[1]); printf("\nY:"); for (i=0;i<72;i++) - printf("%d: %d,%d\n",i,((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]); + printf("%d: %d,%d\n",i,((int16_t*)(&y128[i]))[0],((int16_t *)(&y128[i]))[1]); printf("\n"); - + /* dft96((int16_t *)x,(int16_t *)y,1); printf("\n\n96-point\n"); printf("X: "); @@ -18783,17 +18790,17 @@ int main(int argc, char**argv) for (i=0;i<108;i++) printf("%d: %d,%d\n",i,((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]); printf("\n"); - + */ dft120((int16_t *)x,(int16_t *)y,1); printf("\n\n120-point\n"); printf("X: "); for (i=0;i<120;i++) - printf("%d,%d,",((int16_t*)(&x[i]))[0],((int16_t *)(&x[i]))[1]); + printf("%d,%d,",((int16_t*)(&x128[i]))[0],((int16_t *)(&x128[i]))[1]); printf("\nY:"); for (i=0;i<120;i++) - printf("%d: %d,%d\n",i,((int16_t*)(&y[i]))[0],((int16_t *)(&y[i]))[1]); + printf("%d: %d,%d\n",i,((int16_t*)(&y128[i]))[0],((int16_t *)(&y128[i]))[1]); printf("\n"); - + /* dft144((int16_t *)x,(int16_t *)y,1); printf("\n\n144-point\n"); printf("X: "); diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index dc0b31af58..f8ec3f8e58 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -51,6 +51,9 @@ #define BBU_LOCAL_RADIO_HEAD 0 #define BBU_REMOTE_RADIO_HEAD 1 +#define MAX_CARDS 8 + + typedef int64_t openair0_timestamp; typedef volatile int64_t openair0_vtimestamp; @@ -59,9 +62,9 @@ typedef volatile int64_t openair0_vtimestamp; typedef struct openair0_device_t openair0_device; -#ifndef EXMIMO -#define MAX_CARDS 1 -#endif + + + //#define USRP_GAIN_OFFSET (56.0) // 86 calibrated for USRP B210 @ 2.6 GHz to get equivalent RS EPRE in OAI to SMBV100 output @@ -145,16 +148,12 @@ typedef struct { unsigned int samples_per_frame; //! the sample rate for both transmit and receive. double sample_rate; - //! number of samples per RX/TX packet (USRP + Ethernet) - unsigned int samples_per_packet; - //! delay in sending samples (write) due to hardware access, softmodem processing and fronthaul delay if exist - int tx_scheduling_advance; + //! flag to indicate that the device is doing mmapped DMA transfers + int mmapped_dma; //! offset in samples between TX and RX paths int tx_sample_advance; - //! configurable tx thread lauch delay - int txlaunch_wait; /* 1 or 0 */ - //! configurable tx thread lauch delay - int txlaunch_wait_slotcount; + int samples_per_packet; + int tx_scheduling_advance; //! number of RX channels (=RX antennas) int rx_num_channels; //! number of TX channels (=TX antennas) @@ -165,7 +164,7 @@ typedef struct { //! \brief Center frequency in Hz for TX. //! index: [0..rx_num_channels[ !!! see lte-ue.c:427 FIXME iterates over rx_num_channels double tx_freq[4]; - + //! \brief memory //! \brief Pointer to Calibration table for RX gains rx_gain_calib_table_t *rx_gain_calib_table; diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index 427cd47be8..a8b5f3e21b 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -36,17 +36,34 @@ * 28.01.2013: Initial version */ -#include -#include -#include -#include -#include +#define _GNU_SOURCE #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "openair0_lib.h" #include "openair_device.h" #include "common_lib.h" + +#include + #define max(a,b) ((a)>(b) ? (a) : (b)) exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS]; // contains userspace pointers for each card @@ -66,6 +83,14 @@ static uint32_t rf_vcocal[4] = {910,910,910,910}; static uint32_t rf_vcocal_850[4] = {2015, 2015, 2015, 2015}; static uint32_t rf_rxdc[4] = {32896,32896,32896,32896}; + + +extern volatile int oai_exit; + + +void kill_watchdog(openair0_device *); +void create_watchdog(openair0_device *); + unsigned int log2_int( unsigned int x ) { unsigned int ans = 0 ; @@ -247,16 +272,279 @@ int openair0_stop_without_reset(int card) #define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX) #define RF_MODE_BASE (LNA1ON + RFBBNORM) +static void *watchdog_thread(void *arg) { + + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + exmimo_state_t *exm=((openair0_device *)arg)->priv; + openair0_config_t *cfg=&((openair0_device *)arg)->openair0_cfg[0]; + + volatile unsigned int *daq_mbox = openair0_daq_cnt(); + unsigned int mbox,diff; + + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD threads */ + /* CPU 1 is reserved for all TX threads */ + /* Enable CPU Affinity only if number of CPUs >2 */ + CPU_ZERO(&cpuset); + +#ifdef CPU_AFFINITY + if (get_nprocs() > 2) + { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_setaffinity_np"); + printf("Error setting processor affinity"); + } + } +#endif //CPU_AFFINITY + + /* Check the actual affinity mask assigned to the thread */ + + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_getaffinity_np"); + printf("Error getting processor affinity "); + } + memset(cpu_affinity,0,sizeof(cpu_affinity)); + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) + { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } + + memset(&sparam, 0 , sizeof (sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + policy = SCHED_FIFO ; + + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) + { + perror("pthread_setschedparam : "); + printf("Error setting thread priority"); + } + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) + { + perror("pthread_getschedparam : "); + printf("Error getting thread priority"); + + } + + printf("EXMIMO2 Watchdog TX thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n", + sched_getcpu(), + syscall(__NR_gettid), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, + cpu_affinity ); + + + + + mlockall(MCL_CURRENT | MCL_FUTURE); + + exm->watchdog_exit = 0; + exm->ts = 0; + exm->last_mbox = 0; + + if (cfg->sample_rate==30.72e6) { + exm->samples_per_tick = 15360; + exm->samples_per_frame = 307200; + } + else if (cfg->sample_rate==23.04e6) { + exm->samples_per_tick = 11520; + exm->samples_per_frame = 230400; + } + else if (cfg->sample_rate==15.36e6) { + exm->samples_per_tick = 7680; + exm->samples_per_frame = 153600; + } + else if (cfg->sample_rate==7.68e6) { + exm->samples_per_tick = 3840; + exm->samples_per_frame = 76800; + } + else if (cfg->sample_rate==3.84e6) { + exm->samples_per_tick = 1920; + exm->samples_per_frame = 38400; + } + else if (cfg->sample_rate==1.92e6) { + exm->samples_per_tick = 960; + exm->samples_per_frame = 19200; + } + else { + printf("Unknown sampling rate %f, exiting \n",cfg->sample_rate); + exm->watchdog_exit=1; + } + // main loop to keep up with DMA transfers from exmimo2 + while ((!oai_exit) && (!exm->watchdog_exit)) { + + if (exm->daq_state == running) { + + // grab time from MBOX + mbox = daq_mbox[0]; + if (mboxlast_mbox) { // wrap-around + diff = 150 + mbox - exm->last_mbox; + } + else { + diff = mbox - exm->last_mbox; + } + exm->last_mbox = mbox; + + pthread_mutex_lock(&exm->watchdog_mutex); + exm->ts += (diff*exm->samples_per_frame/150) ; + + if (diff > 10) // we're too late so exit + exm->watchdog_exit = 1; + + if (exm->ts - exm->last_ts_rx > exm->samples_per_frame) { + exm->watchdog_exit = 1; + printf("RX Overflow, exiting\n"); + } + pthread_mutex_unlock(&exm->watchdog_mutex); + } + + + usleep(500); // sleep for 500us + } + + oai_exit=1; + return NULL; +} + +void create_watchdog(openair0_device *dev) { + + exmimo_state_t *priv = dev->priv; + priv->watchdog_exit=0; +#ifndef DEADLINE_SCHEDULER + priv->watchdog_sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_attr_setschedparam(&priv->watchdog_attr,&priv->watchdog_sched_param); + pthread_attr_setschedpolicy(&priv->watchdog_attr,SCHED_FIFO); + pthread_create(&priv->watchdog,&priv->watchdog_attr,watchdog_thread,dev); +#else + pthread_create(&priv->watchdog,NULL,watchdog_thread,devv); +#endif + pthread_mutex_init(&priv->watchdog_mutex,NULL); + + +} + +int trx_exmimo_start(openair0_device *device) { + + exmimo_state_t *exm=device->priv; + + openair0_start_rt_acquisition(0); + exm->daq_state = running; + + return(0); +} + +int trx_exmimo_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc, int flags) { + + return(0); +} + +int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + + exmimo_state_t *exm=device->priv; + openair0_config_t *cfg=&device->openair0_cfg[0]; + openair0_timestamp ts,diff; + int i; + + pthread_mutex_lock(&exm->watchdog_mutex); + ts = exm->ts; + pthread_mutex_unlock(&exm->watchdog_mutex); + while (ts < exm->last_ts_rx + nsamps) { + + diff = exm->last_ts_rx+nsamps - ts; // difference in samples between current timestamp and last RX received sample + // go to sleep until we should have enough samples (1024 for a bit more) + usleep((unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate)); + // get new timestamp, in case we have to sleep again + pthread_mutex_lock(&exm->watchdog_mutex); + ts = exm->ts; + pthread_mutex_unlock(&exm->watchdog_mutex); + } + + if (cfg->mmapped_dma == 0) { // if buff is not the dma buffer, do a memcpy, otherwise do nothing + for (i=0;ilast_ts_rx % exm->samples_per_frame), + nsamps*sizeof(int)); + } + } + + *ptimestamp=exm->last_ts_rx; + exm->last_ts_rx += nsamps; + + return(0); +} + +void trx_exmimo_end(openair0_device *device) { + + exmimo_state_t *exm=device->priv; + + exm->daq_state = idle; + openair0_stop(0); + +} + +int trx_exmimo_get_stats(openair0_device* device) { + + return(0); + +} + +int trx_exmimo_reset_stats(openair0_device* device) { + + return(0); + +} + +int trx_exmimo_stop(int card) { + + return(0); + +} + +int trx_exmimo_set_freq(openair0_device* device, openair0_config_t *openair0_cfg1,int exmimo_dump_config) { + + return(0); +} + +int trx_exmimo_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { + + return(0); + +} + +void kill_watchdog(openair0_device *device) { + + exmimo_state_t *exm=(exmimo_state_t *)device->priv; + exm->watchdog_exit=1; + +} + int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { // Initialize card // exmimo_config_t *p_exmimo_config; exmimo_id_t *p_exmimo_id; int ret; + exmimo_state_t *exm = (exmimo_state_t *)malloc(sizeof(exmimo_state_t)); ret = openair0_open(); - - + if ( ret != 0 ) { if (ret == -1) printf("Error opening /dev/openair0"); @@ -289,6 +577,23 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->type = EXMIMO_DEV; + // Add stuff that was in lte-softmodem here + + // + device->trx_start_func = trx_exmimo_start; + device->trx_end_func = trx_exmimo_end; + device->trx_read_func = trx_exmimo_read; + device->trx_write_func = trx_exmimo_write; + device->trx_get_stats_func = trx_exmimo_get_stats; + device->trx_reset_stats_func = trx_exmimo_reset_stats; + device->trx_stop_func = trx_exmimo_stop; + device->trx_set_freq_func = trx_exmimo_set_freq; + device->trx_set_gains_func = trx_exmimo_set_gains; + device->openair0_cfg = openair0_cfg; + device->priv = (void *)exm; + + create_watchdog(device); + return(0); } @@ -326,8 +631,6 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) p_exmimo_config->framing.multicard_syncmode=SYNCMODE_SLAVE; /* device specific */ - openair0_cfg[card].txlaunch_wait = 1;//manage when TX processing is triggered - openair0_cfg[card].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered openair0_cfg[card].iq_txshift = 4;//shift openair0_cfg[card].iq_rxrescale = 15;//rescale iqs diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h index 0abb27dee2..a2f37b09dc 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h @@ -42,6 +42,29 @@ #include "pcie_interface.h" #include "openair_device.h" #include "common_lib.h" +#include +#include +#include + +typedef enum { + idle=0, + waiting_for_synch, + running +} exmimo_daq_state_t; + +typedef struct { + pthread_t watchdog; + pthread_attr_t watchdog_attr; + struct sched_param watchdog_sched_param; + pthread_mutex_t watchdog_mutex; + int watchdog_exit; + exmimo_daq_state_t daq_state; + openair0_timestamp ts; + openair0_timestamp last_ts_rx; + int samples_per_tick; + int samples_per_frame; + int last_mbox; +} exmimo_state_t; // Use this to access shared memory (configuration structures, adc/dac data buffers, ...) // contains userspace pointers diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 5275bb43bd..f59ec9ba64 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -129,7 +129,7 @@ extern volatile int start_UE; #endif extern volatile int oai_exit; -extern openair0_config_t openair0_cfg[MAX_CARDS]; +extern openair0_config_t *openair0_cfg; extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; @@ -1174,11 +1174,9 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c { int i, CC_id; -#ifndef EXMIMO + uint16_t N_TA_offset = 0; -#else - int j; -#endif + LTE_DL_FRAME_PARMS *frame_parms; @@ -1191,8 +1189,6 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c return(-1); } -#ifndef EXMIMO - if (frame_parms->frame_type == TDD) { if (frame_parms->N_RB_DL == 100) N_TA_offset = 624; @@ -1202,8 +1198,9 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c N_TA_offset = 624/4; } -#endif + + /* // replace RX signal buffers with mmaped HW versions #ifdef EXMIMO openair0_cfg[CC_id].tx_num_channels = 0; @@ -1253,7 +1250,9 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c } } -#else // not EXMIMO +#else // not EXMIMO + */ + rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*)); txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); @@ -1275,7 +1274,7 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c } -#endif + } return(0); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 991438d4d5..66c60056b3 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -100,6 +100,7 @@ extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; extern int sync_var; + extern openair0_config_t openair0_cfg[MAX_CARDS]; extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; From fc13e2005f222d7e48905f3004d5bd335b288e0d Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 20 Jun 2016 10:21:02 +0200 Subject: [PATCH 054/206] if header and data blocks seperated --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 81 +++++++++++++++----------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 36 ++++++------ 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 15e98c36f6..39a07a881b 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -48,21 +48,29 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; + int32_t **rxdataF = eNB->common_vars.rxdataF[0]; + + IF4_dl_header_t *dl_header=NULL; + IF4_ul_header_t *ul_header=NULL; + IF4_prach_header_t *prach_header=NULL; uint16_t symbol_id, element_id; - uint16_t db_fulllength = 12*fp->N_RB_DL; - uint16_t db_halflength = db_fulllength>>1; - int slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; - int blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - - int16_t *data_block = (int16_t*)malloc(db_fulllength*sizeof(int16_t)); + uint16_t db_halflength; + int slotoffsetF, blockoffsetF; + + int16_t *data_block=NULL; +// int16_t *txbuffer = (int16_t*)malloc(db_halflength*sizeof(int16_t)); - // Caller: RCC - DL *** handle RRU case - UL and PRACH *** if (packet_type == IF4_PDLFFT) { - IF4_dl_packet_t *dl_packet = (IF4_dl_packet_t*)malloc(sizeof_IF4_dl_packet_t); - gen_IF4_dl_packet(dl_packet, proc); + dl_header = (IF4_dl_header_t*)malloc(sizeof_IF4_dl_header_t); + gen_IF4_dl_header(dl_header, proc); - dl_packet->data_block = data_block; + db_halflength = (12*fp->N_RB_DL)>>1; + slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; + + printf("Problem here - db_half %d\n", db_halflength); + data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { @@ -78,40 +86,45 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { } // Update information in generated packet - dl_packet->frame_status.sym_num = symbol_id; + dl_header->frame_status.sym_num = symbol_id; + printf("\n Not even here !!\n"); // Write the packet(s) to the fronthaul - // if ((bytes_sent = eNB->ifdevice.trx_write_func(&eNB->ifdevice, - // (proc->timestamp_tx-eNB->ifdevice.openair0_cfg.tx_sample_advance), - // dl_packet, - // eNB->frame_parms.samples_per_tti, - // eNB->frame_parms.nb_antennas_tx, - // 0)) < 0) { - // perror("RCC : ETHERNET write"); - //} + if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, + symbol_id, + &data_block, + 1, + 1, + 0)) < 0) { + perror("RCC : ETHERNET write"); + } slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } } else if (packet_type == IF4_PULFFT) { - IF4_ul_packet_t *ul_packet = (IF4_ul_packet_t*)malloc(sizeof_IF4_ul_packet_t); - gen_IF4_ul_packet(ul_packet, proc); + ul_header = (IF4_ul_header_t*)malloc(sizeof_IF4_ul_header_t); + gen_IF4_ul_header(ul_header, proc); + + db_halflength = (12*fp->N_RB_UL)>>1; + slotoffsetF = (proc->subframe_rx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - ul_packet->data_block = data_block; + data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { // Do compression of the two parts and generate data blocks - rxdataF for (element_id=0; element_id>16) + 32768 ]<<8; + data_block[element_id] = lin2alaw[ (rxdataF[0][blockoffsetF+element_id] & 0xffff) + 32768 ]; + data_block[element_id] |= lin2alaw[ (rxdataF[0][blockoffsetF+element_id]>>16) + 32768 ]<<8; - //data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; - //data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; + data_block[element_id+db_halflength] = lin2alaw[ (rxdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; + data_block[element_id+db_halflength] |= lin2alaw[ (rxdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; } // Update information in generated packet - ul_packet->frame_status.sym_num = symbol_id; + ul_header->frame_status.sym_num = symbol_id; // Write the packet(s) to the fronthaul @@ -131,7 +144,7 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, uint32_t *symbol_number) { *packet_type = 0; - int16_t *data_block=NULL; + //int16_t *data_block=NULL; // Read packet(s) from the fronthaul // for(i=0; isymbols_per_tti; i++) { @@ -166,7 +179,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u return; } -void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { +void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; @@ -183,10 +196,10 @@ void gen_IF4_dl_packet(IF4_dl_packet_t *dl_packet, eNB_rxtx_proc_t *proc) { dl_packet->frame_status.rsvd = 0; // Set frame check sequence - dl_packet->fcs = 0; + } -void gen_IF4_ul_packet(IF4_ul_packet_t *ul_packet, eNB_rxtx_proc_t *proc) { +void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type ul_packet->type = IF4_PACKET_TYPE; ul_packet->sub_type = IF4_PULFFT; @@ -207,10 +220,10 @@ void gen_IF4_ul_packet(IF4_ul_packet_t *ul_packet, eNB_rxtx_proc_t *proc) { ul_packet->gain0.rsvd = 0; // Set frame check sequence - ul_packet->fcs = 0; + } -void gen_IF4_prach_packet(IF4_prach_packet_t *prach_packet, eNB_rxtx_proc_t *proc) { +void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type prach_packet->type = IF4_PACKET_TYPE; prach_packet->sub_type = IF4_PRACH; @@ -226,5 +239,5 @@ void gen_IF4_prach_packet(IF4_prach_packet_t *prach_packet, eNB_rxtx_proc_t *pro prach_packet->prach_conf.exponent = 0; // Set frame check sequence - prach_packet->fcs = 0; + } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index a6ca7eb5c0..d61c0c59a0 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -93,7 +93,7 @@ struct IF4_lte_prach_conf { typedef struct IF4_lte_prach_conf IF4_lte_prach_conf_t; #define sizeof_IF4_lte_prach_conf_t 4 -struct IF4_dl_packet { +struct IF4_dl_header { /// Destination Address /// Source Address @@ -107,15 +107,15 @@ struct IF4_dl_packet { /// Frame Status IF4_frame_status_t frame_status; /// Data Blocks - int16_t *data_block; + /// Frame Check Sequence - uint32_t fcs; + }; -typedef struct IF4_dl_packet IF4_dl_packet_t; -#define sizeof_IF4_dl_packet_t 18 +typedef struct IF4_dl_header IF4_dl_header_t; +#define sizeof_IF4_dl_header_t 12 -struct IF4_ul_packet { +struct IF4_ul_header { /// Destination Address /// Source Address @@ -145,15 +145,15 @@ struct IF4_ul_packet { /// Gain 7 IF4_gain_t gain7; /// Data Blocks - int16_t *data_block; + /// Frame Check Sequence - uint32_t fcs; + }; -typedef struct IF4_ul_packet IF4_ul_packet_t; -#define sizeof_IF4_ul_packet_t 34 +typedef struct IF4_ul_header IF4_ul_header_t; +#define sizeof_IF4_ul_header_t 28 -struct IF4_prach_packet { +struct IF4_prach_header { /// Destination Address /// Source Address @@ -167,19 +167,19 @@ struct IF4_prach_packet { /// LTE Prach Configuration IF4_lte_prach_conf_t prach_conf; /// Prach Data Block (one antenna) - int16_t *data_block; + /// Frame Check Sequence - uint32_t fcs; + }; -typedef struct IF4_prach_packet IF4_prach_packet_t; -#define sizeof_IF4_prach_packet_t 18 +typedef struct IF4_prach_header IF4_prach_header_t; +#define sizeof_IF4_prach_header_t 12 -void gen_IF4_dl_packet(IF4_dl_packet_t*, eNB_rxtx_proc_t*); +void gen_IF4_dl_header(IF4_dl_header_t*, eNB_rxtx_proc_t*); -void gen_IF4_ul_packet(IF4_ul_packet_t*, eNB_rxtx_proc_t*); +void gen_IF4_ul_header(IF4_ul_header_t*, eNB_rxtx_proc_t*); -void gen_IF4_prach_packet(IF4_prach_packet_t*, eNB_rxtx_proc_t*); +void gen_IF4_prach_header(IF4_prach_header_t*, eNB_rxtx_proc_t*); void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t); From 9246b16ca9d168f8490b651944f9ceaddf20e318 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 20 Jun 2016 10:51:40 +0200 Subject: [PATCH 055/206] added logic for recv_if4 function --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 79 ++++++++++++++++++++------ 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 39a07a881b..5da0b0f81f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -96,7 +96,7 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { 1, 1, 0)) < 0) { - perror("RCC : ETHERNET write"); + perror("ETHERNET write"); } slotoffsetF += fp->ofdm_symbol_size; @@ -142,35 +142,78 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { } void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, uint32_t *symbol_number) { + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + int32_t **txdataF = eNB->common_vars.txdataF[0]; + int32_t **rxdataF = eNB->common_vars.rxdataF[0]; + + uint16_t element_id; + uint16_t db_halflength; + int slotoffsetF, blockoffsetF; *packet_type = 0; - //int16_t *data_block=NULL; + void *rxbuffer=NULL; + int16_t *data_block=NULL; // Read packet(s) from the fronthaul -// for(i=0; isymbols_per_tti; i++) { -// if (dev->eth_dev.trx_read_func (&dev->eth_dev, -// timestamp_rx, -// rx_eNB, -// spp_eth, -// dev->eth_dev.openair0_cfg->rx_num_channels -// ) < 0) { -// perror("RRU : ETHERNET read"); -// } -// printf("\n Recv IF4 for frame %d, subframe %d and symbol %d\n", proc->frame_tx, proc->subframe_tx, symbol_id); + if (eNB->ifdevice.trx_read_func (&eNB->ifdevice, + symbol_number, + rxbuffer, + fp->symbols_per_tti, + eNB->ifdevice.openair0_cfg->rx_num_channels + ) < 0) { + perror("ETHERNET read"); + } - //*packet_type = ; + packet_type = (uint16_t*) (rxbuffer+2); if (*packet_type == IF4_PDLFFT) { + data_block = (int16_t*) (rxbuffer+sizeof_IF4_dl_header_t); - // Apply reverse processing - decompression - // txAlawtolinear( Datablock ) - - // Generate and return the OFDM symbols (txdataF) - // txDataF + db_halflength = (12*fp->N_RB_DL)>>1; + // Calculate from received packet + slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; + + data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); + + // Do decompression of the two parts and generate data blocks + for (element_id=0; element_id>8) ]<<16; + + txdataF[0][slotoffsetF+element_id] = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; + txdataF[0][slotoffsetF+element_id] |= alaw2lin[ (data_block[element_id+db_halflength]>>8) ]<<16; + } + + // Find and return symbol_number + *symbol_number = 0; + } else if (*packet_type == IF4_PULFFT) { + data_block = (int16_t*) (rxbuffer+sizeof_IF4_ul_header_t); + + db_halflength = (12*fp->N_RB_UL)>>1; + + // Calculate from received packet + slotoffsetF = (proc->subframe_rx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; + + data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); + + // Do decompression of the two parts and generate data blocks + for (element_id=0; element_id>8) ]<<16; + + rxdataF[0][slotoffsetF+element_id] = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; + rxdataF[0][slotoffsetF+element_id] |= alaw2lin[ (data_block[element_id+db_halflength]>>8) ]<<16; + } + + // Find and return symbol_number + *symbol_number = 0; } else if (*packet_type == IF4_PRACH) { + data_block = (int16_t*) (rxbuffer+sizeof_IF4_prach_header_t); } else { AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type); From f2e183fb2b7bbb56c2813b4d10205447b44bb413 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 20 Jun 2016 18:33:37 +0200 Subject: [PATCH 056/206] handling changes in eth lower level functions --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 131 +++++++++++++++---------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 10 +- 2 files changed, 85 insertions(+), 56 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 5da0b0f81f..946734f81b 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -44,38 +44,34 @@ #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/TOOLS/ALAW/alaw_lut.h" -// Get device information -void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { +// --- Careful to handle buffer memory --- RAW/UDP modes --- PRACH variables and data +void send_IF4(PHY_VARS_eNB *eNB, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; - - IF4_dl_header_t *dl_header=NULL; - IF4_ul_header_t *ul_header=NULL; - IF4_prach_header_t *prach_header=NULL; - + int16_t *prachF = eNB->prach_vars.prachF; + uint16_t symbol_id, element_id; - uint16_t db_halflength; + uint16_t db_fulllength, db_halflength; int slotoffsetF, blockoffsetF; + void *tx_buffer=NULL; int16_t *data_block=NULL; -// int16_t *txbuffer = (int16_t*)malloc(db_halflength*sizeof(int16_t)); if (packet_type == IF4_PDLFFT) { - dl_header = (IF4_dl_header_t*)malloc(sizeof_IF4_dl_header_t); - gen_IF4_dl_header(dl_header, proc); - - db_halflength = (12*fp->N_RB_DL)>>1; + db_fulllength = 12*fp->N_RB_DL; + db_halflength = (db_fulllength)>>1; slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - - printf("Problem here - db_half %d\n", db_halflength); - data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); + tx_buffer = malloc(/*SIZE_OF_MAC_BYTES +*/ sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); + IF4_dl_header_t *dl_header = (IF4_dl_header_t *)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/); + data_block = (int16_t*)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/ + sizeof_IF4_dl_header_t); + + gen_IF4_dl_header(dl_header, proc); + for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - - printf("\n Send IF4 for frame %d, subframe %d and symbol %d\n", proc->frame_tx, proc->subframe_tx, symbol_id); - // Do compression of the two parts and generate data blocks for (element_id=0; element_idframe_status.sym_num = symbol_id; - printf("\n Not even here !!\n"); - // Write the packet(s) to the fronthaul + // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, - symbol_id, - &data_block, - 1, - 1, - 0)) < 0) { - perror("ETHERNET write"); + symbol_id, + tx_buffer, + db_fulllength, + 1, + IF4_PDLFFT)) < 0) { + perror("ETHERNET write for IF4_PDLFFT\n"); } slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } } else if (packet_type == IF4_PULFFT) { - ul_header = (IF4_ul_header_t*)malloc(sizeof_IF4_ul_header_t); - gen_IF4_ul_header(ul_header, proc); - - db_halflength = (12*fp->N_RB_UL)>>1; + db_fulllength = 12*fp->N_RB_UL; + db_halflength = (db_fulllength)>>1; slotoffsetF = (proc->subframe_rx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - - data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); + + tx_buffer = malloc(/*SIZE_OF_MAC_BYTES +*/ sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); + IF4_ul_header_t *ul_header = (IF4_ul_header_t *)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/); + data_block = (int16_t*)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/ + sizeof_IF4_ul_header_t); + + gen_IF4_ul_header(ul_header, proc); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - // Do compression of the two parts and generate data blocks - rxdataF for (element_id=0; element_idframe_status.sym_num = symbol_id; // Write the packet(s) to the fronthaul + if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, + symbol_id, + tx_buffer, + db_fulllength, + 1, + IF4_PULFFT)) < 0) { + perror("ETHERNET write for IF4_PULFFT\n"); + } slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } } else if (packet_type == IF4_PRACH) { - - + // FIX: hard coded prach samples length + db_fulllength = 839; + slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + + tx_buffer = malloc(/*SIZE_OF_MAC_BYTES +*/ sizeof_IF4_prach_header_t + db_fulllength*sizeof(int16_t)); + IF4_prach_header_t *prach_header = (IF4_prach_header_t *)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/); + data_block = (int16_t*)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/ + sizeof_IF4_prach_header_t); + + gen_IF4_prach_header(prach_header, proc); + + // Do compression and generate data blocks + for (element_id=0; element_id>16) + 32768 ]<<8; + } + + // Write the packet to the fronthaul + if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, + symbol_id, + tx_buffer, + db_fulllength, + 1, + IF4_PRACH)) < 0) { + perror("ETHERNET write for IF4_PRACH\n"); + } } else { AssertFatal(1==0, "send_IF4 - Unknown packet_type %x", packet_type); } + free(tx_buffer); return; } -void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, uint32_t *symbol_number) { +void recv_IF4(PHY_VARS_eNB *eNB, uint16_t *packet_type, uint32_t *symbol_number) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -151,23 +180,22 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u int slotoffsetF, blockoffsetF; *packet_type = 0; - void *rxbuffer=NULL; + void *rx_buffer=NULL; int16_t *data_block=NULL; // Read packet(s) from the fronthaul - if (eNB->ifdevice.trx_read_func (&eNB->ifdevice, + if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, symbol_number, - rxbuffer, - fp->symbols_per_tti, - eNB->ifdevice.openair0_cfg->rx_num_channels - ) < 0) { + rx_buffer, + 0, + 0) < 0) { perror("ETHERNET read"); } - packet_type = (uint16_t*) (rxbuffer+2); + packet_type = (uint16_t*) (rx_buffer+2); if (*packet_type == IF4_PDLFFT) { - data_block = (int16_t*) (rxbuffer+sizeof_IF4_dl_header_t); + data_block = (int16_t*) (rx_buffer+sizeof_IF4_dl_header_t); db_halflength = (12*fp->N_RB_DL)>>1; @@ -190,7 +218,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u *symbol_number = 0; } else if (*packet_type == IF4_PULFFT) { - data_block = (int16_t*) (rxbuffer+sizeof_IF4_ul_header_t); + data_block = (int16_t*) (rx_buffer+sizeof_IF4_ul_header_t); db_halflength = (12*fp->N_RB_UL)>>1; @@ -213,16 +241,17 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u *symbol_number = 0; } else if (*packet_type == IF4_PRACH) { - data_block = (int16_t*) (rxbuffer+sizeof_IF4_prach_header_t); + data_block = (int16_t*) (rx_buffer+sizeof_IF4_prach_header_t); } else { AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type); } - + + free(rx_buffer); return; } -void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_rxtx_proc_t *proc) { +void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_proc_t *proc) { // Set Type and Sub-Type dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; @@ -242,7 +271,7 @@ void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_rxtx_proc_t *proc) { } -void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_rxtx_proc_t *proc) { +void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_proc_t *proc) { // Set Type and Sub-Type ul_packet->type = IF4_PACKET_TYPE; ul_packet->sub_type = IF4_PULFFT; @@ -266,7 +295,7 @@ void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_rxtx_proc_t *proc) { } -void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, eNB_rxtx_proc_t *proc) { +void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, eNB_proc_t *proc) { // Set Type and Sub-Type prach_packet->type = IF4_PACKET_TYPE; prach_packet->sub_type = IF4_PRACH; diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index d61c0c59a0..269ecb72a9 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -175,12 +175,12 @@ struct IF4_prach_header { typedef struct IF4_prach_header IF4_prach_header_t; #define sizeof_IF4_prach_header_t 12 -void gen_IF4_dl_header(IF4_dl_header_t*, eNB_rxtx_proc_t*); +void gen_IF4_dl_header(IF4_dl_header_t*, eNB_proc_t*); -void gen_IF4_ul_header(IF4_ul_header_t*, eNB_rxtx_proc_t*); +void gen_IF4_ul_header(IF4_ul_header_t*, eNB_proc_t*); -void gen_IF4_prach_header(IF4_prach_header_t*, eNB_rxtx_proc_t*); +void gen_IF4_prach_header(IF4_prach_header_t*, eNB_proc_t*); -void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t); +void send_IF4(PHY_VARS_eNB*, uint16_t); -void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t*, uint32_t*); +void recv_IF4(PHY_VARS_eNB*, uint16_t*, uint32_t*); From a8def02fbf3d4e0d5b25fd409db88c406e759699 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 20 Jun 2016 18:36:17 +0200 Subject: [PATCH 057/206] starting to add if4 specific eth read, write --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 94 ++++++++++++++++++- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 21 ++++- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 10 ++ 3 files changed, 119 insertions(+), 6 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index a360f26556..14561a25e7 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -140,7 +140,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi //sendto_flag|=flags; eth->tx_nsamps=nsamps; - + for (i=0;ipriv; + int Mod_id = device->Mod_id; + + ssize_t packet_size; + + if (flags == IF4_PDLFFT) { + packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks); + } else if (flags == IF4_PULFFT) { + packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks); + } else { + packet_size = RAW_IF4_PRACH_SIZE_BYTES(nblocks); + } + + eth->tx_nsamps = nblocks; + + memcpy(buff[0], (void*)&eh, MAC_HEADER_SIZE_BYTES); + + bytes_sent = send(eth->sockfd[Mod_id], + buff[0], + packet_size, + 0); + + if (bytes_sent == -1) { + eth->num_tx_errors++; + perror("ETHERNET WRITE: "); + exit(-1); + } else { + eth->tx_actual_nsamps = bytes_sent>>1; + eth->tx_count++; + } + + return (bytes_sent-MAC_HEADER_SIZE_BYTES); +} + + + int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { int bytes_received=0; @@ -256,7 +298,55 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi return (bytes_received-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2; } - + + +int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + + int bytes_received=0; + int i=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + int rcvfrom_flag =0; + + eth->rx_nsamps=nsamps; + + /* buff[i] points to the position in rx buffer where the payload to be received will be placed + buff2 points to the position in rx buffer where the packet header will be placed */ + void *buff2 = (void*)(buff[i]-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES); + + /* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/ + struct ether_header temp = *(struct ether_header *)buff2; + int32_t temp0 = *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES); + openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); + + bytes_received=0; + + while(bytes_received < RAW_PACKET_SIZE_BYTES(nsamps)) { + bytes_received +=recv(eth->sockfd[Mod_id], + buff2, + RAW_PACKET_SIZE_BYTES(nsamps), + rcvfrom_flag); + + if (bytes_received ==-1) { + eth->num_rx_errors++; + perror("ETHERNET READ: "); + exit(-1); + } else { + /* store the timestamp value from packet's header */ + *timestamp = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); + eth->rx_actual_nsamps=bytes_received>>2; + eth->rx_count++; + } + } + + /* tx buffer values restored */ + *(struct ether_header *)buff2 = temp; + *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0; + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1; + + return (bytes_received-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2; +} + int eth_set_dev_conf_raw(openair0_device *device) { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index f15f2d98eb..7537d77e2e 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -313,8 +313,14 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth if (eth_params->transp_preference == 1) { eth->flags = ETH_RAW_MODE; - } else { + } else if (eth_params->transp_preference == 0) { eth->flags = ETH_UDP_MODE; + } else if (eth_params->transp_preference == 3) { + eth->flags = ETH_RAW_IF4_MODE; + } else if (eth_params->transp_preference == 2) { + eth->flags = ETH_UDP_IF4_MODE; + } else { + AssertFatal(0==4, "transport_init: Unknown transport preference %d", eth_params->transp_preference); } printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); @@ -330,14 +336,21 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth device->trx_set_freq_func = trx_eth_set_freq; device->trx_set_gains_func = trx_eth_set_gains; - if ((eth->flags & ETH_RAW_MODE) != 0 ) { + /// handle if4 eth read and write functions + if (eth->flags == ETH_RAW_MODE) { device->trx_write_func = trx_eth_write_raw; device->trx_read_func = trx_eth_read_raw; - } else { + } else if (eth->flags == ETH_UDP_MODE) { device->trx_write_func = trx_eth_write_udp; device->trx_read_func = trx_eth_read_udp; + } else if (eth->flags == ETH_RAW_IF4_MODE) { + device->trx_write_func = trx_eth_write_raw_IF4; + device->trx_read_func = trx_eth_read_raw_IF4; + } else { + device->trx_write_func = trx_eth_write_udp_IF4; + device->trx_read_func = trx_eth_read_udp_IF4; } - + eth->if_name[device->Mod_id] = eth_params->local_if_name; device->priv = eth; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index b4618bb825..beb324cc59 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -54,6 +54,8 @@ #define ETH_RAW_MODE 1 #define ETH_UDP_MODE 0 +#define ETH_RAW_IF4_MODE 3 +#define ETH_UDP_IF4_MODE 2 #define TX_FLAG 1 #define RX_FLAG 0 @@ -65,6 +67,10 @@ #define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) #define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) +#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (2*scaled_nblocks) +#define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4_PRACH_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) /*!\brief opaque ethernet data structure */ typedef struct { @@ -212,6 +218,8 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value); int eth_socket_init_udp(openair0_device *device); int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +//int trx_eth_write_udp_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +//int trx_eth_read_udp_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); int eth_get_dev_conf_udp(openair0_device *device); /*! \fn static int eth_set_dev_conf_udp(openair0_device *device) @@ -226,6 +234,8 @@ int eth_set_dev_conf_udp(openair0_device *device); int eth_socket_init_raw(openair0_device *device); int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +//int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +//int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); int eth_get_dev_conf_raw(openair0_device *device); int eth_set_dev_conf_raw(openair0_device *device); From e5132ebf5f5b11ae331053bbccccd92bb55bb309 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 20 Jun 2016 13:59:00 -0700 Subject: [PATCH 058/206] eNB_proc_t -> eNB_rxtx_proc_t in if4_tools.c, addition on parameter of functions --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 10 ++++------ openair1/PHY/LTE_TRANSPORT/if4_tools.h | 8 ++++---- targets/RT/USER/lte-enb.c | 2 -- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 946734f81b..d07817c310 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -45,9 +45,8 @@ #include "PHY/TOOLS/ALAW/alaw_lut.h" // --- Careful to handle buffer memory --- RAW/UDP modes --- PRACH variables and data -void send_IF4(PHY_VARS_eNB *eNB, uint16_t packet_type) { +void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - eNB_proc_t *proc = &eNB->proc; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; int16_t *prachF = eNB->prach_vars.prachF; @@ -169,9 +168,8 @@ void send_IF4(PHY_VARS_eNB *eNB, uint16_t packet_type) { return; } -void recv_IF4(PHY_VARS_eNB *eNB, uint16_t *packet_type, uint32_t *symbol_number) { +void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, uint32_t *symbol_number) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - eNB_proc_t *proc = &eNB->proc; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -251,7 +249,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, uint16_t *packet_type, uint32_t *symbol_number) return; } -void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_proc_t *proc) { +void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; @@ -271,7 +269,7 @@ void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_proc_t *proc) { } -void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_proc_t *proc) { +void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_rxtx_proc_t *proc) { // Set Type and Sub-Type ul_packet->type = IF4_PACKET_TYPE; ul_packet->sub_type = IF4_PULFFT; diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 269ecb72a9..9d4424ab01 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -175,12 +175,12 @@ struct IF4_prach_header { typedef struct IF4_prach_header IF4_prach_header_t; #define sizeof_IF4_prach_header_t 12 -void gen_IF4_dl_header(IF4_dl_header_t*, eNB_proc_t*); +void gen_IF4_dl_header(IF4_dl_header_t*, eNB_rxtx_proc_t*); -void gen_IF4_ul_header(IF4_ul_header_t*, eNB_proc_t*); +void gen_IF4_ul_header(IF4_ul_header_t*, eNB_rxtx_proc_t*); void gen_IF4_prach_header(IF4_prach_header_t*, eNB_proc_t*); -void send_IF4(PHY_VARS_eNB*, uint16_t); +void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t); -void recv_IF4(PHY_VARS_eNB*, uint16_t*, uint32_t*); +void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t*, uint32_t*); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 0113ee4b5b..8126ef46e0 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1245,8 +1245,6 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); } - - } return(0); From ad9411fcaa5a1ee5e33554cd416f0df6b2196e9c Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 21 Jun 2016 11:05:11 +0200 Subject: [PATCH 059/206] changes to allow if4 specific eth transport modes --- openair2/ENB_APP/enb_config.c | 4 ++ openair2/ENB_APP/enb_config.h | 2 + targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 1 + targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 1 + .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 3 +- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 15 +---- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 57 +++++++++++++++++++ targets/RT/USER/lte-softmodem.c | 13 ++++- 8 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 51d5f3805f..7f8cf95c2b 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2242,6 +2242,10 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; } else if (strcmp(tr_preference, "raw") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; + } else if (strcmp(tr_preference, "udpif4") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udpif4 = 1; + } else if (strcmp(tr_preference, "rawif4") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif4 = 1; } else {//if (strcmp(preference, "no") == 0) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 5f7f2636a3..e53921b4d0 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -86,6 +86,8 @@ typedef struct rrh_gw_config_s { char *remote_address; uint16_t local_port; uint16_t remote_port; + uint8_t udpif4; + uint8_t rawif4; int tx_scheduling_advance; int tx_sample_advance; int iq_txshift; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 14561a25e7..be524b6d5f 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -51,6 +51,7 @@ #include "common_lib.h" #include "ethernet_lib.h" +#include "if_defs.h" #define DEBUG 0 diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index a9706c73bd..55b5e08535 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -52,6 +52,7 @@ #include "common_lib.h" #include "ethernet_lib.h" +#include "if_defs.h" #define DEBUG 0 struct sockaddr_in dest_addr[MAX_INST]; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 7537d77e2e..ee9ba50f66 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -51,7 +51,7 @@ #include "common_lib.h" #include "ethernet_lib.h" - +#include "if_defs.h" int num_devices_eth = 0; struct sockaddr_in dest_addr[MAX_INST]; @@ -336,7 +336,6 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth device->trx_set_freq_func = trx_eth_set_freq; device->trx_set_gains_func = trx_eth_set_gains; - /// handle if4 eth read and write functions if (eth->flags == ETH_RAW_MODE) { device->trx_write_func = trx_eth_write_raw; device->trx_read_func = trx_eth_read_raw; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index beb324cc59..72ddc0e87c 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -52,25 +52,12 @@ #define MAX_INST 4 #define DEFAULT_IF "lo" -#define ETH_RAW_MODE 1 -#define ETH_UDP_MODE 0 -#define ETH_RAW_IF4_MODE 3 -#define ETH_UDP_IF4_MODE 2 - #define TX_FLAG 1 #define RX_FLAG 0 -#define MAX_PACKET_SEQ_NUM(spp,spf) (spf/spp) +#include "if_defs.h" #define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header)) #define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp)) -#define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2) -#define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) -#define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) - -#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (2*scaled_nblocks) -#define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) -#define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) -#define RAW_IF4_PRACH_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) /*!\brief opaque ethernet data structure */ typedef struct { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h new file mode 100644 index 0000000000..f38421bed2 --- /dev/null +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -0,0 +1,57 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/*! \file targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +* \brief +* \author S. Sandeep Kumar, Raymond Knopp +* \date 2016 +* \version 0.1 +* \company Eurecom +* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr +* \note +* \warning +*/ + +// ETH transport preference modes +#define ETH_UDP_MODE 0 +#define ETH_RAW_MODE 1 +#define ETH_UDP_IF4_MODE 2 +#define ETH_RAW_IF4_MODE 3 + +// Time domain RRH packet sizes +#define MAX_PACKET_SEQ_NUM(spp,spf) (spf/spp) +#define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2) +#define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) +#define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) + +// Packet sizes for IF4 interface format +#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (2*scaled_nblocks) +#define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4_PRACH_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 50ffc6e1ff..dd55dacb1f 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -65,6 +65,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "../../ARCH/COMMON/common_lib.h" +#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all @@ -1016,7 +1017,17 @@ static void get_options (int argc, char **argv) (eth_params+j)->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; (eth_params+j)->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; (eth_params+j)->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; - (eth_params+j)->transp_preference = enb_properties->properties[i]->rrh_gw_config[j].raw; + + if (enb_properties->properties[i]->rrh_gw_config[j].raw == 1) { + (eth_params+j)->transp_preference = ETH_RAW_MODE; + } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4 == 1) { + (eth_params+j)->transp_preference = ETH_RAW_IF4_MODE; + } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4 == 1) { + (eth_params+j)->transp_preference = ETH_UDP_IF4_MODE; + } else { + (eth_params+j)->transp_preference = ETH_UDP_MODE; + } + (eth_params+j)->iq_txshift = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift; (eth_params+j)->tx_sample_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance; (eth_params+j)->tx_scheduling_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance; From ba77625411dfa4c0f59512be302aac34dd30a3c8 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 21 Jun 2016 11:50:17 +0200 Subject: [PATCH 060/206] device specific eth headers - needs testing --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 19 +++++++++---------- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 3 ++- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 3 +++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index be524b6d5f..df2018ad0a 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -59,7 +59,6 @@ struct sockaddr_ll dest_addr[MAX_INST]; struct sockaddr_ll local_addr[MAX_INST]; int addr_len[MAX_INST]; struct ifreq if_index[MAX_INST]; -struct ether_header eh; int eth_socket_init_raw(openair0_device *device) { @@ -121,11 +120,11 @@ int eth_socket_init_raw(openair0_device *device) { } /* Construct the Ethernet header */ - ether_aton_r(local_mac, (struct ether_addr *)(&(eh.ether_shost))); - ether_aton_r(remote_mac, (struct ether_addr *)(&(eh.ether_dhost))); - eh.ether_type = htons((short)device->openair0_cfg->my_port); + ether_aton_r(local_mac, (struct ether_addr *)(&(eth->eh.ether_shost))); + ether_aton_r(remote_mac, (struct ether_addr *)(&(eth->eh.ether_dhost))); + eth->eh.ether_type = htons((short)device->openair0_cfg->my_port); - printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5]); + printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5]); return 0; } @@ -153,7 +152,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); bytes_sent = 0; - memcpy(buff2,(void*)&eh,MAC_HEADER_SIZE_BYTES); + memcpy(buff2,(void*)ð->eh,MAC_HEADER_SIZE_BYTES); *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t))=1+(i<<1); *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = timestamp; @@ -220,7 +219,7 @@ int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, eth->tx_nsamps = nblocks; - memcpy(buff[0], (void*)&eh, MAC_HEADER_SIZE_BYTES); + memcpy(buff[0], (void*)ð->eh, MAC_HEADER_SIZE_BYTES); bytes_sent = send(eth->sockfd[Mod_id], buff[0], @@ -365,7 +364,7 @@ int eth_set_dev_conf_raw(openair0_device *device) { msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t); - memcpy(msg,(void*)&eh,MAC_HEADER_SIZE_BYTES); + memcpy(msg,(void*)ð->eh,MAC_HEADER_SIZE_BYTES); memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)device->openair0_cfg,sizeof(openair0_config_t)); if (send(eth->sockfd[Mod_id], @@ -401,10 +400,10 @@ int eth_get_dev_conf_raw(openair0_device *device) { } /* RRH stores the remote MAC address */ - memcpy(eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN); + memcpy(eth->eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN); //memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t)); device->openair0_cfg=(openair0_config_t *)(msg + MAC_HEADER_SIZE_BYTES); - printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5],eh.ether_dhost[0],eh.ether_dhost[1],eh.ether_dhost[2],eh.ether_dhost[3],eh.ether_dhost[4],eh.ether_dhost[5]); + printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5],eth->eh.ether_dhost[0],eth->eh.ether_dhost[1],eth->eh.ether_dhost[2],eth->eh.ether_dhost[3],eth->eh.ether_dhost[4],eth->eh.ether_dhost[5]); return 0; } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 72ddc0e87c..307a312670 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -56,7 +56,6 @@ #define RX_FLAG 0 #include "if_defs.h" -#define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header)) #define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp)) /*!\brief opaque ethernet data structure */ @@ -114,6 +113,8 @@ typedef struct { /*!\brief number of packets received */ uint64_t rx_count; + struct ether_header eh; + } eth_state_t; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index f38421bed2..04cd66e6e8 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -38,6 +38,8 @@ * \warning */ +#include + // ETH transport preference modes #define ETH_UDP_MODE 0 #define ETH_RAW_MODE 1 @@ -45,6 +47,7 @@ #define ETH_RAW_IF4_MODE 3 // Time domain RRH packet sizes +#define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header)) #define MAX_PACKET_SEQ_NUM(spp,spf) (spf/spp) #define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2) #define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) From 12385fbd64e772e8887478a0f282d053a16c5ca0 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 21 Jun 2016 17:05:32 +0200 Subject: [PATCH 061/206] changes to handle different proc in callers --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 98 ++++++++++++++------------ openair1/PHY/LTE_TRANSPORT/if4_tools.h | 11 +-- 2 files changed, 60 insertions(+), 49 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index d07817c310..342512397a 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -44,8 +44,11 @@ #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/TOOLS/ALAW/alaw_lut.h" +#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" + + // --- Careful to handle buffer memory --- RAW/UDP modes --- PRACH variables and data -void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { +void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -61,14 +64,14 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { if (packet_type == IF4_PDLFFT) { db_fulllength = 12*fp->N_RB_DL; db_halflength = (db_fulllength)>>1; - slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - tx_buffer = malloc(/*SIZE_OF_MAC_BYTES +*/ sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); - IF4_dl_header_t *dl_header = (IF4_dl_header_t *)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/); - data_block = (int16_t*)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/ + sizeof_IF4_dl_header_t); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); + IF4_dl_header_t *dl_header = (IF4_dl_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t); - gen_IF4_dl_header(dl_header, proc); + gen_IF4_dl_header(dl_header, frame, subframe); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { // Do compression of the two parts and generate data blocks @@ -99,14 +102,14 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { } else if (packet_type == IF4_PULFFT) { db_fulllength = 12*fp->N_RB_UL; db_halflength = (db_fulllength)>>1; - slotoffsetF = (proc->subframe_rx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - tx_buffer = malloc(/*SIZE_OF_MAC_BYTES +*/ sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); - IF4_ul_header_t *ul_header = (IF4_ul_header_t *)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/); - data_block = (int16_t*)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/ + sizeof_IF4_ul_header_t); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); + IF4_ul_header_t *ul_header = (IF4_ul_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t); - gen_IF4_ul_header(ul_header, proc); + gen_IF4_ul_header(ul_header, frame, subframe); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { // Do compression of the two parts and generate data blocks - rxdataF @@ -123,7 +126,7 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { // Write the packet(s) to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, - symbol_id, + (int64_t) symbol_id, tx_buffer, db_fulllength, 1, @@ -137,13 +140,13 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { } else if (packet_type == IF4_PRACH) { // FIX: hard coded prach samples length db_fulllength = 839; - slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; - tx_buffer = malloc(/*SIZE_OF_MAC_BYTES +*/ sizeof_IF4_prach_header_t + db_fulllength*sizeof(int16_t)); - IF4_prach_header_t *prach_header = (IF4_prach_header_t *)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/); - data_block = (int16_t*)(tx_buffer /*+ MAC_HEADER_SIZE_BYTES*/ + sizeof_IF4_prach_header_t); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + db_fulllength*sizeof(int16_t)); + IF4_prach_header_t *prach_header = (IF4_prach_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t); - gen_IF4_prach_header(prach_header, proc); + gen_IF4_prach_header(prach_header, frame, subframe); // Do compression and generate data blocks for (element_id=0; element_idifdevice.trx_write_func(&eNB->ifdevice, - symbol_id, + (int64_t) symbol_id, tx_buffer, db_fulllength, 1, @@ -168,29 +171,35 @@ void send_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t packet_type) { return; } -void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, uint32_t *symbol_number) { + +void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint32_t *symbol_number) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; + int16_t *prachF = eNB->prach_vars.prachF; uint16_t element_id; - uint16_t db_halflength; + uint16_t db_fulllength, db_halflength; int slotoffsetF, blockoffsetF; - + *packet_type = 0; + + int64_t *ret_type=(int64_t*)malloc(sizeof(int64_t)); void *rx_buffer=NULL; + void **buff=NULL; int16_t *data_block=NULL; // Read packet(s) from the fronthaul if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, - symbol_number, - rx_buffer, + ret_type, + buff, 0, 0) < 0) { perror("ETHERNET read"); } - - packet_type = (uint16_t*) (rx_buffer+2); + + *packet_type = *ret_type; + rx_buffer = buff[0]; if (*packet_type == IF4_PDLFFT) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_dl_header_t); @@ -198,12 +207,10 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u db_halflength = (12*fp->N_RB_DL)>>1; // Calculate from received packet - slotoffsetF = (proc->subframe_tx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); - - // Do decompression of the two parts and generate data blocks + // Do decompression of the two parts and generate txdataF for (element_id=0; element_id>8) ]<<16; @@ -213,7 +220,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u } // Find and return symbol_number - *symbol_number = 0; + *symbol_number = ((IF4_dl_header_t*)(rx_buffer))->frame_status.sym_num; } else if (*packet_type == IF4_PULFFT) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_ul_header_t); @@ -221,12 +228,10 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u db_halflength = (12*fp->N_RB_UL)>>1; // Calculate from received packet - slotoffsetF = (proc->subframe_rx)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - data_block = (int16_t*)malloc(db_halflength*sizeof(int16_t)); - - // Do decompression of the two parts and generate data blocks + // Do decompression of the two parts and generate rxdataF for (element_id=0; element_id>8) ]<<16; @@ -236,10 +241,12 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u } // Find and return symbol_number - *symbol_number = 0; + *symbol_number = ((IF4_ul_header_t*)(rx_buffer))->frame_status.sym_num; } else if (*packet_type == IF4_PRACH) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_prach_header_t); + + db_fulllength = 839; // hard coded } else { AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type); @@ -249,7 +256,8 @@ void recv_IF4(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint16_t *packet_type, u return; } -void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_rxtx_proc_t *proc) { + +void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, int frame, int subframe) { // Set Type and Sub-Type dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; @@ -260,8 +268,8 @@ void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_rxtx_proc_t *proc) { // Set frame status dl_packet->frame_status.ant_num = 0; dl_packet->frame_status.ant_start = 0; - dl_packet->frame_status.rf_num = proc->frame_tx; - dl_packet->frame_status.sf_num = proc->subframe_tx; + dl_packet->frame_status.rf_num = frame; + dl_packet->frame_status.sf_num = subframe; dl_packet->frame_status.sym_num = 0; dl_packet->frame_status.rsvd = 0; @@ -269,7 +277,8 @@ void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, eNB_rxtx_proc_t *proc) { } -void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_rxtx_proc_t *proc) { + +void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, int frame, int subframe) { // Set Type and Sub-Type ul_packet->type = IF4_PACKET_TYPE; ul_packet->sub_type = IF4_PULFFT; @@ -280,8 +289,8 @@ void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_rxtx_proc_t *proc) { // Set frame status ul_packet->frame_status.ant_num = 0; ul_packet->frame_status.ant_start = 0; - ul_packet->frame_status.rf_num = proc->frame_rx; - ul_packet->frame_status.sf_num = proc->subframe_rx; + ul_packet->frame_status.rf_num = frame; + ul_packet->frame_status.sf_num = subframe; ul_packet->frame_status.sym_num = 0; ul_packet->frame_status.rsvd = 0; @@ -293,7 +302,8 @@ void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, eNB_rxtx_proc_t *proc) { } -void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, eNB_proc_t *proc) { + +void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, int frame, int subframe) { // Set Type and Sub-Type prach_packet->type = IF4_PACKET_TYPE; prach_packet->sub_type = IF4_PRACH; @@ -304,8 +314,8 @@ void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, eNB_proc_t *proc) { // Set LTE Prach configuration prach_packet->prach_conf.rsvd = 0; prach_packet->prach_conf.ant = 0; - prach_packet->prach_conf.rf_num = proc->frame_rx; - prach_packet->prach_conf.sf_num = proc->subframe_rx; + prach_packet->prach_conf.rf_num = frame; + prach_packet->prach_conf.sf_num = subframe; prach_packet->prach_conf.exponent = 0; // Set frame check sequence diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 9d4424ab01..46396d3034 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -39,6 +39,7 @@ */ #include +#include "PHY/defs.h" /// Macro for IF4 packet type #define IF4_PACKET_TYPE 0x080A @@ -175,12 +176,12 @@ struct IF4_prach_header { typedef struct IF4_prach_header IF4_prach_header_t; #define sizeof_IF4_prach_header_t 12 -void gen_IF4_dl_header(IF4_dl_header_t*, eNB_rxtx_proc_t*); +void gen_IF4_dl_header(IF4_dl_header_t*, int, int); -void gen_IF4_ul_header(IF4_ul_header_t*, eNB_rxtx_proc_t*); +void gen_IF4_ul_header(IF4_ul_header_t*, int, int); -void gen_IF4_prach_header(IF4_prach_header_t*, eNB_proc_t*); +void gen_IF4_prach_header(IF4_prach_header_t*, int, int); -void send_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t); +void send_IF4(PHY_VARS_eNB*, int, int, uint16_t); -void recv_IF4(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint16_t*, uint32_t*); +void recv_IF4(PHY_VARS_eNB*, int, int, uint16_t*, uint32_t*); From d43b8a3041243e898480e3d34190ca1f5a033ddd Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 21 Jun 2016 17:08:27 +0200 Subject: [PATCH 062/206] handling low level eth function for read --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 88 +++++++++++-------- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 11 +-- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 4 +- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 7 +- 4 files changed, 66 insertions(+), 44 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index df2018ad0a..5041d188a3 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -52,6 +52,7 @@ #include "common_lib.h" #include "ethernet_lib.h" #include "if_defs.h" +#include "openair1/PHY/LTE_TRANSPORT/if4_tools.h" #define DEBUG 0 @@ -214,7 +215,7 @@ int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, } else if (flags == IF4_PULFFT) { packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks); } else { - packet_size = RAW_IF4_PRACH_SIZE_BYTES(nblocks); + packet_size = RAW_IF4_PRACH_SIZE_BYTES; } eth->tx_nsamps = nblocks; @@ -302,49 +303,66 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + int nblocks = nsamps; int bytes_received=0; - int i=0; eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - int rcvfrom_flag =0; - eth->rx_nsamps=nsamps; - - /* buff[i] points to the position in rx buffer where the payload to be received will be placed - buff2 points to the position in rx buffer where the packet header will be placed */ - void *buff2 = (void*)(buff[i]-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES); - - /* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/ - struct ether_header temp = *(struct ether_header *)buff2; - int32_t temp0 = *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES); - openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); - - bytes_received=0; - - while(bytes_received < RAW_PACKET_SIZE_BYTES(nsamps)) { - bytes_received +=recv(eth->sockfd[Mod_id], - buff2, - RAW_PACKET_SIZE_BYTES(nsamps), - rcvfrom_flag); - + ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t; + + void *test_buffer = (void*)malloc(packet_size); + void *rx_buffer=NULL; + IF4_dl_header_t *test_header = (IF4_dl_header_t*)(test_buffer + MAC_HEADER_SIZE_BYTES); + + bytes_received = recv(eth->sockfd[Mod_id], + test_buffer, + packet_size, + 0); if (bytes_received ==-1) { eth->num_rx_errors++; perror("ETHERNET READ: "); exit(-1); - } else { - /* store the timestamp value from packet's header */ - *timestamp = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); - eth->rx_actual_nsamps=bytes_received>>2; - eth->rx_count++; - } - } - - /* tx buffer values restored */ - *(struct ether_header *)buff2 = temp; - *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0; - *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1; + } + + *timestamp = test_header->sub_type; + + if (test_header->sub_type == IF4_PDLFFT) { + buff[0] = (void*)malloc(RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) - MAC_HEADER_SIZE_BYTES); + packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) - packet_size; + + } else if (test_header->sub_type == IF4_PULFFT) { + buff[0] = (void*)malloc(RAW_IF4_PULFFT_SIZE_BYTES(nblocks) - MAC_HEADER_SIZE_BYTES); + packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks) - packet_size; + + } else { + buff[0] = (void*)malloc(RAW_IF4_PRACH_SIZE_BYTES - MAC_HEADER_SIZE_BYTES); + packet_size = RAW_IF4_PRACH_SIZE_BYTES - packet_size; + } - return (bytes_received-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2; + memcpy(buff[0], test_header, sizeof_IF4_dl_header_t); + rx_buffer = (void*)(buff[0]+sizeof_IF4_dl_header_t); + + bytes_received = 0; + + while(bytes_received < packet_size) { + bytes_received += recv(eth->sockfd[Mod_id], + rx_buffer, + packet_size-bytes_received, + 0); + if (bytes_received ==-1) { + eth->num_rx_errors++; + perror("ETHERNET READ: "); + exit(-1); + } else { + eth->rx_actual_nsamps = bytes_received>>1; + eth->rx_count++; + } + } + + eth->rx_nsamps = nsamps; + + free(test_buffer); + return (bytes_received-MAC_HEADER_SIZE_BYTES)>>1; } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index ee9ba50f66..6e5aa11140 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -320,7 +320,8 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth } else if (eth_params->transp_preference == 2) { eth->flags = ETH_UDP_IF4_MODE; } else { - AssertFatal(0==4, "transport_init: Unknown transport preference %d", eth_params->transp_preference); + printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference); + eth->flags = ETH_RAW_MODE; } printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); @@ -346,16 +347,16 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth device->trx_write_func = trx_eth_write_raw_IF4; device->trx_read_func = trx_eth_read_raw_IF4; } else { - device->trx_write_func = trx_eth_write_udp_IF4; - device->trx_read_func = trx_eth_read_udp_IF4; + //device->trx_write_func = trx_eth_write_udp_IF4; + //device->trx_read_func = trx_eth_read_udp_IF4; } eth->if_name[device->Mod_id] = eth_params->local_if_name; device->priv = eth; /* device specific */ - openair0_cfg[0].txlaunch_wait = 0;//manage when TX processing is triggered - openair0_cfg[0].txlaunch_wait_slotcount = 0; //manage when TX processing is triggered + //openair0_cfg[0].txlaunch_wait = 0;//manage when TX processing is triggered + //openair0_cfg[0].txlaunch_wait_slotcount = 0; //manage when TX processing is triggered openair0_cfg[0].iq_rxrescale = 15;//rescale iqs openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 307a312670..66cb13ef12 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -222,8 +222,8 @@ int eth_set_dev_conf_udp(openair0_device *device); int eth_socket_init_raw(openair0_device *device); int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); -//int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); -//int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); int eth_get_dev_conf_raw(openair0_device *device); int eth_set_dev_conf_raw(openair0_device *device); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 04cd66e6e8..5b95e5eeca 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -39,6 +39,7 @@ */ #include +#include // ETH transport preference modes #define ETH_UDP_MODE 0 @@ -54,7 +55,9 @@ #define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) // Packet sizes for IF4 interface format -#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (2*scaled_nblocks) +#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(int16_t)*scaled_nblocks) +#define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839) // FIX hard coded prach size + #define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) #define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) -#define RAW_IF4_PRACH_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + PRACH_BLOCK_SIZE_BYTES) From 21b492f95cd305f83b6e7d17d35caac46b1460b5 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 21 Jun 2016 18:08:10 +0200 Subject: [PATCH 063/206] minimal fixes from rcc test --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 6 +++--- openair1/PHY/LTE_TRANSPORT/prach.c | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 4 ++-- targets/RT/USER/lte-enb.c | 4 ++-- targets/RT/USER/lte-softmodem.c | 6 +++++- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 342512397a..e716695c06 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -89,7 +89,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, symbol_id, - tx_buffer, + &tx_buffer, db_fulllength, 1, IF4_PDLFFT)) < 0) { @@ -127,7 +127,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) // Write the packet(s) to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, (int64_t) symbol_id, - tx_buffer, + &tx_buffer, db_fulllength, 1, IF4_PULFFT)) < 0) { @@ -157,7 +157,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, (int64_t) symbol_id, - tx_buffer, + &tx_buffer, db_fulllength, 1, IF4_PRACH)) < 0) { diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 85330b5a18..23ea2cae53 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1271,7 +1271,7 @@ void rx_prach(PHY_VARS_eNB *eNB, if (eNB->node_function == NGFI_RRU_IF4) { /// **** send_IF4 of prachF to RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - // send_IF4(); + //send_IF4(eNB, frame, subframe, IF4_PRACH); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); return; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 92392070af..3b7052db58 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2572,7 +2572,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - // send_IF4(); + //send_IF4(eNB, frame, subframe, IF4_PULFFT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); } @@ -2624,7 +2624,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl do { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - //recv_IF4(eNB, proc, &packet_type, &symbol_number); + //recv_IF4(eNB, frame, subframe, &packet_type, &symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); if (packet_type == IF4_PULFFT) { diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 8126ef46e0..4031cd5842 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -486,7 +486,7 @@ static void* eNB_thread_rxtx( void* param ) { /// **** recv_IF4 of txdataF from RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - //recv_IF4(eNB, proc, packet_type, symbol_number); + //recv_IF4(eNB, frame, subframe, packet_type, symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); } @@ -536,7 +536,7 @@ static void* eNB_thread_rxtx( void* param ) { /// **** send_IF4 of txdataF to RRU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - //send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc, 0); + send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index dd55dacb1f..dcfa88afbf 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1911,8 +1911,12 @@ int main( int argc, char **argv ) pthread_cond_destroy(&sync_cond); pthread_mutex_destroy(&sync_mutex); - // *** Handle per CC_id openair0 + // *** Handle per CC_id openair0 openair0.trx_end_func(&openair0); + for(CC_id=0; CC_idrfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + } if (ouput_vcd) VCD_SIGNAL_DUMPER_CLOSE(); From 4302afee51c01046ed86f63da631bb58f243b01a Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 22 Jun 2016 08:38:54 +0200 Subject: [PATCH 064/206] small changes --- openair1/SCHED/phy_procedures_lte_eNb.c | 28 ++++++------- .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 40 +++++++++++++++---- .../CONF/enb.dual.band7_band20.conf | 8 ++-- targets/RT/USER/lte-enb.c | 4 +- 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 92392070af..71b31fcad6 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2534,11 +2534,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl proc->first_rx = 0; } - //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + // printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, frame ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, subframe ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); if (rxs != fp->samples_per_tti) exit_fun( "problem receiving samples" ); @@ -2547,27 +2547,27 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl // now do common RX processing for first slot in subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); - remove_7_5_kHz(eNB,subframe<<1); - remove_7_5_kHz(eNB,1+(subframe<<1)); + remove_7_5_kHz(eNB,proc->subframe_rx<<1); + remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1)); for (l=0; lsymbols_per_tti/2; l++) { slot_fep_ul(fp, &eNB->common_vars, l, - subframe<<1, + proc->subframe_rx<<1, 0, 0 ); slot_fep_ul(fp, &eNB->common_vars, l, - 1+(subframe<<1), + 1+(proc->subframe_rx<<1), 0, 0 ); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); - if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, frame, subframe)<=0) { + if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)<=0) { /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// @@ -2579,7 +2579,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { + if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) { // wake up thread for PRACH RX if (pthread_mutex_lock(&proc->mutex_prach) != 0) { LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); @@ -2589,8 +2589,8 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl int cnt_prach = ++proc->instance_cnt_prach; // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; + proc->frame_prach = proc->frame_rx; + proc->subframe_prach = proc->subframe_rx; pthread_mutex_unlock( &proc->mutex_prach ); @@ -2602,7 +2602,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl return; } } else { - LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame); + LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach); exit_fun( "PRACH thread busy" ); return; } @@ -2642,8 +2642,8 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl int cnt_prach = ++proc->instance_cnt_prach; // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; + proc->frame_prach = proc->frame_rx; + proc->subframe_prach = proc->subframe_rx; pthread_mutex_unlock( &proc->mutex_prach ); diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index a8b5f3e21b..b608c8acd2 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -283,7 +283,7 @@ static void *watchdog_thread(void *arg) { volatile unsigned int *daq_mbox = openair0_daq_cnt(); unsigned int mbox,diff; - + int first_acquisition; /* Set affinity mask to include CPUs 1 to MAX_CPUS */ /* CPU 0 is reserved for UHD threads */ @@ -351,8 +351,6 @@ static void *watchdog_thread(void *arg) { cpu_affinity ); - - mlockall(MCL_CURRENT | MCL_FUTURE); exm->watchdog_exit = 0; @@ -387,6 +385,8 @@ static void *watchdog_thread(void *arg) { printf("Unknown sampling rate %f, exiting \n",cfg->sample_rate); exm->watchdog_exit=1; } + + first_acquisition=1; // main loop to keep up with DMA transfers from exmimo2 while ((!oai_exit) && (!exm->watchdog_exit)) { @@ -394,6 +394,7 @@ static void *watchdog_thread(void *arg) { // grab time from MBOX mbox = daq_mbox[0]; + if (mboxlast_mbox) { // wrap-around diff = 150 + mbox - exm->last_mbox; } @@ -405,13 +406,25 @@ static void *watchdog_thread(void *arg) { pthread_mutex_lock(&exm->watchdog_mutex); exm->ts += (diff*exm->samples_per_frame/150) ; - if (diff > 10) // we're too late so exit + if (first_acquisition==1) //set last read to a closest subframe boundary + exm->last_ts_rx = (exm->ts/(exm->samples_per_frame/10))*(exm->samples_per_frame/10); + + if ((diff > 16)&&(first_acquisition==0)) {// we're too late so exit exm->watchdog_exit = 1; + printf("exiting, too late to keep up\n"); + } + first_acquisition=0; + + if (diff == 0) { + exm->watchdog_exit = 1; + printf("exiting, HW stopped\n"); + } if (exm->ts - exm->last_ts_rx > exm->samples_per_frame) { exm->watchdog_exit = 1; printf("RX Overflow, exiting\n"); } + // printf("ts %lu, last_ts_rx %lu, mbox %d, diff %d\n",exm->ts, exm->last_ts_rx,mbox,diff); pthread_mutex_unlock(&exm->watchdog_mutex); } @@ -444,6 +457,7 @@ int trx_exmimo_start(openair0_device *device) { exmimo_state_t *exm=device->priv; + printf("Starting ...\n"); openair0_start_rt_acquisition(0); exm->daq_state = running; @@ -460,7 +474,7 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi exmimo_state_t *exm=device->priv; openair0_config_t *cfg=&device->openair0_cfg[0]; openair0_timestamp ts,diff; - int i; + // int i; pthread_mutex_lock(&exm->watchdog_mutex); ts = exm->ts; @@ -469,25 +483,35 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi diff = exm->last_ts_rx+nsamps - ts; // difference in samples between current timestamp and last RX received sample // go to sleep until we should have enough samples (1024 for a bit more) +#ifdef DEBUG_EXMIMO + printf("Reading %d samples, ts %lu, last_ts_rx %lu (%lu) => sleeping %u us\n",nsamps,ts,exm->last_ts_rx,exm->last_ts_rx+nsamps, + (unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate)); +#endif usleep((unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate)); +#ifdef DEBUG_EXMIMO + printf("back\n"); +#endif // get new timestamp, in case we have to sleep again pthread_mutex_lock(&exm->watchdog_mutex); ts = exm->ts; pthread_mutex_unlock(&exm->watchdog_mutex); } + /* if (cfg->mmapped_dma == 0) { // if buff is not the dma buffer, do a memcpy, otherwise do nothing for (i=0;ilast_ts_rx % exm->samples_per_frame), nsamps*sizeof(int)); + } - } + }*/ *ptimestamp=exm->last_ts_rx; exm->last_ts_rx += nsamps; - return(0); + return(nsamps); } void trx_exmimo_end(openair0_device *device) { @@ -592,6 +616,8 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->openair0_cfg = openair0_cfg; device->priv = (void *)exm; + openair0_config(openair0_cfg,0); + create_watchdog(device); return(0); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.dual.band7_band20.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.dual.band7_band20.conf index 781e2a82e9..02f9077984 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.dual.band7_band20.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.dual.band7_band20.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "92"; + mobile_network_code = "93"; ////////// Physical parameters: @@ -211,7 +211,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.13.11"; + mme_ip_address = ( { ipv4 = "192.168.12.70"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -221,10 +221,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.13.82/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.13.82/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 8126ef46e0..abdbe0fb35 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -127,7 +127,7 @@ extern volatile int start_UE; #endif extern volatile int oai_exit; -extern openair0_config_t *openair0_cfg; +extern openair0_config_t openair0_cfg[MAX_CARDS]; extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; @@ -920,7 +920,7 @@ static void* eNB_thread_prach( void* param ) { exit_fun("Error getting thread priority"); } - LOG_I(HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + LOG_I(HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, IC %d, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(),proc->instance_cnt_prach, (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : From f5eaa7d7edadb179594ebc687af2e33ad8c103ac Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 22 Jun 2016 18:21:28 +0200 Subject: [PATCH 065/206] minimal fixes from base rru run --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 33 +++++++++---------- openair1/SCHED/phy_procedures_lte_eNb.c | 3 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 7 ++-- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 4 +-- targets/RT/USER/lte-enb.c | 10 +++--- 5 files changed, 27 insertions(+), 30 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index e716695c06..bbfea66b31 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -56,7 +56,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) uint16_t symbol_id, element_id; uint16_t db_fulllength, db_halflength; - int slotoffsetF, blockoffsetF; + int slotoffsetF=0, blockoffsetF=0; void *tx_buffer=NULL; int16_t *data_block=NULL; @@ -105,7 +105,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + db_fulllength*sizeof(int16_t)); IF4_ul_header_t *ul_header = (IF4_ul_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t); @@ -126,7 +126,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) // Write the packet(s) to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, - (int64_t) symbol_id, + symbol_id, &tx_buffer, db_fulllength, 1, @@ -156,7 +156,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, - (int64_t) symbol_id, + symbol_id, &tx_buffer, db_fulllength, 1, @@ -172,7 +172,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) } -void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint32_t *symbol_number) { +void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint32_t *symbol_number, uint16_t expected_packet) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -182,30 +182,31 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint16_t db_fulllength, db_halflength; int slotoffsetF, blockoffsetF; - *packet_type = 0; - + if (expected_packet == IF4_PDLFFT) { + db_fulllength = = (12*fp->N_RB_DL); + } else { + db_fulllength = = (12*fp->N_RB_UL); + } + db_halflength = db_fulllength>>1; + int64_t *ret_type=(int64_t*)malloc(sizeof(int64_t)); void *rx_buffer=NULL; - void **buff=NULL; int16_t *data_block=NULL; // Read packet(s) from the fronthaul if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, ret_type, - buff, - 0, + &rx_buffer, + db_fulllength, 0) < 0) { perror("ETHERNET read"); } *packet_type = *ret_type; - rx_buffer = buff[0]; if (*packet_type == IF4_PDLFFT) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_dl_header_t); - - db_halflength = (12*fp->N_RB_DL)>>1; - + // Calculate from received packet slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; @@ -224,9 +225,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } else if (*packet_type == IF4_PULFFT) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_ul_header_t); - - db_halflength = (12*fp->N_RB_UL)>>1; - + // Calculate from received packet slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 16386dfed6..cb033eb904 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2604,9 +2604,8 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, frame, subframe)<=0) { /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - //send_IF4(eNB, frame, subframe, IF4_PULFFT); + send_IF4(eNB, frame, subframe, IF4_PULFFT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 5041d188a3..0cb4fdfabb 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -303,14 +303,15 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + // Read nblocks info from packet itself int nblocks = nsamps; int bytes_received=0; eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t; - + ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t; void *test_buffer = (void*)malloc(packet_size); + void *rx_buffer=NULL; IF4_dl_header_t *test_header = (IF4_dl_header_t*)(test_buffer + MAC_HEADER_SIZE_BYTES); @@ -339,7 +340,7 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, packet_size = RAW_IF4_PRACH_SIZE_BYTES - packet_size; } - memcpy(buff[0], test_header, sizeof_IF4_dl_header_t); + memcpy(buff[0], test_header, sizeof_IF4_dl_header_t); rx_buffer = (void*)(buff[0]+sizeof_IF4_dl_header_t); bytes_received = 0; diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 3c1e1796e6..cfe857f9a2 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -654,8 +654,8 @@ extern "C" { } /* device specific */ - openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered - openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered + //openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered + //openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered openair0_cfg[0].iq_txshift = 4;//shift openair0_cfg[0].iq_rxrescale = 15;//rescale iqs diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index fb224615fe..08390d1f6b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -127,7 +127,7 @@ extern volatile int start_UE; #endif extern volatile int oai_exit; -extern openair0_config_t *openair0_cfg; +extern openair0_config_t openair0_cfg[MAX_CARDS]; extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; @@ -483,10 +483,9 @@ static void* eNB_thread_rxtx( void* param ) { } } else { - /// **** recv_IF4 of txdataF from RCC **** /// - + /// **** recv_IF4 of txdataF from RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - //recv_IF4(eNB, frame, subframe, packet_type, symbol_number); + //recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, packet_type, symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); } @@ -533,8 +532,7 @@ static void* eNB_thread_rxtx( void* param ) { } else { - /// **** send_IF4 of txdataF to RRU **** /// - + /// **** send_IF4 of txdataF to RRU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); From 89052325e1fa4e7c6b44d776422b10d10b9732db Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 23 Jun 2016 11:33:30 +0200 Subject: [PATCH 066/206] handling if send for rxsigF --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 28 ++++++++++--------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 4 +-- openair1/PHY/LTE_TRANSPORT/prach.c | 18 ++++++++---- openair1/SCHED/phy_procedures_lte_eNb.c | 2 +- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 2 +- targets/RT/USER/lte-enb.c | 2 +- 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index bbfea66b31..38641941f8 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -48,13 +48,13 @@ // --- Careful to handle buffer memory --- RAW/UDP modes --- PRACH variables and data -void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) { +void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int k) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; - int16_t *prachF = eNB->prach_vars.prachF; + int16_t **rxsigF = eNB->prach_vars.rxsigF; - uint16_t symbol_id, element_id; + uint16_t symbol_id=0, element_id=0; uint16_t db_fulllength, db_halflength; int slotoffsetF=0, blockoffsetF=0; @@ -139,8 +139,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) } } else if (packet_type == IF4_PRACH) { // FIX: hard coded prach samples length - db_fulllength = 839; - slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + db_fulllength = 839*2; tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + db_fulllength*sizeof(int16_t)); IF4_prach_header_t *prach_header = (IF4_prach_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); @@ -148,11 +147,14 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type) gen_IF4_prach_header(prach_header, frame, subframe); - // Do compression and generate data blocks - for (element_id=0; element_id>16) + 32768 ]<<8; - } + // Generate uncompressed data blocks + memcpy(data_block, (rxsigF[0]+k), db_fulllength*sizeof(int16_t)); + + //for (element_id=0; element_idifdevice.trx_write_func(&eNB->ifdevice, @@ -176,16 +178,16 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; - int16_t *prachF = eNB->prach_vars.prachF; + int16_t **rxsigF = eNB->prach_vars.rxsigF; uint16_t element_id; uint16_t db_fulllength, db_halflength; int slotoffsetF, blockoffsetF; if (expected_packet == IF4_PDLFFT) { - db_fulllength = = (12*fp->N_RB_DL); + db_fulllength = (12*fp->N_RB_DL); } else { - db_fulllength = = (12*fp->N_RB_UL); + db_fulllength = (12*fp->N_RB_UL); } db_halflength = db_fulllength>>1; diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 46396d3034..4828daeddb 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -182,6 +182,6 @@ void gen_IF4_ul_header(IF4_ul_header_t*, int, int); void gen_IF4_prach_header(IF4_prach_header_t*, int, int); -void send_IF4(PHY_VARS_eNB*, int, int, uint16_t); +void send_IF4(PHY_VARS_eNB*, int, int, uint16_t, int); -void recv_IF4(PHY_VARS_eNB*, int, int, uint16_t*, uint32_t*); +void recv_IF4(PHY_VARS_eNB*, int, int, uint16_t*, uint32_t*, uint16_t); diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 23ea2cae53..4634be7321 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -41,6 +41,7 @@ #include "PHY/defs.h" #include "PHY/extern.h" //#include "prach.h" +#include "PHY/LTE_TRANSPORT/if4_tools.h" #include "SCHED/defs.h" #include "SCHED/extern.h" #include "UTIL/LOG/vcd_signal_dumper.h" @@ -1269,18 +1270,25 @@ void rx_prach(PHY_VARS_eNB *eNB, } if (eNB->node_function == NGFI_RRU_IF4) { - /// **** send_IF4 of prachF to RCC **** /// + k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; + + if (k<0) { + k+=(eNB->frame_parms.ofdm_symbol_size); + } + + k*=12; + k+=13; + k*=2; + + /// **** send_IF4 of rxsigF to RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - //send_IF4(eNB, frame, subframe, IF4_PRACH); + send_IF4(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4_PRACH, k); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); return; } // in case of RCC and prach received rx_thread wakes up prach - //else if (eNB->node_function == NGFI_RCC_IF4) { - // wait for prachF from RRU and continue with PRACH processing - //} // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4 diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index cb033eb904..654619fee6 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2605,7 +2605,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - send_IF4(eNB, frame, subframe, IF4_PULFFT); + send_IF4(eNB, frame, subframe, IF4_PULFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 5b95e5eeca..12878badd1 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -56,7 +56,7 @@ // Packet sizes for IF4 interface format #define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(int16_t)*scaled_nblocks) -#define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839) // FIX hard coded prach size +#define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839*2) // FIX hard coded prach size (uncompressed) #define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) #define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 08390d1f6b..b30ed5b390 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -534,7 +534,7 @@ static void* eNB_thread_rxtx( void* param ) { /// **** send_IF4 of txdataF to RRU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT); + send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); } From 8390977e7e6462a9612d17da02f12dbabbcd3397 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 23 Jun 2016 18:36:34 +0200 Subject: [PATCH 067/206] getting rid of bit-fields --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 71 +++++++++++++------------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 37 ++++++-------- 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 38641941f8..a712ae0674 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -84,7 +84,8 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, } // Update information in generated packet - dl_header->frame_status.sym_num = symbol_id; + dl_header->frame_status &= ~(0x000f<<26); + dl_header->frame_status |= (symbol_id&0x000f)<<26; // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, @@ -122,7 +123,8 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, } // Update information in generated packet - ul_header->frame_status.sym_num = symbol_id; + ul_header->frame_status &= ~(0x000f<<26); + ul_header->frame_status |= (symbol_id&0x000f)<<26; // Write the packet(s) to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, @@ -174,7 +176,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, } -void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint32_t *symbol_number, uint16_t expected_packet) { +void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint32_t *symbol_number) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -182,9 +184,9 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint16_t element_id; uint16_t db_fulllength, db_halflength; - int slotoffsetF, blockoffsetF; + int slotoffsetF=0, blockoffsetF=0; - if (expected_packet == IF4_PDLFFT) { + if (eNB->node_function == NGFI_RRU_IF4) { db_fulllength = (12*fp->N_RB_DL); } else { db_fulllength = (12*fp->N_RB_UL); @@ -194,6 +196,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, int64_t *ret_type=(int64_t*)malloc(sizeof(int64_t)); void *rx_buffer=NULL; int16_t *data_block=NULL; + // Read packet(s) from the fronthaul if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, @@ -204,7 +207,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, perror("ETHERNET read"); } - *packet_type = *ret_type; + *packet_type = (uint16_t) *ret_type; if (*packet_type == IF4_PDLFFT) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_dl_header_t); @@ -223,7 +226,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } // Find and return symbol_number - *symbol_number = ((IF4_dl_header_t*)(rx_buffer))->frame_status.sym_num; + *symbol_number = ((((IF4_dl_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; } else if (*packet_type == IF4_PULFFT) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_ul_header_t); @@ -242,12 +245,16 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } // Find and return symbol_number - *symbol_number = ((IF4_ul_header_t*)(rx_buffer))->frame_status.sym_num; + *symbol_number = ((((IF4_ul_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; } else if (*packet_type == IF4_PRACH) { data_block = (int16_t*) (rx_buffer+sizeof_IF4_prach_header_t); - db_fulllength = 839; // hard coded + // FIX: hard coded prach samples length + db_fulllength = 839*2; + + // Generate uncompressed data blocks + memcpy((rxsigF[0]+slotoffsetF), data_block, db_fulllength*sizeof(int16_t)); } else { AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type); @@ -263,18 +270,13 @@ void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, int frame, int subframe) { dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; - // Leave reserved as it is + // Reset frame status dl_packet->rsvd = 0; // Set frame status - dl_packet->frame_status.ant_num = 0; - dl_packet->frame_status.ant_start = 0; - dl_packet->frame_status.rf_num = frame; - dl_packet->frame_status.sf_num = subframe; - dl_packet->frame_status.sym_num = 0; - dl_packet->frame_status.rsvd = 0; - - // Set frame check sequence + dl_packet->frame_status = 0; + dl_packet->frame_status |= (frame&0xffff)<<6; + dl_packet->frame_status |= (subframe&0x000f)<<22; } @@ -288,19 +290,20 @@ void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, int frame, int subframe) { ul_packet->rsvd = 0; // Set frame status - ul_packet->frame_status.ant_num = 0; - ul_packet->frame_status.ant_start = 0; - ul_packet->frame_status.rf_num = frame; - ul_packet->frame_status.sf_num = subframe; - ul_packet->frame_status.sym_num = 0; - ul_packet->frame_status.rsvd = 0; + ul_packet->frame_status = 0; + ul_packet->frame_status |= (frame&0xffff)<<6; + ul_packet->frame_status |= (subframe&0x000f)<<22; // Set antenna specific gain *** set other antenna gain *** - ul_packet->gain0.exponent = 0; - ul_packet->gain0.rsvd = 0; - - // Set frame check sequence - + ul_packet->gain0 = 0; + ul_packet->gain1 = 0; + ul_packet->gain2 = 0; + ul_packet->gain3 = 0; + ul_packet->gain4 = 0; + ul_packet->gain5 = 0; + ul_packet->gain6 = 0; + ul_packet->gain7 = 0; + } @@ -313,12 +316,8 @@ void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, int frame, int subfr prach_packet->rsvd = 0; // Set LTE Prach configuration - prach_packet->prach_conf.rsvd = 0; - prach_packet->prach_conf.ant = 0; - prach_packet->prach_conf.rf_num = frame; - prach_packet->prach_conf.sf_num = subframe; - prach_packet->prach_conf.exponent = 0; + prach_packet->prach_conf = 0; + prach_packet->prach_conf |= (frame&0xffff)<<6; + prach_packet->prach_conf |= (subframe&0x000f)<<22; - // Set frame check sequence - } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 4828daeddb..5d7b5e0f79 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -47,6 +47,10 @@ #define IF4_PDLFFT 0x0020 #define IF4_PRACH 0x0021 +/* + +Bit-field reference + /// IF4 Frame Status (32 bits) struct IF4_frame_status { /// Antenna Numbers @@ -63,9 +67,6 @@ struct IF4_frame_status { uint32_t rsvd:2; }; -typedef struct IF4_frame_status IF4_frame_status_t; -#define sizeof_IF4_frame_status_t 4 - /// IF4 Antenna Gain (16 bits) struct IF4_gain { /// Reserved @@ -74,9 +75,6 @@ struct IF4_gain { uint16_t exponent:6; }; -typedef struct IF4_gain IF4_gain_t; -#define sizeof_IF_gain_t 2 - /// IF4 LTE PRACH Configuration (32 bits) struct IF4_lte_prach_conf { /// Reserved @@ -91,8 +89,7 @@ struct IF4_lte_prach_conf { uint32_t exponent:6; }; -typedef struct IF4_lte_prach_conf IF4_lte_prach_conf_t; -#define sizeof_IF4_lte_prach_conf_t 4 +*/ struct IF4_dl_header { /// Destination Address @@ -106,7 +103,7 @@ struct IF4_dl_header { /// Reserved uint32_t rsvd; /// Frame Status - IF4_frame_status_t frame_status; + uint32_t frame_status; /// Data Blocks /// Frame Check Sequence @@ -128,23 +125,23 @@ struct IF4_ul_header { /// Reserved uint32_t rsvd; /// Frame Status - IF4_frame_status_t frame_status; + uint32_t frame_status; /// Gain 0 - IF4_gain_t gain0; + uint16_t gain0; /// Gain 1 - IF4_gain_t gain1; + uint16_t gain1; /// Gain 2 - IF4_gain_t gain2; + uint16_t gain2; /// Gain 3 - IF4_gain_t gain3; + uint16_t gain3; /// Gain 4 - IF4_gain_t gain4; + uint16_t gain4; /// Gain 5 - IF4_gain_t gain5; + uint16_t gain5; /// Gain 6 - IF4_gain_t gain6; + uint16_t gain6; /// Gain 7 - IF4_gain_t gain7; + uint16_t gain7; /// Data Blocks /// Frame Check Sequence @@ -166,7 +163,7 @@ struct IF4_prach_header { /// Reserved uint32_t rsvd; /// LTE Prach Configuration - IF4_lte_prach_conf_t prach_conf; + uint32_t prach_conf; /// Prach Data Block (one antenna) /// Frame Check Sequence @@ -184,4 +181,4 @@ void gen_IF4_prach_header(IF4_prach_header_t*, int, int); void send_IF4(PHY_VARS_eNB*, int, int, uint16_t, int); -void recv_IF4(PHY_VARS_eNB*, int, int, uint16_t*, uint32_t*, uint16_t); +void recv_IF4(PHY_VARS_eNB*, int, int, uint16_t*, uint32_t*); From 08d89933e1677e890d4ed6c68a5c18fd30071934 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 23 Jun 2016 19:08:01 +0200 Subject: [PATCH 068/206] expressmimo TX ok. --- openair1/SCHED/phy_procedures_lte_eNb.c | 10 +- targets/ARCH/COMMON/common_lib.h | 4 + .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 87 +++++++-- targets/RT/USER/lte-enb.c | 166 +++++++++--------- targets/RT/USER/lte-softmodem.c | 33 +++- 5 files changed, 193 insertions(+), 107 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index c4a57836d0..9b1ab9d2ce 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2562,8 +2562,14 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; if (proc->first_rx == 0) { - AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)",proc->subframe_rx,subframe); - AssertFatal(proc->frame_rx == frame, "Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)",proc->frame_rx,frame); + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + exit_fun("Exiting"); + } + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } } else { proc->first_rx = 0; } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index f8ec3f8e58..6e112f5e43 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -158,6 +158,10 @@ typedef struct { int rx_num_channels; //! number of TX channels (=TX antennas) int tx_num_channels; + //! \brief RX base addresses for mmapped_dma + int32_t* rxbase[4]; + //! \brief TX base addresses for mmapped_dma + int32_t* txbase[4]; //! \brief Center frequency in Hz for RX. //! index: [0..rx_num_channels[ double rx_freq[4]; diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index b608c8acd2..89b43a22cf 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -64,7 +64,10 @@ #include + #define max(a,b) ((a)>(b) ? (a) : (b)) + + exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS]; // contains userspace pointers for each card char *bigshm_top[MAX_CARDS] = INIT_ZEROS; @@ -90,6 +93,7 @@ extern volatile int oai_exit; void kill_watchdog(openair0_device *); void create_watchdog(openair0_device *); +void rt_sleep(struct timespec *,long ); unsigned int log2_int( unsigned int x ) { @@ -272,6 +276,20 @@ int openair0_stop_without_reset(int card) #define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX) #define RF_MODE_BASE (LNA1ON + RFBBNORM) +void rt_sleep(struct timespec *ts,long tv_nsec) { + + clock_gettime(CLOCK_MONOTONIC, ts); + + ts->tv_nsec += tv_nsec; + + if (ts->tv_nsec>=1000000000L) { + ts->tv_nsec -= 1000000000L; + ts->tv_sec++; + } + + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts, NULL); + +} static void *watchdog_thread(void *arg) { int policy, s, j; @@ -284,7 +302,12 @@ static void *watchdog_thread(void *arg) { volatile unsigned int *daq_mbox = openair0_daq_cnt(); unsigned int mbox,diff; int first_acquisition; - + struct timespec sleep_time,wait; + + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ /* CPU 0 is reserved for UHD threads */ /* CPU 1 is reserved for all TX threads */ @@ -388,6 +411,8 @@ static void *watchdog_thread(void *arg) { first_acquisition=1; // main loop to keep up with DMA transfers from exmimo2 + + int cnt_diff0=0; while ((!oai_exit) && (!exm->watchdog_exit)) { if (exm->daq_state == running) { @@ -403,7 +428,7 @@ static void *watchdog_thread(void *arg) { } exm->last_mbox = mbox; - pthread_mutex_lock(&exm->watchdog_mutex); + pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); exm->ts += (diff*exm->samples_per_frame/150) ; if (first_acquisition==1) //set last read to a closest subframe boundary @@ -416,9 +441,14 @@ static void *watchdog_thread(void *arg) { first_acquisition=0; if (diff == 0) { - exm->watchdog_exit = 1; - printf("exiting, HW stopped\n"); + cnt_diff0++; + if (cnt_diff0 == 10) { + exm->watchdog_exit = 1; + printf("exiting, HW stopped\n"); + } } + else + cnt_diff0=0; if (exm->ts - exm->last_ts_rx > exm->samples_per_frame) { exm->watchdog_exit = 1; @@ -427,12 +457,11 @@ static void *watchdog_thread(void *arg) { // printf("ts %lu, last_ts_rx %lu, mbox %d, diff %d\n",exm->ts, exm->last_ts_rx,mbox,diff); pthread_mutex_unlock(&exm->watchdog_mutex); } - - - usleep(500); // sleep for 500us + rt_sleep(&sleep_time,250000L); } oai_exit=1; + printf("Exiting watchdog\n"); return NULL; } @@ -473,13 +502,23 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi exmimo_state_t *exm=device->priv; openair0_config_t *cfg=&device->openair0_cfg[0]; - openair0_timestamp ts,diff; + openair0_timestamp old_ts=0,ts,diff; + struct timespec sleep_time; + unsigned long tv_nsec; // int i; + struct timespec wait; - pthread_mutex_lock(&exm->watchdog_mutex); + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (exm->watchdog_exit == 1) + return(0); + + pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); ts = exm->ts; pthread_mutex_unlock(&exm->watchdog_mutex); - while (ts < exm->last_ts_rx + nsamps) { + while ((ts < exm->last_ts_rx + nsamps) && + (exm->watchdog_exit==0)) { diff = exm->last_ts_rx+nsamps - ts; // difference in samples between current timestamp and last RX received sample // go to sleep until we should have enough samples (1024 for a bit more) @@ -487,14 +526,21 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi printf("Reading %d samples, ts %lu, last_ts_rx %lu (%lu) => sleeping %u us\n",nsamps,ts,exm->last_ts_rx,exm->last_ts_rx+nsamps, (unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate)); #endif - usleep((unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate)); + tv_nsec=(unsigned long)((double)(diff+3840)*1e9/cfg->sample_rate); + // tv_nsec = 500000L; + old_ts = ts; + rt_sleep(&sleep_time,tv_nsec); #ifdef DEBUG_EXMIMO printf("back\n"); #endif // get new timestamp, in case we have to sleep again - pthread_mutex_lock(&exm->watchdog_mutex); + pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); ts = exm->ts; pthread_mutex_unlock(&exm->watchdog_mutex); + if (old_ts == ts) { + printf("ts stopped, returning\n"); + return(0); + } } /* @@ -511,6 +557,7 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi *ptimestamp=exm->last_ts_rx; exm->last_ts_rx += nsamps; + return(nsamps); } @@ -659,6 +706,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) /* device specific */ openair0_cfg[card].iq_txshift = 4;//shift openair0_cfg[card].iq_rxrescale = 15;//rescale iqs + openair0_cfg[card].mmapped_dma = 1; if (openair0_cfg[card].sample_rate==30.72e6) { resampling_factor = 0; @@ -690,6 +738,10 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) #endif for (ant=0; ant<4; ant++) { + + openair0_cfg[card].rxbase[ant] = (int32_t*)openair0_exmimo_pci[card].adc_head[ant]; + openair0_cfg[card].txbase[ant] = (int32_t*)openair0_exmimo_pci[card].dac_head[ant]; + if (openair0_cfg[card].rx_freq[ant] || openair0_cfg[card].tx_freq[ant]) { ACTIVE_RF += (1<rf.rf_mode[ant] = RF_MODE_BASE; @@ -697,14 +749,14 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) printf("card %d, antenna %d, autocal %d\n",card,ant,openair0_cfg[card].autocal[ant]); } - if (openair0_cfg[card].tx_freq[ant]) { + if (openair0_cfg[card].tx_freq[ant]>0) { p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX + TXLPFNORM + TXLPFEN + tx_filter); p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant]; p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant]; - + printf("openair0 : programming card %d TX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]); } - if (openair0_cfg[card].rx_freq[ant]) { + if (openair0_cfg[card].rx_freq[ant]>0) { p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX + RXLPFNORM + RXLPFEN + rx_filter); p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant]; @@ -786,13 +838,14 @@ int openair0_reconfig(openair0_config_t *openair0_cfg) if (openair0_cfg[card].tx_freq[ant]) { p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant]; p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant]; - //printf("openair0 : programming TX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]); + printf("openair0 : programming TX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]); } + if (openair0_cfg[card].rx_freq[ant]) { p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant]; p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant]; - //printf("openair0 : programming RX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]); + printf("openair0 : programming RX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]); switch (openair0_cfg[card].rxg_mode[ant]) { default: diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 51f21b57c8..f915afcb46 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -337,6 +337,10 @@ static void* eNB_thread_rxtx( void* param ) { struct sched_param sparam; char cpu_affinity[1024]; cpu_set_t cpuset; + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; /* Set affinity mask to include CPUs 1 to MAX_CPUS */ /* CPU 0 is reserved for UHD threads */ @@ -402,7 +406,7 @@ static void* eNB_thread_rxtx( void* param ) { while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { + if (pthread_mutex_timedlock(&proc->mutex_rxtx,&wait) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RXn-TXnp4\n"); exit_fun("nothing to add"); break; @@ -442,7 +446,7 @@ static void* eNB_thread_rxtx( void* param ) { * (may be relaxed in the future for performance reasons) */ - if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + if (pthread_mutex_timedlock(&sync_phy_proc.mutex_phy_proc_tx,&wait) != 0) { LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n"); exit_fun("nothing to add"); break; @@ -569,9 +573,9 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); -#ifdef DEBUG_THREADS - printf( "Exiting eNB thread TX\n"); -#endif + + printf( "Exiting eNB thread RXn_TXnp4\n"); + eNB_thread_rxtx_status = 0; return &eNB_thread_rxtx_status; @@ -613,6 +617,10 @@ static void* eNB_thread_rx_common( void* param ) { FILE *rx_time_file = NULL; char rx_time_name[101]; //int i; + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; if (opp_enabled == 1) { snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB"); @@ -766,7 +774,7 @@ static void* eNB_thread_rx_common( void* param ) { // wake up TX for subframe n+4 // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_lock(&proc_rxtx->mutex_rxtx) != 0) { + if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) { LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc_rxtx->instance_cnt_rxtx ); exit_fun( "error locking mutex_rxtx" ); break; @@ -815,9 +823,9 @@ static void* eNB_thread_rx_common( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); } -#ifdef DEBUG_THREADS - printf( "Exiting eNB thread RXn-TXnp4\n"); -#endif + + printf( "Exiting eNB thread rx_common\n"); + eNB_thread_rx_status = 0; return &eNB_thread_rx_status; @@ -832,8 +840,16 @@ static void* eNB_thread_rx_common( void* param ) { static void* eNB_thread_prach( void* param ) { static int eNB_thread_prach_status; + + eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id]; + + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + // set default return value eNB_thread_prach_status = 0; @@ -935,7 +951,7 @@ static void* eNB_thread_prach( void* param ) { if (oai_exit) break; - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + if (pthread_mutex_timedlock(&proc->mutex_prach,&wait) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n"); exit_fun( "error locking mutex" ); break; @@ -957,7 +973,7 @@ static void* eNB_thread_prach( void* param ) { prach_procedures(eNB,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + if (pthread_mutex_timedlock(&proc->mutex_prach,&wait) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); exit_fun( "error locking mutex" ); break; @@ -972,9 +988,9 @@ static void* eNB_thread_prach( void* param ) { } } -#ifdef DEBUG_THREADS + printf( "Exiting eNB thread PRACH\n"); -#endif + eNB_thread_prach_status = 0; return &eNB_thread_prach_status; @@ -1083,16 +1099,17 @@ void kill_eNB_proc(void) { proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race! proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race! + proc->instance_cnt_prach = 0; pthread_cond_signal( &proc_rxtx[0].cond_rxtx ); - pthread_cond_signal( &proc_rxtx[0].cond_rxtx ); + pthread_cond_signal( &proc_rxtx[1].cond_rxtx ); + pthread_cond_signal( &proc->cond_prach ); pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); - -#ifdef DEBUG_THREADS - printf( "Joining eNB TX CC_id %d thread\n", CC_id); -#endif + + pthread_join( proc->pthread_rx, (void**)&status ); + int result,i; - for (i=0;i<1;i++) { + for (i=0;i<2;i++) { pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status ); #ifdef DEBUG_THREADS @@ -1151,6 +1168,7 @@ void kill_eNB_proc(void) { int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) { int i, CC_id; + int j; uint16_t N_TA_offset = 0; @@ -1174,77 +1192,61 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c N_TA_offset = 624/4; } - /* + + + if (openair0_cfg[CC_id].mmapped_dma == 1) { // replace RX signal buffers with mmaped HW versions -#ifdef EXMIMO - openair0_cfg[CC_id].tx_num_channels = 0; - openair0_cfg[CC_id].rx_num_channels = 0; - - for (i=0; inb_antennas_rx; i++) { - printf("Mapping eNB CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); - phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i]; - - if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) { - printf("Error with rf_map! A channel has already been allocated!\n"); - return(-1); - } else { - openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].rx_num_channels++; + + for (i=0; inb_antennas_rx; i++) { + printf("Mapping eNB CC_id %d, rx_ant %d\n",CC_id,i); + free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); + phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = openair0_cfg[CC_id].rxbase[i]; + + + + printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); + + for (j=0; j<16; j++) { + printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j]); + phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j] = 16-j; + } } - - printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); - - for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j]); - phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j] = 16-j; + + for (i=0; inb_antennas_tx; i++) { + printf("Mapping eNB CC_id %d, tx_ant %d\n",CC_id,i); + free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); + phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = openair0_cfg[CC_id].txbase[i];//(int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i]; + + printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); + + for (j=0; j<16; j++) { + printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j]); + phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j] = 16-j; + } } } + else { // not memory-mapped DMA + - for (i=0; inb_antennas_tx; i++) { - printf("Mapping eNB CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i); - free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); - phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i]; - - if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) { - printf("Error with rf_map! A channel has already been allocated!\n"); - return(-1); - } else { - openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i]; - openair0_cfg[rf_map[CC_id].card].tx_num_channels++; + rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*)); + txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); + + for (i=0; inb_antennas_rx; i++) { + free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); + rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory + memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); + printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset); } - - printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); - - for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j]); - phy_vars_eNB[CC_id]->common_vars.txdata[0][i][j] = 16-j; + + for (i=0; inb_antennas_tx; i++) { + free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); + txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i]; + memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); + printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); } } - -#else // not EXMIMO - */ - - rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*)); - txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); - - for (i=0; inb_antennas_rx; i++) { - free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); - rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation - phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory - memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); - printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset); - } - - for (i=0; inb_antennas_tx; i++) { - free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); - txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation - phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i]; - memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); - printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); - } } return(0); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 61a8ccd9a0..0cd5d4d0fc 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -416,11 +416,20 @@ void help (void) { void exit_fun(const char* s) { + int CC_id; + if (s != NULL) { printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s); } oai_exit = 1; + + for(CC_id=0; CC_idrfdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + } #if defined(ENABLE_ITTI) sleep(1); //allow lte-softmodem threads to exit first @@ -1563,8 +1572,16 @@ int main( int argc, char **argv ) for (i=0; i<4; i++) { - openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i]; - openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i]; + if (irfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); - PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); } if (ouput_vcd) From 808494dd44cc2b4b0d1d5a1a59b6f3af60cf6a0e Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 24 Jun 2016 10:52:52 +0200 Subject: [PATCH 069/206] unified if4 header --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 57 +++----- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 123 +----------------- openair1/SCHED/phy_procedures_lte_eNb.c | 13 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 13 +- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 6 +- 5 files changed, 44 insertions(+), 168 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index a712ae0674..10b6ee66b7 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -67,9 +67,9 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + db_fulllength*sizeof(int16_t)); - IF4_dl_header_t *dl_header = (IF4_dl_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(int16_t)); + IF4_header_t *dl_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); gen_IF4_dl_header(dl_header, frame, subframe); @@ -106,9 +106,9 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + db_fulllength*sizeof(int16_t)); - IF4_ul_header_t *ul_header = (IF4_ul_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(int16_t)); + IF4_header_t *ul_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); gen_IF4_ul_header(ul_header, frame, subframe); @@ -143,9 +143,9 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, // FIX: hard coded prach samples length db_fulllength = 839*2; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + db_fulllength*sizeof(int16_t)); - IF4_prach_header_t *prach_header = (IF4_prach_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(int16_t)); + IF4_header_t *prach_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); gen_IF4_prach_header(prach_header, frame, subframe); @@ -208,10 +208,9 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } *packet_type = (uint16_t) *ret_type; + data_block = (int16_t*) (rx_buffer+sizeof_IF4_header_t); - if (*packet_type == IF4_PDLFFT) { - data_block = (int16_t*) (rx_buffer+sizeof_IF4_dl_header_t); - + if (*packet_type == IF4_PDLFFT) { // Calculate from received packet slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; @@ -226,11 +225,9 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } // Find and return symbol_number - *symbol_number = ((((IF4_dl_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; + *symbol_number = ((((IF4_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; - } else if (*packet_type == IF4_PULFFT) { - data_block = (int16_t*) (rx_buffer+sizeof_IF4_ul_header_t); - + } else if (*packet_type == IF4_PULFFT) { // Calculate from received packet slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; @@ -245,11 +242,9 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } // Find and return symbol_number - *symbol_number = ((((IF4_ul_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; - - } else if (*packet_type == IF4_PRACH) { - data_block = (int16_t*) (rx_buffer+sizeof_IF4_prach_header_t); + *symbol_number = ((((IF4_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; + } else if (*packet_type == IF4_PRACH) { // FIX: hard coded prach samples length db_fulllength = 839*2; @@ -265,7 +260,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } -void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, int frame, int subframe) { +void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) { // Set Type and Sub-Type dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; @@ -281,7 +276,7 @@ void gen_IF4_dl_header(IF4_dl_header_t *dl_packet, int frame, int subframe) { } -void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, int frame, int subframe) { +void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) { // Set Type and Sub-Type ul_packet->type = IF4_PACKET_TYPE; ul_packet->sub_type = IF4_PULFFT; @@ -294,20 +289,10 @@ void gen_IF4_ul_header(IF4_ul_header_t *ul_packet, int frame, int subframe) { ul_packet->frame_status |= (frame&0xffff)<<6; ul_packet->frame_status |= (subframe&0x000f)<<22; - // Set antenna specific gain *** set other antenna gain *** - ul_packet->gain0 = 0; - ul_packet->gain1 = 0; - ul_packet->gain2 = 0; - ul_packet->gain3 = 0; - ul_packet->gain4 = 0; - ul_packet->gain5 = 0; - ul_packet->gain6 = 0; - ul_packet->gain7 = 0; - } -void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, int frame, int subframe) { +void gen_IF4_prach_header(IF4_header_t *prach_packet, int frame, int subframe) { // Set Type and Sub-Type prach_packet->type = IF4_PACKET_TYPE; prach_packet->sub_type = IF4_PRACH; @@ -316,8 +301,8 @@ void gen_IF4_prach_header(IF4_prach_header_t *prach_packet, int frame, int subfr prach_packet->rsvd = 0; // Set LTE Prach configuration - prach_packet->prach_conf = 0; - prach_packet->prach_conf |= (frame&0xffff)<<6; - prach_packet->prach_conf |= (subframe&0x000f)<<22; + prach_packet->frame_status = 0; + prach_packet->frame_status |= (frame&0xffff)<<6; + prach_packet->frame_status |= (subframe&0x000f)<<22; } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 5d7b5e0f79..f06072b73e 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -47,55 +47,7 @@ #define IF4_PDLFFT 0x0020 #define IF4_PRACH 0x0021 -/* - -Bit-field reference - -/// IF4 Frame Status (32 bits) -struct IF4_frame_status { - /// Antenna Numbers - uint32_t ant_num:3; - /// Antenna Start - uint32_t ant_start:3; - /// Radio Frame Number - uint32_t rf_num:16; - /// Sub-frame Number - uint32_t sf_num:4; - /// Symbol Number - uint32_t sym_num:4; - /// Reserved - uint32_t rsvd:2; -}; - -/// IF4 Antenna Gain (16 bits) -struct IF4_gain { - /// Reserved - uint16_t rsvd:10; - /// FFT Exponent Output - uint16_t exponent:6; -}; - -/// IF4 LTE PRACH Configuration (32 bits) -struct IF4_lte_prach_conf { - /// Reserved - uint32_t rsvd:3; - /// Antenna Indication - uint32_t ant:3; - /// Radio Frame Number - uint32_t rf_num:16; - /// Sub-frame Number - uint32_t sf_num:4; - /// FFT Exponent Output - uint32_t exponent:6; -}; - -*/ - -struct IF4_dl_header { - /// Destination Address - - /// Source Address - +struct IF4_header { /// Type uint16_t type; /// Sub-Type @@ -104,80 +56,17 @@ struct IF4_dl_header { uint32_t rsvd; /// Frame Status uint32_t frame_status; - /// Data Blocks - - /// Frame Check Sequence }; -typedef struct IF4_dl_header IF4_dl_header_t; -#define sizeof_IF4_dl_header_t 12 +typedef struct IF4_header IF4_header_t; +#define sizeof_IF4_header_t 12 -struct IF4_ul_header { - /// Destination Address - - /// Source Address - - /// Type - uint16_t type; - /// Sub-Type - uint16_t sub_type; - /// Reserved - uint32_t rsvd; - /// Frame Status - uint32_t frame_status; - /// Gain 0 - uint16_t gain0; - /// Gain 1 - uint16_t gain1; - /// Gain 2 - uint16_t gain2; - /// Gain 3 - uint16_t gain3; - /// Gain 4 - uint16_t gain4; - /// Gain 5 - uint16_t gain5; - /// Gain 6 - uint16_t gain6; - /// Gain 7 - uint16_t gain7; - /// Data Blocks +void gen_IF4_dl_header(IF4_header_t*, int, int); - /// Frame Check Sequence +void gen_IF4_ul_header(IF4_header_t*, int, int); -}; - -typedef struct IF4_ul_header IF4_ul_header_t; -#define sizeof_IF4_ul_header_t 28 - -struct IF4_prach_header { - /// Destination Address - - /// Source Address - - /// Type - uint16_t type; - /// Sub-Type - uint16_t sub_type; - /// Reserved - uint32_t rsvd; - /// LTE Prach Configuration - uint32_t prach_conf; - /// Prach Data Block (one antenna) - - /// Frame Check Sequence - -}; - -typedef struct IF4_prach_header IF4_prach_header_t; -#define sizeof_IF4_prach_header_t 12 - -void gen_IF4_dl_header(IF4_dl_header_t*, int, int); - -void gen_IF4_ul_header(IF4_ul_header_t*, int, int); - -void gen_IF4_prach_header(IF4_prach_header_t*, int, int); +void gen_IF4_prach_header(IF4_header_t*, int, int); void send_IF4(PHY_VARS_eNB*, int, int, uint16_t, int); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 46364e82be..ef7b70d179 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2522,7 +2522,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl int prach_rx; uint16_t packet_type; - uint32_t symbol_number; + uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; struct timespec time_req, time_rem; @@ -2649,21 +2649,22 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } else if (eNB->node_function == NGFI_RCC_IF4) { /// **** recv_IF4 of rxdataF from RRU **** /// - /// **** recv_IF4 of prachF from RRU **** /// + /// **** recv_IF4 of rxsigF from RRU **** /// // get frame/subframe information from IF4 interface // timed loop (200 us) - + + symbol_number = 0; symbol_mask = 0; symbol_mask_full = (1<symbols_per_tti)-1; prach_rx = 0; // Block from loop while testing - symbol_mask = symbol_mask_full; - nanosleep(&time_req, &time_rem); + //symbol_mask = symbol_mask_full; + //nanosleep(&time_req, &time_rem); do { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - //recv_IF4(eNB, frame, subframe, &packet_type, &symbol_number); + recv_IF4(eNB, proc->frame_rx, proc->subframe_rx, &packet_type, &symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); if (packet_type == IF4_PULFFT) { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 0cb4fdfabb..f6e7db4c6e 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -309,11 +309,11 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t; + ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t; void *test_buffer = (void*)malloc(packet_size); void *rx_buffer=NULL; - IF4_dl_header_t *test_header = (IF4_dl_header_t*)(test_buffer + MAC_HEADER_SIZE_BYTES); + IF4_header_t *test_header = (IF4_header_t*)(test_buffer + MAC_HEADER_SIZE_BYTES); bytes_received = recv(eth->sockfd[Mod_id], test_buffer, @@ -324,7 +324,7 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, perror("ETHERNET READ: "); exit(-1); } - + *timestamp = test_header->sub_type; if (test_header->sub_type == IF4_PDLFFT) { @@ -337,11 +337,12 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, } else { buff[0] = (void*)malloc(RAW_IF4_PRACH_SIZE_BYTES - MAC_HEADER_SIZE_BYTES); - packet_size = RAW_IF4_PRACH_SIZE_BYTES - packet_size; + packet_size = RAW_IF4_PRACH_SIZE_BYTES - packet_size; + printf(" Came for prach\n"); } - memcpy(buff[0], test_header, sizeof_IF4_dl_header_t); - rx_buffer = (void*)(buff[0]+sizeof_IF4_dl_header_t); + memcpy(buff[0], test_header, sizeof_IF4_header_t); + rx_buffer = (void*)(buff[0]+sizeof_IF4_header_t); bytes_received = 0; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 12878badd1..030bfda147 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -58,6 +58,6 @@ #define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(int16_t)*scaled_nblocks) #define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839*2) // FIX hard coded prach size (uncompressed) -#define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_dl_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) -#define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_ul_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) -#define RAW_IF4_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4_prach_header_t + PRACH_BLOCK_SIZE_BYTES) +#define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + PRACH_BLOCK_SIZE_BYTES) From 19922715895572071400ebd55ec5b2760941e90a Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 24 Jun 2016 16:35:42 +0200 Subject: [PATCH 070/206] rcc recv and send work (not sync with rru yet) --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 15 ++++----- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 33 +++++++------------ 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 10b6ee66b7..4756559ac3 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -193,22 +193,21 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } db_halflength = db_fulllength>>1; - int64_t *ret_type=(int64_t*)malloc(sizeof(int64_t)); void *rx_buffer=NULL; + IF4_header_t *packet_header=NULL; int16_t *data_block=NULL; - - + // Read packet(s) from the fronthaul if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, - ret_type, + (int64_t*) packet_type, &rx_buffer, db_fulllength, 0) < 0) { perror("ETHERNET read"); } - *packet_type = (uint16_t) *ret_type; - data_block = (int16_t*) (rx_buffer+sizeof_IF4_header_t); + packet_header = (IF4_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES); + data_block = (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t); if (*packet_type == IF4_PDLFFT) { // Calculate from received packet @@ -225,7 +224,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } // Find and return symbol_number - *symbol_number = ((((IF4_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; + *symbol_number = ((packet_header->frame_status)>>26)&0x000f; } else if (*packet_type == IF4_PULFFT) { // Calculate from received packet @@ -242,7 +241,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } // Find and return symbol_number - *symbol_number = ((((IF4_header_t*)(rx_buffer))->frame_status)>>26)&0x000f; + *symbol_number = ((packet_header->frame_status)>>26)&0x000f; } else if (*packet_type == IF4_PRACH) { // FIX: hard coded prach samples length diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index f6e7db4c6e..780261d12a 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -312,13 +312,12 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t; void *test_buffer = (void*)malloc(packet_size); - void *rx_buffer=NULL; IF4_header_t *test_header = (IF4_header_t*)(test_buffer + MAC_HEADER_SIZE_BYTES); bytes_received = recv(eth->sockfd[Mod_id], test_buffer, packet_size, - 0); + MSG_PEEK); if (bytes_received ==-1) { eth->num_rx_errors++; perror("ETHERNET READ: "); @@ -328,29 +327,22 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, *timestamp = test_header->sub_type; if (test_header->sub_type == IF4_PDLFFT) { - buff[0] = (void*)malloc(RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) - MAC_HEADER_SIZE_BYTES); - packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) - packet_size; - + packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks); } else if (test_header->sub_type == IF4_PULFFT) { - buff[0] = (void*)malloc(RAW_IF4_PULFFT_SIZE_BYTES(nblocks) - MAC_HEADER_SIZE_BYTES); - packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks) - packet_size; - + packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks); } else { - buff[0] = (void*)malloc(RAW_IF4_PRACH_SIZE_BYTES - MAC_HEADER_SIZE_BYTES); - packet_size = RAW_IF4_PRACH_SIZE_BYTES - packet_size; - printf(" Came for prach\n"); + packet_size = RAW_IF4_PRACH_SIZE_BYTES; } - - memcpy(buff[0], test_header, sizeof_IF4_header_t); - rx_buffer = (void*)(buff[0]+sizeof_IF4_header_t); + + buff[0] = (void*)malloc(packet_size); bytes_received = 0; while(bytes_received < packet_size) { - bytes_received += recv(eth->sockfd[Mod_id], - rx_buffer, - packet_size-bytes_received, - 0); + bytes_received = recv(eth->sockfd[Mod_id], + buff[0], + packet_size, + 0); if (bytes_received ==-1) { eth->num_rx_errors++; perror("ETHERNET READ: "); @@ -361,10 +353,9 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, } } - eth->rx_nsamps = nsamps; - + eth->rx_nsamps = nsamps; free(test_buffer); - return (bytes_received-MAC_HEADER_SIZE_BYTES)>>1; + return(bytes_received); } From 56fcc17ebc6f19183d64489e32da4eee918159cd Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 24 Jun 2016 17:36:40 +0200 Subject: [PATCH 071/206] small compilation rru --- targets/RT/USER/lte-enb.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 5494871521..00d1bdcdaa 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -297,7 +297,10 @@ static void* eNB_thread_rxtx( void* param ) { FILE *tx_time_file = NULL; char tx_time_name[101]; void *txp[PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx]; - + + uint16_t packet_type; + uint32_t symbol_number=0; + if (opp_enabled == 1) { snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf", "eNB"); tx_time_file = fopen(tx_time_name,"w"); @@ -488,8 +491,10 @@ static void* eNB_thread_rxtx( void* param ) { } else { /// **** recv_IF4 of txdataF from RCC **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - //recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, packet_type, symbol_number); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); + while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1) { + recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, &packet_type, &symbol_number); + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); } From 456572c9ada78da6da3e33b6fd3c42cb65a8539a Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 27 Jun 2016 00:58:54 -0700 Subject: [PATCH 072/206] ExMIMO2 RX gain calibration --- .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index 89b43a22cf..582a2f75d2 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -670,6 +670,13 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { return(0); } +unsigned int rxg_max[4] = {128,128,128,126}; +unsigned int rxg_med[4] = {122,123,123,120}; +unsigned int rxg_byp[4] = {116,117,116,116}; +unsigned int nf_max[4] = {7,9,16,12}; +unsigned int nf_med[4] = {12,13,22,17}; +unsigned int nf_byp[4] = {15,20,29,23}; + int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) { int ret; @@ -760,21 +767,42 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX + RXLPFNORM + RXLPFEN + rx_filter); p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant]; - p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant]; + printf("openair0 : programming card %d RX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]); switch (openair0_cfg[card].rxg_mode[ant]) { default: case max_gain: p_exmimo_config->rf.rf_mode[ant] += LNAMax; + if (rxg_max[ant] >= (int)openair0_cfg[card].rx_gain[ant]) { + p_exmimo_config->rf.rx_gain[ant][0] = 30 - (rxg_max[ant] - (int)openair0_cfg[card].rx_gain[ant]); //was measured at rxgain=30; + } + else { + printf("openair0: RX RF gain too high, reduce by %d dB\n", (int)openair0_cfg[card].rx_gain[ant]-rxg_max[ant]); + exit(-1); + } break; case med_gain: p_exmimo_config->rf.rf_mode[ant] += LNAMed; + if (rxg_med[ant] >= (int)openair0_cfg[card].rx_gain[ant]) { + p_exmimo_config->rf.rx_gain[ant][0] = 30 - (rxg_med[ant] - (int)openair0_cfg[card].rx_gain[ant]); //was measured at rxgain=30; + } + else { + printf("openair0: RX RF gain too high, reduce by %d dB\n", (int)openair0_cfg[card].rx_gain[ant]-rxg_med[ant]); + exit(-1); + } break; case byp_gain: p_exmimo_config->rf.rf_mode[ant] += LNAByp; + if (rxg_byp[ant] >= (int)openair0_cfg[card].rx_gain[ant]) { + p_exmimo_config->rf.rx_gain[ant][0] = 30 - (rxg_byp[ant] - (int)openair0_cfg[card].rx_gain[ant]); //was measured at rxgain=30; + } + else { + printf("openair0: RX RF gain too high, reduce by %d dB\n", (int)openair0_cfg[card].rx_gain[ant]-rxg_byp[ant]); + exit(-1); + } break; } } else { From 6ae4123733336959196f538b297b25715f24cd81 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 27 Jun 2016 12:43:43 +0200 Subject: [PATCH 073/206] some fixes for host type/dev type --- openair2/ENB_APP/enb_config.c | 6 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 61 +++++++++++++++++++ .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 17 +++++- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 3 +- targets/RT/USER/lte-softmodem.c | 22 +++---- 5 files changed, 91 insertions(+), 18 deletions(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 7f8cf95c2b..5bc0088ed5 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -298,7 +298,7 @@ void enb_config_display(void) printf( "\ttx_scheduling_advance :\t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_scheduling_advance); printf( "\ttx_sample_advance : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_sample_advance); printf( "\tiq_txshift : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].iq_txshift); - printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); + printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : (enb_properties.properties[i]->rrh_gw_config[j].rawif4 == 1)? "RAW_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].udpif4 == 1)? "UDP_IF4" : "UDP"); if (enb_properties.properties[i]->rrh_gw_config[j].exmimo == 1) { printf( "\tRF target : \tEXMIMO:\n\n"); } else if (enb_properties.properties[i]->rrh_gw_config[j].usrp_b200 == 1) { @@ -2242,9 +2242,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; } else if (strcmp(tr_preference, "raw") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; - } else if (strcmp(tr_preference, "udpif4") == 0) { + } else if (strcmp(tr_preference, "udp_if4") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udpif4 = 1; - } else if (strcmp(tr_preference, "rawif4") == 0) { + } else if (strcmp(tr_preference, "raw_if4") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif4 = 1; } else {//if (strcmp(preference, "no") == 0) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 780261d12a..13dfe574c2 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -390,6 +390,37 @@ int eth_set_dev_conf_raw(openair0_device *device) { } + +int eth_set_dev_conf_raw_IF4(openair0_device *device) { + + int Mod_id = device->Mod_id; + eth_state_t *eth = (eth_state_t*)device->priv; + void *msg; + ssize_t msg_len; + + /* a BBU client sends to RRH a set of configuration parameters (openair0_config_t) + so that RF front end is configured appropriately and + frame/packet size etc. can be set */ + + msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t)); + msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t); + + + memcpy(msg,(void*)ð->eh,MAC_HEADER_SIZE_BYTES); + memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)device->openair0_cfg,sizeof(openair0_config_t)); + + if (send(eth->sockfd[Mod_id], + msg, + msg_len, + 0)==-1) { + perror("ETHERNET: "); + exit(0); + } + + return 0; +} + + int eth_get_dev_conf_raw(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; @@ -418,3 +449,33 @@ int eth_get_dev_conf_raw(openair0_device *device) { return 0; } + + +int eth_get_dev_conf_raw_IF4(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + char str[INET_ADDRSTRLEN]; + void *msg; + ssize_t msg_len; + + msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t)); + msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t); + + /* RRH receives from BBU openair0_config_t */ + if (recv(eth->sockfd[Mod_id], + msg, + msg_len, + 0)==-1) { + perror("ETHERNET: "); + exit(0); + } + + /* RRH stores the remote MAC address */ + memcpy(eth->eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN); + //memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t)); + //device->openair0_cfg=(openair0_config_t *)(msg + MAC_HEADER_SIZE_BYTES); + printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5],eth->eh.ether_dhost[0],eth->eh.ether_dhost[1],eth->eh.ether_dhost[2],eth->eh.ether_dhost[3],eth->eh.ether_dhost[4],eth->eh.ether_dhost[5]); + + return 0; +} diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 6e5aa11140..5802b1569f 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -63,7 +63,7 @@ int trx_eth_start(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; /* initialize socket */ - if ((eth->flags & ETH_RAW_MODE) != 0 ) { + if (eth->flags == ETH_RAW_MODE) { if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ if (device->host_type == BBU_HOST) { @@ -73,6 +73,21 @@ int trx_eth_start(openair0_device *device) { } /* adjust MTU wrt number of samples per packet */ if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; + + } else if (eth->flags == ETH_RAW_IF4_MODE) { + if (eth_socket_init_raw(device)!=0) return -1; + /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ + if (device->host_type == BBU_HOST) { + if(eth_set_dev_conf_raw_IF4(device)!=0) return -1; + } else { + if(eth_get_dev_conf_raw_IF4(device)!=0) return -1; + } + /* adjust MTU wrt number of samples per packet */ + if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; + + } else if (eth->flags == ETH_UDP_IF4_MODE) { + + } else { if (eth_socket_init_udp(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 66cb13ef12..f7753fb517 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -226,6 +226,7 @@ int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); int eth_get_dev_conf_raw(openair0_device *device); int eth_set_dev_conf_raw(openair0_device *device); - +int eth_get_dev_conf_raw_IF4(openair0_device *device); +int eth_set_dev_conf_raw_IF4(openair0_device *device); #endif diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 0cd5d4d0fc..c4d37393bd 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1541,13 +1541,6 @@ int main( int argc, char **argv ) openair0_cfg[card].my_port = eth_params->my_port; } - //if (node_function == NGFI_RCC_IF4 || node_function == NGFI_RRU_IF4) { - //openair0_cfg[card].remote_addr = eth_params->remote_addr; - //openair0_cfg[card].remote_port = eth_params->remote_port; - //openair0_cfg[card].my_addr = eth_params->my_addr; - //openair0_cfg[card].my_port = eth_params->my_port; - //} - printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx), ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); @@ -1648,11 +1641,17 @@ int main( int argc, char **argv ) openair0_cfg[0].log_level = glog_level; for (CC_id=0; CC_idrfdevice.host_type = BBU_HOST; + if (node_function == NGFI_RRU_IF4) { + PHY_vars_eNB_g[0][CC_id]->rfdevice.host_type = RRH_HOST; + PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = RRH_HOST; + } else { + PHY_vars_eNB_g[0][CC_id]->rfdevice.host_type = BBU_HOST; + PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = BBU_HOST; + } + PHY_vars_eNB_g[0][CC_id]->rfdevice.type = NONE_DEV; PHY_vars_eNB_g[0][CC_id]->rfdevice.transp_type = NONE_TP; - PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = BBU_HOST; PHY_vars_eNB_g[0][CC_id]->ifdevice.type = NONE_DEV; PHY_vars_eNB_g[0][CC_id]->ifdevice.transp_type = NONE_TP; } @@ -1663,7 +1662,6 @@ int main( int argc, char **argv ) openair0.type = NONE_DEV; /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ openair0.transp_type = NONE_TP; - //openair0_cfg[0].log_level = glog_level; // Legacy BBU - RRH init //int returns=-1; @@ -1691,9 +1689,7 @@ int main( int argc, char **argv ) //else if (mode==loop_through_memory) { //} //} - - //printf("Done\n"); - + int returns=-1; // Handle spatially distributed MIMO antenna ports From 0d4d8cef0e97480899f5602ce118dfbc3426fd5d Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 27 Jun 2016 17:21:53 +0200 Subject: [PATCH 074/206] added node func BBU and marked split for rf/if read and write --- openair1/PHY/defs.h | 9 +++--- openair1/SCHED/phy_procedures_lte_eNb.c | 38 ++++++++++++------------- targets/RT/USER/lte-enb.c | 19 +++++++++---- targets/RT/USER/lte-softmodem.c | 12 ++++++-- 4 files changed, 46 insertions(+), 32 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index ed3ca5c251..d01edd1ba0 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -157,10 +157,11 @@ enum transmission_access_mode { SCHEDULED_ACCESS, CBA_ACCESS}; -typedef enum { - eNodeB_3GPP=0, // classical eNodeB function - NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) - NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) +typedef enum { + eNodeB_3GPP=0, // classical eNodeB function + eNodeB_3GPP_BBU, // classical eNodeB function with transport interface + NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) + NGFI_RCC_IF4, // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) } eNB_func_t; typedef struct UE_SCAN_INFO_s { diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index ef7b70d179..2754f7842b 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2524,11 +2524,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; - - struct timespec time_req, time_rem; - time_req.tv_sec = 0; - time_req.tv_nsec = 300000; - + if (subframe==9) { subframe=0; frame++; @@ -2547,7 +2543,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) if ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF and front-end processing + (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF for (i=0; inb_antennas_rx; i++) rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; @@ -2563,13 +2559,13 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (proc->first_rx == 0) { if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - exit_fun("Exiting"); - } + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + exit_fun("Exiting"); + } if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - exit_fun("Exiting"); - } + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } } else { proc->first_rx = 0; } @@ -2585,6 +2581,16 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + } else if(eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF + /// **** trx_read_func from IF device **** /// + + } + + + if ((eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == eNodeB_3GPP) || + (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing + // now do common RX processing for first slot in subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); remove_7_5_kHz(eNB,proc->subframe_rx<<1); @@ -2608,12 +2614,10 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)<=0) { - - /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// + /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(eNB, frame, subframe, IF4_PULFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); - } /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) @@ -2657,10 +2661,6 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl symbol_mask = 0; symbol_mask_full = (1<symbols_per_tti)-1; prach_rx = 0; - - // Block from loop while testing - //symbol_mask = symbol_mask_full; - //nanosleep(&time_req, &time_rem); do { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 00d1bdcdaa..0ce83c721f 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -500,12 +500,13 @@ static void* eNB_thread_rxtx( void* param ) { } } - // eNodeB_3GPP and RRU create txdata and write to RF device + // eNodeB_3GPP, _BBU and RRU create txdata if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RCC_IF4) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); - + } + /* short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; int i; @@ -518,8 +519,12 @@ static void* eNB_thread_rxtx( void* param ) { txdata[i+5] = 0; txdata[i+6] = 0; txdata[i+7] = -2047; } - */ + */ + + // eNodeB_3GPP, RRU write to RF device + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP || + PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) { // Transmit TX buffer based on timestamp from RX VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers @@ -539,13 +544,15 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { + /// **** trx_write_func to IF device **** /// + + } else { - /// **** send_IF4 of txdataF to RRU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); - } if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { @@ -744,7 +751,7 @@ static void* eNB_thread_rx_common( void* param ) { #endif // Start RF device for this CC - if (eNB->node_function != NGFI_RCC_IF4) { + if (eNB->node_function == eNodeB_3GPP || eNB->node_function == NGFI_RRU_IF4) { if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) LOG_E(HW,"Could not start the RF device\n"); } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index c4d37393bd..bd877e7aff 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -686,7 +686,8 @@ static void get_options (int argc, char **argv) LONG_OPTION_PHYTEST, LONG_OPTION_RCC, LONG_OPTION_RRU, - LONG_OPTION_ENB + LONG_OPTION_ENB, + LONG_OPTION_ENB_BBU #if T_TRACER , LONG_OPTION_T_PORT, @@ -713,6 +714,7 @@ static void get_options (int argc, char **argv) {"RCC", no_argument, NULL, LONG_OPTION_RCC}, {"RRU", no_argument, NULL, LONG_OPTION_RRU}, {"eNB", no_argument, NULL, LONG_OPTION_ENB}, + {"BBU", no_argument, NULL, LONG_OPTION_ENB_BBU}, #if T_TRACER {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, @@ -815,6 +817,10 @@ static void get_options (int argc, char **argv) case LONG_OPTION_ENB: node_function = eNodeB_3GPP; break; + + case LONG_OPTION_ENB_BBU: + node_function = eNodeB_3GPP_BBU; + break; #if T_TRACER case LONG_OPTION_T_PORT: { @@ -1694,7 +1700,7 @@ int main( int argc, char **argv ) // Handle spatially distributed MIMO antenna ports // Load RF device and initialize - if (node_function != NGFI_RCC_IF4) { + if (node_function == NGFI_RRU_IF4 || node_function == eNodeB_3GPP) { for (CC_id=0; CC_idrfdevice), &openair0_cfg[0]); @@ -1710,7 +1716,7 @@ int main( int argc, char **argv ) } // Load transport protocol and initialize - if (node_function != eNodeB_3GPP){ + if (node_function != eNodeB_3GPP) { for (CC_id=0; CC_idifdevice), &openair0_cfg[0], (eth_params+CC_id)); From 36df9556c287ad6c67384bf7930a0c8480a9295c Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 27 Jun 2016 17:26:43 +0200 Subject: [PATCH 075/206] minor typo --- openair1/PHY/defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index d01edd1ba0..0c61fe0bc7 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -161,7 +161,7 @@ typedef enum { eNodeB_3GPP=0, // classical eNodeB function eNodeB_3GPP_BBU, // classical eNodeB function with transport interface NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) - NGFI_RCC_IF4, // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) + NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) } eNB_func_t; typedef struct UE_SCAN_INFO_s { From 36a3d857270dd5760a3df439dda9bf4b7b32dc54 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 28 Jun 2016 18:05:23 +0200 Subject: [PATCH 076/206] init if before rf, cleaning usrp blocks --- targets/RT/USER/lte-enb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 0ce83c721f..0e3af529c2 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -749,6 +749,12 @@ static void* eNB_thread_rx_common( void* param ) { #if defined(ENABLE_ITTI) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif + + // Start IF device for this CC + if (eNB->node_function != eNodeB_3GPP) { + if (eNB->ifdevice.trx_start_func(&eNB->ifdevice) != 0 ) + LOG_E(HW,"Could not start the IF device\n"); + } // Start RF device for this CC if (eNB->node_function == eNodeB_3GPP || eNB->node_function == NGFI_RRU_IF4) { @@ -756,12 +762,6 @@ static void* eNB_thread_rx_common( void* param ) { LOG_E(HW,"Could not start the RF device\n"); } - // Start IF device for this CC - if (eNB->node_function != eNodeB_3GPP) { - if (eNB->ifdevice.trx_start_func(&eNB->ifdevice) != 0 ) - LOG_E(HW,"Could not start the IF device\n"); - } - // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, 0 ); From 3fd226f7b05de1f36faaa0e897753e76125d3f15 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 29 Jun 2016 17:16:29 +0200 Subject: [PATCH 077/206] added sync between rru and rcc frame, subframe --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 11 +++++++---- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 21 +++++++++++++++++++-- targets/RT/USER/lte-enb.c | 3 ++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 4756559ac3..b71365d6fc 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -176,7 +176,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, } -void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, uint32_t *symbol_number) { +void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -208,10 +208,13 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, packet_header = (IF4_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES); data_block = (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t); + + *frame = ((packet_header->frame_status)>>6)&0xffff; + *subframe = ((packet_header->frame_status)>>22)&0x000f; if (*packet_type == IF4_PDLFFT) { // Calculate from received packet - slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; // Do decompression of the two parts and generate txdataF @@ -228,7 +231,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } else if (*packet_type == IF4_PULFFT) { // Calculate from received packet - slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; // Do decompression of the two parts and generate rxdataF @@ -246,7 +249,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t *packet_type, } else if (*packet_type == IF4_PRACH) { // FIX: hard coded prach samples length db_fulllength = 839*2; - + // Generate uncompressed data blocks memcpy((rxsigF[0]+slotoffsetF), data_block, db_fulllength*sizeof(int16_t)); diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index f06072b73e..18ff2bb8f8 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -70,4 +70,4 @@ void gen_IF4_prach_header(IF4_header_t*, int, int); void send_IF4(PHY_VARS_eNB*, int, int, uint16_t, int); -void recv_IF4(PHY_VARS_eNB*, int, int, uint16_t*, uint32_t*); +void recv_IF4(PHY_VARS_eNB*, int*, int*, uint16_t*, uint32_t*); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 2754f7842b..e5b93dc6ac 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2664,13 +2664,13 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl do { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - recv_IF4(eNB, proc->frame_rx, proc->subframe_rx, &packet_type, &symbol_number); + recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); if (packet_type == IF4_PULFFT) { symbol_mask = symbol_mask | (1<0 && packet_type == PRACH) { + } else if (packet_type == IF4_PRACH) { // wake up thread for PRACH RX prach_rx = 1; @@ -2703,6 +2703,23 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); + if (proc->first_rx == 0) { + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); +// exit_fun("Exiting"); + } + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + // exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); + // Tobi aka mr monaco: ETH } else { // should not get here diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 0e3af529c2..6eb916c41b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -493,10 +493,11 @@ static void* eNB_thread_rxtx( void* param ) { /// **** recv_IF4 of txdataF from RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1) { - recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, &packet_type, &symbol_number); + recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); + // Check the recv frame/subframe } } From b62885663534a087beacc335cf58ffd5925ad916 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 1 Jul 2016 03:10:39 -0700 Subject: [PATCH 078/206] updates in UE for new process scheduling --- openair1/PHY/INIT/lte_init.c | 12 +- openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c | 4 +- .../PHY/LTE_ESTIMATION/lte_ue_measurements.c | 22 +- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 15 +- .../PHY/LTE_TRANSPORT/dlsch_demodulation.c | 2 +- openair1/PHY/LTE_TRANSPORT/drs_modulation.c | 3 +- openair1/PHY/LTE_TRANSPORT/initial_sync.c | 23 +- openair1/PHY/LTE_TRANSPORT/phich.c | 17 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 6 +- openair1/PHY/LTE_TRANSPORT/proto.h | 21 +- openair1/PHY/LTE_TRANSPORT/pucch.c | 9 +- openair1/PHY/LTE_TRANSPORT/rar_tools.c | 7 +- openair1/PHY/TOOLS/lte_phy_scope.c | 2 +- openair1/PHY/defs.h | 102 +- openair1/SCHED/defs.h | 100 +- openair1/SCHED/phy_procedures_lte_ue.c | 4347 ++++++++--------- openair1/SCHED/pucch_pc.c | 6 +- openair1/SCHED/pusch_pc.c | 10 +- targets/RT/USER/lte-softmodem.c | 2 +- targets/RT/USER/lte-ue.c | 559 +-- 20 files changed, 2407 insertions(+), 2862 deletions(-) diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index e3128d7296..a453b8eb8d 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -259,7 +259,7 @@ void phy_config_sib2_ue(uint8_t Mod_id,int CC_id, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_IN); - LOG_I(PHY,"[UE%d] Frame %d: Applying radioResourceConfigCommon from eNB%d\n",Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx,CH_index); + LOG_I(PHY,"[UE%d] Applying radioResourceConfigCommon from eNB%d\n",Mod_id,CH_index); frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; @@ -369,7 +369,7 @@ void phy_config_sib13_ue(uint8_t Mod_id,int CC_id,uint8_t CH_index,int mbsfn_Are LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; - LOG_I(PHY,"[UE%d] Frame %d: Applying MBSFN_Area_id %d for index %d\n",Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx,mbsfn_AreaId_r9,mbsfn_Area_idx); + LOG_I(PHY,"[UE%d] Applying MBSFN_Area_id %d for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx); if (mbsfn_Area_idx == 0) { frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; @@ -517,8 +517,8 @@ void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, Mobility // uint8_t prach_fmt; // int u; - LOG_I(PHY,"[UE%d] Frame %d: Handover triggered: Applying radioResourceConfigCommon from eNB %d\n", - Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx,eNB_id); + LOG_I(PHY,"[UE%d] Handover triggered: Applying radioResourceConfigCommon from eNB %d\n", + Mod_id,eNB_id); frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; frame_parms->prach_config_common.prach_Config_enabled=1; @@ -752,7 +752,7 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t CH_index, if (physicalConfigDedicated) { - LOG_D(PHY,"[UE %d] Frame %d: Received physicalConfigDedicated from eNB %d\n",Mod_id, phy_vars_ue->frame_rx,CH_index); + LOG_D(PHY,"[UE %d] Received physicalConfigDedicated from eNB %d\n",Mod_id, CH_index); LOG_D(PHY,"------------------------------------------------------------------------\n"); if (physicalConfigDedicated->pdsch_ConfigDedicated) { @@ -843,7 +843,7 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t CH_index, #endif } else { - LOG_D(PHY,"[PHY][UE %d] Frame %d: Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, phy_vars_ue->frame_rx,CH_index); + LOG_D(PHY,"[PHY][UE %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id,CH_index); return; } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c index 6980ca358c..b78a7e24fd 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c @@ -51,7 +51,7 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, ncoef = 32767 - coef; #ifdef DEBUG_PHY - LOG_D(PHY,"frame %d, slot %d: rx_offset (before) = %d\n",ue->frame_rx,ue->slot_rx,ue->rx_offset); + LOG_D(PHY,"frame %d: rx_offset (before) = %d\n",ue->proc.proc_rxtx[0].frame_rx,ue->rx_offset); #endif //DEBUG_PHY @@ -95,7 +95,7 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, #ifdef DEBUG_PHY LOG_D(PHY,"frame %d: rx_offset (after) = %d : max_pos = %d,max_pos_fil = %d (peak %d)\n", - ue->frame_rx,ue->rx_offset,max_pos,max_pos_fil,temp); + ue->proc.proc_rxtx[0].frame_rx,ue->rx_offset,max_pos,max_pos_fil,temp); #endif //DEBUG_PHY diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c index ae484092b8..7a9fd1284d 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c @@ -77,7 +77,7 @@ int16_t get_PL(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) RSoffset = 3; */ - LOG_D(PHY,"get_PL : Frame %d : rsrp %f dBm/RE (%f), eNB power %d dBm/RE\n", ue->frame_rx, + LOG_D(PHY,"get_PL : Frame %d : rsrp %f dBm/RE (%f), eNB power %d dBm/RE\n", ue->proc.proc_rxtx[0].frame_rx, (1.0*dB_fixed_times10(ue->measurements.rsrp[eNB_index])-(10.0*ue->rx_total_gain_dB))/10.0, 10*log10((double)ue->measurements.rsrp[eNB_index]), ue->frame_parms.pdsch_config_common.referenceSignalPower); @@ -172,7 +172,7 @@ int8_t set_RSRQ_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rs } void ue_rrc_measurements(PHY_VARS_UE *ue, - uint8_t slot, + uint8_t subframe, uint8_t abstraction_flag) { @@ -192,7 +192,7 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, if (abstraction_flag == 0) { if ((ue->frame_parms.frame_type == FDD) && - ((slot == 0) || (slot == 10))) { // FDD PSS/SSS, compute noise in DTX REs + ((subframe == 0) || (subframe == 5))) { // FDD PSS/SSS, compute noise in DTX REs if (ue->frame_parms.Ncp==NORMAL) { for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { @@ -240,7 +240,7 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, } } else if ((ue->frame_parms.frame_type == TDD) && - (slot == 1)) { // TDD SSS, compute noise in DTX REs + (subframe == 0)) { // TDD SSS, compute noise in DTX REs if (ue->frame_parms.Ncp==NORMAL) { for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { @@ -294,7 +294,7 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, for (l=0,nu=0; l<=(4-ue->frame_parms.Ncp); l+=(4-ue->frame_parms.Ncp),nu=3) { k = (nu + nushift)%6; #ifdef DEBUG_MEAS - LOG_I(PHY,"[UE %d] Frame %d slot %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, nushift %d, eNB_offset %d, k %d, l %d)\n",ue->Mod_id,ue->frame_rx,slot,Nid_cell,nushift, + LOG_I(PHY,"[UE %d] Frame %d subframe %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, nushift %d, eNB_offset %d, k %d, l %d)\n",ue->Mod_id,ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,Nid_cell,nushift, eNB_offset,k,l); #endif @@ -376,15 +376,15 @@ void ue_rrc_measurements(PHY_VARS_UE *ue, // if (slot == 0) { if (eNB_offset == 0) - LOG_I(PHY,"[UE %d] Frame %d, slot %d RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB, gain %d), N0 %d dBm\n",ue->Mod_id, - ue->frame_rx,slot,10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, + LOG_I(PHY,"[UE %d] Frame %d, subframe %d RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB, gain %d), N0 %d dBm\n",ue->Mod_id, + ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, 10*log10(ue->measurements.rssi), ue->rx_total_gain_dB, ue->measurements.n0_power_tot_dBm); - LOG_I(PHY,"[UE %d] Frame %d, slot %d RRC Measurements (idx %d, Cell id %d) => rsrp: %3.1f dBm/RE (%d), rsrq: %3.1f dB\n", + LOG_I(PHY,"[UE %d] Frame %d, subframe %d RRC Measurements (idx %d, Cell id %d) => rsrp: %3.1f dBm/RE (%d), rsrq: %3.1f dB\n", ue->Mod_id, - ue->frame_rx,slot,eNB_offset, + ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,eNB_offset, (eNB_offset>0) ? ue->measurements.adj_cell_id[eNB_offset-1] : ue->frame_parms.Nid_cell, 10*log10(ue->measurements.rsrp[eNB_offset])-ue->rx_total_gain_dB, ue->measurements.rsrp[eNB_offset], @@ -699,9 +699,9 @@ void lte_ue_measurements(PHY_VARS_UE *ue, } -void lte_ue_measurements_emul(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) +void lte_ue_measurements_emul(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id) { - msg("[PHY] EMUL UE lte_ue_measurements_emul last slot %d, eNB_id %d\n",last_slot,eNB_id); + msg("[PHY] EMUL UE lte_ue_measurements_emul subframe %d, eNB_id %d\n",subframe,eNB_id); } diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 18e232e967..3f784e22d3 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -6236,6 +6236,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, uint8_t subframe, DCI_format_t dci_format, PHY_VARS_UE *ue, + UE_rxtx_proc_t *proc, uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, @@ -6269,12 +6270,12 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, harq_pid = 0; else harq_pid = subframe2harq_pid(frame_parms, - pdcch_alloc2ul_frame(frame_parms,ue->frame_rx,subframe), + pdcch_alloc2ul_frame(frame_parms,proc->frame_rx,subframe), pdcch_alloc2ul_subframe(frame_parms,subframe)); if (harq_pid == 255) { LOG_E(PHY, "frame %d, subframe %d, rnti %x, format %d: illegal harq_pid!\n", - ue->frame_rx, subframe, rnti, dci_format); + proc->frame_rx, subframe, rnti, dci_format); return(-1); } @@ -6401,7 +6402,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, if (rballoc > RIV_max) { LOG_E(PHY,"frame %d, subframe %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc > RIV_max\n", - ue->frame_rx, subframe, rnti, dci_format); + proc->frame_rx, subframe, rnti, dci_format); return(-1); } @@ -6416,13 +6417,13 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, if (ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) { LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d: f_pusch (ACC) %d, adjusting by %d (TPC %d)\n", - ue->Mod_id,harq_pid,ue->frame_rx,subframe,ulsch->f_pusch, + ue->Mod_id,harq_pid,proc->frame_rx,subframe,ulsch->f_pusch, delta_PUSCH_acc[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC], ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC); ulsch->f_pusch += delta_PUSCH_acc[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC]; } else { LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d: f_pusch (ABS) %d, adjusting to %d (TPC %d)\n", - ue->Mod_id,harq_pid,ue->frame_rx,subframe,ulsch->f_pusch, + ue->Mod_id,harq_pid,proc->frame_rx,subframe,ulsch->f_pusch, delta_PUSCH_abs[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC], ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC); ulsch->f_pusch = delta_PUSCH_abs[ue->ulsch[eNB_id]->harq_processes[harq_pid]->TPC]; @@ -7044,7 +7045,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, } LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d), nb_rb %d, first_rb %d, mcs %d, round %d, rv %d\n", - ue->Mod_id,harq_pid,ue->frame_rx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift,ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb, + ue->Mod_id,harq_pid,proc->frame_rx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift,ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb, ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->round,ulsch->harq_processes[harq_pid]->rvidx); // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift; @@ -7071,7 +7072,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, return(0); } else { LOG_E(PHY,"frame %d, subframe %d: FATAL ERROR, generate_ue_ulsch_params_from_dci, Illegal dci_format %d\n", - ue->frame_rx, subframe,dci_format); + proc->frame_rx, subframe,dci_format); return(-1); } diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c index c41262727f..ab6c4703d6 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c @@ -123,7 +123,7 @@ int rx_pdsch(PHY_VARS_UE *ue, break; default: - LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",ue->frame_rx,subframe,type); + LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",ue->proc.proc_rxtx[0].frame_rx,subframe,type); return(-1); break; } diff --git a/openair1/PHY/LTE_TRANSPORT/drs_modulation.c b/openair1/PHY/LTE_TRANSPORT/drs_modulation.c index 8ccfc72d20..1f8e605eaf 100644 --- a/openair1/PHY/LTE_TRANSPORT/drs_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/drs_modulation.c @@ -43,6 +43,7 @@ //#define DEBUG_DRS int generate_drs_pusch(PHY_VARS_UE *ue, + UE_rxtx_proc_t *proc, uint8_t eNB_id, short amp, unsigned int subframe, @@ -70,7 +71,7 @@ int generate_drs_pusch(PHY_VARS_UE *ue, uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; int32_t ref_re,ref_im; - uint8_t harq_pid = subframe2harq_pid(frame_parms,ue->frame_tx,subframe); + uint8_t harq_pid = subframe2harq_pid(frame_parms,proc->frame_tx,subframe); cyclic_shift0 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 + diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c index 673b7a4348..57c9a824a2 100644 --- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c @@ -239,20 +239,25 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode) break; } - ue->frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2; - ue->frame_rx += frame_mod4; + ue->proc.proc_rxtx[0].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2; + ue->proc.proc_rxtx[0].frame_rx += frame_mod4; + + ue->proc.proc_rxtx[1].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2; + ue->proc.proc_rxtx[1].frame_rx += frame_mod4; #ifndef USER_MODE // one frame delay - ue->frame_rx ++; + ue->proc.proc_rxtx[0].frame_rx ++; + ue->proc.proc_rxtx[1].frame_rx ++; #endif - ue->frame_tx = ue->frame_rx; + ue->proc.proc_rxtx[0].frame_tx = ue->proc.proc_rxtx[0].frame_rx; + ue->proc.proc_rxtx[1].frame_tx = ue->proc.proc_rxtx[1].frame_rx; #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully mode1_flag %d, tx_ant %d, frame %d, N_RB_DL %d, phich_duration %d, phich_resource %s!\n", ue->Mod_id, frame_parms->mode1_flag, pbch_tx_ant, - ue->frame_rx, + ue->proc.proc_rxtx[0].frame_rx, frame_parms->N_RB_DL, frame_parms->phich_config_common.phich_duration, phich_resource); //frame_parms->phich_config_common.phich_resource); @@ -475,7 +480,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) if (ue->mac_enabled==1) { LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); //mac_resynch(); - mac_xface->dl_phy_sync_success(ue->Mod_id,ue->frame_rx,0,1);//ue->common_vars.eNb_id); + mac_xface->dl_phy_sync_success(ue->Mod_id,ue->proc.proc_rxtx[0].frame_rx,0,1);//ue->common_vars.eNb_id); ue->UE_mode[0] = PRACH; } else { @@ -491,7 +496,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) } LOG_I(PHY,"[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, - ue->frame_rx, + ue->proc.proc_rxtx[0].frame_rx, 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, 10*log10(ue->measurements.rssi), ue->rx_total_gain_dB, @@ -502,7 +507,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) LOG_I(PHY,"[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d\n", ue->Mod_id, - ue->frame_rx, + ue->proc.proc_rxtx[0].frame_rx, duplex_string[ue->frame_parms.frame_type], prefix_string[ue->frame_parms.Ncp], ue->frame_parms.Nid_cell, @@ -513,7 +518,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) LOG_I(PHY,"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, - ue->frame_rx, + ue->proc.proc_rxtx[0].frame_rx, openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, ue->common_vars.freq_offset); diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index 0d0d5832cb..71de66cfc2 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -1055,6 +1055,7 @@ void generate_phich(LTE_DL_FRAME_PARMS *frame_parms, void rx_phich(PHY_VARS_UE *ue, + UE_rxtx_proc_t *proc, uint8_t subframe, uint8_t eNB_id) { @@ -1064,7 +1065,7 @@ void rx_phich(PHY_VARS_UE *ue, LTE_UE_PDCCH **pdcch_vars = ue->pdcch_vars; // uint8_t HI; - uint8_t harq_pid = phich_subframe_to_harq_pid(frame_parms,ue->frame_rx,subframe); + uint8_t harq_pid = phich_subframe_to_harq_pid(frame_parms,proc->frame_rx,subframe); LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id]; int16_t phich_d[24],*phich_d_ptr,HI16; // unsigned int i,aa; @@ -1082,10 +1083,10 @@ void rx_phich(PHY_VARS_UE *ue, uint8_t pusch_subframe; // check if we're expecting a PHICH in this subframe - LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX\n",ue->Mod_id,harq_pid,ue->frame_rx,subframe); + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX\n",ue->Mod_id,harq_pid,proc->frame_rx,subframe); if (ulsch->harq_processes[harq_pid]->status == ACTIVE) { - LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",ue->Mod_id,harq_pid,ue->frame_rx,subframe); + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",ue->Mod_id,harq_pid,proc->frame_rx,subframe); Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48; if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0) @@ -1349,14 +1350,14 @@ void rx_phich(PHY_VARS_UE *ue, if (ue->ulsch_Msg3_active[eNB_id] == 1) { LOG_D(PHY,"[UE %d][PUSCH %d][RAPROC] Frame %d subframe %d Msg3 PHICH, received NAK (%d) nseq %d, ngroup %d\n", ue->Mod_id,harq_pid, - ue->frame_rx, + proc->frame_rx, subframe, HI16, nseq_PHICH, ngroup_PHICH); get_Msg3_alloc_ret(&ue->frame_parms, subframe, - ue->frame_rx, + proc->frame_rx, &ue->ulsch_Msg3_frame[eNB_id], &ue->ulsch_Msg3_subframe[eNB_id]); ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1; @@ -1374,7 +1375,7 @@ void rx_phich(PHY_VARS_UE *ue, //#ifdef DEBUG_PHICH LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received NAK (%d) nseq %d, ngroup %d\n", ue->Mod_id,harq_pid, - ue->frame_rx, + proc->frame_rx, subframe, HI16, nseq_PHICH, @@ -1394,7 +1395,7 @@ void rx_phich(PHY_VARS_UE *ue, if (ue->ulsch_Msg3_active[eNB_id] == 1) { LOG_D(PHY,"[UE %d][PUSCH %d][RAPROC] Frame %d subframe %d Msg3 PHICH, received ACK (%d) nseq %d, ngroup %d\n\n", ue->Mod_id,harq_pid, - ue->frame_rx, + proc->frame_rx, subframe, HI16, nseq_PHICH,ngroup_PHICH); @@ -1402,7 +1403,7 @@ void rx_phich(PHY_VARS_UE *ue, //#ifdef PHICH_DEBUG LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received ACK (%d) nseq %d, ngroup %d\n\n", ue->Mod_id,harq_pid, - ue->frame_rx, + proc->frame_rx, subframe, HI16, nseq_PHICH,ngroup_PHICH); //#endif diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index a175f4cb8e..1653d0e549 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -55,7 +55,7 @@ extern int mac_get_rrc_status(uint8_t Mod_id,uint8_t eNB_flag,uint8_t index); extern openair0_config_t openair0_cfg[]; #endif -int dump_ue_stats(PHY_VARS_UE *ue, char* buffer, int length, runmode_t mode, int input_level_dBm) +int dump_ue_stats(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,char* buffer, int length, runmode_t mode, int input_level_dBm) { uint8_t eNB=0; @@ -78,7 +78,7 @@ int dump_ue_stats(PHY_VARS_UE *ue, char* buffer, int length, runmode_t mode, int /* len += sprintf(&buffer[len], "[UE PROC] Frame count: %d\neNB0 RSSI %d dBm/RE (%d dB, %d dB)\neNB1 RSSI %d dBm/RE (%d dB, %d dB)neNB2 RSSI %d dBm/RE (%d dB, %d dB)\nN0 %d dBm/RE, %f dBm/%dPRB (%d dB, %d dB)\n", - ue->frame_rx, + proc->frame_rx, ue->measurements.rx_rssi_dBm[0], ue->measurements.rx_power_dB[0][0], ue->measurements.rx_power_dB[0][1], @@ -535,7 +535,7 @@ int dump_ue_stats(PHY_VARS_UE *ue, char* buffer, int length, runmode_t mode, int } else { len += sprintf(&buffer[len], "[UE PROC] Frame count: %d, RSSI %3.2f dB (%d dB, %d dB), N0 %3.2f dB (%d dB, %d dB)\n", - ue->frame_rx, + proc->frame_rx, 10*log10(ue->measurements.rssi), ue->measurements.rx_power_dB[0][0], ue->measurements.rx_power_dB[0][1], diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 0afa2936bb..547dd86a9c 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1328,6 +1328,7 @@ int32_t generate_srs_tx(PHY_VARS_UE *phy_vars_ue, */ int32_t generate_drs_pusch(PHY_VARS_UE *phy_vars_ue, + UE_rxtx_proc_t *proc, uint8_t eNB_id, int16_t amp, uint32_t subframe, @@ -1398,7 +1399,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, uint8_t subframe, DCI_format_t dci_format, PHY_VARS_UE *phy_vars_ue, - uint16_t si_rnti, + UE_rxtx_proc_t *proc, + uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, uint16_t cba_rnti, @@ -1406,7 +1408,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, uint8_t use_srs); int32_t generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue, - uint8_t eNB_id); + UE_rxtx_proc_t *proc, + uint8_t eNB_id); double sinr_eff_cqi_calc(PHY_VARS_UE *phy_vars_ue, uint8_t eNB_id); int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB, @@ -1424,16 +1427,13 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB, void dump_ulsch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id); -void dump_dlsch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); -void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); -void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); -void dump_dlsch2(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int round); + int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci); -int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t mode, int input_level_dBm); +int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, UE_rxtx_proc_t *proc, char* buffer, int length, runmode_t mode, int input_level_dBm); int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length); @@ -1550,11 +1550,13 @@ void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, /* \brief This routine demodulates the PHICH and updates PUSCH/ULSCH parameters. @param phy_vars_ue Pointer to UE variables + @param proc Pointer to RXN_TXNp4 proc @param subframe Subframe of received PDCCH/PHICH @param eNB_id Index of eNB */ void rx_phich(PHY_VARS_UE *phy_vars_ue, + UE_rxtx_proc_t *proc, uint8_t subframe, uint8_t eNB_id); @@ -1653,11 +1655,12 @@ void generate_pucch(int32_t **txdataF, uint8_t subframe); void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, + UE_rxtx_proc_t *proc, PUCCH_FMT_t format, uint8_t ncs1, uint8_t *pucch_ack_payload, - uint8_t sr, - uint8_t subframe); + uint8_t sr); + uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index e2876f95e3..cb7803fbfc 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -403,13 +403,16 @@ void generate_pucch(int32_t **txdataF, } void generate_pucch_emul(PHY_VARS_UE *ue, + UE_rxtx_proc_t *proc, PUCCH_FMT_t format, uint8_t ncs1, uint8_t *pucch_payload, - uint8_t sr, - uint8_t subframe) + uint8_t sr) + { + int subframe = proc->subframe_tx; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_flag = format; UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_Ncs1 = ncs1; @@ -428,7 +431,7 @@ void generate_pucch_emul(PHY_VARS_UE *ue, ue->pucch_payload[0] = pucch_payload[0] + (pucch_payload[1]<<1); UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0] + (pucch_payload[1]<<1); } else if (format == pucch_format1) { - LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",ue->Mod_id,ue->frame_tx,subframe,sr); + LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",ue->Mod_id,proc->frame_tx,subframe,sr); } ue->sr[subframe] = sr; diff --git a/openair1/PHY/LTE_TRANSPORT/rar_tools.c b/openair1/PHY/LTE_TRANSPORT/rar_tools.c index dbac1e2280..0cdabe9b9d 100644 --- a/openair1/PHY/LTE_TRANSPORT/rar_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/rar_tools.c @@ -175,6 +175,7 @@ int generate_eNB_ulsch_params_from_rar(unsigned char *rar_pdu, int8_t delta_PUSCH_msg2[8] = {-6,-4,-2,0,2,4,6,8}; int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, + UE_rxtx_proc_t *proc, unsigned char eNB_id ) { @@ -189,13 +190,13 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, // int current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id]; uint8_t *rar = (uint8_t *)(rar_pdu+1); - uint8_t harq_pid = subframe2harq_pid(frame_parms,ue->frame_tx,subframe); + uint8_t harq_pid = subframe2harq_pid(frame_parms,proc->frame_tx,subframe); uint16_t rballoc; uint8_t cqireq; uint16_t *RIV2nb_rb_LUT, *RIV2first_rb_LUT; uint16_t RIV_max = 0; - LOG_D(PHY,"[eNB][RAPROC] Frame %d: generate_ue_ulsch_params_from_rar: subframe %d (harq_pid %d)\n",ue->frame_tx,subframe,harq_pid); + LOG_D(PHY,"[eNB][RAPROC] Frame %d: generate_ue_ulsch_params_from_rar: subframe %d (harq_pid %d)\n",proc->frame_tx,subframe,harq_pid); switch (frame_parms->N_RB_DL) { case 6: @@ -272,7 +273,7 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, ulsch->uci_format = HLC_subband_cqi_nopmi; fill_CQI(ulsch,meas,eNB_id,0,ue->frame_parms.N_RB_DL,0, transmission_mode,ue->sinr_eff); - if (((ue->frame_tx % 100) == 0) || (ue->frame_tx < 10)) + if (((proc->frame_tx % 100) == 0) || (proc->frame_tx < 10)) print_CQI(ulsch->o,ulsch->uci_format,eNB_id,ue->frame_parms.N_RB_DL); } else { ulsch->O_RI = 0; diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 8af3fcf8d1..f3e5e71775 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -509,7 +509,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, float **chest_t_abs; float time[FRAME_LENGTH_COMPLEX_SAMPLES]; float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; - int frame = phy_vars_ue->frame_rx; + int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx; uint32_t total_dlsch_bitrate = phy_vars_ue->bitrate[eNB_id]; int coded_bits_per_codeword = 0; int mcs = 0; diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 0c61fe0bc7..70a661adf0 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -157,11 +157,11 @@ enum transmission_access_mode { SCHEDULED_ACCESS, CBA_ACCESS}; -typedef enum { - eNodeB_3GPP=0, // classical eNodeB function - eNodeB_3GPP_BBU, // classical eNodeB function with transport interface - NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) - NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) +typedef enum { + eNodeB_3GPP=0, // classical eNodeB function + eNodeB_3GPP_BBU, // eNodeB with NGFI IF5 + NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) + NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) } eNB_func_t; typedef struct UE_SCAN_INFO_s { @@ -250,8 +250,58 @@ typedef struct { eNB_rxtx_proc_t proc_rxtx[2]; } eNB_proc_t; -//! \brief Number of eNB TX and RX threads. -//! This number must be equal to the number of LTE subframes (10). Each thread is responsible for a single subframe. + +/// Context data structure for RX/TX portion of subframe processing +typedef struct { + /// Component Carrier index + uint8_t CC_id; + /// timestamp transmitted to HW + openair0_timestamp timestamp_tx; + /// subframe to act upon for transmission + int subframe_tx; + /// subframe to act upon for reception + int subframe_rx; + /// frame to act upon for transmission + int frame_tx; + /// frame to act upon for reception + int frame_rx; + /// \brief Instance count for RXn-TXnp4 processing thread. + /// \internal This variable is protected by \ref mutex_rxtx. + int instance_cnt_rxtx; + /// pthread structure for RXn-TXnp4 processing thread + pthread_t pthread_rxtx; + /// pthread attributes for RXn-TXnp4 processing thread + pthread_attr_t attr_rxtx; + /// condition variable for tx processing thread + pthread_cond_t cond_rxtx; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex_rxtx; + /// scheduling parameters for RXn-TXnp4 thread + struct sched_param sched_param_rxtx; +} UE_rxtx_proc_t; + +/// Context data structure for eNB subframe processing +typedef struct { + /// Component Carrier index + uint8_t CC_id; + /// Last RX timestamp + openair0_timestamp timestamp_rx; + /// \brief Instance count for synch thread. + /// \internal This variable is protected by \ref mutex_synch. + int instance_cnt_synch; + /// pthread attributes for prach processing thread + pthread_attr_t attr_synch; + /// scheduling parameters for synch thread + struct sched_param sched_param_synch; + /// pthread descriptor synch thread + pthread_t pthread_synch; + /// condition variable for UE synch thread; + pthread_cond_t cond_synch; + /// mutex for UE synch thread + pthread_mutex_t mutex_synch; + /// set of scheduling variables RXn-TXnp4 threads + UE_rxtx_proc_t proc_rxtx[2]; +} UE_proc_t; /// Top-level PHY Data Structure for eNB typedef struct PHY_VARS_eNB_s { @@ -491,34 +541,8 @@ typedef struct { int UE_scan_carrier; /// \brief Indicator that UE is synchronized to an eNB int is_synchronized; - /// \brief Instance count of TX processing thread (-1 means ready, 0 means busy) - int instance_cnt_tx; - /// \brief Instance count of RX processing thread (-1 means ready, 0 means busy) - int instance_cnt_rx; - /// \brief Instance count of initial synchronization thread (-1 means ready, 0 means busy). - /// Protected by mutex \ref mutex_synch and condition \ref cond_synch. - int instance_cnt_synch; - /// \brief Condition variable for TX processing thread - pthread_cond_t cond_tx; - /// \brief Condition variable for RX processing thread - pthread_cond_t cond_rx; - /// \brief Condition variable for initial synchronization thread. - /// The corresponding mutex is \ref mutex_synch. - pthread_cond_t cond_synch; - /// \brief Mutex for TX processing thread - pthread_mutex_t mutex_tx; - /// \brief Mutex for RX processing thread - pthread_mutex_t mutex_rx; - /// \brief Mutex for initial synchronization thread. - /// Used to protect \ref instance_cnt_synch. - /// \sa cond_synch - pthread_mutex_t mutex_synch; - /// \brief Pthread structure for RX processing thread - pthread_t thread_rx; - /// \brief Pthread structure for TX processing thread - pthread_t thread_tx; - /// \brief Pthread structure to RX processing thread - pthread_t thread_synch; + /// Data structure for UE process scheduling + UE_proc_t proc; /// \brief Total gain of the TX chain (16-bit baseband I/Q to antenna) uint32_t tx_total_gain_dB; /// \brief Total gain of the RX chain (antenna to baseband I/Q) This is a function of rx_gain_mode (and the corresponding gain) and the rx_gain of the card. @@ -535,10 +559,6 @@ typedef struct { int tx_total_RE; /// \brief Maximum transmit power int8_t tx_power_max_dBm; - /// \brief Frame counters for TX and RX processing - uint32_t frame_rx,frame_tx; - /// \brief Slot counters for TX and RX processing - uint32_t slot_tx,slot_rx; /// \brief Number of eNB seen by UE uint8_t n_connected_eNB; /// \brief indicator that Handover procedure has been initiated @@ -587,10 +607,14 @@ typedef struct { uint32_t high_speed_flag; uint32_t perfect_ce; int16_t ch_est_alpha; + int generate_ul_signal[NUMBER_OF_CONNECTED_eNB_MAX]; + UE_SCAN_INFO_t scan_info[NB_BANDS_MAX]; char ulsch_no_allocation_counter[NUMBER_OF_CONNECTED_eNB_MAX]; + + unsigned char ulsch_Msg3_active[NUMBER_OF_CONNECTED_eNB_MAX]; uint32_t ulsch_Msg3_frame[NUMBER_OF_CONNECTED_eNB_MAX]; unsigned char ulsch_Msg3_subframe[NUMBER_OF_CONNECTED_eNB_MAX]; diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index 62e0a7d9ce..9f0b37ca30 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -72,12 +72,7 @@ enum openair_ERROR { enum openair_SYNCH_STATUS { openair_NOT_SYNCHED=1, -#ifdef OPENAIR_LTE openair_SYNCHED, -#else - openair_SYNCHED_TO_CHSCH, - openair_SYNCHED_TO_MRSCH, -#endif openair_SCHED_EXIT }; @@ -86,65 +81,6 @@ enum openair_SYNCH_STATUS { #define DAQ_AGC_OFF 0 -/* -typedef struct { - boolean_t is_eNB; - uint8_t mode; - uint8_t synch_source; - uint32_t slot_count; - uint32_t sched_cnt; - uint32_t synch_wait_cnt; - uint32_t sync_state; - uint32_t scheduler_interval_ns; - uint32_t last_adac_cnt; - uint8_t first_sync_call; - int32_t instance_cnt; - uint8_t one_shot_get_frame; - uint8_t do_synch; - uint8_t node_configured; // &1..basic config, &3..ue config &5..eNb config - uint8_t node_running; - uint8_t tx_test; - uint8_t mac_registered; - //uint8_t freq; - uint32_t freq; - uint32_t rx_gain_val; - uint32_t rx_gain_mode; - uint32_t tcxo_dac; - uint32_t auto_freq_correction; - int32_t freq_offset; - uint32_t tx_rx_switch_point; - uint32_t manual_timing_advance; /// 1 to override automatic timing advance - int32_t timing_advance; - uint32_t dual_tx; /// 1 for dual-antenna TX, 0 for single-antenna TX - uint32_t tdd; /// 1 for TDD mode, 0 for FDD mode - uint32_t rx_rf_mode; - uint32_t node_id; - uint32_t rach_detection_count; - uint32_t channel_vacant[4]; - uint32_t target_ue_dl_mcs; - uint32_t target_ue_ul_mcs; - uint32_t ue_ul_nb_rb; - uint32_t ue_dl_rb_alloc; - uint32_t dlsch_rate_adaptation; - uint32_t dlsch_transmission_mode; - uint32_t ulsch_allocation_mode; - uint32_t rx_total_gain_dB; - uint32_t hw_frame; - uint32_t get_frame_done; - uint32_t use_ia_receiver; -} OPENAIR_DAQ_VARS; -*/ - -#ifndef USER_MODE -int32_t openair_sched_init(void); -void openair_sched_cleanup(void); -void openair_sched_exit(char *); -void openair1_restart(void); -int32_t init_dlsch_threads(void); -void cleanup_dlsch_threads(void); -#endif //USER_MODE - -#ifdef OPENAIR_LTE /** @addtogroup _PHY_PROCEDURES_ * @{ */ @@ -168,7 +104,7 @@ void phy_procedures_eNB_lte(uint8_t subframe,PHY_VARS_eNB **phy_vars_eNB,uint8_t @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param *phy_vars_rn pointer to RN variables */ -void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); +void phy_procedures_UE_lte(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); #ifdef Rel10 /*! \brief Top-level entry routine for relay node procedures when acting as eNB. This proc will make us of the existing eNB procs. @@ -187,22 +123,24 @@ int phy_procedures_RN_UE_RX(unsigned char last_slot, unsigned char next_slot, re /*! \brief Scheduling for UE TX procedures in normal subframes. @param phy_vars_ue Pointer to UE variables on which to act + @param proc Pointer to RXn-TXnp4 proc information @param eNB_id Local id of eNB on which to act @param abstraction_flag Indicator of PHY abstraction @param mode calib/normal mode @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type); +void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type); /*! \brief Scheduling for UE RX procedures in normal subframes. @param last_slot Index of last slot (0-19) @param phy_vars_ue Pointer to UE variables on which to act + @param proc Pointer to RXn_TXnp4 proc information @param eNB_id Local id of eNB on which to act @param abstraction_flag Indicator of PHY abstraction @param mode calibration/debug mode @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param phy_vars_rn pointer to RN variables */ -int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); +int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); /*! \brief Scheduling for UE TX procedures in TDD S-subframes. @param phy_vars_ue Pointer to UE variables on which to act @@ -385,11 +323,11 @@ uint8_t ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subfram /*! \brief Indicates the SR TXOp in current subframe. Implements Table 10.1-5 from 36.213. @param phy_vars_ue Pointer to UE variables + @param proc Pointer to RXn_TXnp4 thread context @param eNB_id ID of eNB which is to receive the SR - @param subframe index of next subframe @returns 1 if TXOp is active. */ -uint8_t is_SR_TXOp(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); +uint8_t is_SR_TXOp(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id); /*! \brief Indicates the SR TXOp in current subframe for eNB and particular UE index. Implements Table 10.1-5 from 36.213. @param phy_vars_eNB Pointer to eNB variables @@ -426,7 +364,7 @@ int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB); int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rnti); void process_timing_advance(module_id_t Mod_id,uint8_t CC_id,int16_t timing_advance); -void process_timing_advance_rar(PHY_VARS_UE *phy_vars_ue,uint16_t timing_advance); +void process_timing_advance_rar(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint16_t timing_advance); unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb); @@ -436,15 +374,15 @@ void phy_reset_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); subframe n-4 which is acknowledged in subframe n (for FDD) according to n1_pucch = Ncce + N1_pucch. For TDD, this routine computes the complex procedure described in Section 10.1 of 36.213 (through tables 10.1-1,10.1-2) @param phy_vars_ue Pointer to UE variables +@param proc Pointer to RXn-TXnp4 proc information @param eNB_id Index of eNB -@param subframe subframe on which to act @param b Pointer to PUCCH payload (b[0],b[1]) @param SR 1 means there's a positive SR in parallel to ACK/NAK @returns n1_pucch */ uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue, + UE_rxtx_proc_t *proc, uint8_t eNB_id, - uint8_t subframe, uint8_t *b, uint8_t SR); @@ -497,21 +435,21 @@ UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); /*! \brief This function implements the power control mechanism for PUCCH from 36.213. @param phy_vars_ue PHY variables - @param subframe Index of subframe + @param proc Pointer to proc descriptor @param eNB_id Index of eNB @param pucch_fmt Format of PUCCH that is being transmitted @returns Transmit power */ -int8_t pucch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id,PUCCH_FMT_t pucch_fmt); +int8_t pucch_power_cntl(PHY_VARS_UE *phy_vars_ue, UE_rxtx_proc_t *proc,uint8_t eNB_id,PUCCH_FMT_t pucch_fmt); /*! \brief This function implements the power control mechanism for PUCCH from 36.213. @param phy_vars_ue PHY variables - @param subframe Index of subframe + @param proc Pointer to proc descriptor @param eNB_id Index of eNB @param j index of type of PUSCH (SPS, Normal, Msg3) @returns Transmit power */ -void pusch_power_cntl(PHY_VARS_UE *phy_vars_ue,uint8_t subframe,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag); +void pusch_power_cntl(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag); int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index); @@ -543,15 +481,13 @@ int16_t get_target_pucch_rx_power(module_id_t module_idP, uint8_t CC_id); int get_ue_active_harq_pid(uint8_t Mod_id,uint8_t CC_id,uint16_t rnti,int frame, uint8_t subframe,uint8_t *harq_pid,uint8_t *round,uint8_t ul_flag); -void dump_dlsch(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); -void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); -void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe); +void dump_dlsch(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid); +void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe); +void dump_dlsch_ra(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe); +void dump_dlsch2(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int round); /*@}*/ -#endif //OPENAIR_LTE - -extern int slot_irq_handler(int irq, void *cookie); #endif diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index c80fdd0e40..b74a79f148 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -25,7 +25,7 @@ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - *******************************************************************************/ +*******************************************************************************/ /*! \file phy_procedures_lte_ue.c * \brief Implementation of UE procedures from 36.213 LTE specifications @@ -49,14 +49,6 @@ #include "SCHED/phy_procedures_emos.h" #endif -#ifdef EXMIMO -#ifdef DRIVER2013 -#include "openair0_lib.h" -#include "gain_control.h" -extern int card; -#endif -#endif - #define DEBUG_PHY_PROC #ifndef PUCCH @@ -75,9 +67,6 @@ fifo_dump_emos_UE emos_dump_UE; #if defined(ENABLE_ITTI) # include "intertask_interface.h" -# if ENABLE_RAL -# include "timer.h" -# endif #endif @@ -91,24 +80,8 @@ extern int oai_exit; uint8_t ulsch_input_buffer[2700] __attribute__ ((aligned(16))); uint8_t access_mode; -#ifdef DLSCH_THREAD -extern int dlsch_instance_cnt[8]; -extern int dlsch_subframe[8]; -extern pthread_mutex_t dlsch_mutex[8]; -/// Condition variable for dlsch thread -extern pthread_cond_t dlsch_cond[8]; -extern int rx_pdsch_instance_cnt; -extern int rx_pdsch_slot; -extern pthread_mutex_t rx_pdsch_mutex; -/// Condition variable for rx_pdsch thread -extern pthread_cond_t rx_pdsch_cond; -#endif - DCI_ALLOC_t dci_alloc_rx[8]; -#ifdef DIAG_PHY -extern int rx_sig_fifo; -#endif #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) @@ -117,7 +90,7 @@ extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; -void dump_dlsch(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid) +void dump_dlsch(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid) { unsigned int coded_bits_per_codeword; uint8_t nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; @@ -128,7 +101,7 @@ void dump_dlsch(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm, ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - ue->frame_rx,subframe); + proc->frame_rx,subframe); write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1); write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1); @@ -146,7 +119,7 @@ void dump_dlsch(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars[0]->dl_ch_magb0,300*12,1,1); } -void dump_dlsch_SI(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) +void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe) { unsigned int coded_bits_per_codeword; uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); @@ -157,7 +130,7 @@ void dump_dlsch_SI(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) 2, 1, ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - ue->frame_rx,subframe); + proc->frame_rx,subframe); LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", ue->Mod_id, ue->frame_parms.ofdm_symbol_size, @@ -190,43 +163,43 @@ void dump_dlsch_SI(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) //unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162}; /* -unsigned int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL) -{ + unsigned int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL) + { int gain_dB = power_dBm - power_max_dBm; int amp_x_100; switch (N_RB_UL) { case 6: - amp_x_100 = AMP; // PRACH is 6 PRBS so no scale - break; + amp_x_100 = AMP; // PRACH is 6 PRBS so no scale + break; case 15: - amp_x_100 = 158*AMP; // 158 = 100*sqrt(15/6) - break; + amp_x_100 = 158*AMP; // 158 = 100*sqrt(15/6) + break; case 25: - amp_x_100 = 204*AMP; // 204 = 100*sqrt(25/6) - break; + amp_x_100 = 204*AMP; // 204 = 100*sqrt(25/6) + break; case 50: - amp_x_100 = 286*AMP; // 286 = 100*sqrt(50/6) - break; + amp_x_100 = 286*AMP; // 286 = 100*sqrt(50/6) + break; case 75: - amp_x_100 = 354*AMP; // 354 = 100*sqrt(75/6) - break; + amp_x_100 = 354*AMP; // 354 = 100*sqrt(75/6) + break; case 100: - amp_x_100 = 408*AMP; // 408 = 100*sqrt(100/6) - break; + amp_x_100 = 408*AMP; // 408 = 100*sqrt(100/6) + break; default: - LOG_E(PHY,"Unknown PRB size %d\n",N_RB_UL); - mac_xface->macphy_exit(""); - break; + LOG_E(PHY,"Unknown PRB size %d\n",N_RB_UL); + mac_xface->macphy_exit(""); + break; } if (gain_dB < -30) { - return(amp_x_100/3162); + return(amp_x_100/3162); } else if (gain_dB>0) - return(amp_x_100); + return(amp_x_100); else - return(amp_x_100/gain_table[-gain_dB]); // 245 corresponds to the factor sqrt(25/6) -} + return(amp_x_100/gain_table[-gain_dB]); // 245 corresponds to the factor sqrt(25/6) + } */ unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb) @@ -251,7 +224,7 @@ unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb #endif -void dump_dlsch_ra(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) +void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe) { unsigned int coded_bits_per_codeword; uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); @@ -262,7 +235,7 @@ void dump_dlsch_ra(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) 2, 1, ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - ue->frame_rx,subframe); + proc->frame_rx,subframe); LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", ue->Mod_id, ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, @@ -329,7 +302,7 @@ void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) // if contention resolution fails, go back to PRACH PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PRACH; - LOG_E(PHY,"[UE %d] Frame %d Random-access procedure fails, going back to PRACH, setting SIStatus = 0 and State RRC_IDLE\n",Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx); + LOG_E(PHY,"[UE %d] Random-access procedure fails, going back to PRACH, setting SIStatus = 0 and State RRC_IDLE\n",Mod_id); //mac_xface->macphy_exit(""); } @@ -338,7 +311,7 @@ void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) int i; - LOG_I(PHY,"[UE %d][RAPROC] Frame %d Random-access procedure succeeded\n",Mod_id,PHY_vars_UE_g[Mod_id][CC_id]->frame_rx); + LOG_I(PHY,"[UE %d][RAPROC] Random-access procedure succeeded\n",Mod_id); PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0; PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH; @@ -359,19 +332,13 @@ UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index]); } -void process_timing_advance_rar(PHY_VARS_UE *ue,uint16_t timing_advance) -{ - - /* - if ((timing_advance>>10) & 1) //it is negative - timing_advance = timing_advance - (1<<11); - */ +void process_timing_advance_rar(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint16_t timing_advance) { ue->timing_advance = timing_advance*4; #ifdef DEBUG_PHY_PROC - LOG_I(PHY,"[UE %d] Frame %d, received (rar) timing_advance %d, HW timing advance %d\n",ue->Mod_id,ue->frame_rx, ue->timing_advance); + LOG_I(PHY,"[UE %d] Frame %d, received (rar) timing_advance %d, HW timing advance %d\n",ue->Mod_id,proc->frame_rx, ue->timing_advance); #endif } @@ -392,11 +359,13 @@ void process_timing_advance(uint8_t Mod_id,uint8_t CC_id,int16_t timing_advance) } -uint8_t is_SR_TXOp(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) +uint8_t is_SR_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) { + int subframe=proc->subframe_tx; + LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Checking for SR TXOp (sr_ConfigIndex %d)\n", - ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,ue->frame_tx,subframe, + ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,proc->frame_tx,subframe, ue->scheduling_request_config[eNB_id].sr_ConfigIndex); if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 4) { // 5 ms SR period @@ -406,13 +375,13 @@ uint8_t is_SR_TXOp(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) if (subframe==(ue->scheduling_request_config[eNB_id].sr_ConfigIndex-5)) return(1); } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period - if ((10*(ue->frame_tx&1)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15)) + if ((10*(proc->frame_tx&1)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15)) return(1); } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period - if ((10*(ue->frame_tx&3)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35)) + if ((10*(proc->frame_tx&3)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35)) return(1); } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period - if ((10*(ue->frame_tx&7)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75)) + if ((10*(proc->frame_tx&7)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75)) return(1); } @@ -420,8 +389,8 @@ uint8_t is_SR_TXOp(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe) } uint16_t get_n1_pucch(PHY_VARS_UE *ue, + UE_rxtx_proc_t *proc, uint8_t eNB_id, - uint8_t subframe, uint8_t *b, uint8_t SR) { @@ -434,6 +403,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, int sf; int M; // clear this, important for case where n1_pucch selection is not used + int subframe=proc->subframe_tx; ue->pucch_sel[subframe] = 0; @@ -451,10 +421,10 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, #ifdef DEBUG_PHY_PROC if (bundling_flag==bundling) { - LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,ue->frame_tx,subframe,SR, + LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR, ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } else { - LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,ue->frame_tx,subframe,SR, + LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR, ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); } @@ -479,7 +449,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, subframe_offset = 4; } else { LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", - ue->Mod_id,ue->frame_tx,subframe,frame_parms->tdd_config); + ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config); return(0); } @@ -589,858 +559,848 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, } // switch tdd_config } - LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n",ue->frame_tx); + LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n",proc->frame_tx); return(-1); } #ifdef EMOS /* -void phy_procedures_emos_UE_TX(uint8_t next_slot,uint8_t eNB_id) { + void phy_procedures_emos_UE_TX(uint8_t next_slot,uint8_t eNB_id) { uint8_t harq_pid; if (next_slot%2==0) { - // get harq_pid from subframe relationship - harq_pid = subframe2harq_pid(&ue->frame_parms,ue->frame,(next_slot>>1)); - if (harq_pid==255) { - LOG_E(PHY,"[UE%d] Frame %d : FATAL ERROR: illegal harq_pid, returning\n", - 0,ue->frame); - return; - } + // get harq_pid from subframe relationship + harq_pid = subframe2harq_pid(&ue->frame_parms,ue->frame,(next_slot>>1)); + if (harq_pid==255) { + LOG_E(PHY,"[UE%d] Frame %d : FATAL ERROR: illegal harq_pid, returning\n", + 0,ue->frame); + return; + } - if (ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { - emos_dump_UE.uci_cnt[next_slot>>1] = 1; - memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o,ulsch[eNB_id]->o,MAX_CQI_BITS*sizeof(char)); - emos_dump_UE.UCI_data[0][next_slot>>1].O = ulsch[eNB_id]->O; - memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_RI,ulsch[eNB_id]->o_RI,2*sizeof(char)); - emos_dump_UE.UCI_data[0][next_slot>>1].O_RI = ulsch[eNB_id]->O_RI; - memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_ACK,ulsch[eNB_id]->o_ACK,4*sizeof(char)); - emos_dump_UE.UCI_data[0][next_slot>>1].O_ACK = ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK; - } - else { - emos_dump_UE.uci_cnt[next_slot>>1] = 0; - } + if (ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { + emos_dump_UE.uci_cnt[next_slot>>1] = 1; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o,ulsch[eNB_id]->o,MAX_CQI_BITS*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O = ulsch[eNB_id]->O; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_RI,ulsch[eNB_id]->o_RI,2*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O_RI = ulsch[eNB_id]->O_RI; + memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_ACK,ulsch[eNB_id]->o_ACK,4*sizeof(char)); + emos_dump_UE.UCI_data[0][next_slot>>1].O_ACK = ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK; + } + else { + emos_dump_UE.uci_cnt[next_slot>>1] = 0; + } + } } -} */ #endif -int dummy_tx_buffer[3840*4] __attribute__((aligned(16))); -PRACH_RESOURCES_t prach_resources_local; +void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc) { -void phy_procedures_UE_TX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) -{ + int aa; + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + int k,l; + int nsymb; + int subframe_tx = proc->subframe_tx; + int frame_tx = proc->frame_tx; + int ulsch_start; + int overflow=0; - int i; - uint16_t first_rb, nb_rb; - uint8_t harq_pid; - unsigned int input_buffer_length; - unsigned int aa; + int dummy_tx_buffer[3840*4] __attribute__((aligned(16))); + + start_meas(&ue->ofdm_mod_stats); + nsymb = (frame_parms->Ncp == 0) ? 14 : 12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case + ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- + ue->hw_timing_advance- + ue->timing_advance- + ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); +#else //this is the normal case + ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance; +#endif //else EXMIMO + if ((frame_tx%100) == 0) + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: ulsch_start = %d (rxoff %d, HW TA %d, timing advance %d, TA_offset %d\n", + ue->Mod_id,frame_tx,subframe_tx, + ulsch_start, + ue->rx_offset, + ue->hw_timing_advance, + ue->timing_advance, + ue->N_TA_offset); + + + for (aa=0; aanb_antennas_tx; aa++) { + if (frame_parms->Ncp == 1) + PHY_ofdm_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + dummy_tx_buffer, +#else + &ue->common_vars.txdata[aa][ulsch_start], +#endif + frame_parms->ofdm_symbol_size, + nsymb, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + else + normal_prefix_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + dummy_tx_buffer, +#else + &ue->common_vars.txdata[aa][ulsch_start], +#endif + nsymb, + &ue->frame_parms); + + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + apply_7_5_kHz(ue,dummy_tx_buffer,0); + apply_7_5_kHz(ue,dummy_tx_buffer,1); +#else + apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0); + apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1); +#endif + + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + overflow = ulsch_start - 9*frame_parms->samples_per_tti; + + + for (k=ulsch_start,l=0; ksamples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti); k++,l++) { + ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; + } + + for (k=0; kcommon_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; + ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; + } +#if defined(EXMIMO) + // handle switch before 1st TX subframe, guarantee that the slot prior to transmission is switch on + for (k=ulsch_start - (frame_parms->samples_per_tti>>1) ; kcommon_vars.txdata[aa][k+frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + else if (k>(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) + ue->common_vars.txdata[aa][k-frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; + else + ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE; + } +#endif +#endif + + } //nb_antennas_tx + + stop_meas(&ue->ofdm_mod_stats); + + + +} + +void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode) { + + int frame_tx = proc->frame_tx; + int subframe_tx = proc->subframe_tx; + int prach_power; + PRACH_RESOURCES_t prach_resources_local; + + ue->generate_prach=0; + + if (ue->mac_enabled==0){ + ue->prach_resources[eNB_id] = &prach_resources_local; + prach_resources_local.ra_RNTI = 0xbeef; + prach_resources_local.ra_PreambleIndex = 0; + } + + if (ue->mac_enabled==1){ + // ask L2 for RACH transport + if ((mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) && (mode != no_L2_connect) ) { + ue->prach_resources[eNB_id] = mac_xface->ue_get_rach(ue->Mod_id, + ue->CC_id, + frame_tx, + eNB_id, + subframe_tx); + // LOG_I(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[Mod_id].radioResourceConfigCommon); + } + } + + if (ue->prach_resources[eNB_id]!=NULL) { + + ue->generate_prach=1; + ue->prach_cnt=0; +#ifdef SMBV + ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; +#endif +#ifdef OAI_EMU + ue->prach_PreambleIndex=ue->prach_resources[eNB_id]->ra_PreambleIndex; +#endif + + if (abstraction_flag == 0) { + LOG_I(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d : Generating PRACH, preamble %d, TARGET_RECEIVED_POWER %d dBm, PRACH TDD Resource index %d, RA-RNTI %d\n", + ue->Mod_id, + frame_tx, + subframe_tx, + ue->prach_resources[eNB_id]->ra_PreambleIndex, + ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER, + ue->prach_resources[eNB_id]->ra_TDD_map_index, + ue->prach_resources[eNB_id]->ra_RNTI); + + if ((ue->mac_enabled==1) && (mode != calib_prach_tx)) { + ue->tx_power_dBm = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id); + } + else { + ue->tx_power_dBm = ue->tx_power_max_dBm; + ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; + } + + ue->tx_total_RE = 96; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + 6); +#else + ue->prach_vars[eNB_id]->amp = AMP; +#endif + if ((mode == calib_prach_tx) && (((proc->frame_tx&0xfffe)%100)==0)) + LOG_D(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d : PRACH TX power %d dBm, amp %d\n", + ue->Mod_id, + proc->frame_rx, + proc->subframe_tx, + ue->tx_power_dBm, + ue->prach_vars[eNB_id]->amp); + + + // start_meas(&ue->tx_prach); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN); + prach_power = generate_prach(ue,eNB_id,subframe_tx,frame_tx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_OUT); + // stop_meas(&ue->tx_prach); + LOG_D(PHY,"[UE %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n", + ue->Mod_id, + get_PL(ue->Mod_id,ue->CC_id,eNB_id), + ue->tx_power_dBm, + dB_fixed(prach_power), + ue->prach_vars[eNB_id]->amp); + } else { + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_flag=1; + UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_id=ue->prach_resources[eNB_id]->ra_PreambleIndex; + if (ue->mac_enabled==1){ + mac_xface->Msg1_transmitted(ue->Mod_id, + ue->CC_id, + frame_tx, + eNB_id); + } + } + + LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Generating PRACH (eNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB), l3msg \n", + ue->Mod_id,frame_tx,subframe_tx,eNB_id, + ue->prach_resources[eNB_id]->ra_PreambleIndex, + ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id), + get_PL(ue->Mod_id,ue->CC_id,eNB_id)); + + } + + + // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue + if (mode == calib_prach_tx) + ue->prach_resources[eNB_id]=NULL; + + LOG_D(PHY,"[UE %d] frame %d subframe %d : generate_prach %d, prach_cnt %d\n", + ue->Mod_id,frame_tx,subframe_tx,ue->generate_prach,ue->prach_cnt); + + ue->prach_cnt++; + + if (ue->prach_cnt==3) + ue->generate_prach=0; +} + +void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { + + int harq_pid; + int frame_tx=proc->frame_tx; + int subframe_tx=proc->subframe_tx; + int Mod_id = ue->Mod_id; + int CC_id = ue->CC_id; uint8_t Msg3_flag=0; + uint8_t ack_status=0; + uint16_t first_rb, nb_rb; + unsigned int input_buffer_length; + int i; + int aa; + int tx_amp; + + // get harq_pid from subframe relationship + harq_pid = subframe2harq_pid(&ue->frame_parms, + frame_tx, + subframe_tx); + + + if (ue->mac_enabled == 1) { + if ((ue->ulsch_Msg3_active[eNB_id] == 1) && + (ue->ulsch_Msg3_frame[eNB_id] == frame_tx) && + (ue->ulsch_Msg3_subframe[eNB_id] == subframe_tx)) { // Initial Transmission of Msg3 + + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) + generate_ue_ulsch_params_from_rar(ue, + proc, + eNB_id); + + ue->ulsch[eNB_id]->power_offset = 14; + LOG_D(PHY,"[UE %d][RAPROC] Frame %d: Setting Msg3_flag in subframe %d, for harq_pid %d\n", + Mod_id, + frame_tx, + subframe_tx, + harq_pid); + Msg3_flag = 1; + } else { + + if (harq_pid==255) { + LOG_E(PHY,"[UE%d] Frame %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n", + Mod_id,frame_tx); + mac_xface->macphy_exit("Error in ulsch_decoding"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); + stop_meas(&ue->phy_proc_tx); + return; + } + + Msg3_flag=0; + } + } + + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { + + ue->generate_ul_signal[eNB_id] = 1; + + // deactivate service request + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; + + ack_status = get_ack(&ue->frame_parms, + ue->dlsch[eNB_id][0]->harq_ack, + subframe_tx, + ue->ulsch[eNB_id]->o_ACK); + + first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; + nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; + + + + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY, + "[UE %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d\n", + Mod_id,harq_pid,frame_tx,subframe_tx, + first_rb,nb_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, + (ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift+ + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2+ + ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe_tx<<1])%12, + ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2, + ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe_tx<<1], + ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); +#endif + + if (ack_status > 0) { + LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n", + Mod_id, + ue->ulsch[eNB_id]->rnti, + frame_tx,subframe_tx, + ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], + ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); + } + + + + + + if (Msg3_flag == 1) { + LOG_I(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d Generating (RRCConnectionRequest) Msg3 (nb_rb %d, first_rb %d, round %d, rvidx %d) Msg3: %x.%x.%x|%x.%x.%x.%x.%x.%x\n",Mod_id,frame_tx, + subframe_tx, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, + ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, + ue->prach_resources[eNB_id]->Msg3[0], + ue->prach_resources[eNB_id]->Msg3[1], + ue->prach_resources[eNB_id]->Msg3[2], + ue->prach_resources[eNB_id]->Msg3[3], + ue->prach_resources[eNB_id]->Msg3[4], + ue->prach_resources[eNB_id]->Msg3[5], + ue->prach_resources[eNB_id]->Msg3[6], + ue->prach_resources[eNB_id]->Msg3[7], + ue->prach_resources[eNB_id]->Msg3[8]); + + start_meas(&ue->ulsch_encoding_stats); + + if (abstraction_flag==0) { + if (ulsch_encoding(ue->prach_resources[eNB_id]->Msg3, + ue, + harq_pid, + eNB_id, + ue->transmission_mode[eNB_id],0,0)!=0) { + LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); + mac_xface->macphy_exit("Error in ulsch_coding"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); + stop_meas(&ue->phy_proc_tx); + return; + } + } + +#ifdef PHY_ABSTRACTION + else { + ulsch_encoding_emul(ue->prach_resources[eNB_id]->Msg3,ue,eNB_id,harq_pid,0); + } + +#endif + + stop_meas(&ue->ulsch_encoding_stats); + + if (ue->mac_enabled == 1) { + // signal MAC that Msg3 was sent + mac_xface->Msg3_transmitted(Mod_id, + CC_id, + frame_tx, + eNB_id); + } + } // Msg3_flag==1 + else { + input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; + + if (ue->mac_enabled==1) { + // LOG_D(PHY,"[UE %d] ULSCH : Searching for MAC SDUs\n",Mod_id); + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) { + //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { + access_mode=SCHEDULED_ACCESS; + mac_xface->ue_get_sdu(Mod_id, + CC_id, + frame_tx, + subframe_tx, + eNB_id, + ulsch_input_buffer, + input_buffer_length, + &access_mode); + } + +#ifdef DEBUG_PHY_PROC +#ifdef DEBUG_ULSCH + LOG_D(PHY,"[UE] Frame %d, subframe %d : ULSCH SDU (TX harq_pid %d) (%d bytes) : \n",frame_tx,subframe_tx,harq_pid, ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3); + + for (i=0; iulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3; i++) + LOG_T(PHY,"%x.",ulsch_input_buffer[i]); + + LOG_T(PHY,"\n"); +#endif +#endif + } + else { + unsigned int taus(void); + + for (i=0; iulsch_encoding_stats); + + if (abstraction_flag==0) { + + if (ulsch_encoding(ulsch_input_buffer, + ue, + harq_pid, + eNB_id, + ue->transmission_mode[eNB_id],0, + 0)!=0) { // Nbundled, to be updated!!!! + LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); + stop_meas(&ue->phy_proc_tx); + return; + } + } + +#ifdef PHY_ABSTRACTION + else { + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); + } + +#endif + stop_meas(&ue->ulsch_encoding_stats); + } + + if (abstraction_flag == 0) { + if (ue->mac_enabled==1) { + pusch_power_cntl(ue,proc,eNB_id,1, abstraction_flag); + ue->tx_power_dBm = ue->ulsch[eNB_id]->Po_PUSCH; + } + else { + ue->tx_power_dBm = ue->tx_power_max_dBm; + } + ue->tx_total_RE = nb_rb*12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + tx_amp = get_tx_amp(ue->tx_power_dBm, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + nb_rb); +#else + tx_amp = AMP; +#endif + LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", + Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm,ue->tx_power_max_dBm, tx_amp); + start_meas(&ue->ulsch_modulation_stats); + ulsch_modulation(ue->common_vars.txdataF, + tx_amp, + frame_tx, + subframe_tx, + &ue->frame_parms, + ue->ulsch[eNB_id]); + for (aa=0; aa<1/*frame_parms->nb_antennas_tx*/; aa++) + generate_drs_pusch(ue, + proc, + eNB_id, + tx_amp, + subframe_tx, + first_rb, + nb_rb, + aa); + + stop_meas(&ue->ulsch_modulation_stats); + } + + if (abstraction_flag==1) { + // clear SR + ue->sr[subframe_tx]=0; + } + } // subframe_scheduling_flag==1 +} + + +void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { + + uint8_t pucch_ack_payload[2]; uint8_t n1_pucch; ANFBmode_t bundling_flag; PUCCH_FMT_t format; uint8_t SR_payload; - int32_t prach_power; - uint8_t nsymb; - LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - uint8_t generate_ul_signal = 0; - uint8_t ack_status=0; - int8_t Po_PUCCH; - int32_t ulsch_start=0; -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - int overflow=0; - int k,l; -#endif - int slot_tx = ue->slot_tx; - int subframe_tx = ue->slot_tx>>1; - int frame_tx = ue->frame_tx; + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int frame_tx=proc->frame_tx; + int subframe_tx=proc->subframe_tx; int Mod_id = ue->Mod_id; int CC_id = ue->CC_id; int tx_amp; + int8_t Po_PUCCH; + + bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; + + if ((frame_parms->frame_type==FDD) || + (bundling_flag==bundling) || + ((frame_parms->frame_type==TDD)&&(frame_parms->tdd_config==1)&&((subframe_tx!=2)||(subframe_tx!=7)))) { + format = pucch_format1a; + LOG_D(PHY,"[UE] PUCCH 1a\n"); + } else { + format = pucch_format1b; + LOG_D(PHY,"[UE] PUCCH 1b\n"); + } + + // Check for SR and do ACK/NACK accordingly + if (is_SR_TXOp(ue,proc,eNB_id)==1) { + LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d: got SR_TXOp, Checking for SR for PUSCH from MAC\n", + Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx); + + if (ue->mac_enabled==1) { + SR_payload = mac_xface->ue_get_SR(Mod_id, + CC_id, + frame_tx, + eNB_id, + ue->pdcch_vars[eNB_id]->crnti, + subframe_tx); // subframe used for meas gap + } + else { + SR_payload = 1; + } + + if (SR_payload>0) { + ue->generate_ul_signal[eNB_id] = 1; + LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d got the SR for PUSCH is %d\n", + Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx,SR_payload); + } else { + ue->sr[subframe_tx]=0; + } + } else { + SR_payload=0; + } + + if (get_ack(&ue->frame_parms, + ue->dlsch[eNB_id][0]->harq_ack, + subframe_tx,pucch_ack_payload) > 0) { + // we need to transmit ACK/NAK in this subframe + + ue->generate_ul_signal[eNB_id] = 1; + + n1_pucch = get_n1_pucch(ue, + proc, + eNB_id, + pucch_ack_payload, + SR_payload); + + if (ue->mac_enabled == 1) { + Po_PUCCH = pucch_power_cntl(ue,proc,eNB_id,format); + } + else { + Po_PUCCH = ue->tx_power_max_dBm; + } + ue->tx_power_dBm = Po_PUCCH; + ue->tx_total_RE = 12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + tx_amp = get_tx_amp(Po_PUCCH, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + 1); +#else + tx_amp = AMP; +#endif + + if (SR_payload>0) { + LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), n1_pucch %d, Po_PUCCH, amp %d\n", + Mod_id, + ue->dlsch[eNB_id][0]->rnti, + frame_tx, subframe_tx, + pucch_ack_payload[0],pucch_ack_payload[1], + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + Po_PUCCH, + tx_amp); + } else { + LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n", + Mod_id, + ue->dlsch[eNB_id][0]->rnti, + frame_tx, subframe_tx, + n1_pucch,pucch_ack_payload[0],pucch_ack_payload[1],SR_payload, + Po_PUCCH, + tx_amp); + } + + if (abstraction_flag == 0) { + + generate_pucch(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, + format, + &ue->pucch_config_dedicated[eNB_id], + n1_pucch, + 0, // n2_pucch + 1, // shortened format + pucch_ack_payload, + tx_amp, + subframe_tx); + + } else { +#ifdef PHY_ABSTRACTION + LOG_D(PHY,"Calling generate_pucch_emul ... (ACK %d %d, SR %d)\n",pucch_ack_payload[0],pucch_ack_payload[1],SR_payload); + generate_pucch_emul(ue, + proc, + format, + ue->frame_parms.pucch_config_common.nCS_AN, + pucch_ack_payload, + SR_payload, + subframe_tx); +#endif + } + } else if (SR_payload==1) { // no ACK/NAK but SR is triggered by MAC + + if (ue->mac_enabled == 1) { + Po_PUCCH = pucch_power_cntl(ue,proc,eNB_id,pucch_format1); + } + else { + Po_PUCCH = ue->tx_power_max_dBm; + } + ue->tx_power_dBm = Po_PUCCH; + ue->tx_total_RE = 12; + +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + tx_amp = get_tx_amp(Po_PUCCH, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + 1); +#else + tx_amp = AMP; +#endif + LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1 (SR for PUSCH), n1_pucch %d, Po_PUCCH %d\n", + Mod_id, + ue->dlsch[eNB_id][0]->rnti, + frame_tx, subframe_tx, + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + Po_PUCCH); + + if (abstraction_flag == 0) { + + generate_pucch(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, + pucch_format1, + &ue->pucch_config_dedicated[eNB_id], + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + 0, // n2_pucch + 1, // shortened format + pucch_ack_payload, // this is ignored anyway, we just need a pointer + tx_amp, + subframe_tx); + } else { + LOG_D(PHY,"Calling generate_pucch_emul ...\n"); + generate_pucch_emul(ue, + proc, + pucch_format1, + ue->frame_parms.pucch_config_common.nCS_AN, + pucch_ack_payload, + SR_payload); + + } + } // SR_Payload==1 +} + +void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) { + + + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + int32_t ulsch_start=0; + int subframe_tx = proc->subframe_tx; + int frame_tx = proc->frame_tx; + unsigned int aa; + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); + ue->generate_ul_signal[eNB_id] = 0; + start_meas(&ue->phy_proc_tx); #ifdef EMOS //phy_procedures_emos_UE_TX(next_slot); #endif - if ((slot_tx%2)==0) { - ue->tx_power_dBm=-127; - - if (abstraction_flag==0) { - for (aa=0; aanb_antennas_tx; aa++) { - memset(&ue->common_vars.txdataF[aa][subframe_tx*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti], - 0, - frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*sizeof(int32_t)); - } + ue->tx_power_dBm=-127; + + if (abstraction_flag==0) { + for (aa=0; aanb_antennas_tx; aa++) { + memset(&ue->common_vars.txdataF[aa][subframe_tx*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti], + 0, + frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*sizeof(int32_t)); } + } + + if (ue->UE_mode[eNB_id] != PRACH) { - if (ue->UE_mode[eNB_id] != PRACH) { - /* - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d: Generating SRS\n",Mod_id,ue->frame,slot_tx); - #endif - if (abstraction_flag == 0) { - #ifdef OFDMA_ULSCH - generate_srs_tx(ue,eNB_id,AMP,subframe_tx); - #else - generate_srs_tx(ue,eNB_id,AMP,subframe_tx); - #endif - } + ue_ulsch_uespec_procedures(ue,proc,eNB_id,abstraction_flag); - #ifdef PHY_ABSTRACTION - else { - generate_srs_tx_emul(ue,subframe_tx); - } - #endif - */ - // get harq_pid from subframe relationship - harq_pid = subframe2harq_pid(&ue->frame_parms, - frame_tx, - subframe_tx); - - - if (ue->mac_enabled == 1) { - if ((ue->ulsch_Msg3_active[eNB_id] == 1) && - (ue->ulsch_Msg3_frame[eNB_id] == frame_tx) && - (ue->ulsch_Msg3_subframe[eNB_id] == subframe_tx)) { // Initial Transmission of Msg3 - - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; - - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) - generate_ue_ulsch_params_from_rar(ue, - eNB_id); - - ue->ulsch[eNB_id]->power_offset = 14; - LOG_D(PHY,"[UE %d][RAPROC] Frame %d: Setting Msg3_flag in subframe %d, for harq_pid %d\n", - Mod_id, - frame_tx, - subframe_tx, - harq_pid); - Msg3_flag = 1; - } else { - - if (harq_pid==255) { - LOG_E(PHY,"[UE%d] Frame %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n", - Mod_id,frame_tx); - mac_xface->macphy_exit("Error in ulsch_decoding"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); - stop_meas(&ue->phy_proc_tx); - return; - } - - Msg3_flag=0; - } - } - - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { - - generate_ul_signal = 1; - - // deactivate service request - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; - - ack_status = get_ack(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_ack, - subframe_tx, - ue->ulsch[eNB_id]->o_ACK); - - first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; - nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; - - - //frame_parms->pusch_config_c ommon.ul_ReferenceSignalsPUSCH.cyclicShift = 0; - - //frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[20] = 0; - - - -#ifdef DEBUG_PHY_PROC - LOG_D(PHY, - "[UE %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d\n", - Mod_id,harq_pid,frame_tx,subframe_tx, - first_rb,nb_rb, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, - (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift+ - ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2+ - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[slot_tx])%12, - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2, - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[slot_tx], - ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], - ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); -#endif - - if (ack_status > 0) { - LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n", - Mod_id, - ue->ulsch[eNB_id]->rnti, - frame_tx,subframe_tx, - ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], - ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); - } - - - - - - //#ifdef DEBUG_PHY_PROC - // debug_LOG_D(PHY,"[UE %d] Frame %d, Subframe %d ulsch harq_pid %d : O %d, O_ACK %d, O_RI %d, TBS %d\n",Mod_id,ue->frame,subframe_tx,harq_pid,ue->ulsch[eNB_id]->O,ue->ulsch[eNB_id]->O_ACK,ue->ulsch[eNB_id]->O_RI,ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS); - //#endif - if (Msg3_flag == 1) { - LOG_I(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d next slot %d Generating (RRCConnectionRequest) Msg3 (nb_rb %d, first_rb %d, round %d, rvidx %d) Msg3: %x.%x.%x|%x.%x.%x.%x.%x.%x\n",Mod_id,frame_tx, - subframe_tx, slot_tx, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, - ue->prach_resources[eNB_id]->Msg3[0], - ue->prach_resources[eNB_id]->Msg3[1], - ue->prach_resources[eNB_id]->Msg3[2], - ue->prach_resources[eNB_id]->Msg3[3], - ue->prach_resources[eNB_id]->Msg3[4], - ue->prach_resources[eNB_id]->Msg3[5], - ue->prach_resources[eNB_id]->Msg3[6], - ue->prach_resources[eNB_id]->Msg3[7], - ue->prach_resources[eNB_id]->Msg3[8]); - - start_meas(&ue->ulsch_encoding_stats); - - if (abstraction_flag==0) { - if (ulsch_encoding(ue->prach_resources[eNB_id]->Msg3, - ue, - harq_pid, - eNB_id, - ue->transmission_mode[eNB_id],0,0)!=0) { - LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); - mac_xface->macphy_exit("Error in ulsch_coding"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); - stop_meas(&ue->phy_proc_tx); - return; - } - } - -#ifdef PHY_ABSTRACTION - else { - ulsch_encoding_emul(ue->prach_resources[eNB_id]->Msg3,ue,eNB_id,harq_pid,0); - } - -#endif - stop_meas(&ue->ulsch_encoding_stats); - - if (ue->mac_enabled == 1) { - // signal MAC that Msg3 was sent - mac_xface->Msg3_transmitted(Mod_id, - CC_id, - frame_tx, - eNB_id); - } - } else { - input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; - - if (ue->mac_enabled==1) { - // LOG_D(PHY,"[UE %d] ULSCH : Searching for MAC SDUs\n",Mod_id); - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) { - //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { - access_mode=SCHEDULED_ACCESS; - mac_xface->ue_get_sdu(Mod_id, - CC_id, - frame_tx, - subframe_tx, - eNB_id, - ulsch_input_buffer, - input_buffer_length, - &access_mode); - - //} - /* - else { - // Get calibration information from TDD procedures - LOG_D(PHY,"[UE %d] Frame %d, subframe %d : ULSCH: Getting TDD Auto-Calibration information\n", - Mod_id,ue->frame,subframe_tx); - for (i=0;iulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3); - - for (i=0; iulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3; i++) - LOG_T(PHY,"%x.",ulsch_input_buffer[i]); - - LOG_T(PHY,"\n"); -#endif -#endif - } - else { - // the following lines were necessary for the calibration in CROWN - /* - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { - for (i=0;iulsch[eNB_id]->o ,0,MAX_CQI_BYTES*sizeof(uint8_t)); - memset(ue->ulsch[eNB_id]->o_RI ,0,2*sizeof(uint8_t)); - memset(ue->ulsch[eNB_id]->o_ACK,0,4*sizeof(uint8_t)); - for (i=0;iulsch_encoding_stats); - - if (abstraction_flag==0) { - /* - if (ue->frame%100==0) { - LOG_I(PHY,"Encoding ulsch\n"); - } - */ - if (ulsch_encoding(ulsch_input_buffer, - ue, - harq_pid, - eNB_id, - ue->transmission_mode[eNB_id],0, - 0)!=0) { // Nbundled, to be updated!!!! - LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); - stop_meas(&ue->phy_proc_tx); - return; - } - } - -#ifdef PHY_ABSTRACTION - else { - ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); - } - -#endif - stop_meas(&ue->ulsch_encoding_stats); - } - - if (abstraction_flag == 0) { - if (ue->mac_enabled==1) { - pusch_power_cntl(ue,subframe_tx,eNB_id,1, abstraction_flag); - ue->tx_power_dBm = ue->ulsch[eNB_id]->Po_PUSCH; - } - else { - ue->tx_power_dBm = ue->tx_power_max_dBm; - } - ue->tx_total_RE = nb_rb*12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - tx_amp = get_tx_amp(ue->tx_power_dBm, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - nb_rb); -#else - tx_amp = AMP; -#endif - LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", - Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm,ue->tx_power_max_dBm, tx_amp); - start_meas(&ue->ulsch_modulation_stats); - ulsch_modulation(ue->common_vars.txdataF, - tx_amp, - frame_tx, - subframe_tx, - &ue->frame_parms, - ue->ulsch[eNB_id]); - for (aa=0; aa<1/*frame_parms->nb_antennas_tx*/; aa++) - generate_drs_pusch(ue, - eNB_id, - tx_amp, - subframe_tx, - first_rb, - nb_rb, - aa); - - stop_meas(&ue->ulsch_modulation_stats); - } - - if (abstraction_flag==1) { - // clear SR - ue->sr[subframe_tx]=0; - } - } // ULSCH is active - -#ifdef PUCCH - else if (ue->UE_mode[eNB_id] == PUSCH) { // check if we need to use PUCCH 1a/1b - // debug_LOG_D(PHY,"[UE%d] Frame %d, subframe %d: Checking for PUCCH 1a/1b\n",Mod_id,frame_tx,subframe_tx); - bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; - - if ((frame_parms->frame_type==FDD) || - (bundling_flag==bundling) || - ((frame_parms->frame_type==TDD)&&(frame_parms->tdd_config==1)&&((slot_tx!=4)||(slot_tx!=14)))) { - format = pucch_format1a; - LOG_D(PHY,"[UE] PUCCH 1a\n"); - } else { - format = pucch_format1b; - LOG_D(PHY,"[UE] PUCCH 1b\n"); - } - - // Check for SR and do ACK/NACK accordingly - if (is_SR_TXOp(ue,eNB_id,subframe_tx)==1) { - LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d: got SR_TXOp, Checking for SR for PUSCH from MAC\n", - Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx); - - if (ue->mac_enabled==1) { - SR_payload = mac_xface->ue_get_SR(Mod_id, - CC_id, - frame_tx, - eNB_id, - ue->pdcch_vars[eNB_id]->crnti, - subframe_tx); // subframe used for meas gap - } - else { - SR_payload = 1; - } - - if (SR_payload>0) { - generate_ul_signal = 1; - LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d got the SR for PUSCH is %d\n", - Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame_tx,subframe_tx,SR_payload); - } else { - ue->sr[subframe_tx]=0; - } - } else { - SR_payload=0; - } - - if (get_ack(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_ack, - subframe_tx,pucch_ack_payload) > 0) { - // we need to transmit ACK/NAK in this subframe - - generate_ul_signal = 1; - - n1_pucch = get_n1_pucch(ue, - eNB_id, - subframe_tx, - pucch_ack_payload, - SR_payload); - - if (ue->mac_enabled == 1) { - Po_PUCCH = pucch_power_cntl(ue,subframe_tx,eNB_id,format); - } - else { - Po_PUCCH = ue->tx_power_max_dBm; - } - ue->tx_power_dBm = Po_PUCCH; - ue->tx_total_RE = 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - tx_amp = get_tx_amp(Po_PUCCH, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - 1); -#else - tx_amp = AMP; -#endif - - if (SR_payload>0) { - LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), n1_pucch %d, Po_PUCCH, amp %d\n", - Mod_id, - ue->dlsch[eNB_id][0]->rnti, - frame_tx, subframe_tx, - pucch_ack_payload[0],pucch_ack_payload[1], - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - Po_PUCCH, - tx_amp); - } else { - LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n", - Mod_id, - ue->dlsch[eNB_id][0]->rnti, - frame_tx, subframe_tx, - n1_pucch,pucch_ack_payload[0],pucch_ack_payload[1],SR_payload, - Po_PUCCH, - tx_amp); - } - - if (abstraction_flag == 0) { - - generate_pucch(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - format, - &ue->pucch_config_dedicated[eNB_id], - n1_pucch, - 0, // n2_pucch - 1, // shortened format - pucch_ack_payload, - tx_amp, - subframe_tx); - - } else { -#ifdef PHY_ABSTRACTION - LOG_D(PHY,"Calling generate_pucch_emul ... (ACK %d %d, SR %d)\n",pucch_ack_payload[0],pucch_ack_payload[1],SR_payload); - generate_pucch_emul(ue, - format, - ue->frame_parms.pucch_config_common.nCS_AN, - pucch_ack_payload, - SR_payload, - subframe_tx); -#endif - } - } else if (SR_payload==1) { // no ACK/NAK but SR is triggered by MAC - - if (ue->mac_enabled == 1) { - Po_PUCCH = pucch_power_cntl(ue,subframe_tx,eNB_id,pucch_format1); - } - else { - Po_PUCCH = ue->tx_power_max_dBm; - } - ue->tx_power_dBm = Po_PUCCH; - ue->tx_total_RE = 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - tx_amp = get_tx_amp(Po_PUCCH, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - 1); -#else - tx_amp = AMP; -#endif - LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Generating PUCCH 1 (SR for PUSCH), n1_pucch %d, Po_PUCCH %d\n", - Mod_id, - ue->dlsch[eNB_id][0]->rnti, - frame_tx, subframe_tx, - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - Po_PUCCH); - - if (abstraction_flag == 0) { - - generate_pucch(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - pucch_format1, - &ue->pucch_config_dedicated[eNB_id], - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - 0, // n2_pucch - 1, // shortened format - pucch_ack_payload, // this is ignored anyway, we just need a pointer - tx_amp, - subframe_tx); - } else { - LOG_D(PHY,"Calling generate_pucch_emul ...\n"); - generate_pucch_emul(ue, - pucch_format1, - ue->frame_parms.pucch_config_common.nCS_AN, - pucch_ack_payload, - SR_payload, - subframe_tx); - } - } - } - -#endif // PUCCH + } + + if (ue->UE_mode[eNB_id] == PUSCH) { // check if we need to use PUCCH 1a/1b + + } // UE_mode==PUSCH + + #ifdef CBA - - if ((ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag >= 1) && - (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == CBA_ACTIVE)) { - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag=0; //-=1 - // ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; - first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; - nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; - //cba_mcs=ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs; - input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; - access_mode=CBA_ACCESS; - - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: CBA num dci %d\n", - Mod_id,frame_tx,subframe_tx, - ue->ulsch[eNB_id]->num_cba_dci[subframe_tx]); - - mac_xface->ue_get_sdu(Mod_id, - CC_id, - frame_tx, - subframe_tx, - eNB_id, - ulsch_input_buffer, - input_buffer_length, - &access_mode); - - ue->ulsch[eNB_id]->num_cba_dci[subframe_tx]=0; - - if (access_mode > UNKNOWN_ACCESS) { - - if (abstraction_flag==0) { - if (ulsch_encoding(ulsch_input_buffer, - ue, - harq_pid, - eNB_id, - ue->transmission_mode[eNB_id],0, - 0)!=0) { // Nbundled, to be updated!!!! - LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); - return; - } - } - -#ifdef PHY_ABSTRACTION - else { - ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); - } - -#endif - } else { - ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; - //reset_cba_uci(ue->ulsch[eNB_id]->o); - LOG_N(PHY,"[UE %d] Frame %d, subframe %d: CBA transmission cancelled or postponed\n", - Mod_id, frame_tx,subframe_tx); - } + + if ((ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag >= 1) && + (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == CBA_ACTIVE)) { + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag=0; //-=1 + // ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; + first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; + nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; + //cba_mcs=ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs; + input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; + access_mode=CBA_ACCESS; + + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: CBA num dci %d\n", + Mod_id,frame_tx,subframe_tx, + ue->ulsch[eNB_id]->num_cba_dci[subframe_tx]); + + mac_xface->ue_get_sdu(Mod_id, + CC_id, + frame_tx, + subframe_tx, + eNB_id, + ulsch_input_buffer, + input_buffer_length, + &access_mode); + + ue->ulsch[eNB_id]->num_cba_dci[subframe_tx]=0; + + if (access_mode > UNKNOWN_ACCESS) { + + if (abstraction_flag==0) { + if (ulsch_encoding(ulsch_input_buffer, + ue, + harq_pid, + eNB_id, + ue->transmission_mode[eNB_id],0, + 0)!=0) { // Nbundled, to be updated!!!! + LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); + return; + } } - + +#ifdef PHY_ABSTRACTION + else { + ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,harq_pid,0); + } + +#endif + } else { + ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; + //reset_cba_uci(ue->ulsch[eNB_id]->o); + LOG_N(PHY,"[UE %d] Frame %d, subframe %d: CBA transmission cancelled or postponed\n", + Mod_id, frame_tx,subframe_tx); + } + } + #endif // end CBA - if (abstraction_flag == 0) { - nsymb = (frame_parms->Ncp == 0) ? 14 : 12; - + + if (abstraction_flag == 0) { + + if (ue->generate_ul_signal[eNB_id] == 1 ) + ulsch_common_procedures(ue,proc); + else { // no uplink so clear signal buffer instead #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case - ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- - ue->hw_timing_advance- - ue->timing_advance- - ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); + ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- + ue->hw_timing_advance- + ue->timing_advance- + ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); #else //this is the normal case - ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance; + ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance; #endif //else EXMIMO - if ((frame_tx%100) == 0) - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: ulsch_start = %d (rxoff %d, HW TA %d, timing advance %d, TA_offset %d\n", - Mod_id,frame_tx,subframe_tx, - ulsch_start, - ue->rx_offset, - ue->hw_timing_advance, - ue->timing_advance, - ue->N_TA_offset); - - - if (generate_ul_signal == 1 ) { - - - - start_meas(&ue->ofdm_mod_stats); - - for (aa=0; aanb_antennas_tx; aa++) { - if (frame_parms->Ncp == 1) - PHY_ofdm_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - dummy_tx_buffer, -#else - &ue->common_vars.txdata[aa][ulsch_start], -#endif - frame_parms->ofdm_symbol_size, - nsymb, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - else - normal_prefix_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - dummy_tx_buffer, -#else - &ue->common_vars.txdata[aa][ulsch_start], -#endif - nsymb, - &ue->frame_parms); - - /* - if (subframe_tx == 8) { - printf("Symbol 0 %p (offset %d) base %p\n", - &ue->common_vars.txdataF[0][nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe], - nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe, - ue->common_vars.txdataF[0]); - write_output("txsigF8.m","txsF8", &ue->common_vars.txdataF[0][nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*subframe], - ue->frame_parms.ofdm_symbol_size*nsymb,1,1); - write_output("txsig8.m","txs8", &ue->common_vars.txdata[0][ue->frame_parms.samples_per_tti*subframe], - ue->frame_parms.samples_per_tti,1,1); - } - */ -#ifndef OFDMA_ULSCH -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - apply_7_5_kHz(ue,dummy_tx_buffer,0); - apply_7_5_kHz(ue,dummy_tx_buffer,1); -#else - apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0); - apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1); -#endif - /* - if (subframe_tx == 8) { - write_output("txsig8_mod.m","txs8_mod", &ue->common_vars.txdata[0][ue->frame_parms.samples_per_tti*subframe], - ue->frame_parms.samples_per_tti,1,1); - } - */ -#endif - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - overflow = ulsch_start - 9*frame_parms->samples_per_tti; - - //if ((slot_tx==4) && (aa==0)) printf("ulsch_start %d, overflow %d\n",ulsch_start,overflow); - for (k=ulsch_start,l=0; ksamples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti); k++,l++) { - ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; - } - - for (k=0; kcommon_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; - } -#if defined(EXMIMO) - // handle switch before 1st TX subframe, guarantee that the slot prior to transmission is switch on - for (k=ulsch_start - (frame_parms->samples_per_tti>>1) ; kcommon_vars.txdata[aa][k+frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; - else if (k>(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) - ue->common_vars.txdata[aa][k-frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; - else - ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE; - } -#endif -#endif - - } //nb_antennas_tx - - stop_meas(&ue->ofdm_mod_stats); - } // generate_ul_signal == 1 - else { // no uplink so clear signal buffer instead - for (aa=0; aanb_antennas_tx; aa++) { - memset(&ue->common_vars.txdata[aa][ulsch_start],0,frame_parms->samples_per_tti<<2); - } - } + for (aa=0; aanb_antennas_tx; aa++) { + memset(&ue->common_vars.txdata[aa][ulsch_start],0,frame_parms->samples_per_tti<<2); } - } // mode != PRACH - - // }// slot_tx is even - // else { // slot_tx is odd, do the PRACH here - - if ((ue->UE_mode[eNB_id] == PRACH) && (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) { - - // check if we have PRACH opportunity - if (is_prach_subframe(&ue->frame_parms,frame_tx,subframe_tx)) { - ue->generate_prach=0; - - if (ue->mac_enabled==1){ - // ask L2 for RACH transport - if ((mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) && (mode != no_L2_connect) ) { - ue->prach_resources[eNB_id] = mac_xface->ue_get_rach(Mod_id, - CC_id, - frame_tx, - eNB_id, - subframe_tx); - // LOG_I(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[Mod_id].radioResourceConfigCommon); - } - } - - if (ue->prach_resources[eNB_id]!=NULL) { - - ue->generate_prach=1; - ue->prach_cnt=0; -#ifdef SMBV - ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; -#endif -#ifdef OAI_EMU - ue->prach_PreambleIndex=ue->prach_resources[eNB_id]->ra_PreambleIndex; -#endif - - if (abstraction_flag == 0) { - LOG_I(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d : Generating PRACH, preamble %d, TARGET_RECEIVED_POWER %d dBm, PRACH TDD Resource index %d, RA-RNTI %d\n", - Mod_id, - frame_tx, - subframe_tx, - ue->prach_resources[eNB_id]->ra_PreambleIndex, - ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER, - ue->prach_resources[eNB_id]->ra_TDD_map_index, - ue->prach_resources[eNB_id]->ra_RNTI); - - if ((ue->mac_enabled==1) && (mode != calib_prach_tx)) { - ue->tx_power_dBm = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(Mod_id,CC_id,eNB_id); - } - else { - ue->tx_power_dBm = ue->tx_power_max_dBm; - ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; - } - - ue->tx_total_RE = 96; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - 6); -#else - ue->prach_vars[eNB_id]->amp = AMP; -#endif - if ((mode == calib_prach_tx) && (((ue->frame_tx&0xfffe)%100)==0)) - LOG_D(PHY,"[UE %d][RAPROC] Frame %d, Subframe %d : PRACH TX power %d dBm, amp %d\n",Mod_id,ue->frame_rx,ue->slot_tx>>1,ue->tx_power_dBm, - ue->prach_vars[eNB_id]->amp); - - - // start_meas(&ue->tx_prach); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN); - prach_power = generate_prach(ue,eNB_id,subframe_tx,frame_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_OUT); - // stop_meas(&ue->tx_prach); - LOG_D(PHY,"[UE %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n", - Mod_id, - get_PL(Mod_id,CC_id,eNB_id), - ue->tx_power_dBm, - dB_fixed(prach_power), - ue->prach_vars[eNB_id]->amp); - } else { - UE_transport_info[Mod_id][CC_id].cntl.prach_flag=1; - UE_transport_info[Mod_id][CC_id].cntl.prach_id=ue->prach_resources[eNB_id]->ra_PreambleIndex; - if (ue->mac_enabled==1){ - mac_xface->Msg1_transmitted(Mod_id, - CC_id, - frame_tx, - eNB_id); - } - } - - LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Generating PRACH (eNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB), l3msg \n", - Mod_id,frame_tx,subframe_tx,eNB_id, - ue->prach_resources[eNB_id]->ra_PreambleIndex, - ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(Mod_id,CC_id,eNB_id), - get_PL(Mod_id,CC_id,eNB_id)); - - } - - } - // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue - if (mode == calib_prach_tx) - ue->prach_resources[eNB_id]=NULL; - - LOG_D(PHY,"[UE %d] frame %d subframe %d : generate_prach %d, prach_cnt %d\n", - Mod_id,frame_tx,subframe_tx,ue->generate_prach,ue->prach_cnt); - - ue->prach_cnt++; - - if (ue->prach_cnt==3) - ue->generate_prach=0; - } // mode is PRACH - else { - ue->generate_prach=0; } - } // slot_tx is even + } // mode != PRACH + + + if ((ue->UE_mode[eNB_id] == PRACH) && + (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) { + + // check if we have PRACH opportunity + if (is_prach_subframe(&ue->frame_parms,frame_tx,subframe_tx)) { + + ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode); + } + } // mode is PRACH + else { + ue->generate_prach=0; + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); stop_meas(&ue->phy_proc_tx); } @@ -1449,37 +1409,31 @@ void phy_procedures_UE_S_TX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_f { int aa;//i,aa; LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - + if (abstraction_flag==0) { - + for (aa=0; aanb_antennas_tx; aa++) { #if defined(EXMIMO) //this is the EXPRESS MIMO case int i; // set the whole tx buffer to RX for (i=0; isamples_per_tti; i++) - ue->common_vars.txdata[aa][i] = 0x00010001; - + ue->common_vars.txdata[aa][i] = 0x00010001; + #else //this is the normal case memset(&ue->common_vars.txdata[aa][0],0, - (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti)*sizeof(int32_t)); + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti)*sizeof(int32_t)); #endif //else EXMIMO - + } } } -void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode) +void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode) { - + LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - // int aa; -#if defined(EXMIMO) && defined(DRIVER2013) - // exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[0].exmimo_config_ptr; - // int aa; -#endif - int slot_rx = ue->slot_rx; - int subframe_rx = slot_rx>>1; + int subframe_rx = proc->subframe_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN); @@ -1489,25 +1443,25 @@ void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,uint8_t eNB_id,uint8_ LOG_D(PHY,"Calling measurements subframe %d, rxdata %p\n",subframe_rx,ue->common_vars.rxdata); lte_ue_measurements(ue, - (subframe_rx*frame_parms->samples_per_tti+ue->rx_offset)%(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME), - (slot_rx == 2) ? 1 : 0, - 0); + (subframe_rx*frame_parms->samples_per_tti+ue->rx_offset)%(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME), + (subframe_rx == 1) ? 1 : 0, + 0); } else { lte_ue_measurements(ue, - 0, - 0, - 1); + 0, + 0, + 1); } } if (l==(6-ue->frame_parms.Ncp)) { - // make sure we have signal from PSS/SSS for N0 measurement + // make sure we have signal from PSS/SSS for N0 measurement VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_IN); ue_rrc_measurements(ue, - slot_rx, - abstraction_flag); + subframe_rx, + abstraction_flag); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_OUT); if (abstraction_flag==1) @@ -1515,7 +1469,7 @@ void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,uint8_t eNB_id,uint8_ } - if ((slot_rx==1) && (l==(4-frame_parms->Ncp))) { + if ((subframe_rx==0) && (l==(4-frame_parms->Ncp))) { // AGC @@ -1535,10 +1489,10 @@ void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,uint8_t eNB_id,uint8_ if (abstraction_flag == 0) lte_adjust_synch(&ue->frame_parms, - ue, - eNB_id, - 0, - 16384); + ue, + eNB_id, + 0, + 16384); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); @@ -1557,14 +1511,14 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) int Mod_id = ue->Mod_id; /* - if (last_slot<2) + if (last_slot<2) last_slot_emos = last_slot; - else if (last_slot>9) + else if (last_slot>9) last_slot_emos = last_slot - 8; - else { + else { LOG_E(PHY,"emos rx last_slot_emos %d, last_slot %d\n", last_slot_emos,last_slot); mac_xface->macphy_exit("should never happen"); - } + } */ #ifdef EMOS_CHANNEL @@ -1572,14 +1526,14 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) if ((last_slot==10) || (last_slot==11)) { for (i=0; iframe_parms.nb_antennas_rx; i++) for (j=0; jframe_parms.nb_antennas_tx; j++) { - // first OFDM symbol with pilots - memcpy(&emos_dump_UE.channel[i][j][(last_slot%2)*2*ue->frame_parms.ofdm_symbol_size], - &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][0], - ue->frame_parms.ofdm_symbol_size*sizeof(int)); - // second OFDM symbol with pilots - memcpy(&emos_dump_UE.channel[i][j][((last_slot%2)*2+1)*ue->frame_parms.ofdm_symbol_size], - &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][(ue->frame_parms.Ncp == 0 ? 4 : 3)*ue->frame_parms.ofdm_symbol_size], - ue->frame_parms.ofdm_symbol_size*sizeof(int)); + // first OFDM symbol with pilots + memcpy(&emos_dump_UE.channel[i][j][(last_slot%2)*2*ue->frame_parms.ofdm_symbol_size], + &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][0], + ue->frame_parms.ofdm_symbol_size*sizeof(int)); + // second OFDM symbol with pilots + memcpy(&emos_dump_UE.channel[i][j][((last_slot%2)*2+1)*ue->frame_parms.ofdm_symbol_size], + &ue->common_vars.dl_ch_estimates[eNB_id][(j<<1) + i][(ue->frame_parms.Ncp == 0 ? 4 : 3)*ue->frame_parms.ofdm_symbol_size], + ue->frame_parms.ofdm_symbol_size*sizeof(int)); } } @@ -1587,7 +1541,7 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) if (last_slot==0) { emos_dump_UE.timestamp = rt_get_time_ns(); - emos_dump_UE.frame_rx = ue->frame_rx; + emos_dump_UE.frame_rx = proc->frame_rx; emos_dump_UE.UE_mode = ue->UE_mode[eNB_id]; emos_dump_UE.mimo_mode = ue->transmission_mode[eNB_id]; emos_dump_UE.freq_offset = ue->common_vars.freq_offset; @@ -1624,10 +1578,10 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_UE, sizeof(fifo_dump_emos_UE)); if (bytes!=sizeof(fifo_dump_emos_UE)) { - LOG_W(PHY,"[UE %d] frame %d, slot %d, Problem writing EMOS data to FIFO\n",Mod_id,ue->frame_rx, last_slot); + LOG_W(PHY,"[UE %d] frame %d, slot %d, Problem writing EMOS data to FIFO\n",Mod_id,proc->frame_rx, last_slot); } else { - if (ue->frame_rx%100==0) { - LOG_I(PHY,"[UE %d] frame %d, slot %d, Writing %d bytes EMOS data to FIFO\n",Mod_id,ue->frame_rx, last_slot, bytes); + if (proc->frame_rx%100==0) { + LOG_I(PHY,"[UE %d] frame %d, slot %d, Writing %d bytes EMOS data to FIFO\n",Mod_id,proc->frame_rx, last_slot, bytes); } } } @@ -1636,12 +1590,12 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *ue,uint8_t last_slot,uint8_t eNB_id) #endif -void restart_phy(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag) +void restart_phy(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t abstraction_flag) { // uint8_t last_slot; uint8_t i; - LOG_I(PHY,"[UE %d] frame %d, slot %d, restarting PHY!\n",ue->Mod_id,ue->frame_rx,ue->slot_rx); + LOG_I(PHY,"[UE %d] frame %d, slot %d, restarting PHY!\n",ue->Mod_id,proc->frame_rx,proc->subframe_rx); mac_xface->macphy_exit("restart_phy called"); // first_run = 1; @@ -1652,8 +1606,8 @@ void restart_phy(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag) ue->prach_resources[eNB_id]=NULL; } - ue->frame_rx = -1; - ue->frame_tx = -1; + proc->frame_rx = -1; + proc->frame_tx = -1; // ue->synch_wait_cnt=0; // ue->sched_cnt=-1; @@ -1694,7 +1648,7 @@ void restart_phy(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag) } -void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) +void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uint8_t abstraction_flag) { // int i; @@ -1705,8 +1659,9 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) uint8_t pbch_trials = 0; DevAssert(ue); - int slot_rx = ue->slot_rx; - int frame_rx = ue->frame_rx; + + int frame_rx = proc->frame_rx; + int subframe_rx = proc->subframe_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN); @@ -1720,12 +1675,12 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, eNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,eNB_id); if (abstraction_flag == 0) { pbch_tx_ant = rx_pbch(&ue->common_vars, - ue->pbch_vars[eNB_id], - &ue->frame_parms, - eNB_id, - ue->frame_parms.mode1_flag==1?SISO:ALAMOUTI, - ue->high_speed_flag, - pbch_phase); + ue->pbch_vars[eNB_id], + &ue->frame_parms, + eNB_id, + ue->frame_parms.mode1_flag==1?SISO:ALAMOUTI, + ue->high_speed_flag, + pbch_phase); @@ -1734,8 +1689,8 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) #ifdef PHY_ABSTRACTION else { pbch_tx_ant = rx_pbch_emul(ue, - eNB_id, - pbch_phase); + eNB_id, + pbch_phase); } #endif @@ -1778,76 +1733,49 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) if (first_run) { first_run = 0; - LOG_I(PHY,"[UE %d] frame %d, slot %d: Adjusting frame counter (PBCH ant_tx=%d, frame_tx=%d, phase %d).\n", - ue->Mod_id, - frame_rx, - slot_rx, - pbch_tx_ant, - frame_tx, - pbch_phase); - ue->frame_rx = (ue->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); - ue->frame_tx = ue->frame_rx; - frame_rx = ue->frame_rx; - } else if (((frame_tx & 0x03FF) != (ue->frame_rx & 0x03FF))) { + LOG_I(PHY,"[UE %d] frame %d, subframe %d: Adjusting frame counter (PBCH ant_tx=%d, frame_tx=%d, phase %d).\n", + ue->Mod_id, + frame_rx, + subframe_rx, + pbch_tx_ant, + frame_tx, + pbch_phase); + proc->frame_rx = (proc->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); + proc->frame_tx = proc->frame_rx; + frame_rx = proc->frame_rx; + } else if (((frame_tx & 0x03FF) != (proc->frame_rx & 0x03FF))) { //(pbch_tx_ant != ue->frame_parms.nb_antennas_tx)) { - LOG_D(PHY,"[UE %d] frame %d, slot %d: Re-adjusting frame counter (PBCH ant_tx=%d, frame_rx=%d, frame%1024=%d, phase %d).\n", - ue->Mod_id, - ue->frame_rx, - slot_rx, - pbch_tx_ant, - frame_tx, - frame_rx & 0x03FF, - pbch_phase); + LOG_D(PHY,"[UE %d] frame %d, subframe %d: Re-adjusting frame counter (PBCH ant_tx=%d, frame_rx=%d, frame%1024=%d, phase %d).\n", + ue->Mod_id, + proc->frame_rx, + subframe_rx, + pbch_tx_ant, + frame_tx, + frame_rx & 0x03FF, + pbch_phase); + + proc->frame_rx = (proc->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); + proc->frame_tx = proc->frame_rx; + frame_rx = proc->frame_rx; - ue->frame_rx = (ue->frame_rx & 0xFFFFFC00) | (frame_tx & 0x000003FF); - ue->frame_tx = ue->frame_rx; - frame_rx = ue->frame_rx; - /* - LOG_D(PHY,"[UE %d] frame %d, slot %d: PBCH PDU does not match, ignoring it (PBCH ant_tx=%d, frame_tx=%d).\n", - ue->Mod_id, - ue->frame, - slot_rx, - pbch_tx_ant, - frame_tx); - */ - //ue->pbch_vars[eNB_id]->pdu_errors_conseq = 21; // this will make it go out of sync - //ue->pbch_vars[eNB_id]->pdu_errors_conseq += 1; // this will make it go out of sync } #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] frame %d, slot %d, Received PBCH (MIB): mode1_flag %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", - ue->Mod_id, - frame_rx, - slot_rx, - ue->frame_parms.mode1_flag, - pbch_tx_ant, - frame_tx, - ue->frame_parms.N_RB_DL, - ue->frame_parms.phich_config_common.phich_duration, - ue->frame_parms.phich_config_common.phich_resource); - /* - if (frame_rx%100 == 0) { - LOG_I(PHY,"[UE %d] frame %d, slot %d, PBCH: mode1_flag %d, tx_ant %d, frame_tx %d, phase %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6,Frequency offset %d Hz (%d)\n", - ue->Mod_id, - frame_rx, - slot_rx, - ue->frame_parms.mode1_flag, - pbch_tx_ant, - frame_tx, - pbch_phase, - ue->frame_parms.N_RB_DL, - ue->frame_parms.phich_config_common.phich_duration, - ue->frame_parms.phich_config_common.phich_resource, - ue->common_vars.freq_offset,openair_daq_vars.freq_offset); - //dump_frame_parms(&ue->frame_parms); - - } - */ + LOG_D(PHY,"[UE %d] frame %d, subframe %d, Received PBCH (MIB): mode1_flag %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", + ue->Mod_id, + frame_rx, + subframe_rx, + ue->frame_parms.mode1_flag, + pbch_tx_ant, + frame_tx, + ue->frame_parms.N_RB_DL, + ue->frame_parms.phich_config_common.phich_duration, + ue->frame_parms.phich_config_common.phich_resource); #endif } else { LOG_E(PHY,"[UE %d] frame %d, slot %d, Error decoding PBCH!\n", - ue->Mod_id,frame_rx, slot_rx); + ue->Mod_id,frame_rx, subframe_rx); ue->pbch_vars[eNB_id]->pdu_errors_conseq++; ue->pbch_vars[eNB_id]->pdu_errors++; if (ue->mac_enabled == 1) { @@ -1868,24 +1796,20 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n", - ue->Mod_id,frame_rx, slot_rx, - ue->pbch_vars[eNB_id]->pdu_errors, - ue->pbch_vars[eNB_id]->pdu_errors_conseq); + ue->Mod_id,frame_rx, subframe_rx, + ue->pbch_vars[eNB_id]->pdu_errors, + ue->pbch_vars[eNB_id]->pdu_errors_conseq); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); } -int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) +int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t abstraction_flag) { unsigned int dci_cnt=0, i; - //DCI_PDU *DCI_pdu; - //uint16_t ra_RNTI; - - int frame_rx = ue->frame_rx; - int slot_rx = ue->slot_rx; - int subframe_rx = slot_rx>>1; + int frame_rx = proc->frame_rx; + int subframe_rx = proc->subframe_rx; #ifdef PHY_ABSTRACTION @@ -1902,29 +1826,29 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); rx_pdcch(&ue->common_vars, - ue->pdcch_vars, - &ue->frame_parms, - subframe_rx, - eNB_id, - (ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, - ue->high_speed_flag, - ue->is_secondary_ue); + ue->pdcch_vars, + &ue->frame_parms, + subframe_rx, + eNB_id, + (ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, + ue->high_speed_flag, + ue->is_secondary_ue); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_IN); dci_cnt = dci_decoding_procedure(ue, - dci_alloc_rx, - (ue->UE_mode[eNB_id] < PUSCH)? 1 : 0, // if we're in PUSCH don't listen to common search space, - // later when we need paging or RA during connection, update this ... - eNB_id,subframe_rx); + dci_alloc_rx, + (ue->UE_mode[eNB_id] < PUSCH)? 1 : 0, // if we're in PUSCH don't listen to common search space, + // later when we need paging or RA during connection, update this ... + eNB_id,subframe_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT); //LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d PHICH RX\n",ue->Mod_id,frame_rx,subframe_rx); if (is_phich_subframe(&ue->frame_parms,subframe_rx)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_IN); - rx_phich(ue, - subframe_rx,eNB_id); + rx_phich(ue,proc, + subframe_rx,eNB_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH, VCD_FUNCTION_OUT); } } @@ -1933,11 +1857,11 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) else { for (i=0; iframe_parms.Nid_cell == ue->frame_parms.Nid_cell) - break; + if (PHY_vars_eNB_g[i][CC_id]->frame_parms.Nid_cell == ue->frame_parms.Nid_cell) + break; if (CC_id < MAX_NUM_CCs) - break; + break; } if (i==NB_eNB_INST) { @@ -1949,59 +1873,28 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) LOG_D(PHY,"Calling dci_decoding_proc_emul ...\n"); dci_cnt = dci_decoding_procedure_emul(ue->pdcch_vars, - PHY_vars_eNB_g[i][CC_id]->num_ue_spec_dci[subframe_rx&1], - PHY_vars_eNB_g[i][CC_id]->num_common_dci[subframe_rx&1], - PHY_vars_eNB_g[i][CC_id]->dci_alloc[subframe_rx&1], - dci_alloc_rx, - eNB_id); + PHY_vars_eNB_g[i][CC_id]->num_ue_spec_dci[subframe_rx&1], + PHY_vars_eNB_g[i][CC_id]->num_common_dci[subframe_rx&1], + PHY_vars_eNB_g[i][CC_id]->dci_alloc[subframe_rx&1], + dci_alloc_rx, + eNB_id); // printf("DCI: dci_cnt %d\n",dci_cnt); UE_id = (uint32_t)find_ue((int16_t)ue->pdcch_vars[eNB_id]->crnti,PHY_vars_eNB_g[i][CC_id]); if (UE_id>=0) { - // msg("Checking PHICH for UE %d (eNB %d)\n",UE_id,i); + // printf("Checking PHICH for UE %d (eNB %d)\n",UE_id,i); if (is_phich_subframe(&ue->frame_parms,subframe_rx)) { - harq_pid = phich_subframe_to_harq_pid(&ue->frame_parms,frame_rx,subframe_rx); + harq_pid = phich_subframe_to_harq_pid(&ue->frame_parms,frame_rx,subframe_rx); - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == ACTIVE) { - // ue->ulsch[eNB_id]->harq_processes[harq_pid]->phich_ACK=1; - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; - ue->ulsch[eNB_id]->harq_processes[harq_pid]->status = IDLE; - ue->ulsch_Msg3_active[eNB_id] = 0; - ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; - LOG_D(PHY,"Msg3 inactive\n"); - /* Phich is not abstracted for the moment - if (PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[(uint32_t)UE_id]->harq_processes[harq_pid]->phich_ACK==0) { // NAK - if (ue->ulsch_Msg3_active[eNB_id] == 1) { - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Msg3 PHICH, received NAK\n", - ue->Mod_id, - frame_rx, - subframe_rx); - #endif - get_Msg3_alloc_ret(&ue->frame_parms, - subframe_rx, - frame_rx, - &ue->ulsch_Msg3_frame[eNB_id], - &ue->ulsch_Msg3_subframe[eNB_id]); - } - // PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; - // PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->Ndi = 0; - // PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->round++; - } - else { - #ifdef DEBUG_PHY_PROC - if (ue->ulsch_Msg3_active[eNB_id] == 1) - LOG_D(PHY,"[UE %d][RAPROC] Frame %d, subframe %d: Msg3 PHICH, received ACK\n", - ue->Mod_id, - frame_rx, - subframe_rx); - #endif - PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; - PHY_vars_eNB_g[i][CC_id]->ulsch_eNB[UE_id]->harq_processes[harq_pid]->status = IDLE; - // inform MAC? - ue->ulsch_Msg3_active[eNB_id] = 0; - } //phich_ACK */ - } // harq_pid is ACTIVE + if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == ACTIVE) { + // ue->ulsch[eNB_id]->harq_processes[harq_pid]->phich_ACK=1; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag =0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->status = IDLE; + ue->ulsch_Msg3_active[eNB_id] = 0; + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; + LOG_D(PHY,"Msg3 inactive\n"); + + } // harq_pid is ACTIVE } // This is a PHICH subframe } // UE_id exists } @@ -2009,41 +1902,15 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) #endif //#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",ue->Mod_id,frame_rx,slot_rx,mode_string[ue->UE_mode[eNB_id]],dci_cnt); + LOG_D(PHY,"[UE %d] Frame %d, subframe %d, Mode %s: DCI found %i\n",ue->Mod_id,frame_rx,subframe_rx,mode_string[ue->UE_mode[eNB_id]],dci_cnt); //#endif ue->pdcch_vars[eNB_id]->dci_received += dci_cnt; - /* - #ifdef DEBUG_PHY_PROC - if (slot_rx==18) - debug_LOG_D(PHY,"[UE %d] Frame %d, slot %d: PDCCH: DCI errors %d, DCI received %d, DCI missed %d, DCI False Detection %d \n", - ue->Mod_id,frame_rx,slot_rx, - ue->pdcch_vars[eNB_id]->dci_errors, - ue->pdcch_vars[eNB_id]->dci_received, - ue->pdcch_vars[eNB_id]->dci_missed, - ue->pdcch_vars[eNB_id]->dci_false); - #endif - */ + #ifdef EMOS //emos_dump_UE.dci_cnt[subframe_rx] = dci_cnt; #endif - /* - #ifdef DIAG_PHY - //if (ue->UE_mode[eNB_id] == PUSCH) - if (dci_cnt > 1) { - LOG_D(PHY,"[UE %d][DIAG] frame %d, subframe %d: received %d>1 DCI!\n",ue->Mod_id,frame_rx,subframe_rx,dci_cnt); - ue->pdcch_vars[eNB_id]->dci_false++; - } - else if (dci_cnt==0) { - LOG_D(PHY,"[UE %d][DIAG] frame %d, subframe %d: received %d DCI!\n",ue->Mod_id,frame_rx,subframe_rx,dci_cnt); - ue->pdcch_vars[eNB_id]->dci_missed++; - } - #endif - */ - - // dci_cnt = 0; - // ra_RNTI = (ue->prach_resources[eNB_id]) ? ue->prach_resources[eNB_id]->ra_RNTI : 0; for (i=0; iUE_mode[eNB_id] != PRACH) && - // (dci_alloc_rx[i].rnti != 0x1234) && - if ((ue->UE_mode[eNB_id]>PRACH) && (dci_alloc_rx[i].rnti == ue->pdcch_vars[eNB_id]->crnti) && (dci_alloc_rx[i].format != format0)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][DCI][PDSCH %x] frame %d, subframe %d: format %d, num_pdcch_symbols %d, nCCE %d, total CCEs %d\n", - ue->Mod_id,dci_alloc_rx[i].rnti, - frame_rx,subframe_rx, - dci_alloc_rx[i].format, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - ue->pdcch_vars[eNB_id]->nCCE[subframe_rx], - get_nCCE(3,&ue->frame_parms,get_mi(&ue->frame_parms,0))); + ue->Mod_id,dci_alloc_rx[i].rnti, + frame_rx,subframe_rx, + dci_alloc_rx[i].format, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->pdcch_vars[eNB_id]->nCCE[subframe_rx], + get_nCCE(3,&ue->frame_parms,get_mi(&ue->frame_parms,0))); #endif -#ifdef DIAG_PHY - - if (!(((subframe_rx == 7) && (dci_alloc_rx[i].format == format1E_2A_M10PRB)) || - ((subframe_rx == 7) && (dci_alloc_rx[i].format == format1)))) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received C_RNTI Format %d!\n",ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format); - ue->pdcch_vars[eNB_id]->dci_errors++; - ue->pdcch_vars[eNB_id]->dci_false++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - return(-1); - } - -#endif + // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); if ((ue->UE_mode[eNB_id] > PRACH) && @@ -2100,86 +1953,61 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) 0, P_RNTI)==0)) { -#ifdef DIAG_PHY - - if (ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs != (((frame_rx%1024)%28))) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: wrong mcs!\n",ue->Mod_id,frame_rx,subframe_rx, - ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs); - dump_dci(&ue->frame_parms,(void *)&dci_alloc_rx[i]); - } - -#endif - - - ue->dlsch_received[eNB_id]++; + ue->dlsch_received[eNB_id]++; #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generated UE DLSCH C_RNTI format %d\n",ue->Mod_id,dci_alloc_rx[i].format); - dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); - LOG_D(PHY,"[UE %d] *********** dlsch->active in subframe %d (%d)=> %d\n",ue->Mod_id,subframe_rx,slot_rx,ue->dlsch[eNB_id][0]->active); + LOG_D(PHY,"[UE %d] Generated UE DLSCH C_RNTI format %d\n",ue->Mod_id,dci_alloc_rx[i].format); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + LOG_D(PHY,"[UE %d] *********** dlsch->active in subframe %d=> %d\n",ue->Mod_id,subframe_rx,ue->dlsch[eNB_id][0]->active); #endif - // we received a CRNTI, so we're in PUSCH - if (ue->UE_mode[eNB_id] != PUSCH) { + // we received a CRNTI, so we're in PUSCH + if (ue->UE_mode[eNB_id] != PUSCH) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Received DCI with CRNTI %x => Mode PUSCH\n",ue->Mod_id,frame_rx,subframe_rx,ue->pdcch_vars[eNB_id]->crnti); + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Received DCI with CRNTI %x => Mode PUSCH\n",ue->Mod_id,frame_rx,subframe_rx,ue->pdcch_vars[eNB_id]->crnti); #endif - //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); - ue->UE_mode[eNB_id] = PUSCH; - //mac_xface->macphy_exit("Connected. Exiting\n"); - } + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + ue->UE_mode[eNB_id] = PUSCH; + //mac_xface->macphy_exit("Connected. Exiting\n"); + } } else { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Problem in DCI!\n",ue->Mod_id,frame_rx,subframe_rx); - dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Problem in DCI!\n",ue->Mod_id,frame_rx,subframe_rx); + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); } } else if ((dci_alloc_rx[i].rnti == SI_RNTI) && - ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { + ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] subframe %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); - /* - if (((frame_rx%100) == 0) || (frame_rx < 20)) - dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); - */ #endif -#ifdef DIAG_PHY - if ((subframe_rx != 5)) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received SI_RNTI!\n",ue->Mod_id,frame_rx,subframe_rx); - ue->pdcch_vars[eNB_id]->dci_errors++; - ue->pdcch_vars[eNB_id]->dci_false++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - return(-1); - } - -#endif if (generate_ue_dlsch_params_from_dci(frame_rx, subframe_rx, - (void *)&dci_alloc_rx[i].dci_pdu, - SI_RNTI, - dci_alloc_rx[i].format, - &ue->dlsch_SI[eNB_id], - &ue->frame_parms, - ue->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI)==0) { + (void *)&dci_alloc_rx[i].dci_pdu, + SI_RNTI, + dci_alloc_rx[i].format, + &ue->dlsch_SI[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI)==0) { - ue->dlsch_SI_received[eNB_id]++; + ue->dlsch_SI_received[eNB_id]++; LOG_D(PHY,"[UE %d] Frame %d, subframe %d : Generate UE DLSCH SI_RNTI format 1%s\n",ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format==format1A?"A":"C"); - //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); } } else if ((ue->prach_resources[eNB_id]) && - (dci_alloc_rx[i].rnti == ue->prach_resources[eNB_id]->ra_RNTI) && - (dci_alloc_rx[i].format == format1A)) { + (dci_alloc_rx[i].rnti == ue->prach_resources[eNB_id]->ra_RNTI) && + (dci_alloc_rx[i].format == format1A)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][RAPROC] subframe %d: Found RA rnti %x, format 1A, dci_cnt %d\n",ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,i); @@ -2188,57 +2016,32 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); //mac_xface->macphy_exit("so far so good...\n"); #endif -#ifdef DIAG_PHY - if (subframe_rx != 9) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received RA_RNTI!\n",ue->Mod_id,frame_rx,subframe_rx); - ue->pdcch_vars[eNB_id]->dci_errors++; - ue->pdcch_vars[eNB_id]->dci_false++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - return(-1); - } - -#endif if (generate_ue_dlsch_params_from_dci(frame_rx, subframe_rx, - (DCI1A_5MHz_TDD_1_6_t *)&dci_alloc_rx[i].dci_pdu, - ue->prach_resources[eNB_id]->ra_RNTI, - format1A, - &ue->dlsch_ra[eNB_id], - &ue->frame_parms, - ue->pdsch_config_dedicated, - SI_RNTI, - ue->prach_resources[eNB_id]->ra_RNTI, - P_RNTI)==0) { + (DCI1A_5MHz_TDD_1_6_t *)&dci_alloc_rx[i].dci_pdu, + ue->prach_resources[eNB_id]->ra_RNTI, + format1A, + &ue->dlsch_ra[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + ue->prach_resources[eNB_id]->ra_RNTI, + P_RNTI)==0) { - ue->dlsch_ra_received[eNB_id]++; + ue->dlsch_ra_received[eNB_id]++; #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE DLSCH RA_RNTI format 1A, rb_alloc %x, dlsch_ra[eNB_id] %p\n", - ue->Mod_id,ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even[0],ue->dlsch_ra[eNB_id]); + LOG_D(PHY,"[UE %d] Generate UE DLSCH RA_RNTI format 1A, rb_alloc %x, dlsch_ra[eNB_id] %p\n", + ue->Mod_id,ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even[0],ue->dlsch_ra[eNB_id]); #endif } } else if( (dci_alloc_rx[i].rnti == ue->pdcch_vars[eNB_id]->crnti) && - (dci_alloc_rx[i].format == format0)) { + (dci_alloc_rx[i].format == format0)) { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d: Found rnti %x, format 0, dci_cnt %d\n", - ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); - /* - if (((frame_rx%100) == 0) || (frame_rx < 20)) - dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); - */ -#endif -#ifdef DIAG_PHY - - if (subframe_rx != 9) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received C_RNTI Format 0!\n",ue->Mod_id,frame_rx,subframe_rx); - ue->pdcch_vars[eNB_id]->dci_errors++; - ue->pdcch_vars[eNB_id]->dci_false++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - return(-1); - } - + ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); #endif ue->ulsch_no_allocation_counter[eNB_id] = 0; @@ -2250,6 +2053,7 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) subframe_rx, format0, ue, + proc, SI_RNTI, 0, P_RNTI, @@ -2258,34 +2062,22 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) 0)==0)) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx); + LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx); #endif } } else if( (dci_alloc_rx[i].rnti == ue->ulsch[eNB_id]->cba_rnti[0]) && - (dci_alloc_rx[i].format == format0)) { + (dci_alloc_rx[i].format == format0)) { // UE could belong to more than one CBA group // ue->Mod_id%ue->ulsch[eNB_id]->num_active_cba_groups] #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PUSCH] Frame %d subframe %d: Found cba rnti %x, format 0, dci_cnt %d\n", - ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); + ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].rnti,i); /* - if (((frame_rx%100) == 0) || (frame_rx < 20)) - dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + if (((frame_rx%100) == 0) || (frame_rx < 20)) + dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); */ #endif - /* - #ifdef DIAG_PHY - if (subframe_rx != 8) { - LOG_E(PHY,"[UE %d][DIAG] frame %d, subframe %d: should not have received CBA RNTI Format 0!\n", - ue->Mod_id,frame_rx,subframe_rx); - ue->pdcch_vars[eNB_id]->dci_errors++; - ue->pdcch_vars[eNB_id]->dci_false++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - return(-1); - } - #endif - */ ue->ulsch_no_allocation_counter[eNB_id] = 0; //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); @@ -2296,6 +2088,7 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) subframe_rx, format0, ue, + proc, SI_RNTI, 0, P_RNTI, @@ -2304,49 +2097,31 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,uint8_t abstraction_flag) 0)==0)) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx); + LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx); #endif - ue->ulsch[eNB_id]->num_cba_dci[(subframe_rx+4)%10]++; + ue->ulsch[eNB_id]->num_cba_dci[(subframe_rx+4)%10]++; } } else { #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] frame %d, subframe %d: received DCI %d with RNTI=%x (C-RNTI:%x, CBA_RNTI %x) and format %d!\n",ue->Mod_id,frame_rx,subframe_rx,i,dci_alloc_rx[i].rnti, - ue->pdcch_vars[eNB_id]->crnti, - ue->ulsch[eNB_id]->cba_rnti[0], - dci_alloc_rx[i].format); + ue->pdcch_vars[eNB_id]->crnti, + ue->ulsch[eNB_id]->cba_rnti[0], + dci_alloc_rx[i].format); // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); -#endif -#ifdef DIAG_PHY - ue->pdcch_vars[eNB_id]->dci_errors++; - ue->pdcch_vars[eNB_id]->dci_false++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - return(-1); #endif } } -/* - if ((frame_rx > 1000) && ((frame_rx&1)==0) && (subframe_rx == 5)) { - write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],10*ue->frame_parms.samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],ue->frame_parms.ofdm_symbol_size*2*((ue->frame_parms.Ncp==0)?14:12),2,1); - write_output("H00.m","h00",&(ue->common_vars.dl_ch_estimates[0][0][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1); - write_output("pdcch_rxF_ext0.m","pdcch_rxF_ext0",ue->pdcch_vars[eNB_id]->rxdataF_ext[0],3*12*ue->frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",ue->pdcch_vars[eNB_id]->rxdataF_comp[0],4*12*ue->frame_parms.N_RB_DL,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",ue->pdcch_vars[eNB_id]->llr,2400,1,4); - mac_xface->macphy_exit("debug exit"); - } -*/ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(0); } -int phy_procedures_UE_RX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, - relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn) -{ +int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, + relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn) { uint16_t l,m,n_symb; // int eNB_id = 0, @@ -2354,1080 +2129,1005 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag uint8_t harq_pid = -1; int timing_advance; uint8_t pilot1,pilot2,pilot3; -#ifndef DLSCH_THREAD uint8_t i_mod = 0; int eNB_id_i = 1; uint8_t dual_stream_UE = 0; -#endif + uint8_t *rar; int pmch_flag=0; uint8_t sync_area=255; int pmch_mcs=-1; uint8_t mcch_active=0; - int frame_rx = ue->frame_rx; - int slot_rx = ue->slot_rx; - int subframe_rx = slot_rx>>1; + int frame_rx = proc->frame_rx; + int subframe_rx = proc->subframe_rx; int subframe_prev = (subframe_rx+9)%10; int CC_id = ue->CC_id; + int slot; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); start_meas(&ue->phy_proc_rx); + + for (slot=0;slot<2;slot++) { + #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[%s %d] Frame %d subframe %d: Doing phy_procedures_UE_RX(%d)\n", - (r_type == multicast_relay) ? "RN/UE" : "UE", - ue->Mod_id,frame_rx, subframe_rx, slot_rx); + LOG_D(PHY,"[%s %d] Frame %d subframe %d: Doing phy_procedures_UE_RX (%d)\n", + (r_type == multicast_relay) ? "RN/UE" : "UE", + ue->Mod_id,frame_rx, subframe_rx,slot); #endif #ifdef EMOS - - if ((slot_rx == 0)) { - if (frame_rx%1024 == 0) - openair_daq_vars.use_ia_receiver = 0; - else - openair_daq_vars.use_ia_receiver = (openair_daq_vars.use_ia_receiver+1)%3; - - LOG_D(PHY,"[MYEMOS] frame %d, IA receiver %d, MCS %d, bitrate %d\n", - frame_rx, - openair_daq_vars.use_ia_receiver, - ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs, - ue->bitrate[eNB_id]); - } - -#endif - - if (ue->frame_parms.Ncp == 0) { // normal prefix - pilot1 = 4; - pilot2 = 7; - pilot3 = 11; - } else { // extended prefix - pilot1 = 3; - pilot2 = 6; - pilot3 = 9; - } - - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - if (subframe_select(&ue->frame_parms,subframe_rx) == SF_S) { - if ((slot_rx%2)==0) - n_symb = 5;//3; - else - n_symb = 0; - } else { - /* - if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { - if ((slot_rx%2)==0) { - n_symb=2; - pmch_flag=1; - } + + if (subframe_rx == 0) { + if (frame_rx%1024 == 0) + openair_daq_vars.use_ia_receiver = 0; else - n_symb=0; - } - else*/ - n_symb = ue->frame_parms.symbols_per_tti/2; - } + openair_daq_vars.use_ia_receiver = (openair_daq_vars.use_ia_receiver+1)%3; - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // This is normal processing (i.e. not MBSFN) - // RX processing of symbols in slot_rx - - - - for (l=0; lofdm_demod_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - - slot_fep(ue, - l, - slot_rx, - ue->rx_offset, - 0, - 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); - stop_meas(&ue->ofdm_demod_stats); - } - - //if (subframe_select(&ue->frame_parms,subframe_rx) == SF_DL) - ue_measurement_procedures(l,ue,eNB_id,abstraction_flag,mode); - - - if ((slot_rx==1) && (l==4-ue->frame_parms.Ncp)) { - - /* - ue->ulsch_no_allocation_counter[eNB_id]++; - - if (ue->ulsch_no_allocation_counter[eNB_id] == 10) { - #ifdef DEBUG_PHY_PROC - msg("[UE %d] no_allocation : setting mode to PRACH\n",ue->Mod_id); - #endif - ue->UE_mode[eNB_id] = PRACH; - ue->pdcch_vars[eNB_id]->crnti = 0x1234; - } - */ - - ue_pbch_procedures(eNB_id,ue,abstraction_flag); - - /* - if (ue->UE_mode[eNB_id] == RA_RESPONSE) { - ue->Msg3_timer[eNB_id]--; - msg("[UE RAR] frame %d: Msg3_timer %d\n",frame_rx,ue->Msg3_timer); - - if (ue->Msg3_timer[eNB_id] == 0) { - LOG_D(PHY,"[UE %d] Frame %d: Msg3_timer = 0 : setting mode to PRACH\n",ue->Mod_id,frame_rx); - // I guess here we also need to tell the RRC - ue->UE_mode[eNB_id] = PRACH; - ue->pdcch_vars[eNB_id]->crnti = 0x1234; - } - } - */ - } - -#ifdef DLSCH_THREAD - if (ue->dlsch[eNB_id][0]->active == 1) { - // activate thread since Chest is now done for slot before slot_rx - if (l==0) { - LOG_I(PHY,"frame %d, slot_rx %d: Calling rx_pdsch_thread for harq_pid %d\n",frame_rx,slot_rx, ue->dlsch[eNB_id][0]->current_harq_pid); - - if (pthread_mutex_lock (&rx_pdsch_mutex) != 0) { // Signal MAC_PHY Scheduler - LOG_E(PHY,"[UE %d] ERROR pthread_mutex_lock\n",ue->Mod_id); // lock before accessing shared resource - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - } else { - rx_pdsch_instance_cnt++; - (slot_rx == 0) ? (rx_pdsch_slot = 19) : (rx_pdsch_slot = (slot_rx-1)); - pthread_mutex_unlock (&rx_pdsch_mutex); - - if (rx_pdsch_instance_cnt == 0) { - if (pthread_cond_signal(&rx_pdsch_cond) != 0) { - LOG_E(PHY,"[UE %d] ERROR pthread_cond_signal for rx_pdsch_cond\n",ue->Mod_id); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - } - } else { - LOG_W(PHY,"[UE %d] Frame=%d, Slot=%d, RX_PDSCH thread for rx_pdsch_thread busy!!!\n",ue->Mod_id,frame_rx,slot_rx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - } - } - - // trigger DLSCH decoding thread - if ((slot_rx%2)==1) // odd slots - ue->dlsch[eNB_id][0]->active = 0; - } + LOG_D(PHY,"[MYEMOS] frame %d, IA receiver %d, MCS %d, bitrate %d\n", + frame_rx, + openair_daq_vars.use_ia_receiver, + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->mcs, + ue->bitrate[eNB_id]); } #endif - // process last DLSCH symbols + invoke decoding - if (((slot_rx%2)==0) && (l==0)) { - // Regular PDSCH - LOG_D(PHY,"[UE %d] dlsch->active in subframe %d => %d\n",ue->Mod_id,subframe_prev,ue->dlsch[eNB_id][0]->active); + if (ue->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + pilot2 = 7; + pilot3 = 11; + } else { // extended prefix + pilot1 = 3; + pilot2 = 6; + pilot3 = 9; + } - if (ue->dlsch[eNB_id][0]->active == 1) { -#ifndef DLSCH_THREAD //USER_MODE - harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; - LOG_D(PHY,"[UE %d] PDSCH active in subframe %d, harq_pid %d\n",ue->Mod_id,subframe_prev,harq_pid); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + if (subframe_select(&ue->frame_parms,subframe_rx) == SF_S) { + if (slot==0) + n_symb = 5;//3; + else + n_symb = 0; + } else { + n_symb = ue->frame_parms.symbols_per_tti/2; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // This is normal processing (i.e. not MBSFN) + // RX processing of symbols in slot - if ((ue->transmission_mode[eNB_id] == 5) && - (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (ue->use_ia_receiver ==1)) { - dual_stream_UE = 1; - eNB_id_i = ue->n_connected_eNB; - i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; + - if (frame_rx%100==0) { - LOG_I(PHY,"using IA receiver\n"); - } - } else { - dual_stream_UE = 0; - eNB_id_i = eNB_id+1; - i_mod = 0; - } + for (l=0; lofdm_demod_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - // process symbols 10,11,12 and trigger DLSCH decoding - if (abstraction_flag == 0) { + slot_fep(ue, + l, + (subframe_rx<<1)+slot, + ue->rx_offset, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); + stop_meas(&ue->ofdm_demod_stats); + } - start_meas(&ue->dlsch_llr_stats); + ue_measurement_procedures(l,ue,proc,eNB_id,abstraction_flag,mode); - for (m=pilot3; mframe_parms.symbols_per_tti; m++) { + if ((slot==1) && (l==4-ue->frame_parms.Ncp)) { - rx_pdsch(ue, - PDSCH, - eNB_id, - eNB_id_i, - subframe_prev, // subframe - m, // symbol - 0, // first_symbol_flag - dual_stream_UE, - i_mod, - ue->dlsch[eNB_id][0]->current_harq_pid); - } + ue_pbch_procedures(eNB_id,ue,proc,abstraction_flag); - stop_meas(&ue->dlsch_llr_stats); - } + } + + // process last DLSCH symbols + invoke decoding + if ((slot==0) && + (l==0)) { + // Regular PDSCH + LOG_D(PHY,"[UE %d] dlsch->active in subframe %d => %d\n",ue->Mod_id,subframe_prev,ue->dlsch[eNB_id][0]->active); - ue->dlsch[eNB_id][0]->active = 0; + + if (ue->dlsch[eNB_id][0]->active == 1) { - //#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d Scheduling DLSCH decoding\n", - ue->Mod_id, - ue->dlsch[eNB_id][0]->rnti, - harq_pid, - (subframe_prev == 9) ? (frame_rx-1) : frame_rx,subframe_prev); - //#endif + harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; + LOG_D(PHY,"[UE %d] PDSCH active in subframe %d, harq_pid %d\n",ue->Mod_id,subframe_prev,harq_pid); - if (ue->dlsch[eNB_id][0]) { - if (abstraction_flag == 0) { - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->G = get_G(&ue->frame_parms, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - frame_rx,subframe_prev); - start_meas(&ue->dlsch_unscrambling_stats); - dlsch_unscrambling(&ue->frame_parms, - 0, - ue->dlsch[0][0], - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->G, - ue->pdsch_vars[eNB_id]->llr[0], - 0, - subframe_prev<<1); - stop_meas(&ue->dlsch_unscrambling_stats); + if ((ue->transmission_mode[eNB_id] == 5) && + (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && + (ue->use_ia_receiver ==1)) { + dual_stream_UE = 1; + eNB_id_i = ue->n_connected_eNB; + i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; - start_meas(&ue->dlsch_decoding_stats); - ret = dlsch_decoding(ue, - ue->pdsch_vars[eNB_id]->llr[0], - &ue->frame_parms, - ue->dlsch[eNB_id][0], - ue->dlsch[eNB_id][0]->harq_processes[harq_pid], - subframe_prev, - harq_pid, - 1,ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb>10 ? 1 : 0); - stop_meas(&ue->dlsch_decoding_stats); - } + if (frame_rx%100==0) { + LOG_I(PHY,"using IA receiver\n"); + } + } else { + dual_stream_UE = 0; + eNB_id_i = eNB_id+1; + i_mod = 0; + } + + // process symbols 10,11,12 and trigger DLSCH decoding + if (abstraction_flag == 0) { - else { - LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); + start_meas(&ue->dlsch_llr_stats); + + for (m=pilot3; mframe_parms.symbols_per_tti; m++) { + + rx_pdsch(ue, + PDSCH, + eNB_id, + eNB_id_i, + subframe_prev, // subframe + m, // symbol + 0, // first_symbol_flag + dual_stream_UE, + i_mod, + ue->dlsch[eNB_id][0]->current_harq_pid); + } + + stop_meas(&ue->dlsch_llr_stats); + } + + ue->dlsch[eNB_id][0]->active = 0; + + + + //#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d Scheduling DLSCH decoding\n", + ue->Mod_id, + ue->dlsch[eNB_id][0]->rnti, + harq_pid, + (subframe_prev == 9) ? (frame_rx-1) : frame_rx,subframe_prev); + //#endif + + if (ue->dlsch[eNB_id][0]) { + if (abstraction_flag == 0) { + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->G = get_G(&ue->frame_parms, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + frame_rx,subframe_prev); + start_meas(&ue->dlsch_unscrambling_stats); + dlsch_unscrambling(&ue->frame_parms, + 0, + ue->dlsch[0][0], + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->G, + ue->pdsch_vars[eNB_id]->llr[0], + 0, + subframe_prev<<1); + stop_meas(&ue->dlsch_unscrambling_stats); + + start_meas(&ue->dlsch_decoding_stats); + ret = dlsch_decoding(ue, + ue->pdsch_vars[eNB_id]->llr[0], + &ue->frame_parms, + ue->dlsch[eNB_id][0], + ue->dlsch[eNB_id][0]->harq_processes[harq_pid], + subframe_prev, + harq_pid, + 1,ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->nb_rb>10 ? 1 : 0); + stop_meas(&ue->dlsch_decoding_stats); + } + + else { + LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); #ifdef PHY_ABSTRACTION - ret = dlsch_decoding_emul(ue, - subframe_prev, - 2, - eNB_id); + ret = dlsch_decoding_emul(ue, + subframe_prev, + 2, + eNB_id); #endif - } + } - if (ret == (1+ue->dlsch[eNB_id][0]->max_turbo_iterations)) { - ue->dlsch_errors[eNB_id]++; + if (ret == (1+ue->dlsch[eNB_id][0]->max_turbo_iterations)) { + ue->dlsch_errors[eNB_id]++; #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n", - ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, - harq_pid,frame_rx,subframe_prev, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); -/* - if (abstraction_flag ==0 ) - dump_dlsch(ue,eNB_id,subframe_prev,harq_pid); - mac_xface->macphy_exit(""); -*/ + LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n", + ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, + harq_pid,frame_rx,subframe_prev, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); + #endif - } else { - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d (slot_rx %d): Received DLSCH (rv %d,mcs %d,TBS %d)\n", - ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, - harq_pid,frame_rx,subframe_prev,slot_rx, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); + } else { + LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d (slot %d): Received DLSCH (rv %d,mcs %d,TBS %d)\n", + ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, + harq_pid,frame_rx,subframe_prev,slot, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); #ifdef DEBUG_PHY_PROC #ifdef DEBUG_DLSCH - int j; - LOG_D(PHY,"dlsch harq_pid %d (rx): \n",ue->dlsch[eNB_id][0]->current_harq_pid); + int j; + LOG_D(PHY,"dlsch harq_pid %d (rx): \n",ue->dlsch[eNB_id][0]->current_harq_pid); - for (j=0; jdlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->b[j]); + for (j=0; jdlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS>>3; j++) + LOG_T(PHY,"%x.",ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->b[j]); - LOG_T(PHY,"\n"); + LOG_T(PHY,"\n"); #endif #endif - if (ue->mac_enabled == 1) { - mac_xface->ue_send_sdu(ue->Mod_id, - CC_id, - frame_rx, - ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->b, - ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS>>3, - eNB_id); + + if (ue->mac_enabled == 1) { + mac_xface->ue_send_sdu(ue->Mod_id, + CC_id, + frame_rx, + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->b, + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS>>3, + eNB_id); + } + ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS; + ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + + ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS; } - ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + - ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS; - ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + - ue->dlsch[eNB_id][0]->harq_processes[ue->dlsch[eNB_id][0]->current_harq_pid]->TBS; - } - } - + } + #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)\n", - ue->Mod_id, - ue->dlsch[eNB_id][0]->rnti,harq_pid, - frame_rx,subframe_prev,ret, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, - ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); + LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d: PDSCH/DLSCH decoding iter %d (mcs %d, rv %d, TBS %d)\n", + ue->Mod_id, + ue->dlsch[eNB_id][0]->rnti,harq_pid, + frame_rx,subframe_prev,ret, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->mcs, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->rvidx, + ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->TBS); - if (frame_rx%100==0) { - LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d dlsch_errors %d, dlsch_received %d, dlsch_fer %d, current_dlsch_cqi %d\n", - ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, - frame_rx,subframe_prev, - ue->dlsch_errors[eNB_id], - ue->dlsch_received[eNB_id], - ue->dlsch_fer[eNB_id], - ue->measurements.wideband_cqi_tot[eNB_id]); - } - -#endif -#endif //DLSCH_THREAD - } else { - // printf("PDSCH inactive in subframe %d\n",subframe_rx-1); - ue->dlsch[eNB_id][0]->harq_ack[subframe_prev].send_harq_status = 0; - } - - // SI_DLSCH - if (ue->dlsch_SI[eNB_id]->active == 1) { -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"SI is active in subframe %d\n",subframe_prev); -#endif - - // process symbols 10,11,12 (13) of last SF and trigger DLSCH decoding - if (abstraction_flag==0) { - start_meas(&ue->dlsch_llr_stats); - - for (m=pilot3; mframe_parms.symbols_per_tti; m++) { -#ifdef DEBUG_PHY_PROC - - LOG_D(PHY,"[UE %d] Frame %d, slot %d: DLSCH (SI) demod between pilot 3 and 4 (2nd slot), m %d\n", - ue->Mod_id,frame_rx,slot_rx,m); - -#endif - rx_pdsch(ue, - SI_PDSCH, - eNB_id, - eNB_id+1, - subframe_prev, // subframe, - m, - 0, - 0, - ue->is_secondary_ue, - ue->dlsch_SI[eNB_id]->current_harq_pid); - } - - stop_meas(&ue->dlsch_llr_stats); - } - - // write_output("dlsch_ra_llr.m","llr",pdsch_vars_ra[eNB_id]->llr[0],40,1,0); - - ue->dlsch_SI[eNB_id]->active = 0; - - if (frame_rx < ue->dlsch_SI_errors[eNB_id]) - ue->dlsch_SI_errors[eNB_id]=0; - - if (ue->dlsch_SI[eNB_id]) { - - if (abstraction_flag==0) { - - // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); - ue->dlsch_SI[eNB_id]->harq_processes[0]->G = - get_G(&ue->frame_parms, - ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even, - 2, - 1, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - frame_rx,subframe_prev); - -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"Decoding DLSCH_SI : rb_alloc %x : nb_rb %d G %d TBS %d, num_pdcch_sym %d\n",ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], - ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, - ue->dlsch_SI[eNB_id]->harq_processes[0]->G, - ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols); -#endif - - - dlsch_unscrambling(&ue->frame_parms, - 0, - ue->dlsch_SI[eNB_id], - ue->dlsch_SI[eNB_id]->harq_processes[0]->G, - ue->pdsch_vars_SI[eNB_id]->llr[0], - 0, - subframe_prev<<1); - - ret = dlsch_decoding(ue, - ue->pdsch_vars_SI[eNB_id]->llr[0], - &ue->frame_parms, - ue->dlsch_SI[eNB_id], - ue->dlsch_SI[eNB_id]->harq_processes[0], - subframe_prev, - ue->dlsch_SI[eNB_id]->current_harq_pid, - 0,0); - -#ifdef DEBUG_PHY_PROC - - for (int i=0; i<11; i++) - LOG_D(PHY,"dlsch_output_buffer[%d]=%x\n",i,ue->dlsch_SI[eNB_id]->harq_processes[0]->c[0][i]); + if (frame_rx%100==0) { + LOG_D(PHY,"[UE %d][PDSCH %x] Frame %d subframe %d dlsch_errors %d, dlsch_received %d, dlsch_fer %d, current_dlsch_cqi %d\n", + ue->Mod_id,ue->dlsch[eNB_id][0]->rnti, + frame_rx,subframe_prev, + ue->dlsch_errors[eNB_id], + ue->dlsch_received[eNB_id], + ue->dlsch_fer[eNB_id], + ue->measurements.wideband_cqi_tot[eNB_id]); + } #endif - } + } else { + // printf("PDSCH inactive in subframe %d\n",subframe_rx-1); + ue->dlsch[eNB_id][0]->harq_ack[subframe_prev].send_harq_status = 0; + } + + + // SI_DLSCH + if (ue->dlsch_SI[eNB_id]->active == 1) { +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"SI is active in subframe %d\n",subframe_prev); +#endif + + // process symbols 10,11,12 (13) of last SF and trigger DLSCH decoding + if (abstraction_flag==0) { + start_meas(&ue->dlsch_llr_stats); + + for (m=pilot3; mframe_parms.symbols_per_tti; m++) { +#ifdef DEBUG_PHY_PROC + + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: DLSCH (SI) demod between pilot 3 and 4 (2nd slot), m %d\n", + ue->Mod_id,frame_rx,subframe_rx,m); + +#endif + rx_pdsch(ue, + SI_PDSCH, + eNB_id, + eNB_id+1, + subframe_prev, // subframe, + m, + 0, + 0, + ue->is_secondary_ue, + ue->dlsch_SI[eNB_id]->current_harq_pid); + } + + stop_meas(&ue->dlsch_llr_stats); + } + + // write_output("dlsch_ra_llr.m","llr",pdsch_vars_ra[eNB_id]->llr[0],40,1,0); + + ue->dlsch_SI[eNB_id]->active = 0; + + if (frame_rx < ue->dlsch_SI_errors[eNB_id]) + ue->dlsch_SI_errors[eNB_id]=0; + + if (ue->dlsch_SI[eNB_id]) { + + if (abstraction_flag==0) { + + // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + ue->dlsch_SI[eNB_id]->harq_processes[0]->G = + get_G(&ue->frame_parms, + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even, + 2, + 1, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + frame_rx,subframe_prev); + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"Decoding DLSCH_SI : rb_alloc %x : nb_rb %d G %d TBS %d, num_pdcch_sym %d\n",ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], + ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_SI[eNB_id]->harq_processes[0]->G, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols); +#endif + + + dlsch_unscrambling(&ue->frame_parms, + 0, + ue->dlsch_SI[eNB_id], + ue->dlsch_SI[eNB_id]->harq_processes[0]->G, + ue->pdsch_vars_SI[eNB_id]->llr[0], + 0, + subframe_prev<<1); + + ret = dlsch_decoding(ue, + ue->pdsch_vars_SI[eNB_id]->llr[0], + &ue->frame_parms, + ue->dlsch_SI[eNB_id], + ue->dlsch_SI[eNB_id]->harq_processes[0], + subframe_prev, + ue->dlsch_SI[eNB_id]->current_harq_pid, + 0,0); + +#ifdef DEBUG_PHY_PROC + + for (int i=0; i<11; i++) + LOG_D(PHY,"dlsch_output_buffer[%d]=%x\n",i,ue->dlsch_SI[eNB_id]->harq_processes[0]->c[0][i]); + +#endif + + + + + + #ifdef PHY_ABSTRACTION - else { - LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); - ret = dlsch_decoding_emul(ue, - subframe_prev, - 0, - eNB_id); - } + else { + LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); + ret = dlsch_decoding_emul(ue, + subframe_prev, + 0, + eNB_id); + } + +#endif + + + + + + if (ret == (1+ue->dlsch_SI[eNB_id]->max_turbo_iterations)) { + ue->dlsch_SI_errors[eNB_id]++; +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received SI in error (TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", + ue->Mod_id, + frame_rx, + subframe_prev, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, + ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rvidx, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); +#endif + + // dump_dlsch_SI(ue,eNB_id,subframe_prev); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); + stop_meas(&ue->phy_proc_rx); + return(-1); + } else { + + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received SI for TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", + ue->Mod_id,frame_rx,subframe_prev, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, + ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rvidx, + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], + ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); +#endif + + if (ue->mac_enabled == 1) { + mac_xface->ue_decode_si(ue->Mod_id, + CC_id, + frame_rx, + eNB_id, + ue->dlsch_SI[eNB_id]->harq_processes[0]->b, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); + } + } + } + } + } + + if (ue->dlsch_ra[eNB_id]->active == 1) { +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: DLSCH (RA) demod symbols 10,11,12\n",ue->Mod_id,frame_rx,subframe_rx); +#endif + + // process symbols 10,11,12 and trigger DLSCH decoding + if (abstraction_flag==0) { + start_meas(&ue->dlsch_llr_stats); + + for (m=pilot3; mframe_parms.symbols_per_tti; m++) + rx_pdsch(ue, + RA_PDSCH, + eNB_id, + eNB_id+1, + subframe_prev, // subframe, + m, // symbol + 0, // first_symbol_flag + 0, + ue->is_secondary_ue, + ue->dlsch_ra[eNB_id]->current_harq_pid); + } + + stop_meas(&ue->dlsch_llr_stats); + + ue->dlsch_ra[eNB_id]->active = 0; + + if (frame_rx < ue->dlsch_ra_errors[eNB_id]) + ue->dlsch_ra_errors[eNB_id]=0; + + if (ue->prach_resources[eNB_id]!=NULL) + ue->dlsch_ra[eNB_id]->rnti = ue->prach_resources[eNB_id]->ra_RNTI; + else { + LOG_E(PHY,"[UE %d] Frame %d, subframe %d: FATAL, prach_resources is NULL\n",ue->Mod_id,frame_rx,subframe_prev); + mac_xface->macphy_exit("prach_resources is NULL"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); + stop_meas(&ue->phy_proc_rx); + return 0; + } + + if (abstraction_flag==0) { + ue->dlsch_ra[eNB_id]->harq_processes[0]->G = get_G(&ue->frame_parms, + ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, + ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even, + 2, + 1, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + frame_rx, + subframe_prev); + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE] decoding RA (subframe %d): G %d,rnti %x\n" ,subframe_prev, + ue->dlsch_ra[eNB_id]->harq_processes[0]->G, + ue->dlsch_ra[eNB_id]->rnti); +#endif + + dlsch_unscrambling(&ue->frame_parms, + 0, + ue->dlsch_ra[eNB_id], + ue->dlsch_ra[eNB_id]->harq_processes[0]->G, + ue->pdsch_vars_ra[eNB_id]->llr[0], + 0, + subframe_prev<<1); + + ret = dlsch_decoding(ue, + ue->pdsch_vars_ra[eNB_id]->llr[0], + &ue->frame_parms, + ue->dlsch_ra[eNB_id], + ue->dlsch_ra[eNB_id]->harq_processes[0], + subframe_prev, // subframe + ue->dlsch_ra[eNB_id]->current_harq_pid, + 0,0); + } + +#ifdef PHY_ABSTRACTION + else { + LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); + ret = dlsch_decoding_emul(ue, + subframe_prev, + 1, + eNB_id); + } #endif - if (ret == (1+ue->dlsch_SI[eNB_id]->max_turbo_iterations)) { - ue->dlsch_SI_errors[eNB_id]++; + + + if (ret == (1+ue->dlsch_ra[eNB_id]->max_turbo_iterations)) { + ue->dlsch_ra_errors[eNB_id]++; + LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received RA in error\n",ue->Mod_id,frame_rx,subframe_prev); + + // dump_dlsch_ra(ue,eNB_id,subframe_prev); exit(-1); + + // oai_exit=1; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); + stop_meas(&ue->phy_proc_rx); + return(-1); + + } else { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received SI in error (TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", + LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Received RAR mode %d\n", ue->Mod_id, frame_rx, - subframe_prev, - ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, - ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, - ue->dlsch_SI[eNB_id]->harq_processes[0]->rvidx, - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); -#endif - - // dump_dlsch_SI(ue,eNB_id,subframe_prev); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&ue->phy_proc_rx); - return(-1); - } else { - - -#ifdef DEBUG_PHY_PROC - //if ((frame_rx % 100) == 0) - LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received SI for TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", - ue->Mod_id,frame_rx,subframe_prev, - ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS, - ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, - ue->dlsch_SI[eNB_id]->harq_processes[0]->rvidx, - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[1], - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[2], - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even[3]); + subframe_prev, ue->UE_mode[eNB_id]); #endif if (ue->mac_enabled == 1) { - /* - printf("\n\n"); - for (i=0;idlsch_SI[eNB_id]->harq_processes[0]->TBS>>3;i++) - printf("%02x ",ue->dlsch_SI[eNB_id]->harq_processes[0]->b[i]); - printf("\n"); - */ - mac_xface->ue_decode_si(ue->Mod_id, - CC_id, - frame_rx, - eNB_id, - ue->dlsch_SI[eNB_id]->harq_processes[0]->b, - ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); + if ((ue->UE_mode[eNB_id] != PUSCH) && (ue->prach_resources[eNB_id]->Msg3!=NULL)) { + LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Invoking MAC for RAR (current preamble %d)\n", + ue->Mod_id,frame_rx-((subframe_prev==9) ? 1 : 0), + subframe_prev, + ue->prach_resources[eNB_id]->ra_PreambleIndex); + + timing_advance = mac_xface->ue_process_rar(ue->Mod_id, + CC_id, + frame_rx-((subframe_prev==0) ? 1 : 0), + ue->dlsch_ra[eNB_id]->harq_processes[0]->b, + &ue->pdcch_vars[eNB_id]->crnti, + ue->prach_resources[eNB_id]->ra_PreambleIndex); + + + if (timing_advance!=0xffff) { + + LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Got rnti %x and timing advance %d from RAR\n", + ue->Mod_id, + frame_rx-((subframe_prev==9) ? 1 : 0), + subframe_prev, + ue->pdcch_vars[eNB_id]->crnti, + timing_advance); + + //timing_advance = 0; + process_timing_advance_rar(ue,proc,timing_advance); + + if (mode!=debug_prach) { + ue->ulsch_Msg3_active[eNB_id]=1; + get_Msg3_alloc(&ue->frame_parms, + subframe_prev, + frame_rx-((subframe_prev==9) ? 1 : 0), + &ue->ulsch_Msg3_frame[eNB_id], + &ue->ulsch_Msg3_subframe[eNB_id]); + + LOG_D(PHY,"[UE %d][RAPROC] Got Msg3_alloc Frame %d subframe %d: Msg3_frame %d, Msg3_subframe %d\n", + ue->Mod_id, + frame_rx-((subframe_prev==9) ? 1 : 0), + subframe_prev, + ue->ulsch_Msg3_frame[eNB_id], + ue->ulsch_Msg3_subframe[eNB_id]); + harq_pid = subframe2harq_pid(&ue->frame_parms, + ue->ulsch_Msg3_frame[eNB_id], + ue->ulsch_Msg3_subframe[eNB_id]); + ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; + + ue->UE_mode[eNB_id] = RA_RESPONSE; + // ue->Msg3_timer[eNB_id] = 10; + ue->ulsch[eNB_id]->power_offset = 6; + ue->ulsch_no_allocation_counter[eNB_id] = 0; + } + } else { // PRACH preamble doesn't match RAR + LOG_W(PHY,"[UE %d][RAPROC] Received RAR preamble (%d) doesn't match !!!\n", + ue->Mod_id, + ue->prach_resources[eNB_id]->ra_PreambleIndex); + } + } // mode != PUSCH } - } - } - - /* - #ifdef DEBUG_PHY_PROC - debug_LOG_D(PHY,"[UE %d] Frame %d, slot %d: dlsch_decoding (SI) ret %d (%d errors)\n", - ue->Mod_id,frame_rx,slot_rx,ret,ue->dlsch_SI_errors[eNB_id]); - #endif - */ - } - - - if (ue->dlsch_ra[eNB_id]->active == 1) { -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d: DLSCH (RA) demod symbols 10,11,12\n",ue->Mod_id,frame_rx,slot_rx); -#endif - - // process symbols 10,11,12 and trigger DLSCH decoding - if (abstraction_flag==0) { - start_meas(&ue->dlsch_llr_stats); - - for (m=pilot3; mframe_parms.symbols_per_tti; m++) - rx_pdsch(ue, - RA_PDSCH, - eNB_id, - eNB_id+1, - subframe_prev, // subframe, - m, // symbol - 0, // first_symbol_flag - 0, - ue->is_secondary_ue, - ue->dlsch_ra[eNB_id]->current_harq_pid); - } - - stop_meas(&ue->dlsch_llr_stats); - - ue->dlsch_ra[eNB_id]->active = 0; - - if (frame_rx < ue->dlsch_ra_errors[eNB_id]) - ue->dlsch_ra_errors[eNB_id]=0; - - if (ue->prach_resources[eNB_id]!=NULL) - ue->dlsch_ra[eNB_id]->rnti = ue->prach_resources[eNB_id]->ra_RNTI; - else { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d: FATAL, prach_resources is NULL\n",ue->Mod_id,frame_rx,subframe_prev); - mac_xface->macphy_exit("prach_resources is NULL"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&ue->phy_proc_rx); - return 0; - } - - if (abstraction_flag==0) { - ue->dlsch_ra[eNB_id]->harq_processes[0]->G = get_G(&ue->frame_parms, - ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, - ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even, - 2, - 1, - ue->pdcch_vars[eNB_id]->num_pdcch_symbols, - frame_rx, - subframe_prev); - -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE] decoding RA (subframe %d): G %d,rnti %x\n" ,subframe_prev, - ue->dlsch_ra[eNB_id]->harq_processes[0]->G, - ue->dlsch_ra[eNB_id]->rnti); -#endif - - dlsch_unscrambling(&ue->frame_parms, - 0, - ue->dlsch_ra[eNB_id], - ue->dlsch_ra[eNB_id]->harq_processes[0]->G, - ue->pdsch_vars_ra[eNB_id]->llr[0], - 0, - subframe_prev<<1); - - ret = dlsch_decoding(ue, - ue->pdsch_vars_ra[eNB_id]->llr[0], - &ue->frame_parms, - ue->dlsch_ra[eNB_id], - ue->dlsch_ra[eNB_id]->harq_processes[0], - subframe_prev, // subframe - ue->dlsch_ra[eNB_id]->current_harq_pid, - 0,0); - } - -#ifdef PHY_ABSTRACTION - else { - LOG_D(PHY,"Calling dlsch_decoding_emul ...\n"); - ret = dlsch_decoding_emul(ue, - subframe_prev, - 1, - eNB_id); - } - -#endif - - if (ret == (1+ue->dlsch_ra[eNB_id]->max_turbo_iterations)) { - ue->dlsch_ra_errors[eNB_id]++; - LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received RA in error\n",ue->Mod_id,frame_rx,subframe_prev); - - // dump_dlsch_ra(ue,eNB_id,subframe_prev); exit(-1); - - // oai_exit=1; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); - stop_meas(&ue->phy_proc_rx); - return(-1); - - } else { -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Received RAR mode %d\n", - ue->Mod_id, - frame_rx, - subframe_prev, ue->UE_mode[eNB_id]); -#endif - - if (ue->mac_enabled == 1) { - if ((ue->UE_mode[eNB_id] != PUSCH) && (ue->prach_resources[eNB_id]->Msg3!=NULL)) { - LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Invoking MAC for RAR (current preamble %d)\n", - ue->Mod_id,frame_rx-((subframe_prev==9) ? 1 : 0), - subframe_prev, - ue->prach_resources[eNB_id]->ra_PreambleIndex); - - timing_advance = mac_xface->ue_process_rar(ue->Mod_id, - CC_id, - frame_rx-((subframe_prev==0) ? 1 : 0), - ue->dlsch_ra[eNB_id]->harq_processes[0]->b, - &ue->pdcch_vars[eNB_id]->crnti, - ue->prach_resources[eNB_id]->ra_PreambleIndex); - - - if (timing_advance!=0xffff) { - - LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Got rnti %x and timing advance %d from RAR\n", - ue->Mod_id, - frame_rx-((subframe_prev==9) ? 1 : 0), - subframe_prev, - ue->pdcch_vars[eNB_id]->crnti, - timing_advance); - - //timing_advance = 0; - process_timing_advance_rar(ue,timing_advance); - - if (mode!=debug_prach) { - ue->ulsch_Msg3_active[eNB_id]=1; - get_Msg3_alloc(&ue->frame_parms, - subframe_prev, - frame_rx-((subframe_prev==9) ? 1 : 0), - &ue->ulsch_Msg3_frame[eNB_id], - &ue->ulsch_Msg3_subframe[eNB_id]); - - LOG_D(PHY,"[UE %d][RAPROC] Got Msg3_alloc Frame %d subframe %d: Msg3_frame %d, Msg3_subframe %d\n", - ue->Mod_id, - frame_rx-((subframe_prev==9) ? 1 : 0), - subframe_prev, - ue->ulsch_Msg3_frame[eNB_id], - ue->ulsch_Msg3_subframe[eNB_id]); - harq_pid = subframe2harq_pid(&ue->frame_parms, - ue->ulsch_Msg3_frame[eNB_id], - ue->ulsch_Msg3_subframe[eNB_id]); - ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; - - ue->UE_mode[eNB_id] = RA_RESPONSE; - // ue->Msg3_timer[eNB_id] = 10; - ue->ulsch[eNB_id]->power_offset = 6; - ue->ulsch_no_allocation_counter[eNB_id] = 0; - } - } else { // PRACH preamble doesn't match RAR - LOG_W(PHY,"[UE %d][RAPROC] Received RAR preamble (%d) doesn't match !!!\n", - ue->Mod_id, - ue->prach_resources[eNB_id]->ra_PreambleIndex); - } - } // mode != PUSCH - } else { rar = ue->dlsch_ra[eNB_id]->harq_processes[0]->b+1; timing_advance = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); //timing_advance = ue->dlsch_ra[eNB_id]->harq_processes[0]->b[0]; - process_timing_advance_rar(ue,timing_advance); + process_timing_advance_rar(ue,proc,timing_advance); } - } //ret <= MAX_ITERATIONS + } //ret <= MAX_ITERATIONS + } // dlsch_ra[eNB_id]->active == 1 + } + - /* - #ifdef DEBUG_PHY_PROC - debug_LOG_D(PHY,"[UE %d] Frame %d, slot %d: dlsch_decoding (RA) ret %d (%d errors)\n", - ue->Mod_id,frame_rx,slot_rx,ret,ue->dlsch_ra_errors[eNB_id]); - #endif - */ - } // dlsch_ra[eNB_id]->active == 1 - - } - - - if ((((slot_rx%2)==0) && ((l==pilot1))) || - ((pmch_flag==1)&&(l==1))) { + if (((slot==0) && ((l==pilot1))) || + ((pmch_flag==1)&&(l==1))) { #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d: Calling pdcch procedures (eNB %d)\n",ue->Mod_id,frame_rx,slot_rx,eNB_id); + LOG_D(PHY,"[UE %d] Frame %d, slot %d: Calling pdcch procedures (eNB %d)\n",ue->Mod_id,frame_rx,slot,eNB_id); #endif - // rt_printk("[PDCCH] Frame %d, slot %d, start %llu\n",frame_rx,slot_rx,rt_get_time_ns()); - if (ue_pdcch_procedures(eNB_id,ue,abstraction_flag) == -1) { + // rt_printk("[PDCCH] Frame %d, slot %d, start %llu\n",frame_rx,slot_rx,rt_get_time_ns()); + if (ue_pdcch_procedures(eNB_id,ue,proc,abstraction_flag) == -1) { #ifdef DEBUG_PHY_PROC - LOG_E(PHY,"[UE %d] Frame %d, slot %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,slot_rx); + LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,subframe_rx); #endif return(-1); - } + } - // rt_printk("[PDCCH] Frame %d, slot %d, stop %llu\n",frame_rx,slot_rx,rt_get_time_ns()); + // rt_printk("[PDCCH] Frame %d, slot %d, stop %llu\n",frame_rx,slot_rx,rt_get_time_ns()); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[eNB_id]->num_pdcch_symbols); + LOG_D(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[eNB_id]->num_pdcch_symbols); #endif + } + + if (abstraction_flag==0) { + + if ((slot==1) && + (l==0)) { + start_meas(&ue->dlsch_llr_stats); + + for (m=ue->pdcch_vars[eNB_id]->num_pdcch_symbols; + mdlsch[eNB_id][0]->active == 1) { + harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; + LOG_D(PHY,"[UE %d] PDSCH active in subframe %d (%d), harq_pid %d\n",ue->Mod_id,subframe_rx,subframe_rx,harq_pid); + + if ((ue->transmission_mode[eNB_id] == 5) && + (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && + (ue->use_ia_receiver ==1)) { + dual_stream_UE = 1; + eNB_id_i = ue->n_connected_eNB; + i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; + } else { + dual_stream_UE = 0; + eNB_id_i = eNB_id+1; + i_mod = 0; + } + + // process DLSCH received in first slot + + + + rx_pdsch(ue, + PDSCH, + eNB_id, + eNB_id_i, + subframe_rx, // subframe, + m, + (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag + dual_stream_UE, + i_mod, + ue->dlsch[eNB_id][0]->current_harq_pid); + } // CRNTI active + + + + if (ue->dlsch_SI[eNB_id]->active == 1) { + // process SI DLSCH in first slot + rx_pdsch(ue, + SI_PDSCH, + eNB_id, + eNB_id+1, + subframe_rx, // subframe, + m, + (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag + 0, + ue->is_secondary_ue, + ue->dlsch_SI[eNB_id]->current_harq_pid); + } // SI active + + if (ue->dlsch_ra[eNB_id]->active == 1) { + rx_pdsch(ue, + RA_PDSCH, + eNB_id, + eNB_id+1, + subframe_rx, // subframe, + m, + (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, + 0, + ue->is_secondary_ue, + ue->dlsch_ra[eNB_id]->current_harq_pid); + } // RA active + } // loop from first dlsch symbol to end of slot + + stop_meas(&ue->dlsch_llr_stats); + } // 2nd quarter + + + if ((slot==1) && (l==pilot1)) { + start_meas(&ue->dlsch_llr_stats); + + for (m=pilot2; mdlsch[eNB_id][0]->active == 1) { + harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; + + if ((ue->transmission_mode[eNB_id] == 5) && + (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && + (ue->use_ia_receiver ==1)) { + dual_stream_UE = 1; + eNB_id_i = ue->n_connected_eNB; + i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; + } else { + dual_stream_UE = 0; + eNB_id_i = eNB_id+1; + i_mod = 0; + } + + rx_pdsch(ue, + PDSCH, + eNB_id, + eNB_id_i, + subframe_rx, // subframe, + m, + 0, + dual_stream_UE, + i_mod, + ue->dlsch[eNB_id][0]->current_harq_pid); + } // CRNTI active + + + + if(ue->dlsch_SI[eNB_id]->active == 1) { + rx_pdsch(ue, + SI_PDSCH, + eNB_id, + eNB_id+1, + subframe_rx, // subframe, + m, + 0, // first_symbol_flag + 0, + ue->is_secondary_ue, + ue->dlsch_SI[eNB_id]->current_harq_pid); + } // SI active + + if (ue->dlsch_ra[eNB_id]->active == 1) { + rx_pdsch(ue, + RA_PDSCH, + eNB_id, + eNB_id+1, + subframe_rx, // subframe, + m, + 0, // first_symbol_flag + 0, + ue->is_secondary_ue, + ue->dlsch_ra[eNB_id]->current_harq_pid); + } // RA active + + } // loop over 3rd quarter + + stop_meas(&ue->dlsch_llr_stats); + } // 3rd quarter of subframe + } // abstraction_flag==0 + }// l loop + + // calculate some statistics + if ((subframe_rx==9) && + (slot==1)) { + if (frame_rx % 10 == 0) { + if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) + ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); + + ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; + ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; + } + + ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; + ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; + LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", + ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], + ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); + /* + if ((frame_rx % 100 == 0)) { + LOG_I(PHY,"Throughput %5.1f kbps\n",(float) ue->bitrate[eNB_id]/1000.0); + } + */ } - if (abstraction_flag==0) { + if (is_pmch_subframe((subframe_rx==9?-1:0)+frame_rx,subframe_rx,&ue->frame_parms)) { + LOG_D(PHY,"ue calling pmch subframe ..\n "); - if (((slot_rx%2)==1) && (l==0)) { - start_meas(&ue->dlsch_llr_stats); - - for (m=ue->pdcch_vars[eNB_id]->num_pdcch_symbols; - mdlsch[eNB_id][0]->active == 1) { - harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; - LOG_D(PHY,"[UE %d] PDSCH active in subframe %d (%d), harq_pid %d\n",ue->Mod_id,subframe_rx,slot_rx,harq_pid); - - if ((ue->transmission_mode[eNB_id] == 5) && - (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (ue->use_ia_receiver ==1)) { - dual_stream_UE = 1; - eNB_id_i = ue->n_connected_eNB; - i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; - } else { - dual_stream_UE = 0; - eNB_id_i = eNB_id+1; - i_mod = 0; - } - - // process DLSCH received in first slot - - rx_pdsch(ue, - PDSCH, - eNB_id, - eNB_id_i, - subframe_rx, // subframe, - m, - (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag - dual_stream_UE, - i_mod, - ue->dlsch[eNB_id][0]->current_harq_pid); - } // CRNTI active - -#endif - - if (ue->dlsch_SI[eNB_id]->active == 1) { - // process SI DLSCH in first slot - rx_pdsch(ue, - SI_PDSCH, - eNB_id, - eNB_id+1, - subframe_rx, // subframe, - m, - (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag - 0, - ue->is_secondary_ue, - ue->dlsch_SI[eNB_id]->current_harq_pid); - } // SI active - - if (ue->dlsch_ra[eNB_id]->active == 1) { - rx_pdsch(ue, - RA_PDSCH, - eNB_id, - eNB_id+1, - subframe_rx, // subframe, - m, - (m==ue->pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, - 0, - ue->is_secondary_ue, - ue->dlsch_ra[eNB_id]->current_harq_pid); - } // RA active - } // loop from first dlsch symbol to end of slot - - stop_meas(&ue->dlsch_llr_stats); - } // 2nd quarter - - if (((slot_rx%2)==1) && (l==pilot1)) { - start_meas(&ue->dlsch_llr_stats); - - for (m=pilot2; mdlsch[eNB_id][0]->active == 1) { - harq_pid = ue->dlsch[eNB_id][0]->current_harq_pid; - - if ((ue->transmission_mode[eNB_id] == 5) && - (ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && - (ue->use_ia_receiver ==1)) { - dual_stream_UE = 1; - eNB_id_i = ue->n_connected_eNB; - i_mod = ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm; - } else { - dual_stream_UE = 0; - eNB_id_i = eNB_id+1; - i_mod = 0; - } - - rx_pdsch(ue, - PDSCH, - eNB_id, - eNB_id_i, - subframe_rx, // subframe, - m, - 0, - dual_stream_UE, - i_mod, - ue->dlsch[eNB_id][0]->current_harq_pid); - } // CRNTI active - -#endif - - if(ue->dlsch_SI[eNB_id]->active == 1) { - rx_pdsch(ue, - SI_PDSCH, - eNB_id, - eNB_id+1, - subframe_rx, // subframe, - m, - 0, // first_symbol_flag - 0, - ue->is_secondary_ue, - ue->dlsch_SI[eNB_id]->current_harq_pid); - } // SI active - - if (ue->dlsch_ra[eNB_id]->active == 1) { - rx_pdsch(ue, - RA_PDSCH, - eNB_id, - eNB_id+1, - subframe_rx, // subframe, - m, - 0, // first_symbol_flag - 0, - ue->is_secondary_ue, - ue->dlsch_ra[eNB_id]->current_harq_pid); - } // RA active - - } // loop over 3rd quarter - - stop_meas(&ue->dlsch_llr_stats); - } // 3rd quarter of subframe - } // abstraction_flag==0 - }// l loop - - // calculate some statistics - if (slot_rx==19) { - if (frame_rx % 10 == 0) { - if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) - ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); - - ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; - ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; - } - - ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; - ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; - LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", - ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], - ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); - /* - if ((frame_rx % 100 == 0)) { - LOG_I(PHY,"Throughput %5.1f kbps\n",(float) ue->bitrate[eNB_id]/1000.0); - } - */ - } - - if (is_pmch_subframe((subframe_rx==9?-1:0)+frame_rx,subframe_rx,&ue->frame_parms)) { - LOG_D(PHY,"ue calling pmch subframe ..\n "); - - if ((slot_rx%2)==1) { - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation(%d)\n", - ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,slot_rx); + if (slot==1) { + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation(%d)\n", + ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,slot); #ifdef Rel10 - pmch_mcs = mac_xface->ue_query_mch(ue->Mod_id, - CC_id, - (subframe_rx==9?-1:0)+frame_rx, - subframe_rx, - eNB_id, - &sync_area, - &mcch_active); + pmch_mcs = mac_xface->ue_query_mch(ue->Mod_id, + CC_id, + (subframe_rx==9?-1:0)+frame_rx, + subframe_rx, + eNB_id, + &sync_area, + &mcch_active); - if (phy_vars_rn) - phy_vars_rn->mch_avtive[subframe_rx]=0; + if (phy_vars_rn) + phy_vars_rn->mch_avtive[subframe_rx]=0; #else - pmch_mcs=-1; + pmch_mcs=-1; #endif - if (pmch_mcs>=0) { - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Programming PMCH demodulation for mcs %d\n",ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,pmch_mcs); - fill_UE_dlsch_MCH(ue,pmch_mcs,1,0,0); + if (pmch_mcs>=0) { + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Programming PMCH demodulation for mcs %d\n",ue->Mod_id,(subframe_rx==9?-1:0)+frame_rx,subframe_rx,pmch_mcs); + fill_UE_dlsch_MCH(ue,pmch_mcs,1,0,0); - if (abstraction_flag == 0 ) { - for (l=2; l<12; l++) { + if (abstraction_flag == 0 ) { + for (l=2; l<12; l++) { - slot_fep_mbsfn(ue, - l, - subframe_rx, - 0,0);//ue->rx_offset,0); - } + slot_fep_mbsfn(ue, + l, + subframe_rx, + 0,0);//ue->rx_offset,0); + } - for (l=2; l<12; l++) { - rx_pmch(ue, - 0, - subframe_rx, - l); + for (l=2; l<12; l++) { + rx_pmch(ue, + 0, + subframe_rx, + l); - } + } - /* printf("PMCH decoding, Frame %d, subframe %d, G %d\n", - (subframe_rx==9?-1:0)+frame_rx, - subframe_rx, - ue->dlsch_MCH[0]->harq_processes[0]->G); - */ - ue->dlsch_MCH[0]->harq_processes[0]->G = get_G(&ue->frame_parms, - ue->dlsch_MCH[0]->harq_processes[0]->nb_rb, - ue->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even, - ue->dlsch_MCH[0]->harq_processes[0]->Qm, - 1, - 2, - (subframe_rx==9?-1:0)+frame_rx,subframe_rx); + /* printf("PMCH decoding, Frame %d, subframe %d, G %d\n", + (subframe_rx==9?-1:0)+frame_rx, + subframe_rx, + ue->dlsch_MCH[0]->harq_processes[0]->G); + */ + ue->dlsch_MCH[0]->harq_processes[0]->G = get_G(&ue->frame_parms, + ue->dlsch_MCH[0]->harq_processes[0]->nb_rb, + ue->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even, + ue->dlsch_MCH[0]->harq_processes[0]->Qm, + 1, + 2, + (subframe_rx==9?-1:0)+frame_rx,subframe_rx); - dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0], - ue->dlsch_MCH[0]->harq_processes[0]->G, - ue->pdsch_vars_MCH[0]->llr[0],0,subframe_prev<<1); + dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0], + ue->dlsch_MCH[0]->harq_processes[0]->G, + ue->pdsch_vars_MCH[0]->llr[0],0,subframe_prev<<1); - ret = dlsch_decoding(ue, - ue->pdsch_vars_MCH[0]->llr[0], - &ue->frame_parms, - ue->dlsch_MCH[0], - ue->dlsch_MCH[0]->harq_processes[0], - subframe_prev, - 0, - 0,1); - } else { // abstraction + ret = dlsch_decoding(ue, + ue->pdsch_vars_MCH[0]->llr[0], + &ue->frame_parms, + ue->dlsch_MCH[0], + ue->dlsch_MCH[0]->harq_processes[0], + subframe_prev, + 0, + 0,1); + } else { // abstraction #ifdef PHY_ABSTRACTION - ret = dlsch_decoding_emul(ue, - subframe_rx, - 5, // PMCH - eNB_id); + ret = dlsch_decoding_emul(ue, + subframe_rx, + 5, // PMCH + eNB_id); #endif - } + } + + if (mcch_active == 1) + ue->dlsch_mcch_trials[sync_area][0]++; + else + ue->dlsch_mtch_trials[sync_area][0]++; - if (mcch_active == 1) - ue->dlsch_mcch_trials[sync_area][0]++; - else - ue->dlsch_mtch_trials[sync_area][0]++; + if (ret == (1+ue->dlsch_MCH[0]->max_turbo_iterations)) { + if (mcch_active == 1) + ue->dlsch_mcch_errors[sync_area][0]++; + else + ue->dlsch_mtch_errors[sync_area][0]++; - if (ret == (1+ue->dlsch_MCH[0]->max_turbo_iterations)) { - if (mcch_active == 1) - ue->dlsch_mcch_errors[sync_area][0]++; - else - ue->dlsch_mtch_errors[sync_area][0]++; - - LOG_D(PHY,"[%s %d] Frame %d, subframe %d: PMCH in error (%d,%d), not passing to L2 (TBS %d, iter %d,G %d)\n", - (r_type == no_relay)? "UE": "RN/UE", ue->Mod_id, - (subframe_rx==9?-1:0)+frame_rx,subframe_rx, - ue->dlsch_mcch_errors[sync_area][0], - ue->dlsch_mtch_errors[sync_area][0], - ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, - ue->dlsch_MCH[0]->max_turbo_iterations, - ue->dlsch_MCH[0]->harq_processes[0]->G); - dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,subframe_rx); + LOG_D(PHY,"[%s %d] Frame %d, subframe %d: PMCH in error (%d,%d), not passing to L2 (TBS %d, iter %d,G %d)\n", + (r_type == no_relay)? "UE": "RN/UE", ue->Mod_id, + (subframe_rx==9?-1:0)+frame_rx,subframe_rx, + ue->dlsch_mcch_errors[sync_area][0], + ue->dlsch_mtch_errors[sync_area][0], + ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, + ue->dlsch_MCH[0]->max_turbo_iterations, + ue->dlsch_MCH[0]->harq_processes[0]->G); + dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,subframe_rx); #ifdef DEBUG_DLSCH - for (int i=0; idlsch_MCH[0]->harq_processes[0]->TBS>>3; i++) { - LOG_T(PHY,"%02x.",ue->dlsch_MCH[0]->harq_processes[0]->c[0][i]); - } + for (int i=0; idlsch_MCH[0]->harq_processes[0]->TBS>>3; i++) { + LOG_T(PHY,"%02x.",ue->dlsch_MCH[0]->harq_processes[0]->c[0][i]); + } - LOG_T(PHY,"\n"); + LOG_T(PHY,"\n"); #endif - if (subframe_rx==9) - mac_xface->macphy_exit("Why are we exiting here?"); - } else { + if (subframe_rx==9) + mac_xface->macphy_exit("Why are we exiting here?"); + } else { #ifdef Rel10 - if ((r_type == no_relay) || (mcch_active == 1)) { - mac_xface->ue_send_mch_sdu(ue->Mod_id, - CC_id, - frame_rx, - ue->dlsch_MCH[0]->harq_processes[0]->b, - ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, - eNB_id,// not relevant in eMBMS context - sync_area); - /* for (i=0;idlsch_MCH[0]->harq_processes[0]->TBS>>3;i++) - msg("%2x.",ue->dlsch_MCH[0]->harq_processes[0]->b[i]); - msg("\n"); - */ + if ((r_type == no_relay) || (mcch_active == 1)) { + mac_xface->ue_send_mch_sdu(ue->Mod_id, + CC_id, + frame_rx, + ue->dlsch_MCH[0]->harq_processes[0]->b, + ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, + eNB_id,// not relevant in eMBMS context + sync_area); + /* for (i=0;idlsch_MCH[0]->harq_processes[0]->TBS>>3;i++) + printf("%2x.",ue->dlsch_MCH[0]->harq_processes[0]->b[i]); + printf("\n"); + */ - if (mcch_active == 1) - ue->dlsch_mcch_received[sync_area][0]++; - else - ue->dlsch_mtch_received[sync_area][0]++; + if (mcch_active == 1) + ue->dlsch_mcch_received[sync_area][0]++; + else + ue->dlsch_mtch_received[sync_area][0]++; - if (ue->dlsch_mch_received_sf[subframe_rx%5][0] == 1 ) { - ue->dlsch_mch_received_sf[subframe_rx%5][0]=0; - } else { - ue->dlsch_mch_received[0]+=1; - ue->dlsch_mch_received_sf[subframe_rx][0]=1; - } + if (ue->dlsch_mch_received_sf[subframe_rx%5][0] == 1 ) { + ue->dlsch_mch_received_sf[subframe_rx%5][0]=0; + } else { + ue->dlsch_mch_received[0]+=1; + ue->dlsch_mch_received_sf[subframe_rx][0]=1; + } - } else if (r_type == multicast_relay) { // mcch is not active here - // only 1 harq process exists - // Fix me: this could be a pointer copy - memcpy (phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->b, - ue->dlsch_MCH[0]->harq_processes[0]->b, - ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3); - // keep the tbs - phy_vars_rn->mch_avtive[subframe_rx] = 1; - phy_vars_rn->sync_area[subframe_rx] = sync_area; // this could also go the harq data struct - phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS = ue->dlsch_MCH[0]->harq_processes[0]->TBS; - phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs = ue->dlsch_MCH[0]->harq_processes[0]->mcs; - LOG_D(PHY,"[RN/UE %d] Frame %d subframe %d: store the MCH PDU for MBSFN sync area %d (MCS %d, TBS %d)\n", - ue->Mod_id, frame_rx,subframe_rx,sync_area, - phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs, - phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS>>3); + } else if (r_type == multicast_relay) { // mcch is not active here + // only 1 harq process exists + // Fix me: this could be a pointer copy + memcpy (phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->b, + ue->dlsch_MCH[0]->harq_processes[0]->b, + ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3); + // keep the tbs + phy_vars_rn->mch_avtive[subframe_rx] = 1; + phy_vars_rn->sync_area[subframe_rx] = sync_area; // this could also go the harq data struct + phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS = ue->dlsch_MCH[0]->harq_processes[0]->TBS; + phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs = ue->dlsch_MCH[0]->harq_processes[0]->mcs; + LOG_D(PHY,"[RN/UE %d] Frame %d subframe %d: store the MCH PDU for MBSFN sync area %d (MCS %d, TBS %d)\n", + ue->Mod_id, frame_rx,subframe_rx,sync_area, + phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs, + phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS>>3); #ifdef DEBUG_PHY - for (int i=0; idlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS>>3; i++) - msg("%02x ",phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->b[i]); + for (int i=0; idlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS>>3; i++) + printf("%02x ",phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->b[i]); - msg("\n"); + printf("\n"); #endif - } else - LOG_W(PHY,"[UE %d] Frame %d: not supported option\n",ue->Mod_id, frame_rx); + } else + LOG_W(PHY,"[UE %d] Frame %d: not supported option\n",ue->Mod_id, frame_rx); #endif - } + } + } } } - } #ifdef EMOS - phy_procedures_emos_UE_RX(ue,slot_rx,eNB_id); + phy_procedures_emos_UE_RX(ue,slot,eNB_id); #endif + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); stop_meas(&ue->phy_proc_rx); return (0); } - + #ifdef Rel10 int phy_procedures_RN_UE_RX(uint8_t slot_rx, uint8_t next_slot, relaying_type_t r_type) { - + int do_proc =0; // do nothing by default - + switch(r_type) { case no_relay: do_proc=no_relay; // perform the normal UE operation break; - + case multicast_relay: if (slot_rx > 12) do_proc = 0; // do nothing else // SF#1, SF#2, SF3, SF#3, SF#4, SF#5, SF#6(do rx slot 12) do_proc = multicast_relay ; // do PHY procedures UE RX - + break; - + default: // should'not be here LOG_W(PHY,"Not supported relay type %d, do nothing \n", r_type); do_proc= 0; break; } - + return do_proc; } #endif - - -void phy_procedures_UE_lte(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, - relaying_type_t r_type, PHY_VARS_RN *phy_vars_rn) + + +void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, + relaying_type_t r_type, PHY_VARS_RN *phy_vars_rn) { #if defined(ENABLE_ITTI) MessageDef *msg_p; @@ -3436,251 +3136,114 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_fl unsigned int Mod_id; int result; #endif -# if ENABLE_RAL - int CC_id =0; -#endif - int frame_rx = ue->frame_rx; - int frame_tx = ue->frame_tx; - int slot_rx = ue->slot_rx; - int slot_tx = ue->slot_tx; - int subframe_tx = slot_tx>>1; - int subframe_rx = slot_rx>>1; + + int frame_rx = proc->frame_rx; + int frame_tx = proc->frame_tx; + int subframe_rx = proc->subframe_rx; + int subframe_tx = proc->subframe_tx; #undef DEBUG_PHY_PROC - + UE_L2_STATE_t ret; + int slot; if (ue->mac_enabled == 0) { ue->UE_mode[eNB_id]=PUSCH; - ue->prach_resources[eNB_id] = &prach_resources_local; - prach_resources_local.ra_RNTI = 0xbeef; - prach_resources_local.ra_PreambleIndex = 0; } - - + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,1); -#if defined(EXMIMO) -#ifndef OAI_USRP - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[0].rxcnt_ptr[0])); -#endif -#endif start_meas(&ue->phy_proc); #if defined(ENABLE_ITTI) do { // Checks if a message has been sent to PHY sub-task itti_poll_msg (TASK_PHY_UE, &msg_p); - + if (msg_p != NULL) { msg_name = ITTI_MSG_NAME (msg_p); instance = ITTI_MSG_INSTANCE (msg_p); Mod_id = instance - NB_eNB_INST; - + switch (ITTI_MSG_ID(msg_p)) { case PHY_FIND_CELL_REQ: - LOG_I(PHY, "[UE %d] Received %s\n", Mod_id, msg_name); - - /* TODO process the message */ -# if ENABLE_RAL - { - MessageDef *message_p; - - message_p = itti_alloc_new_message(TASK_PHY_UE , PHY_FIND_CELL_IND); - memset(&PHY_FIND_CELL_IND(message_p), 0, sizeof(PHY_FIND_CELL_IND(message_p))); - PHY_FIND_CELL_IND (message_p).transaction_id = PHY_FIND_CELL_REQ(msg_p).transaction_id; - PHY_FIND_CELL_IND (message_p).cell_nb = 1; - PHY_FIND_CELL_IND (message_p).cells[0].earfcn = 1; - PHY_FIND_CELL_IND (message_p).cells[0].cell_id = 06; - PHY_FIND_CELL_IND (message_p).cells[0].rsrp = 39; - PHY_FIND_CELL_IND (message_p).cells[0].rsrq = 39; - - itti_send_msg_to_task(TASK_RRC_UE, instance, message_p); - - } -# endif - break; - -# if ENABLE_RAL - - case TIMER_HAS_EXPIRED: - // check if it is a measurement timer - { - hashtable_rc_t hashtable_rc; - hashtable_rc = hashtable_is_key_exists(ue_g[Mod_id][CC_id]->ral_thresholds_timed, (uint64_t)(TIMER_HAS_EXPIRED(msg_p).timer_id)); - LOG_I(PHY, "[UE %d] Received TIMER HAS EXPIRED: (hash_rc %d, HASH_TABLE_OK %d)\n", Mod_id, hashtable_rc, HASH_TABLE_OK); - - if (hashtable_rc == HASH_TABLE_OK) { - phy_UE_lte_check_measurement_thresholds(instance, (ral_threshold_phy_t*)TIMER_HAS_EXPIRED(msg_p).arg); - } - } - break; - - - case PHY_MEAS_THRESHOLD_REQ: -#warning "TO DO LIST OF THRESHOLDS" - LOG_I(PHY, "[UE %d] Received %s\n", Mod_id, msg_name); - { - ral_threshold_phy_t* threshold_phy_p = NULL; - int index, res; - long timer_id; - hashtable_rc_t hashtable_rc; - - switch (PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.th_action) { - - case RAL_TH_ACTION_CANCEL_THRESHOLD: - break; - - case RAL_TH_ACTION_SET_NORMAL_THRESHOLD: - case RAL_TH_ACTION_SET_ONE_SHOT_THRESHOLD: - for (index = 0; index < PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.num_thresholds; index++) { - threshold_phy_p = calloc(1, sizeof(ral_threshold_phy_t)); - threshold_phy_p->th_action = PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.th_action; - memcpy(&threshold_phy_p->link_param.link_param_type, - &PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type, - sizeof(ral_link_param_type_t)); - - memcpy(&threshold_phy_p->threshold, - &PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.thresholds[index], - sizeof(ral_threshold_t)); - - switch (PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.union_choice) { - - case RAL_LINK_CFG_PARAM_CHOICE_TIMER_NULL: - switch (PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type.choice) { - case RAL_LINK_PARAM_TYPE_CHOICE_GEN: - SLIST_INSERT_HEAD( - &ue_g[Mod_id][CC_id]->ral_thresholds_gen_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_gen], - threshold_phy_p, - ral_thresholds); - break; - - case RAL_LINK_PARAM_TYPE_CHOICE_LTE: - SLIST_INSERT_HEAD( - &ue_g[Mod_id][CC_id]->ral_thresholds_lte_polled[PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type._union.link_param_lte], - threshold_phy_p, - ral_thresholds); - //LOG_E(PHY, "[UE %d] NORMAL/ONE SHOT - TIMER NULL - type LTE in %s\n", Mod_id, msg_name); - break; - - default: - LOG_E(PHY, "[UE %d] BAD PARAMETER cfg_param.link_param_type.choice %d in %s\n", - Mod_id, PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.link_param_type.choice, msg_name); - } - - break; - - case RAL_LINK_CFG_PARAM_CHOICE_TIMER: - res = timer_setup( - (uint32_t)(PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param._union.timer_interval/1000),//uint32_t interval_sec, - (uint32_t)(PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param._union.timer_interval%1000),//uint32_t interval_us, - TASK_PHY_UE, - instance, - TIMER_PERIODIC, - threshold_phy_p, - &timer_id); - - if (res == 0) { - hashtable_rc = hashtable_insert(ue_g[Mod_id][CC_id]->ral_thresholds_timed, (uint64_t )timer_id, (void*)threshold_phy_p); - - if (hashtable_rc == HASH_TABLE_OK) { - threshold_phy_p->timer_id = timer_id; - LOG_I(PHY, "[UE %d] NORMAL/ONE SHOT - TIMER CHOICE - OK - in Hash %s\n", Mod_id, msg_name); - } else { - LOG_E(PHY, "[UE %d] %s: Error in hashtable. Could not configure threshold index %d \n", - Mod_id, msg_name, index); - } - - } else { - LOG_E(PHY, "[UE %d] %s: Could not configure threshold index %d because of timer initialization failure\n", - Mod_id, msg_name, index); - } - - break; - - default: // already checked in RRC, should not happen here - LOG_E(PHY, "[UE %d] BAD PARAMETER cfg_param.union_choice %d in %s\n", - Mod_id, PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.union_choice, msg_name); - } - } - - break; - - default: - LOG_E(PHY, "[UE %d] BAD PARAMETER th_action value %d in %s\n", - Mod_id, PHY_MEAS_THRESHOLD_REQ(msg_p).cfg_param.th_action, msg_name); - } - - } - break; -# endif - + LOG_I(PHY, "[UE %d] Received %s\n", Mod_id, msg_name); + + /* TODO process the message */ + break; + default: - LOG_E(PHY, "[UE %d] Received unexpected message %s\n", Mod_id, msg_name); - break; + LOG_E(PHY, "[UE %d] Received unexpected message %s\n", Mod_id, msg_name); + break; } - + result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } } while(msg_p != NULL); - + #endif - - if ((subframe_select(&ue->frame_parms,subframe_tx)==SF_UL)|| - (ue->frame_parms.frame_type == FDD)) { - phy_procedures_UE_TX(ue,eNB_id,abstraction_flag,mode,r_type); - } - - if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_DL) || - (ue->frame_parms.frame_type == FDD)) { -#ifdef Rel10 - - if (phy_procedures_RN_UE_RX(slot_rx, slot_tx, r_type) != 0 ) -#endif - phy_procedures_UE_RX(ue,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); - } - - if ((subframe_select(&ue->frame_parms,subframe_tx)==SF_S) && - ((slot_tx&1)==1)) { - phy_procedures_UE_S_TX(ue,eNB_id,abstraction_flag,r_type); - } - - if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_S) && - ((slot_rx&1)==0)) { -#ifdef Rel10 - - if (phy_procedures_RN_UE_RX(slot_rx, slot_tx, r_type) != 0 ) -#endif - phy_procedures_UE_RX(ue,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); - } - - if (ue->mac_enabled==1) { - if (slot_rx%2==0) { - ret = mac_xface->ue_scheduler(ue->Mod_id, - frame_tx, - subframe_rx, - subframe_select(&ue->frame_parms,subframe_tx), - eNB_id, - 0/*FIXME CC_id*/); - - if (ret == CONNECTION_LOST) { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",ue->Mod_id, - frame_rx,subframe_tx); - ue->UE_mode[eNB_id] = PRACH; - // mac_xface->macphy_exit("Connection lost"); - } else if (ret == PHY_RESYNCH) { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n", - ue->Mod_id, - frame_rx,subframe_tx); - ue->UE_mode[eNB_id] = RESYNCH; - // mac_xface->macphy_exit("Connection lost"); - } else if (ret == PHY_HO_PRACH) { - LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n", - ue->Mod_id,frame_rx,subframe_tx); - ue->UE_mode[eNB_id] = PRACH; + + for (slot=0;slot<2;slot++) { + + if ((subframe_select(&ue->frame_parms,subframe_tx)==SF_UL)|| + (ue->frame_parms.frame_type == FDD)) { + phy_procedures_UE_TX(ue,proc,eNB_id,abstraction_flag,mode,r_type); } - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,0); - stop_meas(&ue->phy_proc); + + if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_DL) || + (ue->frame_parms.frame_type == FDD)) { +#ifdef Rel10 + + if (phy_procedures_RN_UE_RX(subframe_rx, subframe_tx, r_type) != 0 ) +#endif + phy_procedures_UE_RX(ue,proc,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); + } + + if ((subframe_select(&ue->frame_parms,subframe_tx)==SF_S) && + (slot==1)) { + phy_procedures_UE_S_TX(ue,eNB_id,abstraction_flag,r_type); + } + + if ((subframe_select(&ue->frame_parms,subframe_rx)==SF_S) && + (slot==0)) { +#ifdef Rel10 + + if (phy_procedures_RN_UE_RX(subframe_rx, subframe_tx, r_type) != 0 ) +#endif + phy_procedures_UE_RX(ue,proc,eNB_id,abstraction_flag,mode,r_type,phy_vars_rn); + } + + if (ue->mac_enabled==1) { + if (slot==0) { + ret = mac_xface->ue_scheduler(ue->Mod_id, + frame_tx, + subframe_rx, + subframe_select(&ue->frame_parms,subframe_tx), + eNB_id, + 0/*FIXME CC_id*/); + + if (ret == CONNECTION_LOST) { + LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",ue->Mod_id, + frame_rx,subframe_tx); + ue->UE_mode[eNB_id] = PRACH; + // mac_xface->macphy_exit("Connection lost"); + } else if (ret == PHY_RESYNCH) { + LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n", + ue->Mod_id, + frame_rx,subframe_tx); + ue->UE_mode[eNB_id] = RESYNCH; + // mac_xface->macphy_exit("Connection lost"); + } else if (ret == PHY_HO_PRACH) { + LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n", + ue->Mod_id,frame_rx,subframe_tx); + ue->UE_mode[eNB_id] = PRACH; + } + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,0); + stop_meas(&ue->phy_proc); + } // slot } + + diff --git a/openair1/SCHED/pucch_pc.c b/openair1/SCHED/pucch_pc.c index 229ae3f1a3..7eaf1738dc 100644 --- a/openair1/SCHED/pucch_pc.c +++ b/openair1/SCHED/pucch_pc.c @@ -42,7 +42,7 @@ #include "PHY/LTE_TRANSPORT/proto.h" #include "PHY/extern.h" -int8_t pucch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,PUCCH_FMT_t pucch_fmt) +int8_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,uint8_t eNB_id,PUCCH_FMT_t pucch_fmt) { int8_t Po_PUCCH; @@ -98,7 +98,7 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,PUCCH_FM if (pucch_fmt!=pucch_format1) { LOG_I(PHY,"[UE %d][PDSCH %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n", ue->Mod_id, - ue->dlsch[eNB_id][0]->rnti,ue->frame_tx,subframe, + ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe, Po_PUCCH, ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, get_PL(ue->Mod_id,ue->CC_id,eNB_id), @@ -106,7 +106,7 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,PUCCH_FM } else { LOG_I(PHY,"[UE %d][SR %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n", ue->Mod_id, - ue->dlsch[eNB_id][0]->rnti,ue->frame_tx,subframe, + ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe, Po_PUCCH, ue->frame_parms.ul_power_control_config_common.p0_NominalPUCCH, get_PL(ue->Mod_id,ue->CC_id,eNB_id), diff --git a/openair1/SCHED/pusch_pc.c b/openair1/SCHED/pusch_pc.c index 074cd507ef..6babb4fef0 100644 --- a/openair1/SCHED/pusch_pc.c +++ b/openair1/SCHED/pusch_pc.c @@ -136,13 +136,13 @@ int16_t get_hundred_times_delta_IF(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t harq_p uint8_t alpha_lut[8] = {0,40,50,60,70,80,90,100}; -void pusch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag) +void pusch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag) { uint8_t harq_pid = subframe2harq_pid(&ue->frame_parms, - ue->frame_tx, - subframe); + proc->frame_tx, + proc->subframe_tx); uint8_t nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; int8_t PL; @@ -164,7 +164,7 @@ void pusch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,uint8_t j, ue->ulsch[eNB_id]->Po_PUSCH += (mac_xface->get_Po_NOMINAL_PUSCH(ue->Mod_id,0) + PL); LOG_I(PHY,"[UE %d][RAPROC] frame %d, subframe %d: Msg3 Po_PUSCH %d dBm (%d,%d,100*PL=%d,%d,%d)\n", - ue->Mod_id,ue->frame_tx,subframe,ue->ulsch[eNB_id]->Po_PUSCH, + ue->Mod_id,proc->frame_tx,proc->subframe_tx,ue->ulsch[eNB_id]->Po_PUSCH, 100*mac_xface->get_Po_NOMINAL_PUSCH(ue->Mod_id,0), hundred_times_log10_NPRB[nb_rb-1], 100*PL, @@ -183,7 +183,7 @@ void pusch_power_cntl(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id,uint8_t j, ue->ulsch[eNB_id]->PHR = 40; LOG_D(PHY,"[UE %d][PUSCH %d] frame %d, subframe %d: Po_PUSCH %d dBm : tx power %d, Po_NOMINAL_PUSCH %d,log10(NPRB) %f,PHR %d, PL %d, alpha*PL %f,delta_IF %f,f_pusch %d\n", - ue->Mod_id,harq_pid,ue->frame_tx,subframe, + ue->Mod_id,harq_pid,proc->frame_tx,proc->subframe_tx, ue->ulsch[eNB_id]->Po_PUSCH, ue->tx_power_max_dBm, ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH, diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index bd877e7aff..4447999bfd 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -499,7 +499,7 @@ static void *scope_thread(void *arg) while (!oai_exit) { if (UE_flag==1) { - len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm); + len = dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm); //fl_set_object_label(form_stats->stats_text, stats_buffer); fl_clear_browser(form_stats->stats_text); fl_add_browser_line(form_stats->stats_text, stats_buffer); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 66c60056b3..1c023c4457 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -306,7 +306,7 @@ static void *UE_thread_synch(void *arg) pthread_mutex_unlock(&sync_mutex); printf("unlocked sync_mutex (UE_sync_thread)\n"); - printf("starting UE synch thread (IC %d)\n",UE->instance_cnt_synch); + printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch); ind = 0; found = 0; @@ -358,34 +358,8 @@ static void *UE_thread_synch(void *arg) openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]; openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]; -#ifdef OAI_USRP - openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - -#if 0 // UHD 3.8 - switch(UE->frame_parms.N_RB_DL) { - case 6: - openair0_cfg[card].rx_gain[i] -= 12; - break; - - case 25: - openair0_cfg[card].rx_gain[i] -= 6; - break; - - case 50: - openair0_cfg[card].rx_gain[i] -= 3; - break; - - case 100: - openair0_cfg[card].rx_gain[i] -= 0; - break; - - default: - printf( "Unknown number of RBs %d\n", UE->frame_parms.N_RB_DL ); - break; - } -#endif + openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB; printf( "UE synch: setting RX gain (%d,%d) to %f\n", card, i, openair0_cfg[card].rx_gain[i] ); -#endif } } @@ -393,19 +367,19 @@ static void *UE_thread_synch(void *arg) while (oai_exit==0) { - if (pthread_mutex_lock(&UE->mutex_synch) != 0) { + if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" ); exit_fun("noting to add"); return &UE_thread_synch_retval; } - while (UE->instance_cnt_synch < 0) { + while (UE->proc.instance_cnt_synch < 0) { // the thread waits here most of the time - pthread_cond_wait( &UE->cond_synch, &UE->mutex_synch ); + pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch ); } - if (pthread_mutex_unlock(&UE->mutex_synch) != 0) { + if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) { LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for UE Initial Synch thread\n" ); exit_fun("nothing to add"); return &UE_thread_synch_retval; @@ -437,36 +411,8 @@ static void *UE_thread_synch(void *arg) openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]; openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]; -#ifdef OAI_USRP - openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; // 65 calibrated for USRP B210 @ 2.6 GHz - -#if 0 // UHD 3.8 - switch(UE->frame_parms.N_RB_DL) { - case 6: - openair0_cfg[card].rx_gain[i] -= 12; - break; - - case 25: - openair0_cfg[card].rx_gain[i] -= 6; - break; - - case 50: - openair0_cfg[card].rx_gain[i] -= 3; - break; - - case 100: - openair0_cfg[card].rx_gain[i] -= 0; - break; - - default: - printf("Unknown number of RBs %d\n",UE->frame_parms.N_RB_DL); - break; - } -#endif - + openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB; printf("UE synch: setting RX gain (%d,%d) to %f\n",card,i,openair0_cfg[card].rx_gain[i]); -#endif - } } @@ -537,32 +483,27 @@ static void *UE_thread_synch(void *arg) else { UE->is_synchronized = 1; - if( UE->mode == rx_dump_frame ){ - FILE *fd; - if ((UE->frame_rx&1) == 0) { // this guarantees SIB1 is present - if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { - fwrite((void*)&UE->common_vars.rxdata[0][0], - sizeof(int32_t), - 10*UE->frame_parms.samples_per_tti, - fd); - LOG_I(PHY,"Dummping Frame ... bye bye \n"); - fclose(fd); - exit(0); - } - else { - LOG_E(PHY,"Cannot open file for writing\n"); - exit(0); - } - } - else { - UE->is_synchronized = 0; - } - } - - - - UE->slot_rx = 0; - UE->slot_tx = 4; + if( UE->mode == rx_dump_frame ){ + FILE *fd; + if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) { // this guarantees SIB1 is present + if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { + fwrite((void*)&UE->common_vars.rxdata[0][0], + sizeof(int32_t), + 10*UE->frame_parms.samples_per_tti, + fd); + LOG_I(PHY,"Dummping Frame ... bye bye \n"); + fclose(fd); + exit(0); + } + else { + LOG_E(PHY,"Cannot open file for writing\n"); + exit(0); + } + } + else { + UE->is_synchronized = 0; + } + } } } else { // initial sync failed @@ -631,16 +572,16 @@ static void *UE_thread_synch(void *arg) - if (pthread_mutex_lock(&UE->mutex_synch) != 0) { + if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { LOG_E( PHY, "[SCHED][UE] error locking mutex for UE synch\n" ); exit_fun("noting to add"); return &UE_thread_synch_retval; } // indicate readiness - UE->instance_cnt_synch--; + UE->proc.instance_cnt_synch--; - if (pthread_mutex_unlock(&UE->mutex_synch) != 0) { + if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) { LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE synch\n" ); exit_fun("noting to add"); return &UE_thread_synch_retval; @@ -658,6 +599,7 @@ static void *UE_thread_synch(void *arg) * \param arg is a pointer to a \ref PHY_VARS_UE structure. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ +/* static void *UE_thread_tx(void *arg) { static int UE_thread_tx_retval; @@ -677,7 +619,7 @@ static void *UE_thread_tx(void *arg) attr.sched_nice = 0; attr.sched_priority = 0; - /* This creates a 1ms reservation every 10ms period*/ + // This creates a 1ms reservation every 10ms period attr.sched_policy = SCHED_DEADLINE; attr.sched_runtime = 900000; // each tx thread requires .5ms to finish its job attr.sched_deadline = 1000000; // each tx thread will finish within 1ms @@ -695,8 +637,8 @@ static void *UE_thread_tx(void *arg) char cpu_affinity[1024]; cpu_set_t cpuset; - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ + // Set affinity mask to include CPUs 1 to MAX_CPUS + // CPU 0 is reserved for UHD threads CPU_ZERO(&cpuset); #ifdef CPU_AFFINITY @@ -714,7 +656,7 @@ static void *UE_thread_tx(void *arg) } #endif - /* Check the actual affinity mask assigned to the thread */ + // Check the actual affinity mask assigned to the thread s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); if (s != 0) @@ -836,44 +778,24 @@ static void *UE_thread_tx(void *arg) return &UE_thread_tx_retval; } +*/ + /*! - * \brief This is the UE receive thread. + * \brief This is the UE thread for RX subframe n and TX subframe n+4. * This thread performs the phy_procedures_UE_RX() on every received slot. + * then, if TX is enabled it performs TX for n+4. * \param arg is a pointer to a \ref PHY_VARS_UE structure. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -/* -#ifdef OAI_USRP -void rescale(int16_t *input,int length) -{ -#if defined(__x86_64__) || defined(__i386__) - __m128i *input128 = (__m128i *)input; -#elif defined(__arm__) - int16x8_t *input128 = (int16x8_t *)input; -#endif - int i; - - for (i=0; i>2; i++) { -#if defined(__x86_64__) || defined(__i386__) - input128[i] = _mm_srai_epi16(input128[i],4); -#elif defined(__arm__) - input128[i] = vshrq_n_s16(input128[i],4); -#endif - } -} -#endif -*/ - -static void *UE_thread_rx(void *arg) +static void *UE_thread_rxn_txnp4(void *arg) { static int UE_thread_rx_retval; - PHY_VARS_UE *UE = (PHY_VARS_UE*)arg; - int i; + UE_rxtx_proc_t *proc = (UE_rxtx_proc_t *)arg; int ret; - - UE->instance_cnt_rx=-1; + PHY_VARS_UE *UE=PHY_vars_UE_g[0][proc->CC_id]; + proc->instance_cnt_rxtx=-1; #ifdef DEADLINE_SCHEDULER @@ -970,10 +892,10 @@ static void *UE_thread_rx(void *arg) // Lock memory from swapping. This is a process wide call (not constraint to this thread). mlockall(MCL_CURRENT | MCL_FUTURE); - printf("waiting for sync (UE_thread_rx)\n"); + printf("waiting for sync (UE_thread_rxn_txnp4)\n"); pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_thread_rx)\n"); + printf("Locked sync_mutex, waiting (UE_thread_rxn_txnp4)\n"); while (sync_var<0) pthread_cond_wait(&sync_cond, &sync_mutex); @@ -981,160 +903,76 @@ static void *UE_thread_rx(void *arg) pthread_mutex_unlock(&sync_mutex); printf("unlocked sync_mutex, waiting (UE_thread_rx)\n"); - printf("Starting UE RX thread\n"); + printf("Starting UE RXN_TXNP4 thread\n"); while (!oai_exit) { - if (pthread_mutex_lock(&UE->mutex_rx) != 0) { + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" ); exit_fun("nothing to add"); return &UE_thread_rx_retval; } - while (UE->instance_cnt_rx < 0) { + while (proc->instance_cnt_rxtx < 0) { // most of the time, the thread is waiting here - pthread_cond_wait( &UE->cond_rx, &UE->mutex_rx ); + pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); } - if (pthread_mutex_unlock(&UE->mutex_rx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" ); + if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" ); exit_fun("nothing to add"); return &UE_thread_rx_retval; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, 1 ); - for (i=0; i<2; i++) { - if ((subframe_select( &UE->frame_parms, UE->slot_rx>>1 ) == SF_DL) || - (UE->frame_parms.frame_type == FDD)) { - /* -#ifdef OAI_USRP - // this does the adjustments of RX signal amplitude to bring into least 12 significant bits - int slot_length = UE->frame_parms.samples_per_tti>>1; - int rx_offset = (UE->slot_rx)*slot_length + UE->rx_offset; - int frame_length = UE->frame_parms.samples_per_tti*10; - int aa; - if (rx_offset > frame_length) - rx_offset-=frame_length; - - if (rx_offset >= 0) { - if (rx_offset + slot_length < frame_length) - for (aa=0;aaframe_parms.nb_antennas_rx;aa++) - rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], - slot_length); - else { - int diff = rx_offset + slot_length - frame_length; - for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], - slot_length-diff); - rescale((int16_t*)&UE->common_vars.rxdata[aa][0], - diff); - } - } - } - else { - for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)], - -rx_offset); - rescale((int16_t*)&UE->common_vars.rxdata[aa][0], - slot_length+rx_offset); - } - } -#endif - */ - phy_procedures_UE_RX( UE, 0, 0, UE->mode, no_relay, NULL ); - } - - if ((subframe_select( &UE->frame_parms, UE->slot_rx>>1 ) == SF_S) && - ((UE->slot_rx&1) == 0)) { - /* -#ifdef OAI_USRP - // this does the adjustments of RX signal amplitude to bring into least 12 significant bits - int slot_length = UE->frame_parms.samples_per_tti>>1; - int rx_offset = (UE->slot_rx)*slot_length + UE->rx_offset; - int frame_length = UE->frame_parms.samples_per_tti*10; - if (rx_offset > frame_length) - rx_offset-=frame_length; - int aa; - - if (rx_offset >= 0) { - if (rx_offset + slot_length < frame_length) - for (aa=0;aaframe_parms.nb_antennas_rx;aa++) - rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], - slot_length); - else { - int diff = rx_offset + slot_length - frame_length; - for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)], - slot_length-diff); - rescale((int16_t*)&UE->common_vars.rxdata[aa][0], - diff); - } - } - } - else { - for (aa=0;aaframe_parms.nb_antennas_rx;aa++){ - rescale((int16_t*)&UE->common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)], - -rx_offset); - rescale((int16_t*)&UE->common_vars.rxdata[aa][0], - slot_length+rx_offset); - } - } -#endif - */ - phy_procedures_UE_RX( UE, 0, 0, UE->mode, no_relay, NULL ); - } - - if ((UE->mac_enabled==1) && (i==0)) { - ret = mac_xface->ue_scheduler(UE->Mod_id, - UE->frame_tx, - UE->slot_rx>>1, - subframe_select(&UE->frame_parms,UE->slot_tx>>1), - 0, - 0/*FIXME CC_id*/); - - if (ret == CONNECTION_LOST) { - LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, returning to PRACH\n", - UE->Mod_id, UE->frame_rx, UE->slot_tx>>1 ); - UE->UE_mode[0] = PRACH; - } else if (ret == PHY_RESYNCH) { - LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, trying to resynch\n", - UE->Mod_id, UE->frame_rx, UE->slot_tx>>1 ); - UE->UE_mode[0] = RESYNCH; - } else if (ret == PHY_HO_PRACH) { - LOG_I( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u, return to PRACH and perform a contention-free access\n", - UE->Mod_id, UE->frame_rx, UE->slot_tx>>1 ); - UE->UE_mode[0] = PRACH; - } - } - - UE->slot_rx++; - - if (UE->slot_rx == 20) { - UE->slot_rx = 0; - UE->frame_rx++; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_UE, UE->frame_rx ); - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_UE, UE->slot_rx>>1 ); + if ((subframe_select( &UE->frame_parms, proc->subframe_rx) == SF_DL) || + (UE->frame_parms.frame_type == FDD) || + (subframe_select( &UE->frame_parms, proc->subframe_rx ) == SF_S)) { + phy_procedures_UE_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL ); } + + + if (UE->mac_enabled==1) { + ret = mac_xface->ue_scheduler(UE->Mod_id, + proc->frame_tx, + proc->subframe_rx, + subframe_select(&UE->frame_parms,proc->subframe_tx), + 0, + 0/*FIXME CC_id*/); + + if (ret == CONNECTION_LOST) { + LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, returning to PRACH\n", + UE->Mod_id, proc->frame_rx, proc->subframe_tx ); + UE->UE_mode[0] = PRACH; + } else if (ret == PHY_RESYNCH) { + LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, trying to resynch\n", + UE->Mod_id, proc->frame_rx, proc->subframe_tx ); + UE->UE_mode[0] = RESYNCH; + } else if (ret == PHY_HO_PRACH) { + LOG_I( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u, return to PRACH and perform a contention-free access\n", + UE->Mod_id, proc->frame_rx, proc->subframe_tx ); + UE->UE_mode[0] = PRACH; + } + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, 0 ); - - if (pthread_mutex_lock(&UE->mutex_rx) != 0) { + + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" ); exit_fun("noting to add"); return &UE_thread_rx_retval; } - - UE->instance_cnt_rx--; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, UE->instance_cnt_rx); - - if (pthread_mutex_unlock(&UE->mutex_rx) != 0) { + + proc->instance_cnt_rxtx--; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, proc->instance_cnt_rxtx); + + if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" ); exit_fun("noting to add"); return &UE_thread_rx_retval; } } - + // thread finished return &UE_thread_rx_retval; } @@ -1150,13 +988,185 @@ static void *UE_thread_rx(void *arg) /*! * \brief This is the main UE thread. * This thread controls the other three UE threads: - * - UE_thread_rx - * - UE_thread_tx + * - UE_thread_rxn_txnp4 (even subframes) + * - UE_thread_rxn_txnp4 (odd subframes) * - UE_thread_synch * \param arg unused * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -void *UE_thread(void *arg) + +void *UE_thread(void *arg) { + + static int UE_thread_retval; + PHY_VARS_UE *UE = PHY_vars_UE_g[0][0]; + // int tx_enabled = 0; + unsigned int rxs; + int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti]; + openair0_timestamp timestamp; + void* rxp[2]; + + +#ifdef NAS_UE + MessageDef *message_p; +#endif + + int start_rx_stream = 0; + +#ifdef DEADLINE_SCHEDULER + + struct sched_attr attr; + unsigned int flags = 0; + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0;//sched_get_priority_max(SCHED_DEADLINE); + + // This creates a .5 ms reservation + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = 100000; + attr.sched_deadline = 500000; + attr.sched_period = 500000; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] main eNB thread: sched_setattr failed\n"); + exit_fun("Nothing to add"); + return &UE_thread_retval; + } + LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %lu started on CPU %d\n", + (unsigned long)gettid(), sched_getcpu()); + +#else + struct sched_param sp; + sp.sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); +#endif + + // Lock memory from swapping. This is a process wide call (not constraint to this thread). + mlockall(MCL_CURRENT | MCL_FUTURE); + + printf("waiting for sync (UE_thread)\n"); + pthread_mutex_lock(&sync_mutex); + printf("Locked sync_mutex, waiting (UE_thread)\n"); + + while (sync_var<0) + pthread_cond_wait(&sync_cond, &sync_mutex); + + pthread_mutex_unlock(&sync_mutex); + printf("unlocked sync_mutex, waiting (UE_thread)\n"); + + printf("starting UE thread\n"); + +#ifdef NAS_UE + message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); + itti_send_msg_to_task (TASK_NAS_UE, INSTANCE_DEFAULT, message_p); +#endif + + while (!oai_exit) { + + if (UE->is_synchronized == 0) { + + if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { + LOG_E( PHY, "[SCHED][UE] verror locking mutex for UE initial synch thread\n" ); + exit_fun("nothing to add"); + return &UE_thread_retval; + } + + int instance_cnt_synch = UE->proc.instance_cnt_synch; + + if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE initial synch thread\n" ); + exit_fun("nothing to add"); + return &UE_thread_retval; + } + + if (instance_cnt_synch < 0) { // we can invoke the synch + // grab 10 ms of signal and wakeup synch thread + for (int i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = (void*)&rxdata[i][0]; + + if (UE->mode != loop_through_memory) { + rxs = openair0.trx_read_func(&openair0, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti*10, + UE->frame_parms.nb_antennas_rx); + } + instance_cnt_synch = ++UE->proc.instance_cnt_synch; + if (instance_cnt_synch == 0) { + if (pthread_cond_signal(&UE->proc.cond_synch) != 0) { + LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n" ); + exit_fun("nothing to add"); + return &UE_thread_retval; + } + } else { + LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" ); + exit_fun("nothing to add"); + return &UE_thread_retval; + } + } // + else { + // grab 10 ms of signal into dummy buffer + + if (UE->mode != loop_through_memory) { + for (int i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = (void*)&dummy_rx[i][0]; + for (int sf=0;sf<10;sf++) + rxs = openair0.trx_read_func(&openair0, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_rx); + } + } + + } // UE->is_synchronized==0 + else { + if (start_rx_stream==0) { + start_rx_stream=1; + if (UE->mode != loop_through_memory) { + LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); + rxs = openair0.trx_read_func(&openair0, + ×tamp, + (void**)rxdata, + UE->rx_offset, + UE->frame_parms.nb_antennas_rx); + + if (rxs != UE->rx_offset) { + exit_fun("problem in rx"); + return &UE_thread_retval; + } + UE->rx_offset=0; + } //UE->mode != loop_through_memory + else + rt_sleep_ns(1000000); + // read in first symbol (to process one subframe we need symbol 0 - 14 and 1st symbol of next subframe + rxs = openair0.trx_read_func(&openair0, + ×tamp, + (void**)rxdata, + UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx); + }// start_rx_stream==0 + + if (UE->mode != loop_through_memory) { + for (int sf=0;sf<10;sf++) + for (int i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = (void*)&dummy_rx[i][sf*UE->frame_parms.samples_per_tti]; + + rxs = openair0.trx_read_func(&openair0, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_rx); + } + + } // UE->is_synchronized==1 + + } // while !oai_exit +} // UE_thread + +/* +void *UE_thread_old(void *arg) { UNUSED(arg) static int UE_thread_retval; @@ -1176,6 +1186,7 @@ void *UE_thread(void *arg) int first_rx = 0; RTIME T0; unsigned int rxs; + void* rxp[2]; openair0_timestamp timestamp; @@ -1254,9 +1265,7 @@ void *UE_thread(void *arg) for (int i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rxpos] : (void*)dummy[i]; - /* if (dummy_dump == 0) - printf("writing %d samples to %d (first_rx %d)\n",spp - ((first_rx==1) ? rx_off_diff : 0),rxpos,first_rx);*/ - + if (UE->mode != loop_through_memory) { rxs = openair0.trx_read_func(&openair0, ×tamp, @@ -1342,7 +1351,7 @@ void *UE_thread(void *arg) if (instance_cnt_rx == 0) { LOG_D(HW,"signalling rx thread to wake up, hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 ); - if (pthread_cond_signal(&UE->cond_rx) != 0) { + if (pthread_cond_signal(&UE->proc.cond_rx) != 0) { LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n" ); exit_fun("nothing to add"); return &UE_thread_retval; @@ -1538,7 +1547,7 @@ void *UE_thread(void *arg) return &UE_thread_retval; } - +*/ /*! * \brief Initialize the UE theads. @@ -1561,23 +1570,21 @@ void init_UE_threads(void) #endif // the threads are not yet active, therefore access is allowed without locking - UE->instance_cnt_tx = -1; - UE->instance_cnt_rx = -1; - UE->instance_cnt_synch = -1; - pthread_mutex_init(&UE->mutex_tx,NULL); - pthread_mutex_init(&UE->mutex_rx,NULL); - pthread_mutex_init(&UE->mutex_synch,NULL); - pthread_cond_init(&UE->cond_tx,NULL); - pthread_cond_init(&UE->cond_rx,NULL); - pthread_cond_init(&UE->cond_synch,NULL); - pthread_create(&UE->thread_tx,NULL,UE_thread_tx,(void*)UE); - pthread_setname_np( UE->thread_tx, "UE_thread_tx" ); - pthread_create(&UE->thread_rx,NULL,UE_thread_rx,(void*)UE); - pthread_setname_np( UE->thread_rx, "UE_thread_rx" ); - pthread_create(&UE->thread_synch,NULL,UE_thread_synch,(void*)UE); - pthread_setname_np( UE->thread_synch, "UE_thread_synch" ); - UE->frame_tx = 0; - UE->frame_rx = 0; + UE->proc.proc_rxtx[0].instance_cnt_rxtx = -1; + UE->proc.proc_rxtx[1].instance_cnt_rxtx = -1; + UE->proc.instance_cnt_synch = -1; + pthread_mutex_init(&UE->proc.proc_rxtx[0].mutex_rxtx,NULL); + pthread_mutex_init(&UE->proc.proc_rxtx[1].mutex_rxtx,NULL); + pthread_mutex_init(&UE->proc.mutex_synch,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[0].cond_rxtx,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[1].cond_rxtx,NULL); + pthread_cond_init(&UE->proc.cond_synch,NULL); + pthread_create(&UE->proc.proc_rxtx[0].pthread_rxtx,NULL,UE_thread_rxn_txnp4,(void*)&UE->proc.proc_rxtx[0]); + pthread_setname_np( UE->proc.proc_rxtx[0].pthread_rxtx, "UE_thread_rxn_txnp4_even" ); + pthread_create(&UE->proc.proc_rxtx[1].pthread_rxtx,NULL,UE_thread_rxn_txnp4,(void*)&UE->proc.proc_rxtx[1]); + pthread_setname_np( UE->proc.proc_rxtx[1].pthread_rxtx, "UE_thread_rxn_txnp4_odd" ); + pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE); + pthread_setname_np( UE->proc.pthread_synch, "UE_thread_synch" ); } From 55c194b07dc9a344347d0283bac79cc983e2a2e4 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 1 Jul 2016 19:29:02 +0200 Subject: [PATCH 079/206] added mobipass interface and tested sending dummy and starting stream, no reply yet --- cmake_targets/CMakeLists.txt | 1 + openair2/ENB_APP/enb_config.c | 4 +++- openair2/ENB_APP/enb_config.h | 1 + targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 10 ++++++++-- .../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 16 ++++++++++++++++ targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 5 +++++ targets/RT/USER/lte-enb.c | 18 ++++++++++++++---- targets/RT/USER/lte-softmodem.c | 2 ++ 8 files changed, 50 insertions(+), 7 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 56759ae0e5..f96c63f2bb 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -963,6 +963,7 @@ set(PHY_SRC ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/print_stats.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/initial_sync.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_mobipass_tools.c ${OPENAIR1_DIR}/PHY/MODULATION/ofdm_mod.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_mbsfn.c diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 5bc0088ed5..d67c6eb6d7 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -298,7 +298,7 @@ void enb_config_display(void) printf( "\ttx_scheduling_advance :\t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_scheduling_advance); printf( "\ttx_sample_advance : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_sample_advance); printf( "\tiq_txshift : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].iq_txshift); - printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : (enb_properties.properties[i]->rrh_gw_config[j].rawif4 == 1)? "RAW_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].udpif4 == 1)? "UDP_IF4" : "UDP"); + printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : (enb_properties.properties[i]->rrh_gw_config[j].rawif4 == 1)? "RAW_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].udpif4 == 1)? "UDP_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].rawif5_mobipass == 1)? "RAW_IF5_MOBIPASS" : "UDP"); if (enb_properties.properties[i]->rrh_gw_config[j].exmimo == 1) { printf( "\tRF target : \tEXMIMO:\n\n"); } else if (enb_properties.properties[i]->rrh_gw_config[j].usrp_b200 == 1) { @@ -2246,6 +2246,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udpif4 = 1; } else if (strcmp(tr_preference, "raw_if4") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif4 = 1; + } else if (strcmp(tr_preference, "raw_if5_mobipass") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif5_mobipass = 1; } else {//if (strcmp(preference, "no") == 0) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index e53921b4d0..716d400178 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -88,6 +88,7 @@ typedef struct rrh_gw_config_s { uint16_t remote_port; uint8_t udpif4; uint8_t rawif4; + uint8_t rawif5_mobipass; int tx_scheduling_advance; int tx_sample_advance; int iq_txshift; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 13dfe574c2..17a9a677e0 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -53,6 +53,7 @@ #include "ethernet_lib.h" #include "if_defs.h" #include "openair1/PHY/LTE_TRANSPORT/if4_tools.h" +#include "openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h" #define DEBUG 0 @@ -123,8 +124,11 @@ int eth_socket_init_raw(openair0_device *device) { /* Construct the Ethernet header */ ether_aton_r(local_mac, (struct ether_addr *)(&(eth->eh.ether_shost))); ether_aton_r(remote_mac, (struct ether_addr *)(&(eth->eh.ether_dhost))); - eth->eh.ether_type = htons((short)device->openair0_cfg->my_port); - +// if (((*) device->priv)->flags == ETH_RAW_IF5_MOBIPASS) { + eth->eh.ether_type = htons(0xbffe); +// } else { +// eth->eh.ether_type = htons((short)device->openair0_cfg->my_port); +// } printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5]); return 0; @@ -214,6 +218,8 @@ int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks); } else if (flags == IF4_PULFFT) { packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks); + } else if (flags == IF5_MOBIPASS) { + packet_size = RAW_IF5_MOBIPASS_SIZE_BYTES; } else { packet_size = RAW_IF4_PRACH_SIZE_BYTES; } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 5802b1569f..81e3d7b558 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -88,6 +88,17 @@ int trx_eth_start(openair0_device *device) { } else if (eth->flags == ETH_UDP_IF4_MODE) { + } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { + if (eth_socket_init_raw(device)!=0) return -1; + /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ + //if (device->host_type == BBU_HOST) { + //if(eth_set_dev_conf_raw_IF4(device)!=0) return -1; + //} else { + //if(eth_get_dev_conf_raw_IF4(device)!=0) return -1; +// + /* adjust MTU wrt number of samples per packet */ + // if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; + } else { if (eth_socket_init_udp(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ @@ -334,6 +345,8 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth eth->flags = ETH_RAW_IF4_MODE; } else if (eth_params->transp_preference == 2) { eth->flags = ETH_UDP_IF4_MODE; + } else if (eth_params->transp_preference == 4) { + eth->flags = ETH_RAW_IF5_MOBIPASS; } else { printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference); eth->flags = ETH_RAW_MODE; @@ -361,6 +374,9 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth } else if (eth->flags == ETH_RAW_IF4_MODE) { device->trx_write_func = trx_eth_write_raw_IF4; device->trx_read_func = trx_eth_read_raw_IF4; + } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { + device->trx_write_func = trx_eth_write_raw_IF4; + device->trx_read_func = trx_eth_read_raw_IF4; } else { //device->trx_write_func = trx_eth_write_udp_IF4; //device->trx_read_func = trx_eth_read_udp_IF4; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 030bfda147..e17890836b 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -46,6 +46,7 @@ #define ETH_RAW_MODE 1 #define ETH_UDP_IF4_MODE 2 #define ETH_RAW_IF4_MODE 3 +#define ETH_RAW_IF5_MOBIPASS 4 // Time domain RRH packet sizes #define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header)) @@ -61,3 +62,7 @@ #define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) #define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) #define RAW_IF4_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + PRACH_BLOCK_SIZE_BYTES) + +// Mobipass packet sizes +#define RAW_IF5_MOBIPASS_BLOCK_SIZE_BYTES 1280 +#define RAW_IF5_MOBIPASS_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + RAW_IF5_MOBIPASS_BLOCK_SIZE_BYTES) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 6eb916c41b..1fcd9bb61c 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -69,6 +69,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "PHY/LTE_TRANSPORT/if4_tools.h" +#include "PHY/LTE_TRANSPORT/if5_mobipass_tools.h" #include "PHY/extern.h" #include "SCHED/extern.h" @@ -547,7 +548,7 @@ static void* eNB_thread_rxtx( void* param ) { } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { /// **** trx_write_func to IF device **** /// - + // send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc, 0); } else { /// **** send_IF4 of txdataF to RRU **** /// @@ -624,10 +625,11 @@ static void* eNB_thread_rx_common( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - + + uint8_t seqno=0; FILE *rx_time_file = NULL; char rx_time_name[101]; - //int i; + int i; struct timespec wait; wait.tv_sec=0; @@ -762,7 +764,15 @@ static void* eNB_thread_rx_common( void* param ) { if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) LOG_E(HW,"Could not start the RF device\n"); } - + + // proc->proc_rxtx[0].timestamp_tx = 0; + // seqno = send_IF5(eNB, &proc->proc_rxtx[0], 0); + + // for (i=0; i<1000;i++) { + // seqno = send_IF5(eNB, &proc->proc_rxtx[0], seqno); + // proc->proc_rxtx[0].timestamp_tx += 7680*2; + // } + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, 0 ); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4447999bfd..656c22ced3 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1071,6 +1071,8 @@ static void get_options (int argc, char **argv) (eth_params+j)->transp_preference = ETH_RAW_IF4_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4 == 1) { (eth_params+j)->transp_preference = ETH_UDP_IF4_MODE; + } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif5_mobipass == 1) { + (eth_params+j)->transp_preference = ETH_RAW_IF5_MOBIPASS; } else { (eth_params+j)->transp_preference = ETH_UDP_MODE; } From 5ae509b2dee39e75dec8b24152b45eda3a678712 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 1 Jul 2016 19:30:18 +0200 Subject: [PATCH 080/206] if5_mobipass tools --- .../PHY/LTE_TRANSPORT/if5_mobipass_tools.c | 65 +++++++++++++++++++ .../PHY/LTE_TRANSPORT/if5_mobipass_tools.h | 26 ++++++++ 2 files changed, 91 insertions(+) create mode 100644 openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c create mode 100644 openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h diff --git a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c new file mode 100644 index 0000000000..2306fef39b --- /dev/null +++ b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c @@ -0,0 +1,65 @@ + +#include + +#include "PHY/defs.h" +#include "PHY/LTE_TRANSPORT/if5_mobipass_tools.h" + +#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" + + +uint8_t send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t init_seq) { + + uint8_t seqno=init_seq; + void *txp[2]; + void *tx_buffer=NULL; + __m128i *data_block=NULL,*main_data_block=NULL; + + __m128i *txp128; + __m128i t0, t1; + + uint16_t packet_id=0, i; + uint16_t db_fulllength = 640; + + tx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); + IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (__m128i *)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 4); + main_data_block = data_block; + + header->flags = 0; + header->fifo_status = 0; + header->ack = 0; + header->seqno = seqno; + header->rsvd = 0; + + txp[0] = (void*)&eNB->common_vars.txdata[0][0][proc->subframe_tx*eNB->frame_parms.samples_per_tti]; + txp128 = (__m128i *) txp[0]; + + for (packet_id=0; packet_id<(7680*2)/640; packet_id++) { + header->time_stamp = proc->timestamp_tx + packet_id*640; + data_block = main_data_block; + + for (i=0; i>3; i+=2) { + t0 = _mm_srli_epi16(*txp128++, 4); + t1 = _mm_srli_epi16(*txp128++, 4); + + *data_block++ = _mm_packs_epi16(t0, t1); + } + + // Write the packet to the fronthaul + if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, + packet_id, + &tx_buffer, + db_fulllength, + 1, + IF5_MOBIPASS)) < 0) { + perror("ETHERNET write for IF5_MOBIPASS\n"); + } + + header->seqno += 1; + } + + seqno = header->seqno; + free(tx_buffer); + return(seqno); +} + diff --git a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h new file mode 100644 index 0000000000..307742dc1e --- /dev/null +++ b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h @@ -0,0 +1,26 @@ + +#include +#include "PHY/defs.h" + +#define IF5_MOBIPASS 0x0050 + +struct IF5_mobipass_header { + /// Type + uint16_t flags; + /// Sub-Type + uint16_t fifo_status; + /// Reserved + uint8_t seqno; + + uint8_t ack; + + uint32_t rsvd; + /// Frame Status + uint32_t time_stamp; + +} __attribute__ ((__packed__)); + +typedef struct IF5_mobipass_header IF5_mobipass_header_t; +#define sizeof_IF5_mobipass_header_t 14 + +uint8_t send_IF5(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint8_t); From cfd45a1d9e84b1af8ac6356632fa7bb629c83b91 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 4 Jul 2016 17:42:31 +0200 Subject: [PATCH 081/206] small fixes and mid save --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 2 - openair1/PHY/LTE_TRANSPORT/if4_tools.h | 3 +- .../PHY/LTE_TRANSPORT/if5_mobipass_tools.c | 67 ++++++++++++++----- .../PHY/LTE_TRANSPORT/if5_mobipass_tools.h | 59 +++++++++++++--- openair1/SCHED/phy_procedures_lte_eNb.c | 15 ++++- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 8 +-- targets/RT/USER/lte-enb.c | 16 ++--- 7 files changed, 123 insertions(+), 47 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index b71365d6fc..1a1178ee6f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -38,8 +38,6 @@ * \warning */ -#include - #include "PHY/defs.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/TOOLS/ALAW/alaw_lut.h" diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 18ff2bb8f8..a885d28ec2 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -38,7 +38,6 @@ * \warning */ -#include #include "PHY/defs.h" /// Macro for IF4 packet type @@ -57,7 +56,7 @@ struct IF4_header { /// Frame Status uint32_t frame_status; -}; +} __attribute__ ((__packed__)); typedef struct IF4_header IF4_header_t; #define sizeof_IF4_header_t 12 diff --git a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c index 2306fef39b..d38dfb76a5 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c @@ -1,5 +1,42 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom -#include + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/*! \file PHY/LTE_TRANSPORT/if5_mobipass_tools.c +* \brief +* \author S. Sandeep Kumar, Raymond Knopp +* \date 2016 +* \version 0.1 +* \company Eurecom +* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr +* \note +* \warning +*/ #include "PHY/defs.h" #include "PHY/LTE_TRANSPORT/if5_mobipass_tools.h" @@ -7,36 +44,35 @@ #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" -uint8_t send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t init_seq) { +void send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t *seqno) { - uint8_t seqno=init_seq; - void *txp[2]; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + void *txp[fp->nb_antennas_tx]; void *tx_buffer=NULL; - __m128i *data_block=NULL,*main_data_block=NULL; + __m128i *data_block=NULL, *data_block_head=NULL; __m128i *txp128; __m128i t0, t1; uint16_t packet_id=0, i; - uint16_t db_fulllength = 640; + uint16_t db_fulllength=640; tx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (__m128i *)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 4); - main_data_block = data_block; + data_block_head = (__m128i *)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 4); header->flags = 0; header->fifo_status = 0; + header->seqno = *seqno; header->ack = 0; - header->seqno = seqno; - header->rsvd = 0; + header->word0 = 0; txp[0] = (void*)&eNB->common_vars.txdata[0][0][proc->subframe_tx*eNB->frame_parms.samples_per_tti]; txp128 = (__m128i *) txp[0]; - for (packet_id=0; packet_id<(7680*2)/640; packet_id++) { - header->time_stamp = proc->timestamp_tx + packet_id*640; - data_block = main_data_block; + for (packet_id=0; packet_id<(fp->samples_per_tti*2)/db_fulllength; packet_id++) { + header->time_stamp = proc->timestamp_tx + packet_id * db_fulllength; + data_block = data_block_head; for (i=0; i>3; i+=2) { t0 = _mm_srli_epi16(*txp128++, 4); @@ -58,8 +94,7 @@ uint8_t send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t init_seq) { header->seqno += 1; } - seqno = header->seqno; + *seqno = header->seqno; free(tx_buffer); - return(seqno); + return; } - diff --git a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h index 307742dc1e..e9bc26f9a6 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h @@ -1,26 +1,65 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/*! \file PHY/LTE_TRANSPORT/if5_mobipass_tools.h +* \brief +* \author S. Sandeep Kumar, Raymond Knopp +* \date 2016 +* \version 0.1 +* \company Eurecom +* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr +* \note +* \warning +*/ #include #include "PHY/defs.h" -#define IF5_MOBIPASS 0x0050 +#define IF5_MOBIPASS 0xbffe struct IF5_mobipass_header { - /// Type + /// uint16_t flags; - /// Sub-Type + /// uint16_t fifo_status; - /// Reserved + /// uint8_t seqno; - + /// uint8_t ack; - - uint32_t rsvd; - /// Frame Status + /// + uint32_t word0; + /// uint32_t time_stamp; - + } __attribute__ ((__packed__)); typedef struct IF5_mobipass_header IF5_mobipass_header_t; #define sizeof_IF5_mobipass_header_t 14 -uint8_t send_IF5(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint8_t); +void send_IF5(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint8_t*); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index e5b93dc6ac..a81e9dcfad 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2524,6 +2524,10 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; + + struct timespec time_req, time_rem; + time_req.tv_sec = 0; + time_req.tv_nsec = 900000; if (subframe==9) { subframe=0; @@ -2583,7 +2587,16 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } else if(eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF /// **** trx_read_func from IF device **** /// - + nanosleep(&time_req, &time_rem); + + proc->timestamp_rx += fp->samples_per_tti; + + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 17a9a677e0..bf5554fd26 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -124,11 +124,11 @@ int eth_socket_init_raw(openair0_device *device) { /* Construct the Ethernet header */ ether_aton_r(local_mac, (struct ether_addr *)(&(eth->eh.ether_shost))); ether_aton_r(remote_mac, (struct ether_addr *)(&(eth->eh.ether_dhost))); -// if (((*) device->priv)->flags == ETH_RAW_IF5_MOBIPASS) { + if (eth->flags == ETH_RAW_IF5_MOBIPASS) { eth->eh.ether_type = htons(0xbffe); -// } else { -// eth->eh.ether_type = htons((short)device->openair0_cfg->my_port); -// } + } else { + eth->eh.ether_type = htons((short)device->openair0_cfg->my_port); + } printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5]); return 0; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 1fcd9bb61c..de37789c3d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -302,6 +302,8 @@ static void* eNB_thread_rxtx( void* param ) { uint16_t packet_type; uint32_t symbol_number=0; + uint8_t seqno=0; + if (opp_enabled == 1) { snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf", "eNB"); tx_time_file = fopen(tx_time_name,"w"); @@ -548,8 +550,8 @@ static void* eNB_thread_rxtx( void* param ) { } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { /// **** trx_write_func to IF device **** /// - // send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc, 0); - + send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc, &seqno); + } else { /// **** send_IF4 of txdataF to RRU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); @@ -626,10 +628,8 @@ static void* eNB_thread_rx_common( void* param ) { PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - uint8_t seqno=0; FILE *rx_time_file = NULL; char rx_time_name[101]; - int i; struct timespec wait; wait.tv_sec=0; @@ -764,14 +764,6 @@ static void* eNB_thread_rx_common( void* param ) { if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) LOG_E(HW,"Could not start the RF device\n"); } - - // proc->proc_rxtx[0].timestamp_tx = 0; - // seqno = send_IF5(eNB, &proc->proc_rxtx[0], 0); - - // for (i=0; i<1000;i++) { - // seqno = send_IF5(eNB, &proc->proc_rxtx[0], seqno); - // proc->proc_rxtx[0].timestamp_tx += 7680*2; - // } // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { From 9c1a6fc16e18d980b3c46d5b59de49e3418526f2 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 5 Jul 2016 17:54:35 +0200 Subject: [PATCH 082/206] rru recv frame no fix --- targets/RT/USER/lte-enb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index de37789c3d..7f8988dd0d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -495,12 +495,11 @@ static void* eNB_thread_rxtx( void* param ) { /// **** recv_IF4 of txdataF from RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1) { + do { recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); - } + } while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); - // Check the recv frame/subframe } } From ba11fc848dd749aad66be45f7a4343e739fcfd93 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 5 Jul 2016 18:01:41 +0200 Subject: [PATCH 083/206] keep alaw lut and remove other code --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 2 +- openair1/PHY/TOOLS/ALAW/companders.c | 139 ------------- openair1/PHY/TOOLS/ALAW/companders.h | 90 --------- openair1/PHY/TOOLS/ALAW/compandit.c | 128 ------------ openair1/PHY/TOOLS/ALAW/readme-companders.txt | 185 ------------------ openair1/PHY/TOOLS/{ALAW => }/alaw_lut.h | 0 6 files changed, 1 insertion(+), 543 deletions(-) delete mode 100644 openair1/PHY/TOOLS/ALAW/companders.c delete mode 100644 openair1/PHY/TOOLS/ALAW/companders.h delete mode 100644 openair1/PHY/TOOLS/ALAW/compandit.c delete mode 100644 openair1/PHY/TOOLS/ALAW/readme-companders.txt rename openair1/PHY/TOOLS/{ALAW => }/alaw_lut.h (100%) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 1a1178ee6f..587d139422 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -40,7 +40,7 @@ #include "PHY/defs.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" -#include "PHY/TOOLS/ALAW/alaw_lut.h" +#include "PHY/TOOLS/alaw_lut.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" diff --git a/openair1/PHY/TOOLS/ALAW/companders.c b/openair1/PHY/TOOLS/ALAW/companders.c deleted file mode 100644 index 566c7d6cf3..0000000000 --- a/openair1/PHY/TOOLS/ALAW/companders.c +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @companders.c - implementation - * - * @copy Copyright (C) <2012> - * @author M A Chatterjee - * @version 1.01 M. A. Chatterjee, cleaned up naming - * - * This file contains integer math compander functions for analog/audio representations on - * embedded systems. Linear2Alaw derived from Mark Spencer, Sun Microsystem and from - * the A Law specification - * - * @license: - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - */ - -#include "companders.h" - -DIO_s8 DIO_LinearToALaw(DIO_s16 sample) -{ - const DIO_s16 cClip = 32635; - const static DIO_s8 LogTable[128] = - { - 1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 - }; - - DIO_s32 sign, exponent, mantissa; - DIO_s8 compandedValue; - - sample = (sample ==-32768) ? -32767 : sample; - sign = ((~sample) >> 8) & 0x80; - if (!sign) - sample = (short)-sample; - if (sample > cClip) - sample = cClip; - if (sample >= 256) - { - exponent = (int)LogTable[(sample >> 8) & 0x7F]; - mantissa = (sample >> (exponent + 3) ) & 0x0F; - compandedValue = ((exponent << 4) | mantissa); - } - else - { - compandedValue = (unsigned char)(sample >> 4); - } - compandedValue ^= (sign ^ 0x55); - return compandedValue; -} - -DIO_s16 DIO_ALawToLinear(DIO_s8 aLawByte) -{ - const static DIO_s16 ALawDecompTable[256]={ - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848, - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944, - -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136, - -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472, - -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848}; - DIO_s16 addr = ((DIO_s16)aLawByte)+128; // done for compilers with poor expr type enforcement - return ALawDecompTable[addr]; -} - -// see companders.h -// fixed-radix IIR averager implementation supporting arbitrarily chosen windows -DIO_s32 DIO_IIRavgFR (DIO_s32 prevAvg, DIO_u16 windowLen, DIO_s16 newSample, DIO_u8 radix) -{ - DIO_s32 iirAvg=0; - iirAvg = ((prevAvg * (windowLen-1)) + (DIO_I2FR(newSample,radix)))/windowLen; - return iirAvg; -} - -// see companders.h -// fixed-radix IIR averager implementation using power-of-2 sized windows -// and only shift operations for cpu efficiency -DIO_s32 DIO_IIRavgPower2FR (DIO_s32 prevAvg, DIO_u8 windowLenInBits, DIO_s16 newSample, DIO_u8 radix) -{ - DIO_s32 iirAvg=0; - iirAvg = (((prevAvg<>windowLenInBits; - return iirAvg; -} - - -#ifdef MAIN - -int main(int argc, char* argv[]) -{ - - - - return 0; -} - -#endif diff --git a/openair1/PHY/TOOLS/ALAW/companders.h b/openair1/PHY/TOOLS/ALAW/companders.h deleted file mode 100644 index 4d1ab33f19..0000000000 --- a/openair1/PHY/TOOLS/ALAW/companders.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @companders.h - header definition file for embedded companding routines - * - * @copy Copyright (C) <2001-2012> - * @author M A Chatterjee - * @version 1.01 M. A. Chatterjee, cleaned up naming - * - * This file contains integer math settable fixed point radix math routines for - * use on systems in which floating point is not desired or unavailable. - * - * @license: - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - */ - -#ifndef __DIO_Compand_h__ -#define __DIO_Compand_h__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -//"DIO" prefixes are to assist in prevent name collisions if global namespace is used. - -//typedefs ... change for platform dependant register size -// u/s = unsigned/signed 8/16/32 = num of bits -// keywords "int" and "long" in C/C++ are platform dependant -typedef unsigned char DIO_u8 ; -typedef signed char DIO_s8 ; -typedef unsigned short DIO_u16 ; -typedef signed short DIO_s16 ; -typedef unsigned long DIO_u32 ; -typedef signed long DIO_s32 ; - -// macros for converting from Fixed-Radix to integer, vice-versa -// r represents radix precision in bits, converts to/from integer w truncation -#define DIO_I2FR(x,r) ((x)<<(r)) -#define DIO_FR2I(x,r) ((x)>>(r)) - - -// convert FR to double, this is for debug only and WILL NOT compile under many embedded systems. -// use this in test harnesses. Since this is a macro if its not used it won't expand / link -#define DIO_FR2D(x,r) ((double)(((double)(x))/((double)(1<<(r))))) - -//convert signed linear 16 bit sample to an 8 bit A-Law companded sample -DIO_s8 DIO_LinearToALaw(DIO_s16 sample); - -//convert 8bit Alaw companded representation back to linear 16 bit -DIO_s16 DIO_ALawToLinear(DIO_s8 aLawByte); - - -//DC Offset correction for integer companders -//IIR: y_0=(y_1*(w-1)+x_0)/(w) -//where w is the window length -//below are fixed radix precision IIR averagers which allow runtime tradeoffs for windowLen & precision -//Note that (windowLen)*(1< - * @author M A Chatterjee - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - */ - -#include -#include - - -#include "companders.h" - - -//=============================================== -//main program for testing the functions -int main (int argc, char *argv[]) -{ - int ret_val = 0; - int i=0,j=0; - printf("\n============================================================\n"); - printf("compandit library quikie program\n"); - printf("M. A. Chatterjee (c) 2012\n\n"); - printf("These routines were developed for use on embedded projects\n"); - printf("for more info see the accompanying compand.txt\n"); - printf("\n"); - - //uncomment to - //show how linear-->alaw-->linear-->alaw progression / quantization error works - /* - - { - char alaw=0,alaw2; - short rev=0; - - for (i= -32768; i <= 32767; i++) - { - alaw = DIO_LinearToALaw((short)i); - rev = DIO_ALawToLinear(alaw); - alaw2 =DIO_LinearToALaw(rev); - if (alaw != alaw2) - printf("***********"); - printf("%7d %7d %7d %7d\n",i,(int)alaw,(int)rev,(int)alaw2); - } - } - - - // IIR averager examples - //IIR window length of 8 samples, using fractional precision of 4 bits - { - int a3=0, a4=0; - unsigned char rad=4; //4 bits fixed-radix fractional precision - printf(" index wave IIRav(i) IIRav(f) IIRavP2(i) IIRavP2(f)\n"); - for (i=0; i < 300; i++) - { - j=(i&0x3f)-20; // triangle wave with range -20 to + 43 - a3= DIO_IIRavgFR(a3,8,j,rad); - a4= DIO_IIRavgPower2FR(a4,3,j,rad); - printf("%6d %6d %6d %9.4f %6d %9.4f \n",i,j, - DIO_FR2I(a3,rad),DIO_FR2D(a3,rad) ,DIO_FR2I(a4,rad),DIO_FR2D(a4,rad)); - } - } - //IIR window length of 64 samples - { - int a3=0, a4=0; - unsigned char rad=6; //rad is the number of bits of precision - printf(" index wave IIRav(i) IIRav(f) IIRavP2(i) IIRavP2(f)\n"); - for (i=0; i < 300; i++) - { - j=(i&0x3f)-20; // triangle wave with range -20 to + 43 - a3= DIO_IIRavgFR(a3,64,j,rad); - a4= DIO_IIRavgPower2FR(a4,6,j,rad); - printf("%6d %6d %6d %9.4f %6d %9.4f \n",i,j, - DIO_FR2I(a3,rad),DIO_FR2D(a3,rad) ,DIO_FR2I(a4,rad),DIO_FR2D(a4,rad)); - } - } - // */ - //Typical microcontroller application. See readme-companders.txt - // the input here simulates an A/D which has a range 0..3.3V mapped as 12 bits (0..4095) - // with a DC bias of 1.55V ==> (1.55/3.3)*4095 counts = 1923 counts - - //now window length of 256 is used for rejecting the resistor bias. at 8KHz this window - // would be approx 8000/256 ~= 31 Hz (not quite but explaining Z xforms is beyond what - // can be explained in this small space.) - //we seed the DC average at 3.3/2 = 1.65V (we guess its in the middle) and let the long window - //length hone in on the correct value. (1.65V/3.3V) *4095 = 2048 counts - { - int actualDCbias =1923; - int calculatedDCbias =2048; //2048 is our initial estimate as outlined above - unsigned char windowLenPow2InBits = 8; // 8 bit long window = 256 sample long window - unsigned char rad=6; //rad is the number of bits of precision - - calculatedDCbias = DIO_I2FR(calculatedDCbias,rad); - printf(" index wave actDCbias calcDCbias calcDCbias(f) alaw\n"); - for (i=0; i < 1000; i++) // if 8000 hz sample rate this represents the number of samples captured - { - j=(((i&0x3f)<<1)-63)+1923; // triangle wave w range 0..127 with a bias set at actualDCbias - calculatedDCbias = DIO_IIRavgPower2FR(calculatedDCbias,windowLenPow2InBits,j,rad); - printf("%6d %6d %6d %6d %9.4f %3d\n",i,j,actualDCbias, - DIO_FR2I(calculatedDCbias,rad),DIO_FR2D(calculatedDCbias,rad), - (int)(DIO_LinearToALaw(j-DIO_FR2I(calculatedDCbias,rad)) )); - } - } - printf("\n"); - return ret_val; -} - diff --git a/openair1/PHY/TOOLS/ALAW/readme-companders.txt b/openair1/PHY/TOOLS/ALAW/readme-companders.txt deleted file mode 100644 index dbedc91788..0000000000 --- a/openair1/PHY/TOOLS/ALAW/readme-companders.txt +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @readme-companders.txt - using compander.c / .h and related functions - * - * @copy Copyright (C) <2001-2012> - * @author M A Chatterjee - * - * This document is a brief overview of the simple compander library with - * a small introductory disucssion about fixed radix math IIRs for microcontrollers - * - * @license: - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - */ - -Welcome... - -The accompanying companders.c contains a small set of functions written in C using only integer math for companding operations. I developed this several years ago for use in several embedded interized math projects and this small, slightly cleaned up version is made available for the public here. It worked very well on M*CORE, 80x86 and ARM processors for small embedded systems. - -usage: -#include "companders.h" -no other dependancies are required. -compile and link companders.c - - -*********************** -About companding... - -Companding is a special type of lossy compression in which linear format samples are converted to logarithmic representation in order to preserve dynamic range of the original linear sample at the expense of uniform precision. Companding is an old method and is free of patents (all have expired). - -Theory of how companding works: -Suppose that we have a signed 16 bit linear sample in 2's complement math. The range of this sample can vary from -32768 to + 32767 in integer steps. Now lets put the constraint that we only have 8 bits with which to represent the data not the full 16 bits of the original linear number. A simple way to preserve high order information would be to linearly truncate off the lower 8 bits giving us a signed number from -128 to +127. We could make a mental note to keep track of the fact that we lost the lower 8 bits and so when use this representation we multiply by 8 bits (or 256) to preserve the input range. -so: --128 * 256 = -32768 --127 * 256 = -32512 -... - -1 * 256 = -256 - 0 * 256 = 0 - 1 * 256 = 256 - 2 * 256 = 512 -... - 126 * 256 = 32256 - 127 * 256 = 32512 - - Notice that the steps between these linearly rounded off samples are quite large. This truncated 8 bit representation would be very good at representing a linear quantity system such as linear displacement transducer which moves through its whole range as part of normal operation (like a door). but terrible at logarithmic phenomonen such as audio. Audio information tends to be grouped around zero with occaisonaly peaks of loudness. So with linear quantization soft audio would be lost due to the large quanitization steps at low volumes. To address this companders were developed for use in landline telephony for compressing audio data logarithmically instead of linearly. Hence we use more bits for audio samples near zero and less with audio samples near the integer max extremes. - -A-Law and it cousin mu-Law are companders. Rather than represent samples in linear steps the more bits are allocated to samples near zero while larger magnitude (positive or negative) samples are represented with proportionately larger interval sizes. - -Differential encoding (taking the difference of neighboring samples) can greatly help with compressing data to where we "have more bits" as well, provided samples rates are fast enough. Telephony typically operated with 8 bit non-differential (companded) samples at 8KHz. - -In A-Law the following table (in bits) shows how a 13 bit signed linear integer is companded in to A-Law: -(source is Sun microsystems, a similar table is on wikipedia or the G.711 specification). - - * Linear Input Code Compressed Code - * ------------------------ --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz - - - About this library: - - This free library supports A-Law and IIR averages. A-Law is used for the companding while the IIR averagers can be used for for embedded ADCs where the zero point is set loosely. Since the companders are sensitive, and allocate more bits, to values near zero its important to define a good zero. For example a microcontroller has a pin with an ADC which is fed digitized audio signal. The smallest value for the microtroncoller is 0V = 0x00 and the 3.3V = 0x3ff for 10 effective bits of resolution. A resisitive analog divider is used to center the ADC near the half-input range or about 1.6V while the audio is capacitively coupled as shown here: - - +3.3V - | - R - | - uC_ADC_Pin-----------C----audio_input - | - R - | - GND - - However cheap resistors have tolerances 5 to 10%, so the setpoint voltage could easily be anywhere from 1.4 to 1.8V. To address this software should read the ADC before audio is coming in and determine the actual DC bias voltage set by the resistors. Then when audio is coming in this value is subtracted from the ADC input to give a signed number which is fed to the LinearToAlaw encoder. - - If it not easily possible to turn off the analog / audio source then the long term DC average can be inferred by using one of the IIR functions included here with a long window length (perhaps 2000 samples if sampling at 8 KHz or about 1/4 second). These IIR functions are cheap to run in realtime even with reasonably high sample rates as they take little memory and are simple integer-math IIRs. - - About the Fixed Radix (FR) Math IIR averages - -The (Infinite Impulse Reponse) IIR functions included here use fixed radix math to represent fractional parts of an integer. By providing a settable radix (amount of bits devoted to fractional resolution), the programmer can make tradeoffs between resolution and dynamic range. The larger the radix specified the more bits that will be used in the fractional portion of the representation, which for smaller window sizes may not by necessary. There are more comprehensive ways to deal with fractional representation in binary systems (floating point, bigNum / arbitrary length registers, separation of numerator/denomators etc) but these incur much larger compute/code/memory overhead. The simple system used here avoids the need for testing for overflow/underflow which allows for low foot print code/cpu/memory bandwidth. - - To calculate how many bits of fractional part while preventing overflow use the following formulas: - -Nb = number of bits in use = ceiling(log2(highest_number_represented)) - -radix = 32-Nb(sample_resolution)-Nb(WindowLength)-2 - -for example if you have a ADC generating counts from 0 to 1023 then the Nb(ADC-range) = - Nb = ceiling(log2(1023)) = 10 bits - -If you use a DC average window length of 2000 - Nb = ceiling(log2(2000)) = 11 bits - -so the max radix that should be specified is: - radix = 32 - 10 - 11 - 2 = 32 - 23 = 9 bits - -with 9 bits in the radix fractional precision of 512 units per integer (e.g 1/512) is possible. The "2" in for formula comes from reserving bits for the sign bit and the additional operation in averager. - -The function DIO_s32 DIO_IIRavgFR() allows any integer length window size to be used, while the function DIO_IIRavgPower2FR() specifies window lengths in powers of two but all calculations are based on shift operations which can be significantly faster on lower end microprocessors. - - - -Embedded Systems - -Now back to an embedded microcontroller example. It has a ADC which maps the voltage on 1 pin from 0-3.3V in to 0-4095 counts (12 bit). We capacitively couple the input voltage and use the bias resistors to set mid point in the center of the range. Lets say the the our resistors set the bias at 1.55V. This equals our "zero point". Below this point is negative from the incoming capacitively coupled audio and above this is positive. - -Our "guess" as to the bias = both resistors are the same = (3.3V/2) =1.65V = (1.65V)/(4095 counts/3.3V)= 2048 counts - -Resistor actual set bias "zero point" = 1.55V = (1.55V) *(4095 counts/3.3V)) = 1923 counts -We want this to be "zero" we use for the companded A/D process. - -To do this we start our ADC to periodically sample for sometime before we start "recording" audio. We will feed the ADC values in to our IIR average to find the actual zero point. Note that even when we decide not to "record" we still can still run the A/D and IIR averager so its adapting to the real zero point. - - - -//C-like psuedo code - -#include "companders.h" - -static volatile int32 gIIRavg= 2048; // global static var holds DC average -static volatile int gDoSomethingWithCompandedValue=0; -void processAudioSample() //interrupt handler -{ - short adcValue; - char aLawValue; - - //read the raw uncorrected sample - adcValue= inputPin.read_u16(); // read a 16 bit unsigned sample - - // this updates the IIR average everytime the adc returns a sample - gIIRavg = DIO_IIRavgPower2FR(gIIRavg,11,adcValue,8); - - //now compute companded value with DC offset correction - if (gDoSomethingWithCompandedValue) - { - aLawValue = DIO_LinearToALaw(adcValue-DIO_FR2I(gIIRavg)); - doSomethingWithALaw(aLawValue); // store it to a buffer, send it etc - } -} - -main() -{ - gDoSomethingWithCompandedValue=0; - inputPin.attachInterrupt(&processAudioSample,8000); //attach interrupt handler, 8000 Hz sample rate - - // ... somepoint later in the code - - inputPin.start(); // start the averager - - // ... some time later - gDoSomethingWithCompandedValue=1; //now the interrupt routine will call the doSomethingWithALaw() function - - // ... some time later - gDoSomethingWithCompandedValue=0; //we're no longer collecting ALaw companded date, but we're - // still running the IIR averager - - -} - -Finally, it can be in some systems that we can't turn off the audio input source it may be hard wired to some sensor or mic or perhaps the A/D center bias circuit (the 2 resistors) always is on when the audio is on. In this case running the IIR with a long filter length all the time can remove the bias even when the audio is running. For example in an 8KHz sampling system with an IIR length of 1024 is about 1/8 of a second or a cutoff freq well below 10Hz and costs almost nothing to run. - - - diff --git a/openair1/PHY/TOOLS/ALAW/alaw_lut.h b/openair1/PHY/TOOLS/alaw_lut.h similarity index 100% rename from openair1/PHY/TOOLS/ALAW/alaw_lut.h rename to openair1/PHY/TOOLS/alaw_lut.h From c32304afbf62be70b61e83ae7d340b0e80767f42 Mon Sep 17 00:00:00 2001 From: "S. Sandeep Kumar" Date: Wed, 6 Jul 2016 01:34:12 +0530 Subject: [PATCH 084/206] allow rf and if for eNB build --- cmake_targets/build_oai | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 28ded73d7b..ceb3400d0e 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -296,9 +296,6 @@ function main() { if [ "$HW" = "None" -a "$TP" = "None" ] ; then echo_fatal "Define a local radio head (e.g. -w EXMIMO) or a transport protocol (e.g. -t ETHERNET) to communicate with a remote radio head!" fi - if [ "$HW" != "None" -a "$TP" != "None" ] ; then - echo_fatal "Currently eNB can not support simultaniously local and remote radio heads!!" - fi if [ "$HW" = "None" ] ; then echo_info "No radio head has been selected (HW set to $HW)" fi From 622f91735155fac1ebbed5204697091a574b6a98 Mon Sep 17 00:00:00 2001 From: "S. Sandeep Kumar" Date: Wed, 6 Jul 2016 03:02:53 +0530 Subject: [PATCH 085/206] adjust spp for whole number per subframe --- .../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 81e3d7b558..0ec8971ba8 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -83,7 +83,7 @@ int trx_eth_start(openair0_device *device) { if(eth_get_dev_conf_raw_IF4(device)!=0) return -1; } /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; + if(ethernet_tune (device,MTU_SIZE,RAW_IF4_PRACH_SIZE_BYTES)!=0) return -1; } else if (eth->flags == ETH_UDP_IF4_MODE) { @@ -107,8 +107,6 @@ int trx_eth_start(openair0_device *device) { } else { if(eth_get_dev_conf_udp(device)!=0) return -1; } - /* adjust MTU wrt number of samples per packet */ - //if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; } /* apply additional configuration */ if(ethernet_tune (device, SND_BUF_SIZE,2000000000)!=0) return -1; @@ -386,8 +384,6 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth device->priv = eth; /* device specific */ - //openair0_cfg[0].txlaunch_wait = 0;//manage when TX processing is triggered - //openair0_cfg[0].txlaunch_wait_slotcount = 0; //manage when TX processing is triggered openair0_cfg[0].iq_rxrescale = 15;//rescale iqs openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance; @@ -397,19 +393,19 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth /*Note scheduling advance values valid only for case 7680000 */ switch ((int)openair0_cfg[0].sample_rate) { case 30720000: - openair0_cfg[0].samples_per_packet = 4096; + openair0_cfg[0].samples_per_packet = 3840; break; case 23040000: - openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].samples_per_packet = 2880; break; case 15360000: - openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].samples_per_packet = 1920; break; case 7680000: - openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].samples_per_packet = 960; break; case 1920000: - openair0_cfg[0].samples_per_packet = 256; + openair0_cfg[0].samples_per_packet = 240; break; default: printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); From 8dcc3ddb4d7aac790d3867e63c04026f67e137c7 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 6 Jul 2016 09:56:13 +0200 Subject: [PATCH 086/206] if_defs and eth_lib .h cleanup --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 1 - openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c | 1 - targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 3 --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 1 - targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 1 - targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 3 +++ 6 files changed, 3 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 587d139422..a0e4d2e3f7 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -39,7 +39,6 @@ */ #include "PHY/defs.h" -#include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/TOOLS/alaw_lut.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" diff --git a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c index d38dfb76a5..ab60c2fb0f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c @@ -39,7 +39,6 @@ */ #include "PHY/defs.h" -#include "PHY/LTE_TRANSPORT/if5_mobipass_tools.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index bf5554fd26..699d15350b 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -51,9 +51,6 @@ #include "common_lib.h" #include "ethernet_lib.h" -#include "if_defs.h" -#include "openair1/PHY/LTE_TRANSPORT/if4_tools.h" -#include "openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h" #define DEBUG 0 diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index 55b5e08535..a9706c73bd 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -52,7 +52,6 @@ #include "common_lib.h" #include "ethernet_lib.h" -#include "if_defs.h" #define DEBUG 0 struct sockaddr_in dest_addr[MAX_INST]; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 0ec8971ba8..f29375dac3 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -51,7 +51,6 @@ #include "common_lib.h" #include "ethernet_lib.h" -#include "if_defs.h" int num_devices_eth = 0; struct sockaddr_in dest_addr[MAX_INST]; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index e17890836b..86f580d911 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -41,6 +41,9 @@ #include #include +#include "PHY/LTE_TRANSPORT/if4_tools.h" +#include "PHY/LTE_TRANSPORT/if5_mobipass_tools.h" + // ETH transport preference modes #define ETH_UDP_MODE 0 #define ETH_RAW_MODE 1 From b5fbdbe252734c0725f6251d8e0e626f7bd1814e Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 6 Jul 2016 12:23:00 +0200 Subject: [PATCH 087/206] test if5 send from BBU with new spp --- cmake_targets/CMakeLists.txt | 2 +- .../PHY/LTE_TRANSPORT/if5_mobipass_tools.c | 99 ----------- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 165 ++++++++++++++++++ .../{if5_mobipass_tools.h => if5_tools.h} | 7 +- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 2 +- targets/RT/USER/lte-enb.c | 4 +- 6 files changed, 174 insertions(+), 105 deletions(-) delete mode 100644 openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c create mode 100644 openair1/PHY/LTE_TRANSPORT/if5_tools.c rename openair1/PHY/LTE_TRANSPORT/{if5_mobipass_tools.h => if5_tools.h} (90%) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index f96c63f2bb..a39cf35f6a 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -963,7 +963,7 @@ set(PHY_SRC ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/print_stats.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/initial_sync.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_mobipass_tools.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_tools.c ${OPENAIR1_DIR}/PHY/MODULATION/ofdm_mod.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_mbsfn.c diff --git a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c deleted file mode 100644 index ab60c2fb0f..0000000000 --- a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.c +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ - -/*! \file PHY/LTE_TRANSPORT/if5_mobipass_tools.c -* \brief -* \author S. Sandeep Kumar, Raymond Knopp -* \date 2016 -* \version 0.1 -* \company Eurecom -* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr -* \note -* \warning -*/ - -#include "PHY/defs.h" - -#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" - - -void send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t *seqno) { - - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - void *txp[fp->nb_antennas_tx]; - void *tx_buffer=NULL; - __m128i *data_block=NULL, *data_block_head=NULL; - - __m128i *txp128; - __m128i t0, t1; - - uint16_t packet_id=0, i; - uint16_t db_fulllength=640; - - tx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); - IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block_head = (__m128i *)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 4); - - header->flags = 0; - header->fifo_status = 0; - header->seqno = *seqno; - header->ack = 0; - header->word0 = 0; - - txp[0] = (void*)&eNB->common_vars.txdata[0][0][proc->subframe_tx*eNB->frame_parms.samples_per_tti]; - txp128 = (__m128i *) txp[0]; - - for (packet_id=0; packet_id<(fp->samples_per_tti*2)/db_fulllength; packet_id++) { - header->time_stamp = proc->timestamp_tx + packet_id * db_fulllength; - data_block = data_block_head; - - for (i=0; i>3; i+=2) { - t0 = _mm_srli_epi16(*txp128++, 4); - t1 = _mm_srli_epi16(*txp128++, 4); - - *data_block++ = _mm_packs_epi16(t0, t1); - } - - // Write the packet to the fronthaul - if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, - packet_id, - &tx_buffer, - db_fulllength, - 1, - IF5_MOBIPASS)) < 0) { - perror("ETHERNET write for IF5_MOBIPASS\n"); - } - - header->seqno += 1; - } - - *seqno = header->seqno; - free(tx_buffer); - return; -} diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c new file mode 100644 index 0000000000..ffa1df5863 --- /dev/null +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -0,0 +1,165 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/*! \file PHY/LTE_TRANSPORT/if5_tools.c +* \brief +* \author S. Sandeep Kumar, Raymond Knopp +* \date 2016 +* \version 0.1 +* \company Eurecom +* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr +* \note +* \warning +*/ + +#include "PHY/defs.h" + +#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" + + +void send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t *seqno, uint16_t packet_type) { + + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + void *txp[fp->nb_antennas_tx]; + void *tx_buffer=NULL; + + uint16_t packet_id=0, i=0; + + if (packet_type == IF5_RRH_GW) { + + unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; + unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; + + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] = (void*)&eNB->common_vars.txdata[0][i][proc->subframe_tx*fp->samples_per_tti]; + + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + eNB->ifdevice.trx_write_func(&eNB->ifdevice, + (proc->timestamp_tx-eNB->ifdevice.openair0_cfg->tx_sample_advance + packet_id*spp_eth), + txp, + spp_eth, + fp->nb_antennas_tx, + 0); + } + + printf("SPP = %d and packet_id %d\n", spp_eth, packet_id); + + } else if (packet_type == IF5_MOBIPASS) { + + uint16_t db_fulllength=640; + + __m128i *data_block=NULL, *data_block_head=NULL; + + __m128i *txp128; + __m128i t0, t1; + + tx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); + IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block_head = (__m128i *)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 4); + + header->flags = 0; + header->fifo_status = 0; + header->seqno = *seqno; + header->ack = 0; + header->word0 = 0; + + txp[0] = (void*)&eNB->common_vars.txdata[0][0][proc->subframe_tx*eNB->frame_parms.samples_per_tti]; + txp128 = (__m128i *) txp[0]; + + for (packet_id=0; packet_id<(fp->samples_per_tti*2)/db_fulllength; packet_id++) { + header->time_stamp = proc->timestamp_tx + packet_id * db_fulllength; + data_block = data_block_head; + + for (i=0; i>3; i+=2) { + t0 = _mm_srli_epi16(*txp128++, 4); + t1 = _mm_srli_epi16(*txp128++, 4); + + *data_block++ = _mm_packs_epi16(t0, t1); + } + + // Write the packet to the fronthaul + if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, + packet_id, + &tx_buffer, + db_fulllength, + 1, + IF5_MOBIPASS)) < 0) { + perror("ETHERNET write for IF5_MOBIPASS\n"); + } + + header->seqno += 1; + } + *seqno = header->seqno; + } else { + AssertFatal(1==0, "send_IF5 - Unknown packet_type %x", packet_type); + } + + free(tx_buffer); + return; +} + + +void recv_IF5(PHY_VARS_eNB *eNB, eNB_proc_t *proc, uint16_t packet_type) { + + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + void *rxp[fp->nb_antennas_rx]; + void *rx_buffer=NULL; + + uint16_t packet_id=0, i=0; + + if (packet_type == IF5_RRH_GW) { + + unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; + unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; + + openair0_timestamp timestamp[spsf / spp_eth]; + + for (i=0; i < fp->nb_antennas_rx; i++) + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][proc->subframe_rx*fp->samples_per_tti]; + + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + eNB->ifdevice.trx_read_func(&eNB->ifdevice, + ×tamp[packet_id], + rxp, + spp_eth, + fp->nb_antennas_rx); + } + +// proc->timestamp_rx = timestamp[0]; + + } else if (packet_type == IF5_MOBIPASS) { + + + } else { + AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type); + } + + free(rx_buffer); + return; +} diff --git a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_tools.h similarity index 90% rename from openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h rename to openair1/PHY/LTE_TRANSPORT/if5_tools.h index e9bc26f9a6..07d6865a54 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_mobipass_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.h @@ -27,7 +27,7 @@ *******************************************************************************/ -/*! \file PHY/LTE_TRANSPORT/if5_mobipass_tools.h +/*! \file PHY/LTE_TRANSPORT/if5_tools.h * \brief * \author S. Sandeep Kumar, Raymond Knopp * \date 2016 @@ -41,6 +41,7 @@ #include #include "PHY/defs.h" +#define IF5_RRH_GW 0x0022 #define IF5_MOBIPASS 0xbffe struct IF5_mobipass_header { @@ -62,4 +63,6 @@ struct IF5_mobipass_header { typedef struct IF5_mobipass_header IF5_mobipass_header_t; #define sizeof_IF5_mobipass_header_t 14 -void send_IF5(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint8_t*); +void send_IF5(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint8_t*, uint16_t); + +void recv_IF5(PHY_VARS_eNB*, eNB_proc_t*, uint16_t); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 86f580d911..8fb84e37fc 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -42,7 +42,7 @@ #include #include "PHY/LTE_TRANSPORT/if4_tools.h" -#include "PHY/LTE_TRANSPORT/if5_mobipass_tools.h" +#include "PHY/LTE_TRANSPORT/if5_tools.h" // ETH transport preference modes #define ETH_UDP_MODE 0 diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 7f8988dd0d..9111fe42c6 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -69,7 +69,7 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all #include "PHY/LTE_TRANSPORT/if4_tools.h" -#include "PHY/LTE_TRANSPORT/if5_mobipass_tools.h" +#include "PHY/LTE_TRANSPORT/if5_tools.h" #include "PHY/extern.h" #include "SCHED/extern.h" @@ -549,7 +549,7 @@ static void* eNB_thread_rxtx( void* param ) { } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { /// **** trx_write_func to IF device **** /// - send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc, &seqno); + send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc, &seqno, IF5_RRH_GW); } else { /// **** send_IF4 of txdataF to RRU **** /// From 25952d4450d432fdf155b200525fca8124a0e809 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 6 Jul 2016 17:08:26 +0200 Subject: [PATCH 088/206] added node fn RRU_IF5, split points and vcd logging --- openair1/PHY/defs.h | 7 ++-- openair1/SCHED/phy_procedures_lte_eNb.c | 18 ++++++++-- openair2/UTIL/LOG/vcd_signal_dumper.c | 6 ++-- openair2/UTIL/LOG/vcd_signal_dumper.h | 6 ++-- targets/RT/USER/lte-enb.c | 35 +++++++++++++----- targets/RT/USER/lte-softmodem.c | 47 ++++++++----------------- 6 files changed, 67 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 70a661adf0..f9a4596129 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -158,10 +158,11 @@ enum transmission_access_mode { CBA_ACCESS}; typedef enum { - eNodeB_3GPP=0, // classical eNodeB function + eNodeB_3GPP=0, // classical eNodeB function eNodeB_3GPP_BBU, // eNodeB with NGFI IF5 - NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) - NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) + NGFI_RRU_IF5, // NGFI_RRU with IF5 + NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) + NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) } eNB_func_t; typedef struct UE_SCAN_INFO_s { diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index a81e9dcfad..db069c6440 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2546,7 +2546,8 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) - if ((eNB->node_function == NGFI_RRU_IF4) || + if ((eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == NGFI_RRU_IF5) || (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF for (i=0; inb_antennas_rx; i++) @@ -2586,7 +2587,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); } else if(eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF - /// **** trx_read_func from IF device **** /// + /// **** recv_IF5 of rxdata from RRH **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); + nanosleep(&time_req, &time_rem); proc->timestamp_rx += fp->samples_per_tti; @@ -2598,7 +2603,14 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); } - + + if (eNB->node_function == NGFI_RRU_IF5) { + /// **** send_IF5 of rxdata to BBU **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); + //send_IF5(eNB, proc, ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); + + } if ((eNB->node_function == NGFI_RRU_IF4) || (eNB->node_function == eNodeB_3GPP) || diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 73abd5d698..8fe33fefd5 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -331,9 +331,11 @@ const char* eurecomFunctionsNames[] = { "itti_relay_thread", "test", - /* IF4 signals */ + /* IF4/IF5 signals */ "send_if4", - "recv_if4" + "recv_if4", + "send_if5", + "recv_if5" }; struct vcd_module_s vcd_modules[VCD_SIGNAL_DUMPER_MODULE_END] = { diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index b6d0072603..7bcdc5733b 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -308,10 +308,12 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_ITTI_RELAY_THREAD, VCD_SIGNAL_DUMPER_FUNCTIONS_TEST, - /* IF4 signals */ + /* IF4/IF5 signals */ VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, - + VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, + VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, + VCD_SIGNAL_DUMPER_FUNCTIONS_LAST, VCD_SIGNAL_DUMPER_FUNCTIONS_END = VCD_SIGNAL_DUMPER_FUNCTIONS_LAST, } vcd_signal_dump_functions; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 9111fe42c6..0668764edd 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -436,7 +436,9 @@ static void* eNB_thread_rxtx( void* param ) { if (oai_exit) break; // UE-specific RX processing for subframe n - if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { + if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); // this is the ue-specific processing for the subframe and can be multi-threaded later phy_procedures_eNB_uespec_RX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay ); @@ -474,7 +476,9 @@ static void* eNB_thread_rxtx( void* param ) { if (oai_exit) break; - if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RRU_IF4) { + if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4)) { phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay, NULL ); /* we're done, let the next one proceed */ @@ -491,8 +495,7 @@ static void* eNB_thread_rxtx( void* param ) { exit_fun("nothing to add"); break; } - } else { - + } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) { /// **** recv_IF4 of txdataF from RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); do { @@ -500,11 +503,19 @@ static void* eNB_thread_rxtx( void* param ) { } while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); + } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5) { + /// **** recv_IF5 of txdata from BBU **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); + //recv_IF5(); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); + } } // eNodeB_3GPP, _BBU and RRU create txdata - if (PHY_vars_eNB_g[0][proc->CC_id]->node_function != NGFI_RCC_IF4) { + if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); @@ -526,8 +537,9 @@ static void* eNB_thread_rxtx( void* param ) { // eNodeB_3GPP, RRU write to RF device - if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP || - PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) { + if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) || + (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5)) { // Transmit TX buffer based on timestamp from RX VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers @@ -548,14 +560,17 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { - /// **** trx_write_func to IF device **** /// + /// **** send_IF5 of txdata to RRH **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc, &seqno, IF5_RRH_GW); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); } else { /// **** send_IF4 of txdataF to RRU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + } if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { @@ -759,7 +774,9 @@ static void* eNB_thread_rx_common( void* param ) { } // Start RF device for this CC - if (eNB->node_function == eNodeB_3GPP || eNB->node_function == NGFI_RRU_IF4) { + if ((eNB->node_function == eNodeB_3GPP) || + (eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == NGFI_RRU_IF5)) { if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) LOG_E(HW,"Could not start the RF device\n"); } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 656c22ced3..887f95a111 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -385,9 +385,11 @@ void help (void) { printf(" --ue-txgain set UE TX gain\n"); printf(" --ue-scan_carrier set UE to scan around carrier\n"); printf(" --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n"); - printf(" --RCC run using NGFI RCC node function\n"); - printf(" --RRU run using NGFI RRU node function\n"); + printf(" --RCC run using NGFI RCC node function IF4 split\n"); + printf(" --RRU run using NGFI RRU node function IF4 split\n"); printf(" --eNB run using 3GPP eNB node function\n"); + printf(" --BBU run using 3GPP eNB node function with IF5 split\n"); + printf(" --RRH run using RRH node function with IF5 split\n"); printf(" -C Set the downlink frequency for all component carriers\n"); printf(" -d Enable soft scope and L1 and L2 stats (Xforms)\n"); printf(" -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"); @@ -687,7 +689,8 @@ static void get_options (int argc, char **argv) LONG_OPTION_RCC, LONG_OPTION_RRU, LONG_OPTION_ENB, - LONG_OPTION_ENB_BBU + LONG_OPTION_ENB_BBU, + LONG_OPTION_RRH #if T_TRACER , LONG_OPTION_T_PORT, @@ -715,6 +718,7 @@ static void get_options (int argc, char **argv) {"RRU", no_argument, NULL, LONG_OPTION_RRU}, {"eNB", no_argument, NULL, LONG_OPTION_ENB}, {"BBU", no_argument, NULL, LONG_OPTION_ENB_BBU}, + {"RRH", no_argument, NULL, LONG_OPTION_RRH}, #if T_TRACER {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, @@ -821,6 +825,10 @@ static void get_options (int argc, char **argv) case LONG_OPTION_ENB_BBU: node_function = eNodeB_3GPP_BBU; break; + + case LONG_OPTION_RRH: + node_function = NGFI_RRU_IF5; + break; #if T_TRACER case LONG_OPTION_T_PORT: { @@ -1649,7 +1657,7 @@ int main( int argc, char **argv ) openair0_cfg[0].log_level = glog_level; for (CC_id=0; CC_idrfdevice.host_type = RRH_HOST; PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = RRH_HOST; } else { @@ -1670,39 +1678,12 @@ int main( int argc, char **argv ) openair0.type = NONE_DEV; /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ openair0.transp_type = NONE_TP; - - // Legacy BBU - RRH init - //int returns=-1; - ///* BBU can have either a local or a remote radio head */ - //if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active - load library of radio head and initiate it - //if (mode!=loop_through_memory) { - //returns=openair0_device_load(&openair0, &openair0_cfg[0]); - //printf("openair0_device_init returns %d\n",returns); - //if (returns<0) { - //printf("Exiting, cannot initialize device\n"); - //exit(-1); - //} - //} - //else if (mode==loop_through_memory) { - //} - //} else { //remote radio head active - load library of transport protocol and initiate it - //if (mode!=loop_through_memory) { - //returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params); - //printf("openair0_transport_init returns %d\n",returns); - //if (returns<0) { - //printf("Exiting, cannot initialize transport protocol\n"); - //exit(-1); - //} - //} - //else if (mode==loop_through_memory) { - //} - //} - + int returns=-1; // Handle spatially distributed MIMO antenna ports // Load RF device and initialize - if (node_function == NGFI_RRU_IF4 || node_function == eNodeB_3GPP) { + if (node_function == NGFI_RRU_IF5 || node_function == NGFI_RRU_IF4 || node_function == eNodeB_3GPP) { for (CC_id=0; CC_idrfdevice), &openair0_cfg[0]); From f57a8b8c8f5891f126ce36e7433e355598629cc2 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 6 Jul 2016 18:28:57 +0200 Subject: [PATCH 089/206] changes to send/recv if5 --- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 73 ++++++++++++++++++------- openair1/PHY/LTE_TRANSPORT/if5_tools.h | 7 ++- openair1/SCHED/phy_procedures_lte_eNb.c | 5 +- targets/RT/USER/lte-enb.c | 4 +- 4 files changed, 62 insertions(+), 27 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index ffa1df5863..afbe33bd7f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -43,35 +43,47 @@ #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" -void send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t *seqno, uint16_t packet_type) { +void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe, uint8_t *seqno, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - void *txp[fp->nb_antennas_tx]; + void *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; void *tx_buffer=NULL; uint16_t packet_id=0, i=0; - if (packet_type == IF5_RRH_GW) { - + if (packet_type == IF5_RRH_GW_DL) { unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] = (void*)&eNB->common_vars.txdata[0][i][proc->subframe_tx*fp->samples_per_tti]; + txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { eNB->ifdevice.trx_write_func(&eNB->ifdevice, - (proc->timestamp_tx-eNB->ifdevice.openair0_cfg->tx_sample_advance + packet_id*spp_eth), - txp, + (proc_timestamp - eNB->ifdevice.openair0_cfg->tx_sample_advance + packet_id*spp_eth), + (txp + packet_id*spp_eth), spp_eth, fp->nb_antennas_tx, 0); } - printf("SPP = %d and packet_id %d\n", spp_eth, packet_id); - - } else if (packet_type == IF5_MOBIPASS) { + } else if (packet_type == IF5_RRH_GW_UL) { + unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; + unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; + for (i=0; i < fp->nb_antennas_rx; i++) + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; + + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + eNB->ifdevice.trx_write_func(&eNB->ifdevice, + (proc_timestamp + packet_id*spp_eth), + (rxp + packet_id*spp_eth), + spp_eth, + fp->nb_antennas_rx, + 0); + } + + } else if (packet_type == IF5_MOBIPASS) { uint16_t db_fulllength=640; __m128i *data_block=NULL, *data_block_head=NULL; @@ -89,11 +101,11 @@ void send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t *seqno, uint16_t header->ack = 0; header->word0 = 0; - txp[0] = (void*)&eNB->common_vars.txdata[0][0][proc->subframe_tx*eNB->frame_parms.samples_per_tti]; + txp[0] = (void*)&eNB->common_vars.txdata[0][0][subframe*eNB->frame_parms.samples_per_tti]; txp128 = (__m128i *) txp[0]; for (packet_id=0; packet_id<(fp->samples_per_tti*2)/db_fulllength; packet_id++) { - header->time_stamp = proc->timestamp_tx + packet_id * db_fulllength; + header->time_stamp = proc_timestamp + packet_id*db_fulllength; data_block = data_block_head; for (i=0; i>3; i+=2) { @@ -116,6 +128,7 @@ void send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t *seqno, uint16_t header->seqno += 1; } *seqno = header->seqno; + } else { AssertFatal(1==0, "send_IF5 - Unknown packet_type %x", packet_type); } @@ -125,34 +138,52 @@ void send_IF5(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, uint8_t *seqno, uint16_t } -void recv_IF5(PHY_VARS_eNB *eNB, eNB_proc_t *proc, uint16_t packet_type) { +void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - void *rxp[fp->nb_antennas_rx]; + void *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; void *rx_buffer=NULL; uint16_t packet_id=0, i=0; - if (packet_type == IF5_RRH_GW) { - + if (packet_type == IF5_RRH_GW_DL) { + unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; + unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; + + openair0_timestamp timestamp[spsf / spp_eth]; + + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; + + for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + eNB->ifdevice.trx_read_func(&eNB->ifdevice, + ×tamp[packet_id], + (txp + packet_id*spp_eth), + spp_eth, + fp->nb_antennas_tx); + } + + *proc_timestamp = timestamp[0]; + + } else if (packet_type == IF5_RRH_GW_UL) { unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; openair0_timestamp timestamp[spsf / spp_eth]; for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][proc->subframe_rx*fp->samples_per_tti]; + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], - rxp, + (rxp + packet_id*spp_eth), spp_eth, fp->nb_antennas_rx); } - -// proc->timestamp_rx = timestamp[0]; - + + *proc_timestamp = timestamp[0]; + } else if (packet_type == IF5_MOBIPASS) { diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_tools.h index 07d6865a54..f46897cc51 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.h @@ -41,7 +41,8 @@ #include #include "PHY/defs.h" -#define IF5_RRH_GW 0x0022 +#define IF5_RRH_GW_DL 0x0022 +#define IF5_RRH_GW_UL 0x0023 #define IF5_MOBIPASS 0xbffe struct IF5_mobipass_header { @@ -63,6 +64,6 @@ struct IF5_mobipass_header { typedef struct IF5_mobipass_header IF5_mobipass_header_t; #define sizeof_IF5_mobipass_header_t 14 -void send_IF5(PHY_VARS_eNB*, eNB_rxtx_proc_t*, uint8_t*, uint16_t); +void send_IF5(PHY_VARS_eNB*, openair0_timestamp, int, uint8_t*, uint16_t); -void recv_IF5(PHY_VARS_eNB*, eNB_proc_t*, uint16_t); +void recv_IF5(PHY_VARS_eNB*, openair0_timestamp*, int, uint16_t); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index db069c6440..725bc60715 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -45,6 +45,7 @@ #include "SCHED/extern.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" +#include "PHY/LTE_TRANSPORT/if5_tools.h" #ifdef EMOS #include "SCHED/phy_procedures_emos.h" @@ -2521,6 +2522,8 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl int prach_rx; + uint8_t seqno=0; + uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; @@ -2607,7 +2610,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (eNB->node_function == NGFI_RRU_IF5) { /// **** send_IF5 of rxdata to BBU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - //send_IF5(eNB, proc, ); + send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); } diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 0668764edd..ce4504ff0d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -506,7 +506,7 @@ static void* eNB_thread_rxtx( void* param ) { } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5) { /// **** recv_IF5 of txdata from BBU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - //recv_IF5(); + recv_IF5(PHY_vars_eNB_g[0][proc->CC_id], &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); } @@ -562,7 +562,7 @@ static void* eNB_thread_rxtx( void* param ) { } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { /// **** send_IF5 of txdata to RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc, &seqno, IF5_RRH_GW); + send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); } else { From 9cbf5819c143926a071142a097b8da06f9df8710 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 7 Jul 2016 11:27:50 +0200 Subject: [PATCH 090/206] fixes from bbu/rrh trial run --- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 20 ++++++++++--- openair1/SCHED/phy_procedures_lte_eNb.c | 38 ++++++++++++++++--------- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index afbe33bd7f..9fdd67c09e 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -59,9 +59,12 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] += packet_id*spp_eth; + eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp - eNB->ifdevice.openair0_cfg->tx_sample_advance + packet_id*spp_eth), - (txp + packet_id*spp_eth), + txp, spp_eth, fp->nb_antennas_tx, 0); @@ -75,9 +78,12 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + for (i=0; i < fp->nb_antennas_rx; i++) + rxp[i] += packet_id*spp_eth; + eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), - (rxp + packet_id*spp_eth), + rxp, spp_eth, fp->nb_antennas_rx, 0); @@ -156,9 +162,12 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] += packet_id*spp_eth; + eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], - (txp + packet_id*spp_eth), + txp, spp_eth, fp->nb_antennas_tx); } @@ -175,9 +184,12 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + for (i=0; i < fp->nb_antennas_tx; i++) + rxp[i] += packet_id*spp_eth; + eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], - (rxp + packet_id*spp_eth), + rxp, spp_eth, fp->nb_antennas_rx); } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 725bc60715..478ae20c30 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2592,29 +2592,33 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } else if(eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - + recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - nanosleep(&time_req, &time_rem); - - proc->timestamp_rx += fp->samples_per_tti; + //nanosleep(&time_req, &time_rem); + //proc->timestamp_rx += fp->samples_per_tti; proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + if (proc->first_rx == 0) { + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + //exit_fun("Exiting"); + } + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + //exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + } + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); } - if (eNB->node_function == NGFI_RRU_IF5) { - /// **** send_IF5 of rxdata to BBU **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); - - } - if ((eNB->node_function == NGFI_RRU_IF4) || (eNB->node_function == eNodeB_3GPP) || (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing @@ -2679,6 +2683,12 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } } + } else if (eNB->node_function == NGFI_RRU_IF5) { + /// **** send_IF5 of rxdata to BBU **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); + send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); + } else if (eNB->node_function == NGFI_RCC_IF4) { /// **** recv_IF4 of rxdataF from RRU **** /// /// **** recv_IF4 of rxsigF from RRU **** /// @@ -2734,11 +2744,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl if (proc->first_rx == 0) { if (proc->subframe_rx != subframe){ LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); -// exit_fun("Exiting"); + //exit_fun("Exiting"); } if (proc->frame_rx != frame) { LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - // exit_fun("Exiting"); + //exit_fun("Exiting"); } } else { proc->first_rx = 0; From 5f0e15a4b854643c03f9e8ca7c0a38afbdb841f4 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Thu, 7 Jul 2016 19:05:14 +0200 Subject: [PATCH 091/206] save for switching pc --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 16 ++++++++-------- targets/RT/USER/lte-enb.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index a0e4d2e3f7..e7c3294ce8 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -210,8 +210,11 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ *subframe = ((packet_header->frame_status)>>22)&0x000f; if (*packet_type == IF4_PDLFFT) { + // Find and return symbol_number + *symbol_number = ((packet_header->frame_status)>>26)&0x000f; + // Calculate from received packet - slotoffsetF = (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; // Do decompression of the two parts and generate txdataF @@ -222,13 +225,13 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ txdataF[0][slotoffsetF+element_id] = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; txdataF[0][slotoffsetF+element_id] |= alaw2lin[ (data_block[element_id+db_halflength]>>8) ]<<16; } - + + } else if (*packet_type == IF4_PULFFT) { // Find and return symbol_number *symbol_number = ((packet_header->frame_status)>>26)&0x000f; - - } else if (*packet_type == IF4_PULFFT) { + // Calculate from received packet - slotoffsetF = (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; // Do decompression of the two parts and generate rxdataF @@ -240,9 +243,6 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ rxdataF[0][slotoffsetF+element_id] |= alaw2lin[ (data_block[element_id+db_halflength]>>8) ]<<16; } - // Find and return symbol_number - *symbol_number = ((packet_header->frame_status)>>26)&0x000f; - } else if (*packet_type == IF4_PRACH) { // FIX: hard coded prach samples length db_fulllength = 839*2; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index ce4504ff0d..29122757b0 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -501,6 +501,14 @@ static void* eNB_thread_rxtx( void* param ) { do { recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); } while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1); + + if (proc->subframe_tx == 0 && proc->frame_tx == 0) { + write_output("eNBtxsigF.m","txF",PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdataF[0][0], + PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti * PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.ofdm_symbol_size, + 1,1); + exit(1); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5) { @@ -570,6 +578,13 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + + if (proc->subframe_tx == 0 && proc->frame_tx == 0) { + write_output("fr_bf_comp.m","txF",PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdataF[0][0], + PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti * PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.ofdm_symbol_size, + 1,1); + exit(1); + } } From 8934fed89ee0361416717fb72766a1a37991a5a2 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 8 Jul 2016 17:01:06 +0200 Subject: [PATCH 092/206] fixed issue with offset and sign extension --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 93 ++++++++----------- openair1/PHY/TOOLS/alaw_lut.h | 10 +- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 2 +- 3 files changed, 45 insertions(+), 60 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index e7c3294ce8..cf1776754c 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -29,11 +29,11 @@ /*! \file PHY/LTE_TRANSPORT/if4_tools.c * \brief -* \author Fredrik Skretteberg, Tobias Schuster, Mauricio Gunther, S. Sandeep Kumar, Raymond Knopp +* \author S. Sandeep Kumar, Raymond Knopp * \date 2016 * \version 0.1 * \company Eurecom -* \email: knopp@eurecom.fr +* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr * \note * \warning */ @@ -44,7 +44,6 @@ #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" -// --- Careful to handle buffer memory --- RAW/UDP modes --- PRACH variables and data void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int k) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; @@ -56,35 +55,33 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int slotoffsetF=0, blockoffsetF=0; void *tx_buffer=NULL; - int16_t *data_block=NULL; + uint16_t *data_block=NULL, *i=NULL; if (packet_type == IF4_PDLFFT) { db_fulllength = 12*fp->N_RB_DL; db_halflength = (db_fulllength)>>1; slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; - blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(int16_t)); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(uint16_t)); IF4_header_t *dl_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); + data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); gen_IF4_dl_header(dl_header, frame, subframe); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - // Do compression of the two parts and generate data blocks + for (element_id=0; element_id>16) + 32768 ]<<8; - - data_block[element_id+db_halflength] = lin2alaw[ (txdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; - data_block[element_id+db_halflength] |= lin2alaw[ (txdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; + i = (uint16_t*) &txdataF[0][blockoffsetF+element_id]; + data_block[element_id] = ((uint16_t) lin2alaw[*i]) | (lin2alaw[*(i+1)]<<8); + + i = (uint16_t*) &txdataF[0][slotoffsetF+element_id]; + data_block[element_id+db_halflength] = ((uint16_t) lin2alaw[*i]) | (lin2alaw[*(i+1)]<<8); } - // Update information in generated packet dl_header->frame_status &= ~(0x000f<<26); dl_header->frame_status |= (symbol_id&0x000f)<<26; - // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, symbol_id, &tx_buffer, @@ -101,29 +98,27 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, db_fulllength = 12*fp->N_RB_UL; db_halflength = (db_fulllength)>>1; slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; - blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(int16_t)); + tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(uint16_t)); IF4_header_t *ul_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); + data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); gen_IF4_ul_header(ul_header, frame, subframe); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { - // Do compression of the two parts and generate data blocks - rxdataF + for (element_id=0; element_id>16) + 32768 ]<<8; - - data_block[element_id+db_halflength] = lin2alaw[ (rxdataF[0][slotoffsetF+element_id] & 0xffff) + 32768 ]; - data_block[element_id+db_halflength] |= lin2alaw[ (rxdataF[0][slotoffsetF+element_id]>>16) + 32768 ]<<8; + i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id]; + data_block[element_id] = ((uint16_t) lin2alaw[*i]) | (lin2alaw[*(i+1)]<<8); + + i = (uint16_t*) &rxdataF[0][slotoffsetF+element_id]; + data_block[element_id+db_halflength] = ((uint16_t) lin2alaw[*i]) | (lin2alaw[*(i+1)]<<8); } - // Update information in generated packet ul_header->frame_status &= ~(0x000f<<26); ul_header->frame_status |= (symbol_id&0x000f)<<26; - // Write the packet(s) to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, symbol_id, &tx_buffer, @@ -142,7 +137,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(int16_t)); IF4_header_t *prach_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); + data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); gen_IF4_prach_header(prach_header, frame, subframe); @@ -155,7 +150,6 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, // prachoffsetF += 2; //} - // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, symbol_id, &tx_buffer, @@ -192,9 +186,8 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ void *rx_buffer=NULL; IF4_header_t *packet_header=NULL; - int16_t *data_block=NULL; + uint16_t *data_block=NULL, *i=NULL; - // Read packet(s) from the fronthaul if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, (int64_t*) packet_type, &rx_buffer, @@ -204,43 +197,41 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ } packet_header = (IF4_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES); - data_block = (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t); + data_block = (uint16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t); *frame = ((packet_header->frame_status)>>6)&0xffff; *subframe = ((packet_header->frame_status)>>22)&0x000f; if (*packet_type == IF4_PDLFFT) { - // Find and return symbol_number *symbol_number = ((packet_header->frame_status)>>26)&0x000f; - // Calculate from received packet slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; - blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; - - // Do decompression of the two parts and generate txdataF + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; + for (element_id=0; element_id>8) ]<<16; + i = (uint16_t*) &txdataF[0][blockoffsetF+element_id]; + *i = alaw2lin[ (data_block[element_id] & 0xff) ]; + *(i+1) = alaw2lin[ (data_block[element_id]>>8) ]; - txdataF[0][slotoffsetF+element_id] = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; - txdataF[0][slotoffsetF+element_id] |= alaw2lin[ (data_block[element_id+db_halflength]>>8) ]<<16; + i = (uint16_t*) &txdataF[0][slotoffsetF+element_id]; + *i = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; + *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ]; } } else if (*packet_type == IF4_PULFFT) { - // Find and return symbol_number *symbol_number = ((packet_header->frame_status)>>26)&0x000f; - // Calculate from received packet slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; - blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength; + blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - // Do decompression of the two parts and generate rxdataF for (element_id=0; element_id>8) ]<<16; + i = (uint16_t*) &rxdataF[0][blockoffsetF+element_id]; + *i = alaw2lin[ (data_block[element_id] & 0xff) ]; + *(i+1) = alaw2lin[ (data_block[element_id]>>8) ]; - rxdataF[0][slotoffsetF+element_id] = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; - rxdataF[0][slotoffsetF+element_id] |= alaw2lin[ (data_block[element_id+db_halflength]>>8) ]<<16; + i = (uint16_t*) &rxdataF[0][slotoffsetF+element_id]; + *i = alaw2lin[ (data_block[element_id+db_halflength] & 0xff) ]; + *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ]; } } else if (*packet_type == IF4_PRACH) { @@ -260,11 +251,9 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) { - // Set Type and Sub-Type dl_packet->type = IF4_PACKET_TYPE; dl_packet->sub_type = IF4_PDLFFT; - // Reset frame status dl_packet->rsvd = 0; // Set frame status @@ -276,11 +265,9 @@ void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) { void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) { - // Set Type and Sub-Type ul_packet->type = IF4_PACKET_TYPE; ul_packet->sub_type = IF4_PULFFT; - // Leave reserved as it is ul_packet->rsvd = 0; // Set frame status @@ -292,11 +279,9 @@ void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) { void gen_IF4_prach_header(IF4_header_t *prach_packet, int frame, int subframe) { - // Set Type and Sub-Type prach_packet->type = IF4_PACKET_TYPE; prach_packet->sub_type = IF4_PRACH; - // Leave reserved as it is prach_packet->rsvd = 0; // Set LTE Prach configuration diff --git a/openair1/PHY/TOOLS/alaw_lut.h b/openair1/PHY/TOOLS/alaw_lut.h index bcb9bea790..52ff6d87da 100644 --- a/openair1/PHY/TOOLS/alaw_lut.h +++ b/openair1/PHY/TOOLS/alaw_lut.h @@ -39,9 +39,9 @@ */ // Linear to ALaw -// 16 bit signed integer to 8 bit unsigned integer -const uint8_t lin2alaw[65536] = {42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170}; - +// 16 bit signed integer (typecasted as uint16_t) to 8 bit unsigned integer +const uint8_t lin2alaw[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85}; + // ALaw to Linear -// 8 bit unsigned integer to 16 bit signed integer -const int16_t alaw2lin[256] = {-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; +// 8 bit unsigned integer to 16 bit signed integer (typecasted as uint16_t) +const uint16_t alaw2lin[256] = {60032, 60288, 59520, 59776, 61056, 61312, 60544, 60800, 57984, 58240, 57472, 57728, 59008, 59264, 58496, 58752, 62784, 62912, 62528, 62656, 63296, 63424, 63040, 63168, 61760, 61888, 61504, 61632, 62272, 62400, 62016, 62144, 43520, 44544, 41472, 42496, 47616, 48640, 45568, 46592, 35328, 36352, 33280, 34304, 39424, 40448, 37376, 38400, 54528, 55040, 53504, 54016, 56576, 57088, 55552, 56064, 50432, 50944, 49408, 49920, 52480, 52992, 51456, 51968, 65192, 65208, 65160, 65176, 65256, 65272, 65224, 65240, 65064, 65080, 65032, 65048, 65128, 65144, 65096, 65112, 65448, 65464, 65416, 65432, 65512, 65528, 65480, 65496, 65320, 65336, 65288, 65304, 65384, 65400, 65352, 65368, 64160, 64224, 64032, 64096, 64416, 64480, 64288, 64352, 63648, 63712, 63520, 63584, 63904, 63968, 63776, 63840, 64848, 64880, 64784, 64816, 64976, 65008, 64912, 64944, 64592, 64624, 64528, 64560, 64720, 64752, 64656, 64688, 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344, 328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88, 72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688, 656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848}; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 8fb84e37fc..038129cf36 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -59,7 +59,7 @@ #define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) // Packet sizes for IF4 interface format -#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(int16_t)*scaled_nblocks) +#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(uint16_t)*scaled_nblocks) #define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839*2) // FIX hard coded prach size (uncompressed) #define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) From a3c41ed7ffae6e76b97bdbf8daeb65b2165c4298 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 8 Jul 2016 19:43:09 +0200 Subject: [PATCH 093/206] remove writeop, rru tx works --- targets/RT/USER/lte-enb.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 29122757b0..2a45832d45 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -502,13 +502,6 @@ static void* eNB_thread_rxtx( void* param ) { recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); } while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1); - if (proc->subframe_tx == 0 && proc->frame_tx == 0) { - write_output("eNBtxsigF.m","txF",PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdataF[0][0], - PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti * PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.ofdm_symbol_size, - 1,1); - exit(1); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5) { @@ -579,13 +572,6 @@ static void* eNB_thread_rxtx( void* param ) { send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); - if (proc->subframe_tx == 0 && proc->frame_tx == 0) { - write_output("fr_bf_comp.m","txF",PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdataF[0][0], - PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti * PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.ofdm_symbol_size, - 1,1); - exit(1); - } - } if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { From 0789ee95602731130b5c2819b56952040bbc4333 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 12 Jul 2016 17:58:02 +0200 Subject: [PATCH 094/206] ifdevice tx/rx buffer per cc --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 37 ++++++++----------- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 2 + openair1/PHY/defs.h | 3 +- openair1/SCHED/phy_procedures_lte_eNb.c | 7 ---- targets/ARCH/COMMON/common_lib.h | 8 ++++ targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 19 ++++------ targets/RT/USER/lte-enb.c | 12 ++++++ 7 files changed, 47 insertions(+), 41 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index cf1776754c..0fb5404538 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -49,12 +49,12 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; int16_t **rxsigF = eNB->prach_vars.rxsigF; + void *tx_buffer = eNB->ifbuffer.tx; uint16_t symbol_id=0, element_id=0; uint16_t db_fulllength, db_halflength; int slotoffsetF=0, blockoffsetF=0; - void *tx_buffer=NULL; uint16_t *data_block=NULL, *i=NULL; if (packet_type == IF4_PDLFFT) { @@ -63,7 +63,6 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(uint16_t)); IF4_header_t *dl_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); @@ -100,7 +99,6 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(uint16_t)); IF4_header_t *ul_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); @@ -135,21 +133,15 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, // FIX: hard coded prach samples length db_fulllength = 839*2; - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + db_fulllength*sizeof(int16_t)); IF4_header_t *prach_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); gen_IF4_prach_header(prach_header, frame, subframe); - // Generate uncompressed data blocks - memcpy(data_block, (rxsigF[0]+k), db_fulllength*sizeof(int16_t)); - - //for (element_id=0; element_idifdevice.trx_write_func(&eNB->ifdevice, symbol_id, &tx_buffer, @@ -162,7 +154,6 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, AssertFatal(1==0, "send_IF4 - Unknown packet_type %x", packet_type); } - free(tx_buffer); return; } @@ -172,6 +163,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; int16_t **rxsigF = eNB->prach_vars.rxsigF; + void *rx_buffer = eNB->ifbuffer.rx; uint16_t element_id; uint16_t db_fulllength, db_halflength; @@ -184,7 +176,6 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ } db_halflength = db_fulllength>>1; - void *rx_buffer=NULL; IF4_header_t *packet_header=NULL; uint16_t *data_block=NULL, *i=NULL; @@ -238,14 +229,14 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ // FIX: hard coded prach samples length db_fulllength = 839*2; - // Generate uncompressed data blocks - memcpy((rxsigF[0]+slotoffsetF), data_block, db_fulllength*sizeof(int16_t)); + memcpy((&rxsigF[0][0]), + (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t), + db_fulllength*sizeof(int16_t)); } else { AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type); } - free(rx_buffer); return; } @@ -260,7 +251,6 @@ void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) { dl_packet->frame_status = 0; dl_packet->frame_status |= (frame&0xffff)<<6; dl_packet->frame_status |= (subframe&0x000f)<<22; - } @@ -274,7 +264,6 @@ void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) { ul_packet->frame_status = 0; ul_packet->frame_status |= (frame&0xffff)<<6; ul_packet->frame_status |= (subframe&0x000f)<<22; - } @@ -288,5 +277,11 @@ void gen_IF4_prach_header(IF4_header_t *prach_packet, int frame, int subframe) { prach_packet->frame_status = 0; prach_packet->frame_status |= (frame&0xffff)<<6; prach_packet->frame_status |= (subframe&0x000f)<<22; - } + + +void malloc_IF4_buffer(PHY_VARS_eNB *eNB) { + // Keep the size large enough + eNB->ifbuffer.tx = malloc(RAW_IF4_PRACH_SIZE_BYTES); + eNB->ifbuffer.rx = malloc(RAW_IF4_PRACH_SIZE_BYTES); +} diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index a885d28ec2..7276d97efa 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -70,3 +70,5 @@ void gen_IF4_prach_header(IF4_header_t*, int, int); void send_IF4(PHY_VARS_eNB*, int, int, uint16_t, int); void recv_IF4(PHY_VARS_eNB*, int*, int*, uint16_t*, uint32_t*); + +void malloc_IF4_buffer(PHY_VARS_eNB*); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index f9a4596129..e1b2627c09 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -514,7 +514,8 @@ typedef struct PHY_VARS_eNB_s { /// RF and Interface devices per CC openair0_device rfdevice; openair0_device ifdevice; - // *** Handle spatially distributed MIMO antenna ports + /// Pointer for ifdevice buffer struct + if_buffer_t ifbuffer; } PHY_VARS_eNB; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 478ae20c30..789ebc1427 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2527,10 +2527,6 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; - - struct timespec time_req, time_rem; - time_req.tv_sec = 0; - time_req.tv_nsec = 900000; if (subframe==9) { subframe=0; @@ -2594,9 +2590,6 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - - //nanosleep(&time_req, &time_rem); - //proc->timestamp_rx += fp->samples_per_tti; proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 6e112f5e43..c371e12520 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -236,6 +236,14 @@ typedef struct { } eth_params_t; +typedef struct { + //! Tx buffer for if device + void *tx; + //! Rx buffer for if device + void *rx; +} if_buffer_t; + + /*!\brief structure holds the parameters to configure USRP devices */ struct openair0_device_t { /*!brief Module ID of this device */ diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 699d15350b..faf19c9fda 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -312,13 +312,11 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t; - void *test_buffer = (void*)malloc(packet_size); - - IF4_header_t *test_header = (IF4_header_t*)(test_buffer + MAC_HEADER_SIZE_BYTES); + ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t; + IF4_header_t *test_header = (IF4_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES); bytes_received = recv(eth->sockfd[Mod_id], - test_buffer, + buff[0], packet_size, MSG_PEEK); if (bytes_received ==-1) { @@ -336,11 +334,7 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, } else { packet_size = RAW_IF4_PRACH_SIZE_BYTES; } - - buff[0] = (void*)malloc(packet_size); - - bytes_received = 0; - + while(bytes_received < packet_size) { bytes_received = recv(eth->sockfd[Mod_id], buff[0], @@ -357,7 +351,6 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, } eth->rx_nsamps = nsamps; - free(test_buffer); return(bytes_received); } @@ -394,7 +387,8 @@ int eth_set_dev_conf_raw(openair0_device *device) { -int eth_set_dev_conf_raw_IF4(openair0_device *device) { +int eth_set_dev_conf_raw_IF4(openair0_device *device) { + // use for cc_id info int Mod_id = device->Mod_id; eth_state_t *eth = (eth_state_t*)device->priv; @@ -455,6 +449,7 @@ int eth_get_dev_conf_raw(openair0_device *device) { int eth_get_dev_conf_raw_IF4(openair0_device *device) { + // use for cc_id info eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 2a45832d45..df40cca1ce 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -768,6 +768,18 @@ static void* eNB_thread_rx_common( void* param ) { wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif + // Create buffer for IF device and free when stopping + if (eNB->node_function == NGFI_RCC_IF4 || eNB->node_function == NGFI_RRU_IF4) { + malloc_IF4_buffer(eNB); + + } else if (eNB->node_function == NGFI_RRU_IF5 || eNB->node_function == eNodeB_3GPP_BBU) { + //malloc_IF5_buffer(eNB); + + } else { + eNB->ifbuffer.tx = NULL; + eNB->ifbuffer.rx = NULL; + } + // Start IF device for this CC if (eNB->node_function != eNodeB_3GPP) { if (eNB->ifdevice.trx_start_func(&eNB->ifdevice) != 0 ) From b804f1e47e61c83874102a634755b48519b226c9 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 13 Jul 2016 19:33:40 +0200 Subject: [PATCH 095/206] send correct timing --- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 9fdd67c09e..545c892c2a 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -63,7 +63,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe txp[i] += packet_id*spp_eth; eNB->ifdevice.trx_write_func(&eNB->ifdevice, - (proc_timestamp - eNB->ifdevice.openair0_cfg->tx_sample_advance + packet_id*spp_eth), + (proc_timestamp + packet_id*spp_eth), txp, spp_eth, fp->nb_antennas_tx, From 7e2a39733e3086aa5a97a97fe363d3d3c58b90dd Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 15 Jul 2016 00:04:04 -0700 Subject: [PATCH 096/206] modifications for oaisim. oaisim_noS1 compiles at this point. --- openair1/PHY/LTE_TRANSPORT/dci.c | 6 +- openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c | 42 +- openair1/PHY/LTE_TRANSPORT/initial_sync.c | 3 +- openair1/PHY/LTE_TRANSPORT/pbch.c | 9 +- openair1/PHY/LTE_TRANSPORT/proto.h | 5 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 9 +- openair1/SCHED/phy_procedures_lte_eNb.c | 36 +- openair1/SCHED/phy_procedures_lte_ue.c | 5 +- .../SIMULATION/ETH_TRANSPORT/emu_transport.c | 45 +- targets/SIMU/USER/channel_sim.c | 26 +- targets/SIMU/USER/oaisim.c | 794 +++++++----------- targets/SIMU/USER/oaisim_functions.c | 62 +- 12 files changed, 432 insertions(+), 610 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index f5e0a987f7..0117c8e7d2 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -2390,14 +2390,14 @@ uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB, if (dci_alloc[n_dci].format > 0) { // exclude the uplink dci if (dci_alloc[n_dci].rnti == SI_RNTI) { - dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_eNB_SI; + dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_SI; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 0;//SI; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = 0; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[0]->TBS>>3; LOG_D(PHY,"[DCI][EMUL]SI tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl],n_dci_dl, eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl]); } else if (dci_alloc[n_dci_dl].ra_flag == 1) { - dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_eNB_ra; + dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_ra; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 1;//RA; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = 0; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[0]->TBS>>3; @@ -2406,7 +2406,7 @@ uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB, } else { ue_id = find_ue(dci_alloc[n_dci_dl].rnti,PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]); DevAssert( ue_id != (uint8_t)-1 ); - dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_eNB[ue_id][0]; + dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch[ue_id][0]; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 2;//TB0; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = dlsch_eNB->current_harq_pid; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c index 17180af613..b6fcfbb1e8 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c @@ -832,7 +832,7 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, // may not be necessary for PMCH?? for (eNB_id2=0; eNB_id2lte_frame_parms.Nid_cell == phy_vars_ue->lte_frame_parms.Nid_cell) + if (PHY_vars_eNB_g[eNB_id2][CC_id]->frame_parms.Nid_cell == phy_vars_ue->frame_parms.Nid_cell) break; } @@ -847,9 +847,9 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, switch (dlsch_id) { - case PDSCH_SI: // SI - dlsch_ue = phy_vars_ue->dlsch_ue_SI[eNB_id]; - dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_SI; + case SI_PDSCH: // SI + dlsch_ue = phy_vars_ue->dlsch_SI[eNB_id]; + dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_SI; // printf("Doing SI: TBS %d\n",dlsch_ue->harq_processes[0]->TBS>>3); memcpy(dlsch_ue->harq_processes[0]->b,dlsch_eNB->harq_processes[0]->b,dlsch_ue->harq_processes[0]->TBS>>3); #ifdef DEBUG_DLSCH_DECODING @@ -863,9 +863,9 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, return(1); break; - case PDSCH_RA: // RA - dlsch_ue = phy_vars_ue->dlsch_ue_ra[eNB_id]; - dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_ra; + case RA_PDSCH: // RA + dlsch_ue = phy_vars_ue->dlsch_ra[eNB_id]; + dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_ra; memcpy(dlsch_ue->harq_processes[0]->b,dlsch_eNB->harq_processes[0]->b,dlsch_ue->harq_processes[0]->TBS>>3); #ifdef DEBUG_DLSCH_DECODING LOG_D(PHY,"RA Decoded\n"); @@ -879,11 +879,11 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, break; case PDSCH: // TB0 - dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id][0]; + dlsch_ue = phy_vars_ue->dlsch[eNB_id][0]; harq_pid = dlsch_ue->current_harq_pid; - ue_id= (uint32_t)find_ue((int16_t)phy_vars_ue->lte_ue_pdcch_vars[(uint32_t)eNB_id]->crnti,PHY_vars_eNB_g[eNB_id2][CC_id]); + ue_id= (uint32_t)find_ue((int16_t)phy_vars_ue->pdcch_vars[(uint32_t)eNB_id]->crnti,PHY_vars_eNB_g[eNB_id2][CC_id]); DevAssert( ue_id != (uint32_t)-1 ); - dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB[ue_id][0]; + dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch[ue_id][0]; #ifdef DEBUG_DLSCH_DECODING @@ -918,18 +918,18 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, dlsch_ue->harq_ack[subframe].ack = 0; dlsch_ue->harq_ack[subframe].harq_id = harq_pid; dlsch_ue->harq_ack[subframe].send_harq_status = 1; - dlsch->last_iteration_cnt = 1+dlsch_ue->max_turbo_iterations; + dlsch_ue->last_iteration_cnt = 1+dlsch_ue->max_turbo_iterations; return(1+dlsch_ue->max_turbo_iterations); } break; - case 3: { // TB1 - dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id][1]; + case PDSCH1: { // TB1 + dlsch_ue = phy_vars_ue->dlsch[eNB_id][1]; harq_pid = dlsch_ue->current_harq_pid; - int8_t UE_id = find_ue( phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti, PHY_vars_eNB_g[eNB_id2][CC_id] ); + int8_t UE_id = find_ue( phy_vars_ue->pdcch_vars[eNB_id]->crnti, PHY_vars_eNB_g[eNB_id2][CC_id] ); DevAssert( UE_id != -1 ); - dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB[UE_id][1]; + dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch[UE_id][1]; // reset HARQ dlsch_ue->harq_processes[harq_pid]->status = SCH_IDLE; dlsch_ue->harq_processes[harq_pid]->round = 0; @@ -945,8 +945,8 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, case PMCH: // PMCH - dlsch_ue = phy_vars_ue->dlsch_ue_MCH[eNB_id]; - dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_eNB_MCH; + dlsch_ue = phy_vars_ue->dlsch_MCH[eNB_id]; + dlsch_eNB = PHY_vars_eNB_g[eNB_id2][CC_id]->dlsch_MCH; LOG_D(PHY,"decoding pmch emul (size is %d, enb %d %d)\n", dlsch_ue->harq_processes[0]->TBS>>3, eNB_id, eNB_id2); #ifdef DEBUG_DLSCH_DECODING @@ -968,20 +968,20 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, memcpy(dlsch_ue->harq_processes[0]->b, dlsch_eNB->harq_processes[0]->b, dlsch_ue->harq_processes[0]->TBS>>3); - dlsch->last_iteration_cnt = 1; + dlsch_ue->last_iteration_cnt = 1; return(1); } else { // retransmission - dlsch->last_iteration_cnt = 1+dlsch_ue->max_turbo_iterations; + dlsch_ue->last_iteration_cnt = 1+dlsch_ue->max_turbo_iterations; return(1+dlsch_ue->max_turbo_iterations); } break; default: - dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id][0]; + dlsch_ue = phy_vars_ue->dlsch[eNB_id][0]; LOG_E(PHY,"dlsch_decoding_emul: FATAL, unknown DLSCH_id %d\n",dlsch_id); - dlsch->last_iteration_cnt = 1+dlsch_ue->max_turbo_iterations; + dlsch_ue->last_iteration_cnt = 1+dlsch_ue->max_turbo_iterations; return(1+dlsch_ue->max_turbo_iterations); } diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c index bec0c424ed..71372d9e59 100644 --- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c @@ -516,12 +516,13 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) phich_string[ue->frame_parms.phich_config_common.phich_resource], ue->frame_parms.nb_antennas_tx_eNB); +#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) LOG_I(PHY,"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, ue->proc.proc_rxtx[0].frame_rx, openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, ue->common_vars.freq_offset); - +#endif } else { #ifdef DEBUG_INITIAL_SYNC LOG_I(PHY,"[UE%d] Initial sync : PBCH not ok\n",ue->Mod_id); diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c index b7b7149c62..2213ca4da2 100755 --- a/openair1/PHY/LTE_TRANSPORT/pbch.c +++ b/openair1/PHY/LTE_TRANSPORT/pbch.c @@ -1053,9 +1053,10 @@ uint16_t rx_pbch_emul(PHY_VARS_UE *phy_vars_ue, double bler=0.0;//, x=0.0; double sinr=0.0; - uint16_t nb_rb = phy_vars_ue->lte_frame_parms.N_RB_DL; + uint16_t nb_rb = phy_vars_ue->frame_parms.N_RB_DL; int16_t f; uint8_t CC_id=phy_vars_ue->CC_id; + int frame_rx = phy_vars_ue->proc.proc_rxtx[0].frame_rx; // compute effective sinr // TODO: adapt this to varible bandwidth @@ -1074,10 +1075,10 @@ uint16_t rx_pbch_emul(PHY_VARS_UE *phy_vars_ue, sinr, bler); - if (pbch_phase == (phy_vars_ue->frame_rx % 4)) { + if (pbch_phase == (frame_rx % 4)) { if (uniformrandom() >= bler) { - memcpy(phy_vars_ue->lte_ue_pbch_vars[eNB_id]->decoded_output,PHY_vars_eNB_g[eNB_id][CC_id]->pbch_pdu,PBCH_PDU_SIZE); - return(PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.nb_antennas_tx_eNB); + memcpy(phy_vars_ue->pbch_vars[eNB_id]->decoded_output,PHY_vars_eNB_g[eNB_id][CC_id]->pbch_pdu,PBCH_PDU_SIZE); + return(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_tx_eNB); } else return(-1); } else diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 547dd86a9c..6993dd18c0 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1039,7 +1039,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, uint8_t subframe, - uint8_t dlsch_id, + PDSCH_t dlsch_id, uint8_t eNB_id); /** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs @@ -1539,7 +1539,8 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, uint8_t llr8_flag); uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, - uint8_t UE_index, + eNB_rxtx_proc_t *proc, + uint8_t UE_index, uint16_t *crnti); void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 02bf98c372..6ed0f91101 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -1520,16 +1520,9 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, #endif for (UE_id=0; UE_idlte_ue_pdcch_vars[0]->crnti) + if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti) break; - /* - msg("[PHY] EMUL eNB %d ulsch_decoding_emul : subframe ue id %d crnti %x nb ue %d\n", - eNB->Mod_id, - UE_id, - PHY_vars_UE_g[UE_id]->lte_ue_pdcch_vars[0]->crnti, - NB_UE_INST); - */ } if (UE_id==NB_UE_INST) { diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 79a6a1d0b7..653b5aeb1e 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2119,6 +2119,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq #ifdef PHY_ABSTRACTION else { metric0_SR = rx_pucch_emul(eNB, + proc, UE_id, pucch_format1, 0, @@ -2192,11 +2193,12 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq } else { #ifdef PHY_ABSTRACTION - metric0 = rx_pucch_emul(eNB,UE_id, + metric0 = rx_pucch_emul(eNB, + proc, + UE_id, pucch_format1a, 0, - pucch_payload0, - subframe); + pucch_payload0); #endif } @@ -2251,11 +2253,11 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq PUCCH1a_THRES); else { #ifdef PHY_ABSTRACTION - metric0 = rx_pucch_emul(eNB,UE_id, + metric0 = rx_pucch_emul(eNB,proc, + UE_id, format, 0, - pucch_payload0, - subframe); + pucch_payload0); #endif } } else { //using n1_pucch0/n1_pucch1 resources @@ -2283,11 +2285,12 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq PUCCH1a_THRES); else { #ifdef PHY_ABSTRACTION - metric0 = rx_pucch_emul(eNB,UE_id, + metric0 = rx_pucch_emul(eNB, + proc, + UE_id, format, 0, - pucch_payload0, - subframe); + pucch_payload0); #endif } } @@ -2307,13 +2310,12 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq PUCCH1a_THRES); else { #ifdef PHY_ABSTRACTION - metric1 = rx_pucch_emul(eNB,UE_id, + metric1 = rx_pucch_emul(eNB, + proc, + UE_id, format, 1, - pucch_payload1, - subframe); - - + pucch_payload1); #endif } } @@ -2389,7 +2391,6 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p #ifdef PHY_ABSTRACTION else { rx_ulsch_emul(eNB,proc, - subframe, eNB->UE_stats[UE_id].sector, // this is the effective sector id UE_id); } @@ -2407,6 +2408,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p #ifdef PHY_ABSTRACTION else { ret = ulsch_decoding_emul(eNB, + proc, UE_id, &rnti); } @@ -2909,7 +2911,6 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const #ifdef PHY_ABSTRACTION else { rx_ulsch_emul(eNB,proc, - subframe, eNB->UE_stats[i].sector, // this is the effective sector id i); } @@ -2930,7 +2931,8 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const #ifdef PHY_ABSTRACTION else { - ret = ulsch_decoding_emul(eNB,proc, + ret = ulsch_decoding_emul(eNB, + proc, i, &rnti); } diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 4f1cc56f80..38609c6f43 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -1209,8 +1209,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin format, ue->frame_parms.pucch_config_common.nCS_AN, pucch_ack_payload, - SR_payload, - subframe_tx); + SR_payload); #endif } } else if (SR_payload==1) { // no ACK/NAK but SR is triggered by MAC @@ -2503,7 +2502,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, #ifdef PHY_ABSTRACTION ret = dlsch_decoding_emul(ue, subframe_rx, - dlsch, + pdsch, eNB_id); #endif } diff --git a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c index ec15e7c668..d2ae35b29a 100644 --- a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c +++ b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c @@ -348,7 +348,7 @@ void fill_phy_enb_vars(unsigned int enb_id, uint8_t CC_id,unsigned int next_slot switch (eNB_transport_info[enb_id][CC_id].dlsch_type[n_dci_dl]) { case 0: //SI: - memcpy(PHY_vars_eNB_g[enb_id][CC_id]->dlsch_eNB_SI->harq_processes[0]->b, + memcpy(PHY_vars_eNB_g[enb_id][CC_id]->dlsch_SI->harq_processes[0]->b, &eNB_transport_info[enb_id][CC_id].transport_blocks[payload_offset], eNB_transport_info[enb_id][CC_id].tbs[n_dci_dl]); #ifdef DEBUG_EMU @@ -358,7 +358,7 @@ void fill_phy_enb_vars(unsigned int enb_id, uint8_t CC_id,unsigned int next_slot break; case 1: //RA: - memcpy(PHY_vars_eNB_g[enb_id][CC_id]->dlsch_eNB_ra->harq_processes[0]->b, + memcpy(PHY_vars_eNB_g[enb_id][CC_id]->dlsch_ra->harq_processes[0]->b, &eNB_transport_info[enb_id][CC_id].transport_blocks[payload_offset], eNB_transport_info[enb_id][CC_id].tbs[n_dci_dl]); #ifdef DEBUG_EMU @@ -370,9 +370,9 @@ void fill_phy_enb_vars(unsigned int enb_id, uint8_t CC_id,unsigned int next_slot case 2://TB0: harq_pid = eNB_transport_info[enb_id][CC_id].harq_pid[n_dci_dl]; ue_id = eNB_transport_info[enb_id][CC_id].ue_id[n_dci_dl]; - PHY_vars_eNB_g[enb_id][CC_id]->dlsch_eNB[ue_id][0]->rnti= + PHY_vars_eNB_g[enb_id][CC_id]->dlsch[ue_id][0]->rnti= eNB_transport_info[enb_id][CC_id].dci_alloc[n_dci_dl].rnti; - dlsch_eNB = PHY_vars_eNB_g[enb_id][CC_id]->dlsch_eNB[ue_id][0]; + dlsch_eNB = PHY_vars_eNB_g[enb_id][CC_id]->dlsch[ue_id][0]; #ifdef DEBUG_EMU LOG_D(EMU, " enb_id %d ue id is %d rnti is %x dci index %d, harq_pid %d tbs %d \n", @@ -393,9 +393,9 @@ void fill_phy_enb_vars(unsigned int enb_id, uint8_t CC_id,unsigned int next_slot case 3://TB1: harq_pid = eNB_transport_info[enb_id][CC_id].harq_pid[n_dci_dl]; ue_id = eNB_transport_info[enb_id][CC_id].ue_id[n_dci_dl]; - PHY_vars_eNB_g[enb_id][CC_id]->dlsch_eNB[ue_id][1]->rnti= + PHY_vars_eNB_g[enb_id][CC_id]->dlsch[ue_id][1]->rnti= eNB_transport_info[enb_id][CC_id].dci_alloc[n_dci_dl].rnti; - dlsch_eNB = PHY_vars_eNB_g[enb_id][CC_id]->dlsch_eNB[ue_id][1]; + dlsch_eNB = PHY_vars_eNB_g[enb_id][CC_id]->dlsch[ue_id][1]; memcpy(dlsch_eNB->harq_processes[harq_pid]->b, &eNB_transport_info[enb_id][CC_id].transport_blocks[payload_offset], @@ -403,7 +403,7 @@ void fill_phy_enb_vars(unsigned int enb_id, uint8_t CC_id,unsigned int next_slot break; case 5: - memcpy(PHY_vars_eNB_g[enb_id][CC_id]->dlsch_eNB_MCH->harq_processes[0]->b, + memcpy(PHY_vars_eNB_g[enb_id][CC_id]->dlsch_MCH->harq_processes[0]->b, &eNB_transport_info[enb_id][CC_id].transport_blocks[payload_offset], eNB_transport_info[enb_id][CC_id].tbs[n_dci_dl]); #ifdef DEBUG_EMU @@ -491,52 +491,45 @@ void fill_phy_ue_vars(unsigned int ue_id, uint8_t CC_id,unsigned int last_slot) #endif for (n_enb = 0; n_enb < UE_transport_info[ue_id][CC_id].num_eNB; n_enb++) { -#ifdef DEBUG_EMU - /* LOG_D(EMU,"Setting ulsch vars for ue %d rnti %x harq pid is %d \n", - ue_id, UE_transport_info[ue_id][CC_id].rnti[n_enb], - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]); - */ -#endif + rnti = UE_transport_info[ue_id][CC_id].rnti[n_enb]; enb_id = UE_transport_info[ue_id][CC_id].eNB_id[n_enb]; - PHY_vars_UE_g[ue_id][CC_id]->lte_ue_pdcch_vars[enb_id]->crnti=rnti; + PHY_vars_UE_g[ue_id][CC_id]->pdcch_vars[enb_id]->crnti=rnti; harq_pid = UE_transport_info[ue_id][CC_id].harq_pid[n_enb]; - //ulsch = PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]; - - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->o_RI[0] = + PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->o_RI[0] = ue_cntl_delay[ue_id][CC_id][last_slot%2].pusch_ri & 0x1; - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->o_RI[1] = + PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->o_RI[1] = (ue_cntl_delay[ue_id][CC_id][last_slot%2].pusch_ri>>1) & 0x1; - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->o_ACK[0]= + PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->o_ACK[0]= ue_cntl_delay[ue_id][CC_id][last_slot%2].pusch_ack & 0x1; - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->o_ACK[1]= + PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->o_ACK[1]= (ue_cntl_delay[ue_id][CC_id][last_slot%2].pusch_ack>>1) & 0x1; //*(uint32_t *)ulsch->o = ue_cntl_delay[ue_id][CC_id][last_slot%2].pusch_uci; if ((last_slot % 2) == 1) { - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->O = + PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->O = ue_cntl_delay[ue_id][CC_id][last_slot%2].length_uci; - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->uci_format = + PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->uci_format = ue_cntl_delay[ue_id][CC_id][last_slot%2].uci_format; - memcpy(PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->o, + memcpy(PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->o, ue_cntl_delay[ue_id][CC_id][last_slot%2].pusch_uci, MAX_CQI_BYTES); - ulsch = PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]; + ulsch = PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]; // if (((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1) LOG_D(EMU, "[UE %d] subframe %d last slot %d copy the payload from eNB %d to UE %d with harq id %d cqi (val %d, length %d) \n", ue_id, subframe, last_slot, enb_id, ue_id, harq_pid, ((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1, - PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->O); + PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->O); } - memcpy(PHY_vars_UE_g[ue_id][CC_id]->ulsch_ue[enb_id]->harq_processes[harq_pid]->b, + memcpy(PHY_vars_UE_g[ue_id][CC_id]->ulsch[enb_id]->harq_processes[harq_pid]->b, UE_transport_info[ue_id][CC_id].transport_blocks, UE_transport_info[ue_id][CC_id].tbs[enb_id]); diff --git a/targets/SIMU/USER/channel_sim.c b/targets/SIMU/USER/channel_sim.c index 187f1109c0..5970adfa5f 100644 --- a/targets/SIMU/USER/channel_sim.c +++ b/targets/SIMU/USER/channel_sim.c @@ -130,7 +130,7 @@ void do_DL_sig(double **r_re0,double **r_im0, // find out which eNB the UE is attached to for (eNB_id=0; eNB_idlte_ue_pdcch_vars[0]->crnti,PHY_vars_eNB_g[eNB_id][CC_id])>=0) { + if (find_ue(PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti,PHY_vars_eNB_g[eNB_id][CC_id])>=0) { // UE with UE_id is connected to eNb with eNB_id att_eNB_id=eNB_id; LOG_D(OCM,"A: UE attached to eNB (UE%d->eNB%d)\n",UE_id,eNB_id); @@ -165,7 +165,7 @@ void do_DL_sig(double **r_re0,double **r_im0, //dlsch_abstraction(PHY_vars_UE_g[UE_id]->sinr_dB, rb_alloc, 8); // fill in perfect channel estimates channel_desc_t *desc1 = eNB2UE[att_eNB_id][UE_id][CC_id]; - int32_t **dl_channel_est = PHY_vars_UE_g[UE_id][CC_id]->lte_ue_common_vars.dl_ch_estimates[0]; + int32_t **dl_channel_est = PHY_vars_UE_g[UE_id][CC_id]->common_vars.dl_ch_estimates[0]; // double scale = pow(10.0,(enb_data[att_eNB_id]->tx_power_dBm + eNB2UE[att_eNB_id][UE_id]->path_loss_dB + (double) PHY_vars_UE_g[UE_id]->rx_total_gain_dB)/20.0); double scale = pow(10.0,(frame_parms->pdsch_config_common.referenceSignalPower+eNB2UE[att_eNB_id][UE_id][CC_id]->path_loss_dB + (double) PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB)/20.0); LOG_D(OCM,"scale =%lf (%d dB)\n",scale,(int) (20*log10(scale))); @@ -201,13 +201,13 @@ void do_DL_sig(double **r_re0,double **r_im0, // calculate the SNR for the attached eNB (this assumes eNB always uses PMI stored in eNB_UE_stats; to be improved) init_snr(eNB2UE[att_eNB_id][UE_id][CC_id], enb_data[att_eNB_id], ue_data[UE_id], PHY_vars_UE_g[UE_id][CC_id]->sinr_dB, &PHY_vars_UE_g[UE_id][CC_id]->N0, - PHY_vars_UE_g[UE_id][CC_id]->transmission_mode[att_eNB_id], PHY_vars_eNB_g[att_eNB_id][CC_id]->eNB_UE_stats[UE_id].DL_pmi_single, - PHY_vars_eNB_g[att_eNB_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off,PHY_vars_eNB_g[att_eNB_id][CC_id]->lte_frame_parms.N_RB_DL); + PHY_vars_UE_g[UE_id][CC_id]->transmission_mode[att_eNB_id], PHY_vars_eNB_g[att_eNB_id][CC_id]->UE_stats[UE_id].DL_pmi_single, + PHY_vars_eNB_g[att_eNB_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off,PHY_vars_eNB_g[att_eNB_id][CC_id]->frame_parms.N_RB_DL); // calculate sinr here for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) { if (att_eNB_id != eNB_id) { - calculate_sinr(eNB2UE[eNB_id][UE_id][CC_id], enb_data[eNB_id], ue_data[UE_id], PHY_vars_UE_g[UE_id][CC_id]->sinr_dB,PHY_vars_eNB_g[att_eNB_id][CC_id]->lte_frame_parms.N_RB_DL); + calculate_sinr(eNB2UE[eNB_id][UE_id][CC_id], enb_data[eNB_id], ue_data[UE_id], PHY_vars_UE_g[UE_id][CC_id]->sinr_dB,PHY_vars_eNB_g[att_eNB_id][CC_id]->frame_parms.N_RB_DL); } } } // hold channel @@ -233,7 +233,7 @@ void do_DL_sig(double **r_re0,double **r_im0, // eNB2UE[eNB_id][UE_id]->path_loss_dB) <= -107.0) // break; - txdata = PHY_vars_eNB_g[eNB_id][CC_id]->lte_eNB_common_vars.txdata[0]; + txdata = PHY_vars_eNB_g[eNB_id][CC_id]->common_vars.txdata[0]; slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); slot_offset_meas = ((next_slot&1)==0) ? slot_offset : (slot_offset-(frame_parms->samples_per_tti>>1)); tx_pwr = dac_fixed_gain(s_re, @@ -355,7 +355,7 @@ void do_DL_sig(double **r_re0,double **r_im0, LOG_D(OCM,"[SIM][DL] UE %d : ADC in %f dBm for slot %d (subframe %d)\n",UE_id,10*log10(rx_pwr),next_slot,next_slot>>1); #endif - rxdata = PHY_vars_UE_g[UE_id][CC_id]->lte_ue_common_vars.rxdata; + rxdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.rxdata; slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); adc(r_re, @@ -463,12 +463,6 @@ void do_UL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double #endif } else { //without abstraction - /* - for (UE_id=0;UE_idlte_ue_common_vars.txdataF,PHY_vars_UE_g[UE_id]->lte_ue_common_vars.txdata,next_slot,&PHY_vars_UE_g[UE_id]->lte_frame_parms); - } - */ - for (eNB_id=0; eNB_idsamples_per_tti>>1); i++) { @@ -481,7 +475,7 @@ void do_UL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double // Compute RX signal for eNB = eNB_id for (UE_id=0; UE_idlte_ue_common_vars.txdata; + txdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.txdata; slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); slot_offset_meas = ((next_slot&1)==0) ? slot_offset : (slot_offset-(frame_parms->samples_per_tti>>1)); @@ -571,14 +565,14 @@ void do_UL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double nb_antennas_rx, frame_parms->samples_per_tti>>1, 1e3/UE2eNB[0][eNB_id][CC_id]->sampling_rate, // sampling time (ns) - (double)PHY_vars_eNB_g[eNB_id][CC_id]->rx_total_gain_eNB_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) + (double)PHY_vars_eNB_g[eNB_id][CC_id]->rx_total_gain_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) #ifdef DEBUG_SIM rx_pwr = signal_energy_fp(r_re,r_im,nb_antennas_rx,frame_parms->samples_per_tti>>1,0)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); LOG_D(OCM,"[SIM][UL] rx_pwr (ADC in) %f dB for slot %d (subframe %d)\n",10*log10(rx_pwr),next_slot,next_slot>>1); #endif - rxdata = PHY_vars_eNB_g[eNB_id][CC_id]->lte_eNB_common_vars.rxdata[0]; + rxdata = PHY_vars_eNB_g[eNB_id][CC_id]->common_vars.rxdata[0]; slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); adc(r_re, diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c index adfa4ab545..2472328c76 100644 --- a/targets/SIMU/USER/oaisim.c +++ b/targets/SIMU/USER/oaisim.c @@ -25,17 +25,17 @@ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - *******************************************************************************/ +*******************************************************************************/ /*! \file oaisim.c -* \brief oaisim top level -* \author Navid Nikaein -* \date 2013-2015 -* \version 1.0 -* \company Eurecom -* \email: openair_tech@eurecom.fr -* \note -* \warning -*/ + * \brief oaisim top level + * \author Navid Nikaein + * \date 2013-2015 + * \version 1.0 + * \company Eurecom + * \email: openair_tech@eurecom.fr + * \note + * \warning + */ #include #include @@ -116,11 +116,11 @@ char smbv_ip[16]; #include "T.h" /* - DCI0_5MHz_TDD0_t UL_alloc_pdu; - DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; - DCI2_5MHz_2A_L10PRB_TDD_t DLSCH_alloc_pdu1; - DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2; - */ + DCI0_5MHz_TDD0_t UL_alloc_pdu; + DCI1A_5MHz_TDD_1_6_t CCCH_alloc_pdu; + DCI2_5MHz_2A_L10PRB_TDD_t DLSCH_alloc_pdu1; + DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2; +*/ #define UL_RB_ALLOC computeRIV(lte_frame_parms->N_RB_UL,0,24) #define CCCH_RB_ALLOC computeRIV(lte_frame_parms->N_RB_UL,0,3) @@ -352,8 +352,8 @@ int omv_write(int pfd, node_list* enb_node_list, node_list* ue_node_list, Data_F omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j; omv_data.geo[i].Neighbors++; LOG_D( - OMG, - "[eNB %d][UE %d] is_UE_active(i,j) %d geo (x%d, y%d) num neighbors %d\n", i, j-NB_eNB_INST, is_UE_active(i,j-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors); + OMG, + "[eNB %d][UE %d] is_UE_active(i,j) %d geo (x%d, y%d) num neighbors %d\n", i, j-NB_eNB_INST, is_UE_active(i,j-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors); } } } @@ -388,8 +388,8 @@ int omv_write(int pfd, node_list* enb_node_list, node_list* ue_node_list, Data_F omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j; omv_data.geo[i].Neighbors++; LOG_D( - OMG, - "[UE %d][eNB %d] is_UE_active %d geo (x%d, y%d) num neighbors %d\n", i-NB_eNB_INST, j, is_UE_active(j,i-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors); + OMG, + "[UE %d][eNB %d] is_UE_active %d geo (x%d, y%d) num neighbors %d\n", i-NB_eNB_INST, j, is_UE_active(j,i-NB_eNB_INST), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors); } } } @@ -441,16 +441,14 @@ l2l1_task (void *args_p) int CC_id; // Framing variables - int32_t slot, last_slot, next_slot; + int32_t sf; #ifdef Rel10 relaying_type_t r_type = no_relay; // no relaying #endif - - lte_subframe_t direction; - + char fname[64], vname[64]; - int sf; + protocol_ctxt_t ctxt; //#ifdef XFORMS // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) @@ -478,22 +476,7 @@ l2l1_task (void *args_p) char eNB_stats_th_filename[255]; #endif - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) - for (eNB_inst = 0; eNB_inst < NB_eNB_INST; eNB_inst++) { - for (sf = 0; sf < 10; sf++) { - PHY_vars_eNB_g[eNB_inst][CC_id]->proc[sf].frame_tx = 0; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc[sf].frame_rx = 0; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc[sf].subframe_tx = (sf + 1) - % 10; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc[sf].subframe_rx = (sf + 9) - % 10; - } - PHY_vars_eNB_g[eNB_inst][CC_id]->proc[0].frame_rx = 1023; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc[9].frame_tx = 1; - } - - //#ifdef XFORMS if (xforms==1) { xargv[0] = xname; fl_initialize (&xargc, xargv, NULL, 0, 0); @@ -520,7 +503,7 @@ l2l1_task (void *args_p) } } - //#endif + #ifdef PRINT_STATS @@ -689,55 +672,34 @@ l2l1_task (void *args_p) omv_write (pfd[1], enb_node_list, ue_node_list, omv_data); } -#endif -#ifdef DEBUG_OMG - /* - if ((((int) oai_emulation.info.time_s) % 100) == 0) { - for (UE_inst = oai_emulation.info.first_ue_local; UE_inst < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local); UE_inst++) { - get_node_position (UE, UE_inst); - } - } - */ #endif update_ocm (); - for (slot = 0; slot < 20; slot++) { - if (slot % 2 == 0) - start_meas (&oaisim_stats_f); + for (sf = 0; sf < 10; sf++) { + start_meas (&oaisim_stats_f); wait_for_slot_isr (); #if defined(ENABLE_ITTI) - itti_update_lte_time(frame % MAX_FRAME_NUMBER, slot); + itti_update_lte_time(frame % MAX_FRAME_NUMBER, sf<<1); #endif - last_slot = (slot - 1) % 20; - - if (last_slot < 0) - last_slot += 20; - - next_slot = (slot + 1) % 20; - - oai_emulation.info.time_ms = frame * 10 + (slot >> 1); - - direction = subframe_select (frame_parms[0], next_slot >> 1); + oai_emulation.info.time_ms = frame * 10 + sf; #ifdef PROC - if(Channel_Flag==1) - Channel_Func(s_re2,s_im2,r_re2,r_im2,r_re02,r_im02,r_re0_d,r_im0_d,r_re0_u,r_im0_u,eNB2UE,UE2eNB,enb_data,ue_data,abstraction_flag,frame_parms,slot); + if(Channel_Flag==1) + Channel_Func(s_re2,s_im2,r_re2,r_im2,r_re02,r_im02,r_re0_d,r_im0_d,r_re0_u,r_im0_u,eNB2UE,UE2eNB,enb_data,ue_data,abstraction_flag,frame_parms,sf<<1); - if(Channel_Flag==0) + if(Channel_Flag==0) #endif - { + { // SUBFRAME INNER PART #if defined(ENABLE_ITTI) log_set_instance_type (LOG_INSTANCE_ENB); #endif - // if ((next_slot % 2) == 0) - if ((slot & 1) == 0) - clear_eNB_transport_info (oai_emulation.info.nb_enb_local); + clear_eNB_transport_info (oai_emulation.info.nb_enb_local); for (eNB_inst = oai_emulation.info.first_enb_local; (eNB_inst @@ -745,41 +707,50 @@ l2l1_task (void *args_p) + oai_emulation.info.nb_enb_local)); eNB_inst++) { if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) { - if ((slot & 1) == 0) { - T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(slot/2)); - LOG_D(EMU, - "PHY procedures eNB %d for frame %d, slot %d (subframe TX %d, RX %d) TDD %d/%d Nid_cell %d\n", - eNB_inst, - frame % MAX_FRAME_NUMBER, - slot, - PHY_vars_eNB_g[eNB_inst][0]->proc[slot >> 1].subframe_tx, - PHY_vars_eNB_g[eNB_inst][0]->proc[slot >> 1].subframe_rx, - PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.frame_type, - PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.tdd_config, - PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.Nid_cell); - } + + T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(sf)); + LOG_D(EMU, + "PHY procedures eNB %d for frame %d, subframe %d TDD %d/%d Nid_cell %d\n", + eNB_inst, + frame % MAX_FRAME_NUMBER, + sf, + PHY_vars_eNB_g[eNB_inst][0]->frame_parms.frame_type, + PHY_vars_eNB_g[eNB_inst][0]->frame_parms.tdd_config, + PHY_vars_eNB_g[eNB_inst][0]->frame_parms.Nid_cell); + #ifdef OPENAIR2 - //Application: traffic gen + //Application: traffic gen update_otg_eNB (eNB_inst, oai_emulation.info.time_ms); //IP/OTG to PDCP and PDCP to IP operation // pdcp_run (frame, 1, 0, eNB_inst); //PHY_vars_eNB_g[eNB_id]->Mod_id #endif - // PHY_vars_eNB_g[eNB_id]->frame = frame; - if ((slot & 1) == 0) - phy_procedures_eNB_lte (slot >> 1, - PHY_vars_eNB_g[eNB_inst], - abstraction_flag, no_relay, - NULL); + CC_id=0; + PHY_vars_eNB_g[eNB_inst][CC_id]->proc.frame_rx = frame; + PHY_vars_eNB_g[eNB_inst][CC_id]->proc.subframe_rx = sf; + PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].frame_rx = frame; + PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].subframe_rx = sf; + PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].subframe_tx = (sf+4)%10; + PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].frame_tx = (sf<6) ? frame : frame+1; + phy_procedures_eNB_common_RX(PHY_vars_eNB_g[eNB_inst][CC_id], + abstraction_flag); + phy_procedures_eNB_uespec_RX(PHY_vars_eNB_g[eNB_inst][CC_id], + &PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1], + abstraction_flag, + no_relay); + phy_procedures_eNB_TX(PHY_vars_eNB_g[eNB_inst][CC_id], + &PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1], + 0,no_relay,NULL); + #ifdef PRINT_STATS - if(last_slot==9 && frame%10==0) + if((sf==9) && frame%10==0) if(eNB_avg_thr) - fprintf(eNB_avg_thr,"%d %d\n",PHY_vars_eNB_g[eNB_inst][0]->proc[slot>>1].frame_tx, - (PHY_vars_eNB_g[eNB_inst][0]->total_system_throughput)/((PHY_vars_eNB_g[eNB_inst][0]->proc[slot>>1].frame_tx+1)*10)); + fprintf(eNB_avg_thr,"%d %d\n",PHY_vars_eNB_g[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx, + (PHY_vars_eNB_g[eNB_inst][0]->total_system_throughput)/((PHY_vars_eNB_g[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx+1)*10)); if (eNB_stats[eNB_inst]) { len = dump_eNB_stats(PHY_vars_eNB_g[eNB_inst][0], stats_buffer, 0); @@ -800,7 +771,7 @@ l2l1_task (void *args_p) #endif #endif } - } + }// eNB_inst loop // Call ETHERNET emulation here //emu_transport (frame, last_slot, next_slot, direction, oai_emulation.info.frame_type, ethernet_flag); @@ -809,9 +780,7 @@ l2l1_task (void *args_p) log_set_instance_type (LOG_INSTANCE_UE); #endif - if ((next_slot % 2) == 0) - // if ((slot&1) == 0) - clear_UE_transport_info (oai_emulation.info.nb_ue_local); + clear_UE_transport_info (oai_emulation.info.nb_ue_local); for (UE_inst = oai_emulation.info.first_ue_local; (UE_inst < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local)); @@ -823,435 +792,302 @@ l2l1_task (void *args_p) if (frame >= (UE_inst * 20)) // activate UE only after 20*UE_id frames so that different UEs turn on separately #endif - { - LOG_D(EMU, - "PHY procedures UE %d for frame %d, slot %d (subframe TX %d, RX %d)\n", - UE_inst, frame % MAX_FRAME_NUMBER, slot, next_slot >> 1, - last_slot >> 1); + { // UE_PROCEDURES + LOG_D(EMU, + "PHY procedures UE %d for frame %d, subframe %d\n", + UE_inst, frame % MAX_FRAME_NUMBER, sf); - if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0] - != NOT_SYNCHED) { - if (frame > 0) { - PHY_vars_UE_g[UE_inst][0]->frame_rx = frame % MAX_FRAME_NUMBER; - PHY_vars_UE_g[UE_inst][0]->slot_rx = last_slot; - PHY_vars_UE_g[UE_inst][0]->slot_tx = next_slot; - - if (next_slot > 1) - PHY_vars_UE_g[UE_inst][0]->frame_tx = frame % MAX_FRAME_NUMBER; - else - PHY_vars_UE_g[UE_inst][0]->frame_tx = (frame + 1) % MAX_FRAME_NUMBER; + if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0] + != NOT_SYNCHED) { + if (frame > 0) { + PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].frame_rx = frame % MAX_FRAME_NUMBER; + PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].subframe_rx = sf; + PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].frame_tx = ((sf<6) ? frame : frame+1)% MAX_FRAME_NUMBER; + PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].subframe_tx = (sf+4)%10; #ifdef OPENAIR2 - //Application - update_otg_UE (UE_inst, oai_emulation.info.time_ms); + //Application + update_otg_UE (UE_inst, oai_emulation.info.time_ms); - //Access layer - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, 0, ENB_FLAG_NO, NOT_A_RNTI, frame % MAX_FRAME_NUMBER, next_slot); - pdcp_run (&ctxt); + //Access layer + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, 0, ENB_FLAG_NO, NOT_A_RNTI, frame % MAX_FRAME_NUMBER, sf); + pdcp_run (&ctxt); #endif - for (CC_id = 0; CC_id < MAX_NUM_CCs; - CC_id++) { - phy_procedures_UE_lte ( - PHY_vars_UE_g[UE_inst][CC_id], - 0, abstraction_flag, - normal_txrx, no_relay, - NULL); - } + for (CC_id = 0; CC_id < MAX_NUM_CCs; + CC_id++) { + phy_procedures_UE_RX(PHY_vars_UE_g[UE_inst][CC_id], + &PHY_vars_UE_g[UE_inst][CC_id]->proc.proc_rxtx[sf&1], + 0, abstraction_flag, + normal_txrx, no_relay, + NULL); + phy_procedures_UE_TX(PHY_vars_UE_g[UE_inst][CC_id], + &PHY_vars_UE_g[UE_inst][CC_id]->proc.proc_rxtx[sf&1], + 0, + abstraction_flag, + normal_txrx, + no_relay); + } - ue_data[UE_inst]->tx_power_dBm = - PHY_vars_UE_g[UE_inst][0]->tx_power_dBm; - } - } else { - if (abstraction_flag == 1) { - LOG_E(EMU, - "sync not supported in abstraction mode (UE%d,mode%d)\n", - UE_inst, - PHY_vars_UE_g[UE_inst][0]->UE_mode[0]); - exit (-1); - } + ue_data[UE_inst]->tx_power_dBm = + PHY_vars_UE_g[UE_inst][0]->tx_power_dBm; + } + } else { + if (abstraction_flag == 1) { + LOG_E(EMU, + "sync not supported in abstraction mode (UE%d,mode%d)\n", + UE_inst, + PHY_vars_UE_g[UE_inst][0]->UE_mode[0]); + exit (-1); + } - if ((frame > 0) - && (last_slot - == (LTE_SLOTS_PER_FRAME - - 2))) { - initial_sync (PHY_vars_UE_g[UE_inst][0], - normal_txrx); + if ((frame > 0) + && (sf==9)){ - /* - write_output("dlchan00.m","dlch00",&(PHY_vars_UE_g[0]->lte_ue_common_vars.dl_ch_estimates[0][0][0]),(6*(PHY_vars_UE_g[0]->lte_frame_parms.ofdm_symbol_size)),1,1); - if (PHY_vars_UE_g[0]->lte_frame_parms.nb_antennas_rx>1) - write_output("dlchan01.m","dlch01",&(PHY_vars_UE_g[0]->lte_ue_common_vars.dl_ch_estimates[0][1][0]),(6*(PHY_vars_UE_g[0]->lte_frame_parms.ofdm_symbol_size)),1,1); - write_output("dlchan10.m","dlch10",&(PHY_vars_UE_g[0]->lte_ue_common_vars.dl_ch_estimates[0][2][0]),(6*(PHY_vars_UE_g[0]->lte_frame_parms.ofdm_symbol_size)),1,1); - if (PHY_vars_UE_g[0]->lte_frame_parms.nb_antennas_rx>1) - write_output("dlchan11.m","dlch11",&(PHY_vars_UE_g[0]->lte_ue_common_vars.dl_ch_estimates[0][3][0]),(6*(PHY_vars_UE_g[0]->lte_frame_parms.ofdm_symbol_size)),1,1); - write_output("rxsig.m","rxs",PHY_vars_UE_g[0]->lte_ue_common_vars.rxdata[0],PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti*10,1,1); - write_output("rxsigF.m","rxsF",PHY_vars_UE_g[0]->lte_ue_common_vars.rxdataF[0],2*PHY_vars_UE_g[0]->lte_frame_parms.symbols_per_tti*PHY_vars_UE_g[0]->lte_frame_parms.ofdm_symbol_size,2,1); - write_output("pbch_rxF_ext0.m","pbch_ext0",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->rxdataF_ext[0],6*12*4,1,1); - write_output("pbch_rxF_comp0.m","pbch_comp0",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->rxdataF_comp[0],6*12*4,1,1); - write_output("pbch_rxF_llr.m","pbch_llr",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->llr,(frame_parms->Ncp==0) ? 1920 : 1728,1,4); - */ - } - } + initial_sync (PHY_vars_UE_g[UE_inst][0], + normal_txrx); + + /* + write_output("dlchan00.m","dlch00",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][0][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); + if (PHY_vars_UE_g[0]->frame_parms.nb_antennas_rx>1) + write_output("dlchan01.m","dlch01",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][1][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); + write_output("dlchan10.m","dlch10",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][2][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); + if (PHY_vars_UE_g[0]->frame_parms.nb_antennas_rx>1) + write_output("dlchan11.m","dlch11",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][3][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); + write_output("rxsig.m","rxs",PHY_vars_UE_g[0]->common_vars.rxdata[0],PHY_vars_UE_g[0]->frame_parms.samples_per_tti*10,1,1); + write_output("rxsigF.m","rxsF",PHY_vars_UE_g[0]->common_vars.rxdataF[0],2*PHY_vars_UE_g[0]->frame_parms.symbols_per_tti*PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size,2,1); + write_output("pbch_rxF_ext0.m","pbch_ext0",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->rxdataF_ext[0],6*12*4,1,1); + write_output("pbch_rxF_comp0.m","pbch_comp0",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->rxdataF_comp[0],6*12*4,1,1); + write_output("pbch_rxF_llr.m","pbch_llr",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->llr,(frame_parms->Ncp==0) ? 1920 : 1728,1,4); + */ + } + } #ifdef PRINT_STATS - if(last_slot==2 && frame%10==0) { - if (UE_stats_th[UE_inst]) { - fprintf(UE_stats_th[UE_inst],"%d %d\n",frame % MAX_FRAME_NUMBER, PHY_vars_UE_g[UE_inst][0]->bitrate[0]/1000); - } - } + if((sf==1) && frame%10==0) { + if (UE_stats_th[UE_inst]) { + fprintf(UE_stats_th[UE_inst],"%d %d\n",frame % MAX_FRAME_NUMBER, PHY_vars_UE_g[UE_inst][0]->bitrate[0]/1000); + } + } - if (UE_stats[UE_inst]) { - len = dump_ue_stats (PHY_vars_UE_g[UE_inst][0], stats_buffer, 0, normal_txrx, 0); - rewind (UE_stats[UE_inst]); - fwrite (stats_buffer, 1, len, UE_stats[UE_inst]); - fflush(UE_stats[UE_inst]); - } + if (UE_stats[UE_inst]) { + len = dump_ue_stats (PHY_vars_UE_g[UE_inst][0], &PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1],stats_buffer, 0, normal_txrx, 0); + rewind (UE_stats[UE_inst]); + fwrite (stats_buffer, 1, len, UE_stats[UE_inst]); + fflush(UE_stats[UE_inst]); + } #endif - } + } // UE_PROCEDURES } - } + } // UE_inst -#ifdef Rel10 - - for (RN_id=oai_emulation.info.first_rn_local; - RN_idframe = frame % MAX_FRAME_NUMBER; - - if ( oai_emulation.info.frame_type == 0) { - // RN == UE - if (frame>0) { - if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0] != NOT_SYNCHED) { - LOG_D(EMU,"[RN %d] PHY procedures UE %d for frame %d, slot %d (subframe TX %d, RX %d)\n", - RN_id, UE_inst, frame, slot, next_slot >> 1,last_slot>>1); - PHY_vars_UE_g[UE_inst][0]->frame_rx = frame % MAX_FRAME_NUMBER; - PHY_vars_UE_g[UE_inst][0]->slot_rx = last_slot; - PHY_vars_UE_g[UE_inst][0]->slot_tx = next_slot; - - if (next_slot>1) PHY_vars_UE_g[UE_inst][0]->frame_tx = frame % MAX_FRAME_NUMBER; - else PHY_vars_UE_g[UE_inst][0]->frame_tx = (frame+1) % MAX_FRAME_NUMBER; - - phy_procedures_UE_lte (PHY_vars_UE_g[UE_inst][0], 0, abstraction_flag,normal_txrx, - r_type, PHY_vars_RN_g[RN_id]); - } else if (last_slot == (LTE_SLOTS_PER_FRAME-2)) { - initial_sync(PHY_vars_UE_g[UE_inst][0],normal_txrx); - } - } - - // RN == eNB - LOG_D(EMU,"[RN %d] PHY procedures eNB %d for frame %d, slot %d (subframe TX %d, RX %d)\n", - RN_id, eNB_inst, frame % MAX_FRAME_NUMBER, slot, next_slot >> 1,last_slot>>1); - phy_procedures_eNB_lte(slot>>1, PHY_vars_eNB_g[eNB_inst], abstraction_flag, - r_type, PHY_vars_RN_g[RN_id]); - } else { - LOG_E(EMU,"TDD is not supported for multicast relaying %d\n", r_type); - exit(-1); - } - } - -#endif - emu_transport (frame % MAX_FRAME_NUMBER, last_slot, next_slot, direction, + emu_transport (frame % MAX_FRAME_NUMBER, sf<<1, ((sf+4)%10)<<1, subframe_select(&PHY_vars_eNB_g[0][0]->frame_parms,sf), oai_emulation.info.frame_type[0], ethernet_flag); - if ((direction == SF_DL) - || (frame_parms[0]->frame_type == FDD)) { - // consider only sec id 0 - /* for (eNB_id=0;eNB_idlte_eNB_common_vars.txdataF[0], - PHY_vars_eNB_g[eNB_id]->lte_eNB_common_vars.txdata[0], - frame,next_slot, - frame_parms); - } - }*/ - start_meas (&dl_chan_stats); + start_meas (&dl_chan_stats); + + for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + //#warning figure out what to do with UE frame_parms during initial_sync + do_DL_sig (r_re0, + r_im0, + r_re, + r_im, + s_re, + s_im, + eNB2UE, + enb_data, + ue_data, + PHY_vars_eNB_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1, + abstraction_flag, + &PHY_vars_eNB_g[0][CC_id]->frame_parms, + UE_inst, CC_id); + do_DL_sig (r_re0, + r_im0, + r_re, + r_im, + s_re, + s_im, + eNB2UE, + enb_data, + ue_data, + (PHY_vars_eNB_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1)+1, + abstraction_flag, + &PHY_vars_eNB_g[0][CC_id]->frame_parms, + UE_inst, CC_id); + } - for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { -//#warning figure out what to do with UE frame_parms during initial_sync - do_DL_sig (r_re0, - r_im0, - r_re, - r_im, - s_re, - s_im, - eNB2UE, - enb_data, - ue_data, - next_slot, - abstraction_flag, - &PHY_vars_eNB_g[0][CC_id]->lte_frame_parms, - UE_inst, CC_id); - } + stop_meas (&dl_chan_stats); + - stop_meas (&dl_chan_stats); - } + start_meas (&ul_chan_stats); + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + //#warning figure out what to do with UE frame_parms during initial_sync + do_UL_sig (r_re0, r_im0, r_re, r_im, s_re, s_im, UE2eNB, + enb_data, ue_data, + PHY_vars_UE_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1, + abstraction_flag, + &PHY_vars_eNB_g[0][CC_id]->frame_parms, + frame % MAX_FRAME_NUMBER, CC_id); + do_UL_sig (r_re0, r_im0, r_re, r_im, s_re, s_im, UE2eNB, + enb_data, ue_data, + (PHY_vars_UE_g[0][CC_id]->proc.proc_rxtx[sf&1].subframe_tx<<1)+1, + abstraction_flag, + &PHY_vars_eNB_g[0][CC_id]->frame_parms, + frame % MAX_FRAME_NUMBER, CC_id); + } + + stop_meas (&ul_chan_stats); - if ((direction == SF_UL) || (frame_parms[0]->frame_type == 0)) { //if ((subframe<2) || (subframe>4)) - start_meas (&ul_chan_stats); - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { -//#warning figure out what to do with UE frame_parms during initial_sync - do_UL_sig (r_re0, r_im0, r_re, r_im, s_re, s_im, UE2eNB, - enb_data, ue_data, next_slot, - abstraction_flag, - &PHY_vars_eNB_g[0][CC_id]->lte_frame_parms, - frame % MAX_FRAME_NUMBER, CC_id); - } - - stop_meas (&ul_chan_stats); - /* - int ccc; - fprintf(SINRpost,"SINRdb For eNB New Subframe : \n "); - for(ccc = 0 ; ccc<301; ccc++) - { - fprintf(SINRpost,"_ %f ", SINRpost_eff[ccc]); - } - fprintf(SINRpost,"SINRdb For eNB : %f \n ", SINRpost_eff[ccc]); - */ - } - - if ((direction == SF_S)) { //it must be a special subframe - if (next_slot % 2 == 0) { //DL part - /* for (eNB_id=0;eNB_idlte_eNB_common_vars.txdataF[0], - PHY_vars_eNB_g[eNB_id]->lte_eNB_common_vars.txdata[0], - frame,next_slot, - frame_parms); - } - }*/ - start_meas (&dl_chan_stats); - - for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { -//#warning check dimensions of r_reN,r_imN for multiple CCs - do_DL_sig (r_re0, - r_im0, - r_re, - r_im, - s_re, - s_im, - eNB2UE, - enb_data, - ue_data, - next_slot, - abstraction_flag, - &PHY_vars_eNB_g[0][CC_id]->lte_frame_parms, - UE_inst, CC_id); - } - - stop_meas (&dl_chan_stats); - /* - for (aarx=0;aarxnb_rx;aarx++) - for (aatx=0;aatxnb_tx;aatx++) - for (k=0;kchannel_length;k++) - printf("SB(%d,%d,%d)->(%f,%f)\n",k,aarx,aatx,UE2eNB[1][0]->ch[aarx+(aatx*UE2eNB[1][0]->nb_rx)][k].r,UE2eNB[1][0]->ch[aarx+(aatx*UE2eNB[1][0]->nb_rx)][k].i); - */ - } else { // UL part - start_meas (&ul_chan_stats); - - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { -//#warning check dimensions of r_reN,r_imN for multiple CCs - do_UL_sig (r_re0, - r_im0, - r_re, - r_im, - s_re, - s_im, - UE2eNB, - enb_data, - ue_data, - next_slot, - abstraction_flag, - &PHY_vars_eNB_g[0][CC_id]->lte_frame_parms, - frame % MAX_FRAME_NUMBER, CC_id); - } - - stop_meas (&ul_chan_stats); - - /* int ccc; - fprintf(SINRpost,"SINRdb For eNB New Subframe : \n "); - for(ccc = 0 ; ccc<301; ccc++) - { - fprintf(SINRpost,"_ %f ", SINRpost_eff[ccc]); - } - fprintf(SINRpost,"SINRdb For eNB : %f \n ", SINRpost_eff[ccc]); - } - */ - } - } - - if ((last_slot == 1) && ((frame % MAX_FRAME_NUMBER) == 0) && (abstraction_flag == 0) - && (oai_emulation.info.n_frames == 1)) { - - write_output ("dlchan0.m", - "dlch0", - &(PHY_vars_UE_g[0][0]->lte_ue_common_vars.dl_ch_estimates[0][0][0]), - (6 - * (PHY_vars_UE_g[0][0]->lte_frame_parms.ofdm_symbol_size)), - 1, 1); - write_output ("dlchan1.m", - "dlch1", - &(PHY_vars_UE_g[0][0]->lte_ue_common_vars.dl_ch_estimates[1][0][0]), - (6 - * (PHY_vars_UE_g[0][0]->lte_frame_parms.ofdm_symbol_size)), - 1, 1); - write_output ("dlchan2.m", - "dlch2", - &(PHY_vars_UE_g[0][0]->lte_ue_common_vars.dl_ch_estimates[2][0][0]), - (6 - * (PHY_vars_UE_g[0][0]->lte_frame_parms.ofdm_symbol_size)), - 1, 1); - write_output ("pbch_rxF_comp0.m", - "pbch_comp0", - PHY_vars_UE_g[0][0]->lte_ue_pbch_vars[0]->rxdataF_comp[0], - 6 * 12 * 4, 1, 1); - write_output ("pbch_rxF_llr.m", "pbch_llr", - PHY_vars_UE_g[0][0]->lte_ue_pbch_vars[0]->llr, - (frame_parms[0]->Ncp == 0) ? 1920 : 1728, 1, - 4); - } - - /* - if ((last_slot==1) && (frame==1)) { - write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0",PHY_vars_UE->lte_ue_pdsch_vars[eNB_id]->rxdataF_comp[0],300*(-(PHY_vars_UE->lte_frame_parms.Ncp*2)+14),1,1); - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",PHY_vars_UE->lte_ue_pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1); - } - */ - } // if Channel_Flag==0 - - if (slot % 2 == 1) - stop_meas (&oaisim_stats_f); - } //end of slot + if ((sf == 0) && ((frame % MAX_FRAME_NUMBER) == 0) && (abstraction_flag == 0) + && (oai_emulation.info.n_frames == 1)) { + + write_output ("dlchan0.m", + "dlch0", + &(PHY_vars_UE_g[0][0]->common_vars.dl_ch_estimates[0][0][0]), + (6 + * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)), + 1, 1); + write_output ("dlchan1.m", + "dlch1", + &(PHY_vars_UE_g[0][0]->common_vars.dl_ch_estimates[1][0][0]), + (6 + * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)), + 1, 1); + write_output ("dlchan2.m", + "dlch2", + &(PHY_vars_UE_g[0][0]->common_vars.dl_ch_estimates[2][0][0]), + (6 + * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)), + 1, 1); + write_output ("pbch_rxF_comp0.m", + "pbch_comp0", + PHY_vars_UE_g[0][0]->pbch_vars[0]->rxdataF_comp[0], + 6 * 12 * 4, 1, 1); + write_output ("pbch_rxF_llr.m", "pbch_llr", + PHY_vars_UE_g[0][0]->pbch_vars[0]->llr, + (frame_parms[0]->Ncp == 0) ? 1920 : 1728, 1, + 4); + } + + stop_meas (&oaisim_stats_f); + } // SUBFRAME INNER PART + } + if ((frame >= 10) && (frame <= 11) && (abstraction_flag == 0) #ifdef PROC - &&(Channel_Flag==0) + &&(Channel_Flag==0) #endif - ) { + ) { sprintf (fname, "UEtxsig%d.m", frame % MAX_FRAME_NUMBER); sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER); write_output (fname, - vname, - PHY_vars_UE_g[0][0]->lte_ue_common_vars.txdata[0], - PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti - * 10, - 1, 1); + vname, + PHY_vars_UE_g[0][0]->common_vars.txdata[0], + PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti + * 10, + 1, 1); sprintf (fname, "eNBtxsig%d.m", frame % MAX_FRAME_NUMBER); sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER); write_output (fname, - vname, - PHY_vars_eNB_g[0][0]->lte_eNB_common_vars.txdata[0][0], - PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti - * 10, - 1, 1); + vname, + PHY_vars_eNB_g[0][0]->common_vars.txdata[0][0], + PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti + * 10, + 1, 1); sprintf (fname, "eNBtxsigF%d.m", frame % MAX_FRAME_NUMBER); sprintf (vname, "txsF%d", frame % MAX_FRAME_NUMBER); write_output (fname, - vname, - PHY_vars_eNB_g[0][0]->lte_eNB_common_vars.txdataF[0][0], - PHY_vars_eNB_g[0][0]->lte_frame_parms.symbols_per_tti - * PHY_vars_eNB_g[0][0]->lte_frame_parms.ofdm_symbol_size, - 1, 1); + vname, + PHY_vars_eNB_g[0][0]->common_vars.txdataF[0][0], + PHY_vars_eNB_g[0][0]->frame_parms.symbols_per_tti + * PHY_vars_eNB_g[0][0]->frame_parms.ofdm_symbol_size, + 1, 1); sprintf (fname, "UErxsig%d.m", frame % MAX_FRAME_NUMBER); sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER); write_output (fname, - vname, - PHY_vars_UE_g[0][0]->lte_ue_common_vars.rxdata[0], - PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti - * 10, - 1, 1); + vname, + PHY_vars_UE_g[0][0]->common_vars.rxdata[0], + PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti + * 10, + 1, 1); sprintf (fname, "eNBrxsig%d.m", frame % MAX_FRAME_NUMBER); sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER); write_output (fname, - vname, - PHY_vars_eNB_g[0][0]->lte_eNB_common_vars.rxdata[0][0], - PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti - * 10, - 1, 1); + vname, + PHY_vars_eNB_g[0][0]->common_vars.rxdata[0][0], + PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti + * 10, + 1, 1); } - + //#ifdef XFORMS if (xforms==1) { - eNB_inst = 0; + eNB_inst = 0; + + for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) { + for (CC_id=0;CC_idlte_frame_parms); + smbv_write_config_from_frame_parms(smbv_fname, &PHY_vars_eNB_g[0][0]->frame_parms); #endif // add events to future event list: Currently not used @@ -1862,38 +1698,38 @@ oai_shutdown (void) if (abstraction_flag == 0 && Channel_Flag==0 && Process_Flag==0) #else - if (abstraction_flag == 0) + if (abstraction_flag == 0) #endif - { - /* - #ifdef IFFT_FPGA - free(txdataF2[0]); - free(txdataF2[1]); - free(txdataF2); - free(txdata[0]); - free(txdata[1]); - free(txdata); - #endif - */ + { + /* + #ifdef IFFT_FPGA + free(txdataF2[0]); + free(txdataF2[1]); + free(txdataF2); + free(txdata[0]); + free(txdata[1]); + free(txdata); + #endif + */ - for (int i = 0; i < 2; i++) { - free (s_re[i]); - free (s_im[i]); - free (r_re[i]); - free (r_im[i]); - } + for (int i = 0; i < 2; i++) { + free (s_re[i]); + free (s_im[i]); + free (r_re[i]); + free (r_im[i]); + } - free (s_re); - free (s_im); - free (r_re); - free (r_im); - s_re = 0; - s_im = 0; - r_re = 0; - r_im = 0; + free (s_re); + free (s_im); + free (r_re); + free (r_im); + s_re = 0; + s_im = 0; + r_re = 0; + r_im = 0; - lte_sync_time_free (); - } + lte_sync_time_free (); + } // added for PHY abstraction if (oai_emulation.info.ocm_enabled == 1) { @@ -1961,3 +1797,5 @@ get_OAI_emulation () { return &oai_emulation; } + + diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 922114aa8e..5a970ca038 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -958,21 +958,21 @@ void init_openair1(void) PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = beta_ACK; PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_RI_Index = beta_RI; PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = beta_CQI; - PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antennas_tx_eNB>1) ? 1 : 0; // rho_A = rho_B + PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antennas_tx_eNB>1) ? 1 : 0; // rho_A = rho_B PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index = beta_ACK; PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_RI_Index = beta_RI; PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index = beta_CQI; - PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antennas_tx_eNB>1) ? 1 : 0; // rho_A = rho_B + PHY_vars_UE_g[UE_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antennas_tx_eNB>1) ? 1 : 0; // rho_A = rho_B } } } printf ("AFTER init: MAX_NUM_CCs %d, Nid_cell %d frame_type %d,tdd_config %d\n", MAX_NUM_CCs, - PHY_vars_eNB_g[0][0]->lte_frame_parms.Nid_cell, - PHY_vars_eNB_g[0][0]->lte_frame_parms.frame_type, - PHY_vars_eNB_g[0][0]->lte_frame_parms.tdd_config); + PHY_vars_eNB_g[0][0]->frame_parms.Nid_cell, + PHY_vars_eNB_g[0][0]->frame_parms.frame_type, + PHY_vars_eNB_g[0][0]->frame_parms.tdd_config); number_of_cards = 1; @@ -993,12 +993,12 @@ void init_openair1(void) for (UE_id=0; UE_iduse_ia_receiver = 0; - if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.frame_type == TDD) { - if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.N_RB_DL == 100) + if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.frame_type == TDD) { + if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.N_RB_DL == 100) PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 624; - else if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.N_RB_DL == 50) + else if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.N_RB_DL == 50) PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 624/2; - else if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.N_RB_DL == 25) + else if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.N_RB_DL == 25) PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 624/4; } else { PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 0; @@ -1006,12 +1006,12 @@ void init_openair1(void) } for (eNB_id=0; eNB_idlte_frame_parms.frame_type == TDD) { - if (PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL == 100) + if (PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.frame_type == TDD) { + if (PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.N_RB_DL == 100) PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 624; - else if (PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL == 50) + else if (PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.N_RB_DL == 50) PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 624/2; - else if (PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL == 25) + else if (PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.N_RB_DL == 25) PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 624/4; } else { PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 0; @@ -1048,7 +1048,7 @@ void init_openair1(void) else PHY_vars_UE_g[UE_id][CC_id]->mac_enabled=1; - PHY_vars_UE_g[UE_id][CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235 + UE_id; + PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0]->crnti = 0x1235 + UE_id; PHY_vars_UE_g[UE_id][CC_id]->current_dlsch_cqi[0] = 10; LOG_I(EMU, "UE %d mode is initialized to %d\n", UE_id, PHY_vars_UE_g[UE_id][CC_id]->UE_mode[0] ); @@ -1077,7 +1077,7 @@ void init_openair2(void) //#warning "eNB index is hard coded to zero" for (CC_id=0; CC_idlte_frame_parms, + l2_init (&PHY_vars_eNB_g[0][CC_id]->frame_parms, oai_emulation.info.eMBMS_active_state, NULL, oai_emulation.info.cba_group_active, @@ -1167,8 +1167,8 @@ void init_ocm(void) map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option), eNB_id, UE_id); /* if (oai_emulation.info.transmission_mode == 5) - eNB2UE[eNB_id][UE_id] = new_channel_desc_scm(PHY_vars_eNB_g[eNB_id]->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE_g[UE_id]->lte_frame_parms.nb_antennas_rx, + eNB2UE[eNB_id][UE_id] = new_channel_desc_scm(PHY_vars_eNB_g[eNB_id]->frame_parms.nb_antennas_tx, + PHY_vars_UE_g[UE_id]->frame_parms.nb_antennas_rx, (UE_id == 0)? Rice1_corr : Rice1_anticorr, oai_emulation.environment_system_config.system_bandwidth_MB, forgetting_factor, @@ -1179,11 +1179,11 @@ void init_ocm(void) */ eNB2UE[eNB_id][UE_id][CC_id] = - new_channel_desc_scm(PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.nb_antennas_rx, + new_channel_desc_scm(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_tx, + PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_rx, map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option), - N_RB2sampling_rate(PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.N_RB_DL), forgetting_factor, 0, 0); @@ -1192,11 +1192,11 @@ void init_ocm(void) map_str_to_int(small_scale_names, oai_emulation.environment_system_config.fading.small_scale.selected_option),UE_id, eNB_id); UE2eNB[UE_id][eNB_id][CC_id] = - new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.nb_antennas_tx, - PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.nb_antennas_rx, + new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx, + PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_rx, map_str_to_int(small_scale_names, oai_emulation.environment_system_config.fading.small_scale.selected_option), - N_RB2sampling_rate(PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_UL), - N_RB2channel_bandwidth(PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_UL), + N_RB2sampling_rate(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.N_RB_UL), + N_RB2channel_bandwidth(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.N_RB_UL), forgetting_factor, 0, 0); @@ -1265,7 +1265,7 @@ void update_ocm() int CC_id; for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) - enb_data[eNB_id]->tx_power_dBm = PHY_vars_eNB_g[eNB_id][0]->lte_frame_parms.pdsch_config_common.referenceSignalPower; + enb_data[eNB_id]->tx_power_dBm = PHY_vars_eNB_g[eNB_id][0]->frame_parms.pdsch_config_common.referenceSignalPower; for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) ue_data[UE_id]->tx_power_dBm = PHY_vars_UE_g[UE_id][0]->tx_power_dBm; @@ -1315,16 +1315,16 @@ void update_ocm() //pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE if (eNB_id == (UE_id % NB_eNB_INST)) { - eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.pdsch_config_common.referenceSignalPower; - UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + snr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.pdsch_config_common.referenceSignalPower; + eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; + UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + snr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; } else { - eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.pdsch_config_common.referenceSignalPower; - UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.pdsch_config_common.referenceSignalPower; + eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; + UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; } LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",eNB_id,UE_id,CC_id, eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB, - PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.pdsch_config_common.referenceSignalPower,snr_dB); + PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB); // printf("[SIM] Path loss from UE %d to eNB %d => %f dB\n",UE_id,eNB_id,UE2eNB[UE_id][eNB_id]->path_loss_dB); } } From 29fdf1a35a7c49fd1b3d9be1e206c5b3b99f87cb Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 17 Jul 2016 22:50:24 +0200 Subject: [PATCH 097/206] modifications for UE on ExpressMIMO2, validation on USRP. Only RX path is activated. --- openair2/UTIL/LOG/vcd_signal_dumper.c | 19 +- openair2/UTIL/LOG/vcd_signal_dumper.h | 19 +- targets/ARCH/COMMON/common_lib.h | 3 +- .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 224 +++++++++++++----- .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h | 1 + targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 2 +- targets/RT/USER/lte-softmodem.c | 20 +- targets/RT/USER/lte-ue.c | 70 ++++-- targets/RT/USER/ue_usrp.gtkw | 35 +-- 9 files changed, 263 insertions(+), 130 deletions(-) diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 8fe33fefd5..a643874444 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -81,12 +81,14 @@ const char* eurecomVariablesNames[] = { "subframe_number_RX_eNB", "runtime_TX_eNB", "runtime_RX_eNB", - "frame_number_TX_UE", - "frame_number_RX_UE", - "slot_number_TX_UE", - "slot_number_RX_UE", - "subframe_number_TX_UE", - "subframe_number_RX_UE", + "frame_number_TX0_UE", + "frame_number_TX1_UE", + "frame_number_RX0_UE", + "frame_number_RX1_UE", + "subframe_TX0_UE", + "subframe_TX1_UE", + "subframe_RX0_UE", + "subframe_RX1_UE", "missed_slot_enb", "daq_mbox", "rx_offset_mbox", @@ -187,8 +189,9 @@ const char* eurecomFunctionsNames[] = { "eNB_thread_rxtx1", "eNB_thread_rx", "eNB_thread_prach", - "ue_thread_tx", - "ue_thread_rx", + "ue_thread_synch", + "ue_thread_rxtx0", + "ue_thread_rxtx1", /* RRH signals */ "eNB_tx", diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index 7bcdc5733b..cd1b86fbd9 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -53,12 +53,14 @@ typedef enum { VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, - VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_UE, - VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_UE, - VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX_UE, - VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX_UE, - VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_UE, - VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_UE, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_UE, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX1_UE, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_UE, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_UE, VCD_SIGNAL_DUMPER_VARIABLES_MISSED_SLOTS_ENB, VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, VCD_SIGNAL_DUMPER_VARIABLES_UE_OFFSET_MBOX, @@ -161,8 +163,9 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX1, VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_PRACH, - VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX, - VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, + VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, + VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0, + VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX1, /* RRH signals */ VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index c371e12520..70f098217a 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -326,9 +326,8 @@ struct openair0_device_t { void (*trx_end_func)(openair0_device *device); /*! \brief Stop operation of the transceiver - * \param card RF Card to use */ - int (*trx_stop_func)(int card); + int (*trx_stop_func)(openair0_device *device); /* Functions API related to UE*/ diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index 582a2f75d2..736e126ccb 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -67,6 +67,7 @@ #define max(a,b) ((a)>(b) ? (a) : (b)) +//#define DEBUG_EXMIMO exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS]; // contains userspace pointers for each card @@ -306,7 +307,7 @@ static void *watchdog_thread(void *arg) { wait.tv_sec=0; - wait.tv_nsec=5000000L; + wait.tv_nsec=50000000L; /* Set affinity mask to include CPUs 1 to MAX_CPUS */ /* CPU 0 is reserved for UHD threads */ @@ -410,6 +411,8 @@ static void *watchdog_thread(void *arg) { } first_acquisition=1; + printf("Locking watchdog for first acquisition\n"); + pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); // main loop to keep up with DMA transfers from exmimo2 int cnt_diff0=0; @@ -428,19 +431,22 @@ static void *watchdog_thread(void *arg) { } exm->last_mbox = mbox; - pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); + if (first_acquisition==0) + pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); + exm->ts += (diff*exm->samples_per_frame/150) ; - if (first_acquisition==1) //set last read to a closest subframe boundary - exm->last_ts_rx = (exm->ts/(exm->samples_per_frame/10))*(exm->samples_per_frame/10); - if ((diff > 16)&&(first_acquisition==0)) {// we're too late so exit + if ((exm->daq_state == running) && + (diff > 16)&& + (first_acquisition==0)) {// we're too late so exit exm->watchdog_exit = 1; printf("exiting, too late to keep up\n"); } first_acquisition=0; - if (diff == 0) { + if ((exm->daq_state == running) && + (diff == 0)) { cnt_diff0++; if (cnt_diff0 == 10) { exm->watchdog_exit = 1; @@ -450,13 +456,19 @@ static void *watchdog_thread(void *arg) { else cnt_diff0=0; - if (exm->ts - exm->last_ts_rx > exm->samples_per_frame) { + if ((exm->daq_state == running) && + (exm->wait_first_read==0) && + (exm->ts - exm->last_ts_rx > exm->samples_per_frame)) { exm->watchdog_exit = 1; - printf("RX Overflow, exiting\n"); + printf("RX Overflow, exiting (TS %llu, TS last read %llu)\n", + exm->ts,exm->last_ts_rx); } // printf("ts %lu, last_ts_rx %lu, mbox %d, diff %d\n",exm->ts, exm->last_ts_rx,mbox,diff); pthread_mutex_unlock(&exm->watchdog_mutex); } + else { + first_acquisition=1; + } rt_sleep(&sleep_time,250000L); } @@ -487,9 +499,10 @@ int trx_exmimo_start(openair0_device *device) { exmimo_state_t *exm=device->priv; printf("Starting ...\n"); + openair0_config(device->openair0_cfg,0); openair0_start_rt_acquisition(0); exm->daq_state = running; - + exm->wait_first_read = 1; return(0); } @@ -498,6 +511,8 @@ int trx_exmimo_write(openair0_device *device,openair0_timestamp ptimestamp, void return(0); } + + int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { exmimo_state_t *exm=device->priv; @@ -505,57 +520,134 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi openair0_timestamp old_ts=0,ts,diff; struct timespec sleep_time; unsigned long tv_nsec; - // int i; + int i; struct timespec wait; + int n,n1,n2,ntot,first_len; + int ret; wait.tv_sec=0; - wait.tv_nsec=5000000L; + wait.tv_nsec=50000000L; if (exm->watchdog_exit == 1) return(0); - pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); - ts = exm->ts; - pthread_mutex_unlock(&exm->watchdog_mutex); - while ((ts < exm->last_ts_rx + nsamps) && - (exm->watchdog_exit==0)) { + if (exm->daq_state == idle) { + tv_nsec=(unsigned long)((double)(nsamps)*1e9/cfg->sample_rate); + return(0); + } + ret = pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); - diff = exm->last_ts_rx+nsamps - ts; // difference in samples between current timestamp and last RX received sample - // go to sleep until we should have enough samples (1024 for a bit more) -#ifdef DEBUG_EXMIMO - printf("Reading %d samples, ts %lu, last_ts_rx %lu (%lu) => sleeping %u us\n",nsamps,ts,exm->last_ts_rx,exm->last_ts_rx+nsamps, - (unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate)); + + switch (ret) { + case EINVAL: +#ifdef DEBUG_EXMIMO + printf("trx_exmimo_read: mutex_timedlock returned EINVAL\n"); #endif - tv_nsec=(unsigned long)((double)(diff+3840)*1e9/cfg->sample_rate); - // tv_nsec = 500000L; - old_ts = ts; - rt_sleep(&sleep_time,tv_nsec); -#ifdef DEBUG_EXMIMO - printf("back\n"); + return(0); + break; + case ETIMEDOUT: +#ifdef DEBUG_EXMIMO + printf("trx_exmimo_read: mutex_timedlock returned ETIMEDOUT\n"); #endif - // get new timestamp, in case we have to sleep again - pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); - ts = exm->ts; - pthread_mutex_unlock(&exm->watchdog_mutex); - if (old_ts == ts) { - printf("ts stopped, returning\n"); - return(0); - } + return(0); + break; + case EAGAIN: +#ifdef DEBUG_EXMIMO + printf("trx_exmimo_read: mutex_timedlock returned EAGAIN\n"); +#endif + return(0); + break; + case EDEADLK: +#ifdef DEBUG_EXMIMO + printf("trx_exmimo_read: mutex_timedlock returned EDEADLK\n"); +#endif + return(0); + break; + } + ts = exm->ts; + if (exm->wait_first_read==1) { + exm->wait_first_read=0; + exm->last_ts_rx = ts; } - /* - if (cfg->mmapped_dma == 0) { // if buff is not the dma buffer, do a memcpy, otherwise do nothing - for (i=0;ilast_ts_rx % exm->samples_per_frame), - nsamps*sizeof(int)); - - } - }*/ + pthread_mutex_unlock(&exm->watchdog_mutex); + // dump_frame_parms(frame_parms[0]); - *ptimestamp=exm->last_ts_rx; - exm->last_ts_rx += nsamps; + if (nsamps > (exm->samples_per_frame>>1)) { + n1 = nsamps>>1; + n2 = nsamps-n1; + } + else { + n1=nsamps; + n2=0; + } + +#ifdef DEBUG_EXMIMO + printf("Reading %d samples, ts %lu (%d), last_ts_rx %lu (%lu)\n",nsamps,ts,ts%exm->samples_per_frame,exm->last_ts_rx,exm->last_ts_rx+nsamps); +#endif + for (n=n1,ntot=0;ntotlast_ts_rx + n) && + (exm->watchdog_exit==0)) { + + diff = exm->last_ts_rx+n - ts; // difference in samples between current timestamp and last RX received sample + // go to sleep until we should have enough samples (1024 for a bit more) +#ifdef DEBUG_EXMIMO + printf("portion %d samples, ts %lu, last_ts_rx %lu (%lu) => sleeping %u us\n",n,ts,exm->last_ts_rx,exm->last_ts_rx+n, + (unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate)); +#endif + tv_nsec=(unsigned long)((double)(diff+3840)*1e9/cfg->sample_rate); + // tv_nsec = 500000L; + old_ts = ts; + rt_sleep(&sleep_time,tv_nsec); +#ifdef DEBUG_EXMIMO + printf("back\n"); +#endif + // get new timestamp, in case we have to sleep again + pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); + ts = exm->ts; + pthread_mutex_unlock(&exm->watchdog_mutex); + if (old_ts == ts) { + printf("ts stopped, returning\n"); + return(0); + } + } + + + + if (cfg->mmapped_dma == 0) { // if buff is not the dma buffer, do a memcpy, otherwise do nothing + for (i=0;ilast_ts_rx % exm->samples_per_frame)); +#endif + if ((n+(exm->last_ts_rx%exm->samples_per_frame))samples_per_frame) { + memcpy(buff[i]+(ntot*sizeof(int)), + (void*)(openair0_exmimo_pci[0].adc_head[i]+(exm->last_ts_rx % exm->samples_per_frame)), + n*sizeof(int)); + } + else { + first_len = (exm->samples_per_frame-(exm->last_ts_rx%exm->samples_per_frame)); +#ifdef DEBUG_EXMIMO + printf("split: first_len %d, remainder %d\n",first_len,n-first_len); +#endif + memcpy(buff[i]+(ntot*sizeof(int)), + (void*)(openair0_exmimo_pci[0].adc_head[i]+(exm->last_ts_rx % exm->samples_per_frame)), + first_len*sizeof(int)); + memcpy(buff[i]+(ntot+first_len)*sizeof(int), + (void*)openair0_exmimo_pci[0].adc_head[i], + (n-first_len)*sizeof(int)); + } + } + } + pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); + exm->last_ts_rx += n; + pthread_mutex_unlock(&exm->watchdog_mutex); + if (n==n1) { + *ptimestamp=exm->last_ts_rx; + } + ntot+=n; + } + + return(nsamps); @@ -582,14 +674,21 @@ int trx_exmimo_reset_stats(openair0_device* device) { } -int trx_exmimo_stop(int card) { +int trx_exmimo_stop(openair0_device* device) { + + exmimo_state_t *exm=device->priv; + + printf("Stopping ...\n"); + exm->daq_state = idle; + openair0_stop(0); return(0); } -int trx_exmimo_set_freq(openair0_device* device, openair0_config_t *openair0_cfg1,int exmimo_dump_config) { +int trx_exmimo_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { + openair0_set_frequencies(device,openair0_cfg,0); return(0); } @@ -663,7 +762,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->openair0_cfg = openair0_cfg; device->priv = (void *)exm; - openair0_config(openair0_cfg,0); + create_watchdog(device); @@ -684,6 +783,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) int resampling_factor=2; int rx_filter=RXLPF25, tx_filter=TXLPF25; int ACTIVE_RF=0; + int i; exmimo_config_t *p_exmimo_config; exmimo_id_t *p_exmimo_id; @@ -713,7 +813,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) /* device specific */ openair0_cfg[card].iq_txshift = 4;//shift openair0_cfg[card].iq_rxrescale = 15;//rescale iqs - openair0_cfg[card].mmapped_dma = 1; + if (openair0_cfg[card].sample_rate==30.72e6) { resampling_factor = 0; @@ -761,6 +861,12 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant]; p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant]; printf("openair0 : programming card %d TX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]); + + printf("Setting TX buffer to all-RX\n"); + + for (i=0;i<307200;i++) { + ((uint32_t*)openair0_exmimo_pci[card].dac_head[ant])[i] = 0x00010001; + } } if (openair0_cfg[card].rx_freq[ant]>0) { @@ -813,7 +919,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) p_exmimo_config->rf.rf_local[ant] = rf_local[ant]; p_exmimo_config->rf.rf_rxdc[ant] = rf_rxdc[ant]; - if (( p_exmimo_config->rf.rf_freq_tx[ant] >= 850000000) && ( p_exmimo_config->rf.rf_freq_tx[ant] <= 865000000)) { + if (( p_exmimo_config->rf.rf_freq_tx[ant] >= 790000000) && ( p_exmimo_config->rf.rf_freq_tx[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 (( p_exmimo_config->rf.rf_freq_tx[ant] >= 1900000000) && ( p_exmimo_config->rf.rf_freq_tx[ant] <= 2000000000)) { @@ -826,7 +932,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) } if (openair0_cfg[card].duplex_mode==duplex_mode_FDD) { - p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD; + p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD;// + TXRXSWITCH_LSB + TXRXSWITCH_LSB + ACTIVE_RF+ ACTIVE_RF; printf("!!!!!setting FDD (tdd_config=%d)\n",p_exmimo_config->framing.tdd_config); } else { @@ -857,6 +963,9 @@ int openair0_reconfig(openair0_config_t *openair0_cfg) return(-1); } +#ifdef DEBUG_EXMIMO + printf("Reconfiguration of gains/frequencies\n"); +#endif for (card=0; cardrf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant]; p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant]; - printf("openair0 : programming TX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]); +#ifdef DEBUG_EXMIMO + printf("openair0 - %d : programming TX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]); +#endif } if (openair0_cfg[card].rx_freq[ant]) { p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant]; p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant]; - printf("openair0 : programming RX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]); - +#ifdef DEBUG_EXMIMO + printf("openair0 - %d : programming RX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]); +#endif switch (openair0_cfg[card].rxg_mode[ant]) { default: case max_gain: diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h index a2f37b09dc..f9428c8519 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.h @@ -58,6 +58,7 @@ typedef struct { struct sched_param watchdog_sched_param; pthread_mutex_t watchdog_mutex; int watchdog_exit; + int wait_first_read; exmimo_daq_state_t daq_state; openair0_timestamp ts; openair0_timestamp last_ts_rx; diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 20a191a06c..d8a65dc2ca 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -377,7 +377,7 @@ int trx_usrp_set_gains(openair0_device* device, /*! \brief Stop USRP * \param card refers to the hardware index to use */ -int trx_usrp_stop(int card) { +int trx_usrp_stop(openair0_device* device) { return(0); } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index eb32a90b9c..c8b8eea760 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1514,6 +1514,11 @@ int main( int argc, char **argv ) for (card=0; cardN_RB_DL == 100) { if (frame_parms[0]->threequarter_fs) { openair0_cfg[card].sample_rate=23.04e6; @@ -1796,14 +1801,7 @@ int main( int argc, char **argv ) exit(-1); } - printf("Setting UE buffer to all-RX\n"); - // Set LSBs for antenna switch (ExpressMIMO) - for (CC_id=0; CC_idsamples_per_tti*10; i++) - for (aa=0; aanb_antennas_tx; aa++) - UE[CC_id]->common_vars.txdata[aa][i] = 0x00010001; - } if (input_fd) { printf("Reading in from file to antenna buffer %d\n",0); @@ -1905,18 +1903,12 @@ int main( int argc, char **argv ) else init_eNB(node_function); // Sleep to allow all threads to setup - sleep(1); + sleep(3); // *** Handle per CC_id openair0 -#ifndef USRP_DEBUG - if ((UE_flag==1) && (mode!=loop_through_memory)) - if (openair0.trx_start_func(&openair0) != 0 ) - LOG_E(HW,"Could not start the device\n"); - -#endif printf("Sending sync to all threads\n"); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index b94c48e734..4fa06f1bc8 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -297,14 +297,7 @@ static void *UE_thread_synch(void *arg) #endif - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_sync_thread)\n"); - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); - - pthread_mutex_unlock(&sync_mutex); - printf("unlocked sync_mutex (UE_sync_thread)\n"); printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch); ind = 0; @@ -344,6 +337,10 @@ static void *UE_thread_synch(void *arg) openair0_cfg[0].rx_freq[i] = downlink_frequency[0][i]; openair0_cfg[0].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i]; openair0_cfg[0].autocal[i] = 1; + if (uplink_frequency_offset[0][i] != 0) // + openair0_cfg[0].duplex_mode = duplex_mode_FDD; + else //FDD + openair0_cfg[0].duplex_mode = duplex_mode_TDD; } sync_mode = pbch; @@ -365,6 +362,19 @@ static void *UE_thread_synch(void *arg) } + if (openair0.trx_start_func(&openair0) != 0 ) { + LOG_E(HW,"Could not start the device\n"); + oai_exit=1; + } + pthread_mutex_lock(&sync_mutex); + printf("Locked sync_mutex, waiting (UE_sync_thread)\n"); + + while (sync_var<0) + pthread_cond_wait(&sync_cond, &sync_mutex); + + pthread_mutex_unlock(&sync_mutex); + printf("Started device, unlocked sync_mutex (UE_sync_thread)\n"); + while (oai_exit==0) { if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { @@ -385,7 +395,7 @@ static void *UE_thread_synch(void *arg) return &UE_thread_synch_retval; } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 1 ); switch (sync_mode) { case pss: @@ -474,11 +484,15 @@ static void *UE_thread_synch(void *arg) break; } - openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0); + //openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0); //openair0.trx_set_gains_func(&openair0,&openair0_cfg[0]); - //openair0.trx_stop_func(0); + openair0.trx_stop_func(&openair0); sleep(1); init_frame_parms(&UE->frame_parms,1); + if (openair0.trx_start_func(&openair0) != 0 ) { + LOG_E(HW,"Could not start the device\n"); + oai_exit=1; + } } else { UE->is_synchronized = 1; @@ -546,7 +560,7 @@ static void *UE_thread_synch(void *arg) openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]+freq_offset; openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]+freq_offset; - openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0); + openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; @@ -554,10 +568,12 @@ static void *UE_thread_synch(void *arg) } } + // openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0); + if (UE->UE_scan_carrier==1) { - for (i=0;iproc.mutex_synch) != 0) { LOG_E( PHY, "[SCHED][UE] error locking mutex for UE synch\n" ); @@ -587,7 +600,7 @@ static void *UE_thread_synch(void *arg) return &UE_thread_synch_retval; } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 ); } // while !oai_exit return &UE_thread_synch_retval; @@ -923,7 +936,11 @@ static void *UE_thread_rxn_txnp4(void *arg) return &UE_thread_rx_retval; } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_UE+(proc->subframe_rx&1), proc->subframe_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_UE+(proc->subframe_tx&1), proc->subframe_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE+(proc->subframe_rx&1), proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE+(proc->subframe_tx&1), proc->frame_tx ); if ((subframe_select( &UE->frame_parms, proc->subframe_rx) == SF_DL) || (UE->frame_parms.frame_type == FDD) || @@ -955,8 +972,8 @@ static void *UE_thread_rxn_txnp4(void *arg) UE->UE_mode[0] = PRACH; } } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 0 ); + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" ); @@ -1114,6 +1131,7 @@ void *UE_thread(void *arg) { for (int i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (void*)&dummy_rx[i][0]; for (int sf=0;sf<10;sf++) { + // printf("Reading dummy sf %d\n",sf); rxs = openair0.trx_read_func(&openair0, ×tamp, rxp, @@ -1164,7 +1182,6 @@ void *UE_thread(void *arg) { }// start_rx_stream==0 else { - // printf("Frame %d, rx_offset %d (diff %d, timer %d)\n",UE->proc.proc_rxtx[0].frame_rx,UE->rx_offset,rx_off_diff,rx_correction_timer); UE->proc.proc_rxtx[0].frame_rx++; UE->proc.proc_rxtx[1].frame_rx++; @@ -1172,6 +1189,7 @@ void *UE_thread(void *arg) { for (int i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (void*)&rxdata[i][UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti)]; // grab signal for subframe + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); if (UE->mode != loop_through_memory) { if (sf<9) { rxs = openair0.trx_read_func(&openair0, @@ -1196,7 +1214,7 @@ void *UE_thread(void *arg) { rx_off_diff = 0; } } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); // operate on thread sf mod 2 UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[sf&1]; @@ -1650,8 +1668,8 @@ void *UE_thread_old(void *arg) /*! * \brief Initialize the UE theads. * Creates the UE threads: - * - UE_thread_tx - * - UE_thread_rx + * - UE_thread_rxtx0 + * - UE_thread_rxtx1 * - UE_thread_synch * and the locking between them. */ @@ -1751,6 +1769,7 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, free( phy_vars_ue[CC_id]->common_vars.rxdata[i] ); rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD + printf("rxdata[%d] : %p\n",i,rxdata[i]); } for (i=0; inb_antennas_tx; i++) { @@ -1758,6 +1777,7 @@ int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, free( phy_vars_ue[CC_id]->common_vars.txdata[i] ); txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i]; + printf("txdata[%d] : %p\n",i,txdata[i]); } // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x] diff --git a/targets/RT/USER/ue_usrp.gtkw b/targets/RT/USER/ue_usrp.gtkw index 81940b5643..becc47ea0b 100644 --- a/targets/RT/USER/ue_usrp.gtkw +++ b/targets/RT/USER/ue_usrp.gtkw @@ -1,12 +1,12 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sun Mar 20 18:27:06 2016 +[*] Sun Jul 17 20:46:59 2016 [*] [dumpfile] "/tmp/openair_dump_UE.vcd" -[dumpfile_mtime] "Sun Mar 20 18:14:17 2016" -[dumpfile_size] 92262400 -[savefile] "/home/papillon/openairinterface5g/targets/RT/USER/ue_usrp.gtkw" -[timestart] 30032830000 +[dumpfile_mtime] "Sun Jul 17 20:46:29 2016" +[dumpfile_size] 10932224 +[savefile] "/home/fourmi/openairinterface5g/targets/RT/USER/ue_usrp.gtkw" +[timestart] 11696930000 [size] 1215 640 [pos] 105 102 *-22.292629 30041590000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 @@ -19,22 +19,25 @@ variables.hw_subframe[63:0] @28 functions.trx_read functions.trx_write +functions.ue_thread_synch +functions.ue_thread_rxtx0 @24 -variables.subframe_number_RX_UE[63:0] -variables.subframe_number_TX_UE[63:0] +variables.subframe_RX0_UE[63:0] +variables.subframe_TX0_UE[63:0] +variables.frame_number_RX0_UE[63:0] +variables.frame_number_TX0_UE[63:0] @28 -functions.ue_thread_rx -functions.ue_thread_tx -@420 -variables.ue_inst_cnt_rx[63:0] -variables.ue_inst_cnt_tx[63:0] +functions.ue_thread_rxtx1 +@24 +variables.subframe_RX1_UE[63:0] +variables.subframe_TX1_UE[63:0] +@25 +variables.frame_number_RX1_UE[63:0] +@24 +variables.frame_number_TX1_UE[63:0] @28 functions.phy_procedures_ue_rx functions.phy_procedures_ue_tx -@24 -variables.frame_number_RX_UE[63:0] -variables.frame_number_TX_UE[63:0] -@28 functions.ue_slot_fep functions.lte_ue_measurement_procedures functions.ue_rrc_measurements From fa4cfad5cb83068957c48e05a552876e006fccaa Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 19 Jul 2016 15:53:19 +0200 Subject: [PATCH 098/206] add mmapped-dma option for lte-softmodem --- targets/RT/USER/lte-softmodem.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index c8b8eea760..eedc641574 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -169,6 +169,7 @@ volatile int oai_exit = 0; static char UE_flag=0; +unsigned int mmapped_dma=0; //static uint8_t eNB_id=0,UE_id=0; static char threequarter_fs=0; @@ -385,11 +386,12 @@ void help (void) { printf(" --ue-txgain set UE TX gain\n"); printf(" --ue-scan_carrier set UE to scan around carrier\n"); printf(" --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n"); + printf(" --mmapped-dma sets flag for improved EXMIMO UE performance\n"); printf(" --RCC run using NGFI RCC node function IF4 split\n"); printf(" --RRU run using NGFI RRU node function IF4 split\n"); printf(" --eNB run using 3GPP eNB node function\n"); printf(" --BBU run using 3GPP eNB node function with IF5 split\n"); - printf(" --RRH run using RRH node function with IF5 split\n"); + printf(" --RRH run using RRH node function with IF5 split\n"); printf(" -C Set the downlink frequency for all component carriers\n"); printf(" -d Enable soft scope and L1 and L2 stats (Xforms)\n"); printf(" -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"); @@ -686,6 +688,7 @@ static void get_options (int argc, char **argv) LONG_OPTION_DUMP_FRAME, LONG_OPTION_LOOPMEMORY, LONG_OPTION_PHYTEST, + LONG_OPTION_MMAPPED_DMA, LONG_OPTION_RCC, LONG_OPTION_RRU, LONG_OPTION_ENB, @@ -714,6 +717,7 @@ static void get_options (int argc, char **argv) {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME}, {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY}, {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST}, + {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA}, {"RCC", no_argument, NULL, LONG_OPTION_RCC}, {"RRU", no_argument, NULL, LONG_OPTION_RRU}, {"eNB", no_argument, NULL, LONG_OPTION_ENB}, @@ -810,6 +814,10 @@ static void get_options (int argc, char **argv) phy_test = 1; break; + case LONG_OPTION_MMAPPED_DMA: + mmapped_dma = 1; + break; + case LONG_OPTION_RCC: node_function = NGFI_RCC_IF4; break; @@ -829,7 +837,7 @@ static void get_options (int argc, char **argv) case LONG_OPTION_RRH: node_function = NGFI_RRU_IF5; break; - + #if T_TRACER case LONG_OPTION_T_PORT: { extern int T_port; @@ -1514,10 +1522,7 @@ int main( int argc, char **argv ) for (card=0; cardN_RB_DL == 100) { if (frame_parms[0]->threequarter_fs) { From bbe47d6fb5765de9bb8fc6270e8973bd9577581b Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 20 Jul 2016 12:55:12 +0200 Subject: [PATCH 099/206] some additions to config files, needs merge --- openair1/PHY/defs.h | 5 ++++ openair2/ENB_APP/enb_config.c | 51 ++++++++++++++++++++++++++++++----- openair2/ENB_APP/enb_config.h | 4 ++- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index e1b2627c09..8232900c9f 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -164,6 +164,11 @@ typedef enum { NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) } eNB_func_t; + +typedef enum { + synch_to_device=0, + synch_to_other +} eNB_timing_t; typedef struct UE_SCAN_INFO_s { /// 10 best amplitudes (linear) for each pss signals diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index d67c6eb6d7..c7a74277bf 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -73,6 +73,9 @@ #define ENB_CONFIG_STRING_COMPONENT_CARRIERS "component_carriers" +#define ENB_CONFIG_STRING_CC_NODE_FUNCTION "node_function" +#define ENB_CONFIG_STRING_CC_NODE_TIMING "node_timing" + #define ENB_CONFIG_STRING_FRAME_TYPE "frame_type" #define ENB_CONFIG_STRING_TDD_CONFIG "tdd_config" #define ENB_CONFIG_STRING_TDD_CONFIG_S "tdd_config_s" @@ -316,6 +319,10 @@ void enb_config_display(void) } for (j=0; j< enb_properties.properties[i]->nb_cc; j++) { + // CC_ID node function/timing + printf( "\tnode_function for CC %d:\t%d:\n",j,enb_properties.properties[i]->cc_node_function[j]); + printf( "\tnode_timing for CC %d:\t%d:\n",j,enb_properties.properties[i]->cc_node_timing[j]); + printf( "\teutra band for CC %d: \t%"PRId16":\n",j,enb_properties.properties[i]->eutra_band[j]); printf( "\tdownlink freq for CC %d: \t%"PRIu64":\n",j,enb_properties.properties[i]->downlink_frequency[j]); printf( "\tuplink freq offset for CC %d: \t%"PRId32":\n",j,enb_properties.properties[i]->uplink_frequency_offset[j]); @@ -324,7 +331,7 @@ void enb_config_display(void) printf( "\tN_RB_DL for CC %d:\t%"PRId16":\n",j,enb_properties.properties[i]->N_RB_DL[j]); printf( "\tnb_antennas_tx for CC %d:\t%d:\n",j,enb_properties.properties[i]->nb_antennas_tx[j]); printf( "\tnb_antennas_rx for CC %d:\t%d:\n",j,enb_properties.properties[i]->nb_antennas_rx[j]); - + // RACH-Config printf( "\trach_numberOfRA_Preambles for CC %d:\t%ld:\n",j,enb_properties.properties[i]->rach_numberOfRA_Preambles[j]); printf( "\trach_preamblesGroupAConfig for CC %d:\t%d:\n",j,enb_properties.properties[i]->rach_preamblesGroupAConfig[j]); @@ -409,17 +416,17 @@ void enb_config_display(void) printf( "\tue_TimersAndConstants_t310 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_t310[j]); printf( "\tue_TimersAndConstants_n310 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n310[j]); printf( "\tue_TimersAndConstants_t311 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_t311[j]); - printf( "\tue_TimersAndConstants_n311 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n311[j]); + printf( "\tue_TimersAndConstants_n311 for CC %d:\t%ld:\n\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n311[j]); } for (j=0; j < enb_properties.properties[i]->num_otg_elements; j++) { - printf( "\n\tOTG Destination UE ID: \t%"PRIu16, enb_properties.properties[i]->otg_ue_id[j]); + printf( "\tOTG Destination UE ID: \t%"PRIu16, enb_properties.properties[i]->otg_ue_id[j]); printf( "\n\tOTG App Type: \t%"PRIu8, enb_properties.properties[i]->otg_app_type[j]); printf( "\n\tOTG Background Traffic: \t%s\n", (enb_properties.properties[i]->otg_bg_traffic[j]==1) ? "Enabled" : "Disabled"); } - printf( "\n\tGlobal log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->glog_level)); + printf( "\tGlobal log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->glog_level)); printf( "\tHW log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->hw_log_level)); printf( "\tPHY log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->phy_log_level)); printf( "\tMAC log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->mac_log_level)); @@ -511,6 +518,10 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) int j = 0; int parse_errors = 0; libconfig_int enb_id = 0; + + const char* cc_node_function = NULL; + const char* cc_node_timing = NULL; + const char* cell_type = NULL; const char* tac = 0; const char* enb_name = NULL; @@ -787,7 +798,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) component_carrier = config_setting_get_elem(setting_component_carriers, j); //printf("Component carrier %d\n",component_carrier); - if (!(config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_FRAME_TYPE, &frame_type) + if (!(config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_CC_NODE_FUNCTION, &cc_node_function) + && config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_CC_NODE_TIMING, &cc_node_timing) + && config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_FRAME_TYPE, &frame_type) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_TDD_CONFIG, &tdd_config) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_TDD_CONFIG_S, &tdd_config_s) && config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_PREFIX_TYPE, &prefix_type) @@ -865,6 +878,32 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->nb_cc++; + if (strcmp(cc_node_function, "eNodeB_3GPP") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = eNodeB_3GPP; + } else if (strcmp(cc_node_function, "eNodeB_3GPP_BBU") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = eNodeB_3GPP_BBU; + } else if (strcmp(cc_node_function, "NGFI_RCC_IF4") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RCC_IF4; + } else if (strcmp(cc_node_function, "NGFI_RRU_IF4") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF4; + } else if (strcmp(cc_node_function, "NGFI_RRU_IF5") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF5; + } else { + AssertError (0, parse_errors ++, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for node_function choice: eNodeB_3GPP or eNodeB_3GPP_BBU or NGFI_IF4_RCC or NGFI_IF4_RRU or NGFI_IF5_RRU !\n", + lib_config_file_name_pP, i, cc_node_function); + } + + if (strcmp(cc_node_timing, "SYNCH_TO_DEVICE") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_device; + } else if (strcmp(cc_node_timing, "SYNCH_TO_OTHER") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_other; + } else { + AssertError (0, parse_errors ++, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for node_function choice: SYNCH_TO_DEVICE or SYNCH_TO_OTHER !\n", + lib_config_file_name_pP, i, cc_node_timing); + } + enb_properties.properties[enb_properties_index]->tdd_config[j] = tdd_config; AssertError (tdd_config <= TDD_Config__subframeAssignment_sa6, parse_errors ++, "Failed to parse eNB configuration file %s, enb %d illegal tdd_config %d (should be 0-%d)!", @@ -888,7 +927,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for prefix_type choice: NORMAL or EXTENDED !\n", lib_config_file_name_pP, i, prefix_type); } - + enb_properties.properties[enb_properties_index]->eutra_band[j] = eutra_band; enb_properties.properties[enb_properties_index]->downlink_frequency[j] = (uint32_t) downlink_frequency; enb_properties.properties[enb_properties_index]->uplink_frequency_offset[j] = (unsigned int) uplink_frequency_offset; diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 716d400178..3feeb5e828 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -45,6 +45,7 @@ #include "platform_types.h" #include "platform_constants.h" #include "PHY/impl_defs_lte.h" +#include "PHY/defs.h" #include "s1ap_messages_types.h" #ifdef CMAKER #include "SystemInformationBlockType2.h" @@ -129,6 +130,8 @@ typedef struct Enb_properties_s { /* Physical parameters */ int16_t nb_cc; + eNB_func_t cc_node_function[1+MAX_NUM_CCs]; + eNB_timing_t cc_node_timing[1+MAX_NUM_CCs]; lte_frame_type_t frame_type[1+MAX_NUM_CCs]; uint8_t tdd_config[1+MAX_NUM_CCs]; uint8_t tdd_config_s[1+MAX_NUM_CCs]; @@ -202,7 +205,6 @@ typedef struct Enb_properties_s { long ue_TimersAndConstants_n310[1+MAX_NUM_CCs]; long ue_TimersAndConstants_n311[1+MAX_NUM_CCs]; - long srb1_timer_poll_retransmit; long srb1_timer_reordering; long srb1_timer_status_prohibit; From 07b3a0a9d10689bd77f29ff7835657b1460e632b Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 20 Jul 2016 19:56:17 +0200 Subject: [PATCH 100/206] prach data seems ok but no rx yet --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 2 +- openair1/PHY/LTE_TRANSPORT/prach.c | 36 ++++++++++++++++++++++++- openair1/SCHED/phy_procedures_lte_eNb.c | 9 +++---- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 0fb5404538..572bcd73b7 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -139,7 +139,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, gen_IF4_prach_header(prach_header, frame, subframe); memcpy((int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t), - (&rxsigF[0][0]+k), + (&rxsigF[0][k]), db_fulllength*sizeof(int16_t)); if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 4634be7321..752aee11cd 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1104,7 +1104,12 @@ void rx_prach(PHY_VARS_eNB *eNB, for (aa=0; aacommon_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_tti-eNB->N_TA_offset]; } - + + int energy = dB_fixed(signal_energy(prach[0], eNB->frame_parms.samples_per_tti)); + //if (energy >= 45) { + // printf("prach subframe energy %d\n",energy); + //} + // First compute physical root sequence if (restricted_set == 0) { if (Ncs_config>15) { @@ -1285,7 +1290,36 @@ void rx_prach(PHY_VARS_eNB *eNB, send_IF4(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4_PRACH, k); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + energy = dB_fixed(signal_energy(&rxsigF[0][k], 839)); + if (energy >=45) { + printf(" prach freq-domain energy %d\n",eNB->proc.frame_rx, energy); + //write_output("beforecomp.m","rxF",&rxsigF[0][k],839*2,1,0); + //exit(1); + } + return; + } else if (eNB->node_function == NGFI_RCC_IF4) { + k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; + + if (k<0) { + k+=(eNB->frame_parms.ofdm_symbol_size); + } + + k*=12; + k+=13; + k*=2; + + // Adjust received rxsigF offset + memmove((&rxsigF[0][k]), + (&rxsigF[0][0]), + 839*2*sizeof(int16_t)); + + energy = dB_fixed(signal_energy(&rxsigF[0][k], 839)); + if (energy >=45) { + printf(" prach freq-domain energy %d\n",eNB->proc.frame_rx, energy); + //write_output("aftercomp.m","rxF",&rxsigF[0][k],839*2,1,0); + //exit(1); + } } // in case of RCC and prach received rx_thread wakes up prach diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 79a6a1d0b7..9262afcdb9 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2641,11 +2641,12 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); - if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)<=0) { + if (eNB->node_function == NGFI_RRU_IF4) { /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - send_IF4(eNB, frame, subframe, IF4_PULFFT, 0); + send_IF4(eNB, proc->frame_rx, proc->subframe_rx, IF4_PULFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + } /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) @@ -2735,7 +2736,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } } - } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); + } while(symbol_mask != symbol_mask_full); if (proc->first_rx == 0) { if (proc->subframe_rx != subframe){ @@ -2753,8 +2754,6 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); - - // Tobi aka mr monaco: ETH } else { // should not get here AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); From af489a783bbe378a2025af1721c9aff0bb60c31f Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 20 Jul 2016 16:32:38 -0700 Subject: [PATCH 101/206] addition of asynchronous RX threads and inter CC synchronization --- openair1/PHY/defs.h | 61 ++-- openair1/SCHED/phy_procedures_lte_eNb.c | 237 +++----------- targets/RT/USER/lte-enb.c | 405 +++++++++++++++++++----- targets/SIMU/USER/oaisim_functions.c | 11 - 4 files changed, 408 insertions(+), 306 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index e1b2627c09..e280b3f625 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -165,6 +165,12 @@ typedef enum { NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) } eNB_func_t; +typedef enum { + synch_to_ext_device=0, // synch to RF or Ethernet device + synch_to_other // synch to another source (timer, other CC_id) +} eNB_timing_t; + + typedef struct UE_SCAN_INFO_s { /// 10 best amplitudes (linear) for each pss signals int32_t amp[3][10]; @@ -211,7 +217,7 @@ typedef struct { struct sched_param sched_param_rxtx; } eNB_rxtx_proc_t; /// Context data structure for eNB subframe processing -typedef struct { +typedef struct eNB_proc_t_s { /// Component Carrier index uint8_t CC_id; /// thread index @@ -226,29 +232,46 @@ typedef struct { int frame_rx; /// frame to act upon for PRACH int frame_prach; + /// \brief Instance count for FH processing thread. + /// \internal This variable is protected by \ref mutex_FH. + int instance_cnt_FH; /// \brief Instance count for rx processing thread. /// \internal This variable is protected by \ref mutex_prach. int instance_cnt_prach; - /// pthread structure for rx processing thread - pthread_t pthread_rx; + /// pthread structure for FH processing thread + pthread_t pthread_FH; + /// pthread structure for asychronous RX processing thread + pthread_t pthread_asynch_rx; /// flag to indicate first RX acquisition int first_rx; - /// pthread attributes for rx processing thread - pthread_attr_t attr_rx; + /// pthread attributes for FH processing thread + pthread_attr_t attr_FH; /// pthread attributes for prach processing thread pthread_attr_t attr_prach; - /// scheduling parameters for rx thread - struct sched_param sched_param_rx; + /// pthread attributes for asynchronous RX thread + pthread_attr_t attr_asynch_rx; + /// scheduling parameters for FH thread + struct sched_param sched_param_FH; /// scheduling parameters for prach thread struct sched_param sched_param_prach; - /// condition variable for prach processing thread + /// scheduling parameters for asynch_rx thread + struct sched_param sched_param_asynch_rx; + /// condition variable for FH thread pthread_t pthread_prach; - /// condition variable for rx processing thread; + /// condition variable for FH thread + pthread_cond_t cond_FH; + /// condition variable for PRACH processing thread; pthread_cond_t cond_prach; - /// mutex for tx processing thread + /// mutex for FH + pthread_mutex_t mutex_FH; + /// mutex for PRACH thread pthread_mutex_t mutex_prach; /// set of scheduling variables RXn-TXnp4 threads eNB_rxtx_proc_t proc_rxtx[2]; + /// number of slave threads + int num_slaves; + /// array of pointers to slaves + struct eNB_proc_t_s **slave_proc; } eNB_proc_t; @@ -311,6 +334,7 @@ typedef struct PHY_VARS_eNB_s { uint8_t CC_id; eNB_proc_t proc; eNB_func_t node_function; + eNB_timing_t node_timing; uint8_t local_flag; uint32_t rx_total_gain_dB; LTE_DL_FRAME_PARMS frame_parms; @@ -456,11 +480,6 @@ typedef struct PHY_VARS_eNB_s { time_stats_t phy_proc; time_stats_t phy_proc_tx; time_stats_t phy_proc_rx; - /* - time_stats_t phy_proc_sf[10]; // for each subframe - time_stats_t phy_proc_tx_sf[10]; - time_stats_t phy_proc_rx_sf[10]; - */ time_stats_t rx_prach; time_stats_t ofdm_mod_stats; @@ -505,11 +524,6 @@ typedef struct PHY_VARS_eNB_s { int32_t pusch_stats_mcs[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240]; -#if ENABLE_RAL - hash_table_t *ral_thresholds_timed; - SLIST_HEAD(ral_thresholds_gen_poll_enb_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX]; - SLIST_HEAD(ral_thresholds_lte_poll_enb_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; -#endif /// RF and Interface devices per CC openair0_device rfdevice; @@ -520,13 +534,6 @@ typedef struct PHY_VARS_eNB_s { } PHY_VARS_eNB; #define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg -//#define debug_msg msg - -/* -typedef enum { - max_gain=0,med_gain,byp_gain -} rx_gain_t; -*/ /// Top-level PHY Data Structure for UE typedef struct { diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 653b5aeb1e..1a1c2f4ad0 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2519,29 +2519,17 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl int i,l; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - void *rxp[fp->nb_antennas_rx]; - unsigned int rxs; + eNB_proc_t *proc = &eNB->proc; int subframe = proc->subframe_rx; int frame = proc->frame_rx; - int prach_rx; - uint8_t seqno=0; - uint16_t packet_type; - uint32_t symbol_number=0; - uint32_t symbol_mask, symbol_mask_full; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); - if (subframe==9) { - subframe=0; - frame++; - frame&=1023; - } else { - subframe++; - } + - // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_COMMON_RX,1); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC @@ -2549,77 +2537,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl #endif if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) - - if ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == NGFI_RRU_IF5) || - (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF - for (i=0; inb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, - &proc->timestamp_rx, - rxp, - fp->samples_per_tti, - fp->nb_antennas_rx); - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; - proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - - if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - exit_fun("Exiting"); - } - if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - } - - // printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); - - if (rxs != fp->samples_per_tti) - exit_fun( "problem receiving samples" ); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - - } else if(eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF - /// **** recv_IF5 of rxdata from RRH **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; - proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - - if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - //exit_fun("Exiting"); - } - if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - //exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); - } - if ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == eNodeB_3GPP) || - (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing + (eNB->node_function == eNodeB_3GPP) || + (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing // now do common RX processing for first slot in subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); @@ -2641,131 +2563,61 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl 0 ); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); - if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)<=0) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); + + if (eNB->node_function == NGFI_RRU_IF4) { /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(eNB, frame, subframe, IF4_PULFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); } - /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) - // check if we have to detect PRACH first - if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) { - // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); - exit_fun( "error locking mutex_prach" ); - return; - } - - int cnt_prach = ++proc->instance_cnt_prach; - // set timing for prach thread - proc->frame_prach = proc->frame_rx; - proc->subframe_prach = proc->subframe_rx; - - pthread_mutex_unlock( &proc->mutex_prach ); - - if (cnt_prach == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - } else { - LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach); - exit_fun( "PRACH thread busy" ); - return; - } - } - } else if (eNB->node_function == NGFI_RRU_IF5) { + } + else if (eNB->node_function == NGFI_RRU_IF5) { /// **** send_IF5 of rxdata to BBU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); - - } else if (eNB->node_function == NGFI_RCC_IF4) { - /// **** recv_IF4 of rxdataF from RRU **** /// - /// **** recv_IF4 of rxsigF from RRU **** /// - // get frame/subframe information from IF4 interface - // timed loop (200 us) - - symbol_number = 0; - symbol_mask = 0; - symbol_mask_full = (1<symbols_per_tti)-1; - prach_rx = 0; - - do { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); - - if (packet_type == IF4_PULFFT) { - symbol_mask = symbol_mask | (1<mutex_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); - exit_fun( "error locking mutex_prach" ); - return; - } - - int cnt_prach = ++proc->instance_cnt_prach; - // set timing for prach thread - proc->frame_prach = proc->frame_rx; - proc->subframe_prach = proc->subframe_rx; - - pthread_mutex_unlock( &proc->mutex_prach ); - - if (cnt_prach == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame); - exit_fun( "PRACH thread busy" ); - return; - } - } - - } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); - - if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - //exit_fun("Exiting"); - } - if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - //exit_fun("Exiting"); - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); + } + + /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) + // check if we have to detect PRACH first + if ((eNB->node_function != NGFI_RRU_IF5) && + (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0)) { // any other node must call prach procedure + // wake up thread for PRACH RX + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); + exit_fun( "error locking mutex_prach" ); + return; + } + + int cnt_prach = ++proc->instance_cnt_prach; + // set timing for prach thread + proc->frame_prach = proc->frame_rx; + proc->subframe_prach = proc->subframe_rx; + + pthread_mutex_unlock( &proc->mutex_prach ); + + if (cnt_prach == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } } else { - proc->first_rx = 0; + LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach); + exit_fun( "PRACH thread busy" ); + return; } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); - - // Tobi aka mr monaco: ETH - - } else { // should not get here - AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); } - } else { // grab transport channel information from network interface } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); } @@ -2784,7 +2636,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); @@ -3346,7 +3198,8 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const phy_procedures_emos_eNB_RX(subframe,eNB); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); + stop_meas(&eNB->phy_proc_rx); } diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index bb00aced66..c16fbb5e8d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -435,14 +435,16 @@ static void* eNB_thread_rxtx( void* param ) { if (oai_exit) break; + // Common procedures + phy_procedures_eNB_common_RX(PHY_vars_eNB_g[0][proc->CC_id], 0); + // UE-specific RX processing for subframe n if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) || (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); + // this is the ue-specific processing for the subframe and can be multi-threaded later phy_procedures_eNB_uespec_RX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); } // TX processing for subframe n+4 @@ -629,23 +631,122 @@ static void wait_system_ready (char *message, volatile int *start_flag) { } #endif - /*! - * \brief The RX common thread of eNB. + * \brief The Asynchronous RX FH thread of RAU/RCC/eNB. + * This handles the RX FH for an asynchronous RRU/UE * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_rx_common( void* param ) { - - static int eNB_thread_rx_status; +static void* eNB_thread_asynch_rx( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + openair0_timestamp timestamp_rx; + int frame_rx,subframe_rx; + int first_rx = 1; + uint16_t packet_type; + uint32_t symbol_number=0; + uint32_t symbol_mask, symbol_mask_full; + int prach_rx; + + if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF + /// **** recv_IF5 of rxdata from RRH **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); + recv_IF5(eNB, ×tamp_rx, subframe_rx++, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); + if (first_rx == 1) { + first_rx = 0; + subframe_rx = (timestamp_rx/fp->samples_per_tti)%10; + } + else { + // check timestamp + if ((timestamp_rx - proc->timestamp_rx) < (2*fp->samples_per_tti)) + printf("RX overflow ...\n"); + + } + } // eNodeB_3GPP_BBU + else if (eNB->node_function == NGFI_RCC_IF4) { + /// **** recv_IF4 of rxdataF from RRU **** /// + /// **** recv_IF4 of rxsigF from RRU **** /// + // get frame/subframe information from IF4 interface + // timed loop (200 us) + + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<symbols_per_tti)-1; + prach_rx = 0; + + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); + recv_IF4(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); + + if (packet_type == IF4_PULFFT) { + symbol_mask = symbol_mask | (1<first_rx == 0) { + if (subframe_rx < proc->subframe_rx+2){ + LOG_E(PHY,"RX overflow (proc->subframe_rx %d, subframe_rx %d)\n",proc->subframe_rx,subframe_rx); + } + } else { + proc->first_rx = 0; + } + } // node_timing == synch_to_externs, node_function = NGFI_IF4 + else { // should not get here + AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); + } + +} + +/*! + * \brief The Fronthaul thread of RRU/RAU/RCC/eNB + * In the case of RRU/eNB, handles interface with external RF + * In the case of RAU/RCC, handles fronthaul interface with RRU/RAU + * \param param is a \ref eNB_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +static void* eNB_thread_FH( void* param ) { + + static int eNB_thread_FH_status; + + eNB_proc_t *proc = (eNB_proc_t*)param; + PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + void *rxp[fp->nb_antennas_rx]; + unsigned int rxs; FILE *rx_time_file = NULL; char rx_time_name[101]; struct timespec wait; + int i; + int prach_rx; + + + + uint16_t packet_type; + uint32_t symbol_number=0; + uint32_t symbol_mask, symbol_mask_full; + + int subframe = proc->subframe_rx; + int frame = proc->frame_rx; + if (subframe==9) { + subframe=0; + frame++; + frame&=1023; + } else { + subframe++; + } wait.tv_sec=0; wait.tv_nsec=5000000L; @@ -655,7 +756,7 @@ static void* eNB_thread_rx_common( void* param ) { rx_time_file = fopen(rx_time_name,"w"); } // set default return value - eNB_thread_rx_status = 0; + eNB_thread_FH_status = 0; MSC_START_USE(); @@ -678,7 +779,7 @@ static void* eNB_thread_rx_common( void* param ) { if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB RX sched_setattr failed\n"); - return &eNB_thread_rx_status; + return &eNB_thread_FH_status; } LOG_I( HW, "[SCHED] eNB RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); @@ -796,32 +897,205 @@ static void* eNB_thread_rx_common( void* param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); - start_meas( &softmodem_stats_rx_sf ); if (oai_exit) break; - if ((((fp->frame_type == TDD )&&(subframe_select(fp,proc->subframe_rx)==SF_UL)) || - (fp->frame_type == FDD))) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); - // this spawns the prach inside and updates the frame and subframe counters - phy_procedures_eNB_common_RX(eNB, 0); + + if ((eNB->node_timing == synch_to_other) && + ((eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == NGFI_RRU_IF5) || + (eNB->node_function == eNodeB_3GPP))) { // This case is for synchronization to another thread + //wait for event + + // how long should we wait here, for MOBIPASS this could be long + // if (pthread_mutex_timedlock(&proc->mutex_FH,&wait) != 0) { + if (pthread_mutex_lock(&proc->mutex_FH) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH\n"); + exit_fun( "error locking mutex" ); + break; + } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); + while (proc->instance_cnt_FH < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_prach is -1 + pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); // this unlocks mutex_rxtx while waiting and then locks it again + } + + proc->instance_cnt_FH++; + + + } + // Remaining cases are all for synchronization on FH interface + else if ((eNB->node_timing == synch_to_ext_device) && + ((eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == NGFI_RRU_IF5) || + (eNB->node_function == eNodeB_3GPP))) { // acquisition from RF + + for (i=0; inb_antennas_rx; i++) + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); + + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, + &proc->timestamp_rx, + rxp, + fp->samples_per_tti, + fp->nb_antennas_rx); + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + + + if (proc->first_rx == 0) { + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + exit_fun("Exiting"); + } + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + } + + // printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); + + if (rxs != fp->samples_per_tti) + exit_fun( "problem receiving samples" ); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + + } // node_timing==synch_to_ext_device && node_function == RRU || eNodeB + else if ((eNB->node_timing == synch_to_ext_device) && + (eNB->node_function == eNodeB_3GPP_BBU)) { // acquisition from IF + /// **** recv_IF5 of rxdata from RRH **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); + recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); + + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + + if (proc->first_rx == 0) { + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + //exit_fun("Exiting"); + } + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + //exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); + } // eNodeB_3GPP_BBU && node_timing == synch_to_ext_device + + else if ((eNB->node_timing == synch_to_ext_device) && + (eNB->node_function == NGFI_RCC_IF4)) { + /// **** recv_IF4 of rxdataF from RRU **** /// + /// **** recv_IF4 of rxsigF from RRU **** /// + // get frame/subframe information from IF4 interface + // timed loop (200 us) + + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<symbols_per_tti)-1; + prach_rx = 0; + + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); + recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); + + if (packet_type == IF4_PULFFT) { + symbol_mask = symbol_mask | (1<first_rx == 0) { + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + //exit_fun("Exiting"); + } + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + //exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); + + + } // node_timing == synch_to_externs, node_function = NGFI_IF4 + else { // should not get here + AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); } + // At this point, all information for subframe has been received on FH interface + // If this proc is to provide synchronization, do so + for (i=0;inum_slaves;i++) { + eNB_proc_t *slave_proc = proc->slave_proc[i]; + // wake up slave FH thread + // lock the FH mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d (IC %d)\n",proc->CC_id,slave_proc->CC_id); + exit_fun( "error locking mutex_rxtx" ); + break; + } + int cnt_slave = ++slave_proc->instance_cnt_FH; + slave_proc->frame_rx = proc->frame_rx; + slave_proc->subframe_rx = proc->subframe_rx; + slave_proc->timestamp_rx = proc->timestamp_rx; + + pthread_mutex_unlock( &slave_proc->mutex_FH ); + + if (cnt_slave == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&slave_proc->cond_FH) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB CCid %d, slave CCid %d\n",proc->CC_id,slave_proc->CC_id); + exit_fun( "ERROR pthread_cond_signal" ); + break; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_rxtx %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); + exit_fun( "TX thread busy" ); + break; + } + } + + // wake up RXn_TXnp4 thread for the subframe // choose even or odd thread for RXn-TXnp4 processing eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[proc->subframe_rx&1]; // wake up TX for subframe n+4 // lock the TX mutex and make sure the thread is ready if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc_rxtx->instance_cnt_rxtx ); + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx ); exit_fun( "error locking mutex_rxtx" ); break; } int cnt_rxtx = ++proc_rxtx->instance_cnt_rxtx; + // We have just received and processed the common part of a subframe, say n. // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). @@ -865,12 +1139,20 @@ static void* eNB_thread_rx_common( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); } - - printf( "Exiting eNB thread rx_common\n"); + if (eNB->node_timing == synch_to_ext_device) { + proc->instance_cnt_FH--; + + if (pthread_mutex_unlock(&proc->mutex_FH) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for FH\n"); + exit_fun( "error unlocking mutex" ); + } + } + + printf( "Exiting FH thread \n"); - eNB_thread_rx_status = 0; - return &eNB_thread_rx_status; + eNB_thread_FH_status = 0; + return &eNB_thread_FH_status; } @@ -1070,9 +1352,9 @@ void init_eNB_proc(void) { pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); - proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_rx, &proc->sched_param_rx); - pthread_attr_setschedpolicy (&proc->attr_rx, SCHED_FIFO); + proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_FH, &proc->sched_param_FH); + pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO); proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); @@ -1083,6 +1365,7 @@ void init_eNB_proc(void) { proc_rxtx[0].instance_cnt_rxtx = -1; proc_rxtx[1].instance_cnt_rxtx = -1; proc->instance_cnt_prach = -1; + proc->instance_cnt_FH = -1; proc->CC_id = CC_id; proc->first_rx=4; @@ -1093,24 +1376,30 @@ void init_eNB_proc(void) { pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); pthread_cond_init( &proc->cond_prach, NULL); + pthread_cond_init( &proc->cond_FH, NULL); #ifndef DEADLINE_SCHEDULER pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); - pthread_create( &proc->pthread_rx, &proc->attr_rx, eNB_thread_rx_common, &eNB->proc ); + pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); + if (eNB->node_timing == synch_to_other) + pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc ); #else pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); - pthread_create( &proc->pthread_rx, NULL, eNB_thread_rx_common, &eNB->proc ); + pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); + if (eNB->node_timing == synch_to_other) + pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc ); + #endif char name[16]; snprintf( name, sizeof(name), "RXTX0 %d", i ); pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); snprintf( name, sizeof(name), "RXTX1 %d", i ); pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); - snprintf( name, sizeof(name), "RX %d", i ); - pthread_setname_np( proc->pthread_rx, name ); + snprintf( name, sizeof(name), "FH %d", i ); + pthread_setname_np( proc->pthread_FH, name ); } /* setup PHY proc TX sync mechanism */ @@ -1142,63 +1431,27 @@ void kill_eNB_proc(void) { proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race! proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race! proc->instance_cnt_prach = 0; + proc->instance_cnt_FH = 0; pthread_cond_signal( &proc_rxtx[0].cond_rxtx ); pthread_cond_signal( &proc_rxtx[1].cond_rxtx ); pthread_cond_signal( &proc->cond_prach ); + pthread_cond_signal( &proc->cond_FH ); pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); - pthread_join( proc->pthread_rx, (void**)&status ); + pthread_join( proc->pthread_FH, (void**)&status ); + pthread_mutex_destroy( &proc->mutex_FH ); + pthread_cond_destroy( &proc->cond_FH ); + + pthread_join( proc->pthread_prach, (void**)&status ); + pthread_mutex_destroy( &proc->mutex_prach ); + pthread_cond_destroy( &proc->cond_prach ); - - int result,i; + int i; for (i=0;i<2;i++) { pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status ); - -#ifdef DEBUG_THREADS - - if (result != 0) { - printf( "Error joining thread.\n" ); - } else { - if (status) { - printf( "status %d\n", *status ); - } else { - printf( "The thread was killed. No status available.\n" ); - } - } -#else - UNUSED(result); -#endif - pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx ); pthread_cond_destroy( &proc_rxtx[i].cond_rxtx ); } - -#ifdef DEBUG_THREADS - printf( "Killing RX CC_id %d thread\n", CC_id); -#endif - -#ifdef DEBUG_THREADS - printf( "Joining eNB RX CC_id %d thread ...\n", CC_id); -#endif - - result = pthread_join( proc->pthread_rx, (void**)&status ); - -#ifdef DEBUG_THREADS - if (result != 0) { - printf( "Error joining thread.\n" ); - } else { - if (status) { - printf( "status %d\n", *status ); - } else { - printf( "The thread was killed. No status available.\n" ); - } - } -#else - UNUSED(result); -#endif - - pthread_mutex_destroy( &proc->mutex_prach ); - pthread_cond_destroy( &proc->cond_prach ); } } diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 5a970ca038..867d578ce9 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -1166,17 +1166,6 @@ void init_ocm(void) LOG_D(OCM,"Initializing channel (%s, %d) from eNB %d to UE %d\n", oai_emulation.environment_system_config.fading.small_scale.selected_option, map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option), eNB_id, UE_id); - /* if (oai_emulation.info.transmission_mode == 5) - eNB2UE[eNB_id][UE_id] = new_channel_desc_scm(PHY_vars_eNB_g[eNB_id]->frame_parms.nb_antennas_tx, - PHY_vars_UE_g[UE_id]->frame_parms.nb_antennas_rx, - (UE_id == 0)? Rice1_corr : Rice1_anticorr, - oai_emulation.environment_system_config.system_bandwidth_MB, - forgetting_factor, - 0, - 0); - - else - */ eNB2UE[eNB_id][UE_id][CC_id] = new_channel_desc_scm(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_tx, From 6a120cf286dd36b3f2d1a906ade8aea349629021 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 22 Jul 2016 15:40:47 +0200 Subject: [PATCH 102/206] fixes for reading cc_synch --- openair1/PHY/defs.h | 8 ------- openair2/ENB_APP/enb_config.c | 40 +++++++++++++++++++++++------------ openair2/ENB_APP/enb_config.h | 1 + 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 4c46674ecb..f876860a55 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -170,7 +170,6 @@ typedef enum { synch_to_other // synch to another source (timer, other CC_id) } eNB_timing_t; - typedef struct UE_SCAN_INFO_s { /// 10 best amplitudes (linear) for each pss signals int32_t amp[3][10]; @@ -800,11 +799,4 @@ typedef struct { #include "SIMULATION/ETH_TRANSPORT/defs.h" #endif //OPENAIR_LTE - #endif // __PHY_DEFS__H__ - - - - - - diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index c1de6a7935..35d02f8842 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -74,7 +74,8 @@ #define ENB_CONFIG_STRING_COMPONENT_CARRIERS "component_carriers" #define ENB_CONFIG_STRING_CC_NODE_FUNCTION "node_function" -#define ENB_CONFIG_STRING_CC_NODE_TIMING "node_timing" +#define ENB_CONFIG_STRING_CC_NODE_TIMING "node_timing" +#define ENB_CONFIG_STRING_CC_NODE_SYNCH_REF "node_synch_ref" #define ENB_CONFIG_STRING_FRAME_TYPE "frame_type" #define ENB_CONFIG_STRING_TDD_CONFIG "tdd_config" @@ -303,25 +304,26 @@ void enb_config_display(void) printf( "\tiq_txshift : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].iq_txshift); printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : (enb_properties.properties[i]->rrh_gw_config[j].rawif4 == 1)? "RAW_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].udpif4 == 1)? "UDP_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].rawif5_mobipass == 1)? "RAW_IF5_MOBIPASS" : "UDP"); if (enb_properties.properties[i]->rrh_gw_config[j].exmimo == 1) { - printf( "\tRF target : \tEXMIMO:\n\n"); + printf( "\tRF target : \tEXMIMO:\n"); } else if (enb_properties.properties[i]->rrh_gw_config[j].usrp_b200 == 1) { - printf( "\tRF target : \tUSRP_B200:\n\n"); + printf( "\tRF target : \tUSRP_B200:\n"); } else if (enb_properties.properties[i]->rrh_gw_config[j].usrp_x300 == 1) { - printf( "\tRF target : \tUSRP_X300:\n\n"); + printf( "\tRF target : \tUSRP_X300:\n"); } else if (enb_properties.properties[i]->rrh_gw_config[j].bladerf == 1) { - printf( "\tRF target : \tBLADERF:\n\n"); + printf( "\tRF target : \tBLADERF:\n"); } else if (enb_properties.properties[i]->rrh_gw_config[j].lmssdr == 1) { - printf( "\tRF target : \tLMSSDR:\n\n"); + printf( "\tRF target : \tLMSSDR:\n"); } else { - printf( "\tRF target : \tNONE:\n\n"); + printf( "\tRF target : \tNONE:\n"); } } } for (j=0; j< enb_properties.properties[i]->nb_cc; j++) { // CC_ID node function/timing - printf( "\tnode_function for CC %d:\t%d:\n",j,enb_properties.properties[i]->cc_node_function[j]); - printf( "\tnode_timing for CC %d:\t%d:\n",j,enb_properties.properties[i]->cc_node_timing[j]); + printf( "\n\tnode_function for CC %d: \t%d:\n",j,enb_properties.properties[i]->cc_node_function[j]); + printf( "\tnode_timing for CC %d: \t%d:\n",j,enb_properties.properties[i]->cc_node_timing[j]); + printf( "\tnode_synch_ref for CC %d: \t%d:\n",j,enb_properties.properties[i]->cc_node_synch_ref[j]); printf( "\teutra band for CC %d: \t%"PRId16":\n",j,enb_properties.properties[i]->eutra_band[j]); printf( "\tdownlink freq for CC %d: \t%"PRIu64":\n",j,enb_properties.properties[i]->downlink_frequency[j]); @@ -416,17 +418,17 @@ void enb_config_display(void) printf( "\tue_TimersAndConstants_t310 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_t310[j]); printf( "\tue_TimersAndConstants_n310 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n310[j]); printf( "\tue_TimersAndConstants_t311 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_t311[j]); - printf( "\tue_TimersAndConstants_n311 for CC %d:\t%ld:\n\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n311[j]); + printf( "\tue_TimersAndConstants_n311 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n311[j]); } for (j=0; j < enb_properties.properties[i]->num_otg_elements; j++) { - printf( "\tOTG Destination UE ID: \t%"PRIu16, enb_properties.properties[i]->otg_ue_id[j]); + printf( "\n\tOTG Destination UE ID: \t%"PRIu16, enb_properties.properties[i]->otg_ue_id[j]); printf( "\n\tOTG App Type: \t%"PRIu8, enb_properties.properties[i]->otg_app_type[j]); printf( "\n\tOTG Background Traffic: \t%s\n", (enb_properties.properties[i]->otg_bg_traffic[j]==1) ? "Enabled" : "Disabled"); } - printf( "\tGlobal log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->glog_level)); + printf( "\n\tGlobal log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->glog_level)); printf( "\tHW log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->hw_log_level)); printf( "\tPHY log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->phy_log_level)); printf( "\tMAC log level: \t%s\n", map_int_to_str(log_level_names,enb_properties.properties[i]->mac_log_level)); @@ -521,6 +523,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) const char* cc_node_function = NULL; const char* cc_node_timing = NULL; + int cc_node_synch_ref = 0; const char* cell_type = NULL; const char* tac = 0; @@ -800,6 +803,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) //printf("Component carrier %d\n",component_carrier); if (!(config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_CC_NODE_FUNCTION, &cc_node_function) && config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_CC_NODE_TIMING, &cc_node_timing) + && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_CC_NODE_SYNCH_REF, &cc_node_synch_ref) && config_setting_lookup_string(component_carrier, ENB_CONFIG_STRING_FRAME_TYPE, &frame_type) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_TDD_CONFIG, &tdd_config) && config_setting_lookup_int(component_carrier, ENB_CONFIG_STRING_TDD_CONFIG_S, &tdd_config_s) @@ -894,9 +898,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) lib_config_file_name_pP, i, cc_node_function); } - if (strcmp(cc_node_timing, "SYNCH_TO_DEVICE") == 0) { + if (strcmp(cc_node_timing, "synch_to_ext_device") == 0) { enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_ext_device; - } else if (strcmp(cc_node_timing, "SYNCH_TO_OTHER") == 0) { + } else if (strcmp(cc_node_timing, "synch_to_other") == 0) { enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_other; } else { AssertError (0, parse_errors ++, @@ -904,6 +908,14 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) lib_config_file_name_pP, i, cc_node_timing); } + if ((cc_node_synch_ref >= -1) && (cc_node_synch_ref < num_component_carriers)) { + enb_properties.properties[enb_properties_index]->cc_node_synch_ref[j] = (int16_t) cc_node_synch_ref; + } else { + AssertError (0, parse_errors ++, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for node_synch_ref choice: valid CC_id or -1 !\n", + lib_config_file_name_pP, i, cc_node_synch_ref); + } + enb_properties.properties[enb_properties_index]->tdd_config[j] = tdd_config; AssertError (tdd_config <= TDD_Config__subframeAssignment_sa6, parse_errors ++, "Failed to parse eNB configuration file %s, enb %d illegal tdd_config %d (should be 0-%d)!", diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 3feeb5e828..6a8483c3d0 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -132,6 +132,7 @@ typedef struct Enb_properties_s { int16_t nb_cc; eNB_func_t cc_node_function[1+MAX_NUM_CCs]; eNB_timing_t cc_node_timing[1+MAX_NUM_CCs]; + int16_t cc_node_synch_ref[1+MAX_NUM_CCs]; lte_frame_type_t frame_type[1+MAX_NUM_CCs]; uint8_t tdd_config[1+MAX_NUM_CCs]; uint8_t tdd_config_s[1+MAX_NUM_CCs]; From 631b4cacf41a8a205d9606d554daf26577531c3c Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 22 Jul 2016 16:51:37 +0200 Subject: [PATCH 103/206] read node fn, timing from config data --- targets/RT/USER/lte-enb.c | 12 +-- targets/RT/USER/lte-softmodem.c | 131 +++++++------------------------- 2 files changed, 35 insertions(+), 108 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 3317d289e0..1f80e17502 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -157,7 +157,7 @@ static struct { void exit_fun(const char* s); -void init_eNB(eNB_func_t node_function); +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[]); void stop_eNB(void); @@ -1577,13 +1577,15 @@ void print_opp_meas(void) { } -void init_eNB(eNB_func_t node_function) { +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[]) { int CC_id; - for (CC_id=0;CC_idnode_function = node_function; - + for (CC_id=0;CC_idnode_function = node_function[CC_id]; + PHY_vars_eNB_g[0][CC_id]->node_timing = node_timing[CC_id]; + } + init_eNB_proc(); sleep(1); LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index eedc641574..42cefe4154 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -119,7 +119,7 @@ unsigned short config_frames[4] = {2,9,11,13}; // In lte-enb.c extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); -extern void init_eNB(eNB_func_t); +extern void init_eNB(eNB_func_t *, eNB_timing_t *); extern void stop_eNB(void); extern void kill_eNB_proc(void); @@ -229,7 +229,9 @@ int otg_enabled; static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; -eNB_func_t node_function=eNodeB_3GPP; +eNB_func_t node_function[MAX_NUM_CCs]; +eNB_timing_t node_timing[MAX_NUM_CCs]; +int16_t node_synch_ref[MAX_NUM_CCs]; uint32_t target_dl_mcs = 28; //maximum allowed mcs uint32_t target_ul_mcs = 20; @@ -237,8 +239,6 @@ uint32_t timing_advance = 0; uint8_t exit_missed_slots=1; uint64_t num_missed_slots=0; // counter for the number of missed slots - - extern void reset_opp_meas(void); extern void print_opp_meas(void); int transmission_mode=1; @@ -387,11 +387,6 @@ void help (void) { printf(" --ue-scan_carrier set UE to scan around carrier\n"); printf(" --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n"); printf(" --mmapped-dma sets flag for improved EXMIMO UE performance\n"); - printf(" --RCC run using NGFI RCC node function IF4 split\n"); - printf(" --RRU run using NGFI RRU node function IF4 split\n"); - printf(" --eNB run using 3GPP eNB node function\n"); - printf(" --BBU run using 3GPP eNB node function with IF5 split\n"); - printf(" --RRH run using RRH node function with IF5 split\n"); printf(" -C Set the downlink frequency for all component carriers\n"); printf(" -d Enable soft scope and L1 and L2 stats (Xforms)\n"); printf(" -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"); @@ -688,12 +683,7 @@ static void get_options (int argc, char **argv) LONG_OPTION_DUMP_FRAME, LONG_OPTION_LOOPMEMORY, LONG_OPTION_PHYTEST, - LONG_OPTION_MMAPPED_DMA, - LONG_OPTION_RCC, - LONG_OPTION_RRU, - LONG_OPTION_ENB, - LONG_OPTION_ENB_BBU, - LONG_OPTION_RRH + LONG_OPTION_MMAPPED_DMA #if T_TRACER , LONG_OPTION_T_PORT, @@ -718,11 +708,6 @@ static void get_options (int argc, char **argv) {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY}, {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST}, {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA}, - {"RCC", no_argument, NULL, LONG_OPTION_RCC}, - {"RRU", no_argument, NULL, LONG_OPTION_RRU}, - {"eNB", no_argument, NULL, LONG_OPTION_ENB}, - {"BBU", no_argument, NULL, LONG_OPTION_ENB_BBU}, - {"RRH", no_argument, NULL, LONG_OPTION_RRH}, #if T_TRACER {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, @@ -817,26 +802,6 @@ static void get_options (int argc, char **argv) case LONG_OPTION_MMAPPED_DMA: mmapped_dma = 1; break; - - case LONG_OPTION_RCC: - node_function = NGFI_RCC_IF4; - break; - - case LONG_OPTION_RRU: - node_function = NGFI_RRU_IF4; - break; - - case LONG_OPTION_ENB: - node_function = eNodeB_3GPP; - break; - - case LONG_OPTION_ENB_BBU: - node_function = eNodeB_3GPP_BBU; - break; - - case LONG_OPTION_RRH: - node_function = NGFI_RRU_IF5; - break; #if T_TRACER case LONG_OPTION_T_PORT: { @@ -1116,6 +1081,10 @@ static void get_options (int argc, char **argv) } for (CC_id=0; CC_idproperties[i]->cc_node_function[CC_id]; + node_timing[CC_id] = enb_properties->properties[i]->cc_node_timing[CC_id]; + node_synch_ref[CC_id] = enb_properties->properties[i]->cc_node_synch_ref[CC_id]; + frame_parms[CC_id]->frame_type = enb_properties->properties[i]->frame_type[CC_id]; frame_parms[CC_id]->tdd_config = enb_properties->properties[i]->tdd_config[CC_id]; frame_parms[CC_id]->tdd_config_S = enb_properties->properties[i]->tdd_config_s[CC_id]; @@ -1668,7 +1637,7 @@ int main( int argc, char **argv ) if (UE_flag == 0) { for (CC_id=0; CC_idrfdevice.host_type = RRH_HOST; PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = RRH_HOST; } else { @@ -1683,69 +1652,39 @@ int main( int argc, char **argv ) openair0.type = NONE_DEV; /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ openair0.transp_type = NONE_TP; - - // Legacy BBU - RRH init - //int returns=-1; - ///* BBU can have either a local or a remote radio head */ - //if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active - load library of radio head and initiate it - //if (mode!=loop_through_memory) { - //returns=openair0_device_load(&openair0, &openair0_cfg[0]); - //printf("openair0_device_init returns %d\n",returns); - //if (returns<0) { - //printf("Exiting, cannot initialize device\n"); - //exit(-1); - //} - //} - //else if (mode==loop_through_memory) { - //} - //} else { //remote radio head active - load library of transport protocol and initiate it - //if (mode!=loop_through_memory) { - //returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params); - //printf("openair0_transport_init returns %d\n",returns); - //if (returns<0) { - //printf("Exiting, cannot initialize transport protocol\n"); - //exit(-1); - //} - //} - //else if (mode==loop_through_memory) { - //} - //} - + int returns=-1; - // Handle spatially distributed MIMO antenna ports // Load RF device and initialize - if (node_function == NGFI_RRU_IF5 || node_function == NGFI_RRU_IF4 || node_function == eNodeB_3GPP) { - for (CC_id=0; CC_idrfdevice), &openair0_cfg[0]) : - openair0_device_load(&openair0, &openair0_cfg[0]); - + returns = (UE_flag == 0) ? + openair0_device_load(&(PHY_vars_eNB_g[0][CC_id]->rfdevice), &openair0_cfg[0]) : + openair0_device_load(&openair0, &openair0_cfg[0]); printf("openair0_device_init returns %d for CC_id %d\n",returns,CC_id); if (returns<0) { - printf("Exiting, cannot initialize device\n"); - exit(-1); + printf("Exiting, cannot initialize device\n"); + exit(-1); } - } - else if (mode==loop_through_memory) { + } else if (mode==loop_through_memory) { + } } } // Load transport protocol and initialize - - if ((UE_flag==0) && (node_function != eNodeB_3GPP)){ - for (CC_id=0; CC_idifdevice), &openair0_cfg[0], (eth_params+CC_id)); + returns = openair0_transport_load(&(PHY_vars_eNB_g[0][CC_id]->ifdevice), &openair0_cfg[0], (eth_params+CC_id)); printf("openair0_transport_init returns %d for CC_id %d\n",returns,CC_id); if (returns<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); } - } - else if (mode==loop_through_memory) { + } else if (mode==loop_through_memory) { + } } } @@ -1783,7 +1722,6 @@ int main( int argc, char **argv ) number_of_cards = 1; - for(CC_id=0; CC_id Date: Fri, 22 Jul 2016 18:51:04 +0200 Subject: [PATCH 104/206] eNB tx working --- targets/RT/USER/lte-enb.c | 165 +++++++++++++++++--------------------- 1 file changed, 72 insertions(+), 93 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 1f80e17502..1355bb5a2a 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -496,7 +496,7 @@ static void* eNB_thread_rxtx( void* param ) { LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n"); exit_fun("nothing to add"); break; - } + } } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) { /// **** recv_IF4 of txdataF from RCC **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); @@ -604,10 +604,8 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - printf( "Exiting eNB thread RXn_TXnp4\n"); - eNB_thread_rxtx_status = 0; return &eNB_thread_rxtx_status; } @@ -679,7 +677,6 @@ static void* eNB_thread_asynch_rx( void* param ) { prach_rx = 0; do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); recv_IF4(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); @@ -690,10 +687,7 @@ static void* eNB_thread_asynch_rx( void* param ) { } else if (packet_type == IF4_PRACH) { // wake up thread for PRACH RX prach_rx = 1; - } - - - + } } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); if (proc->first_rx == 0) { @@ -732,16 +726,12 @@ static void* eNB_thread_FH( void* param ) { int i; int prach_rx; - - uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; - int subframe = proc->subframe_rx; - int frame = proc->frame_rx; - - + int subframe=0, frame=0; + wait.tv_sec=0; wait.tv_nsec=5000000L; @@ -835,7 +825,7 @@ static void* eNB_thread_FH( void* param ) { exit_fun("Error getting thread priority"); } - LOG_I(HW, "[SCHED][eNB] RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + LOG_I(HW, "[SCHED][eNB] FH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -849,7 +839,7 @@ static void* eNB_thread_FH( void* param ) { mlockall(MCL_CURRENT | MCL_FUTURE); // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe of TX and RX threads - printf( "waiting for sync (eNB_thread_rx_common)\n"); + printf( "waiting for sync (eNB_thread_FH)\n"); pthread_mutex_lock( &sync_mutex ); while (sync_var<0) @@ -892,76 +882,75 @@ static void* eNB_thread_FH( void* param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - if (oai_exit) break; - + if (oai_exit) break; + // This case is for synchronization to another thread if ((eNB->node_timing == synch_to_other) && - ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == NGFI_RRU_IF5) || - (eNB->node_function == eNodeB_3GPP))) { // This case is for synchronization to another thread + ((eNB->node_function == NGFI_RCC_IF4) || + (eNB->node_function == eNodeB_3GPP_BBU))) { //wait for event // how long should we wait here, for MOBIPASS this could be long // if (pthread_mutex_timedlock(&proc->mutex_FH,&wait) != 0) { if (pthread_mutex_lock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH\n"); - exit_fun( "error locking mutex" ); - break; + LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH\n"); + exit_fun( "error locking mutex" ); + break; } while (proc->instance_cnt_FH < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_prach is -1 - pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); // this unlocks mutex_rxtx while waiting and then locks it again - } - + // most of the time the thread is waiting here + // proc->instance_cnt_prach is -1 + pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); // this unlocks mutex_rxtx while waiting and then locks it again + } proc->instance_cnt_FH++; - } // Remaining cases are all for synchronization on FH interface else if ((eNB->node_timing == synch_to_ext_device) && - ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == NGFI_RRU_IF5) || - (eNB->node_function == eNodeB_3GPP))) { // acquisition from RF + ((eNB->node_function == NGFI_RRU_IF4) || + (eNB->node_function == NGFI_RRU_IF5) || + (eNB->node_function == eNodeB_3GPP))) { // acquisition from RF for (i=0; inb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - // sanitycheck if (subframe==9) { - subframe=0; - frame++; - frame&=1023; + subframe=0; + frame++; + frame&=1023; } else { - subframe++; + subframe++; } rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, - &proc->timestamp_rx, - rxp, - fp->samples_per_tti, - fp->nb_antennas_rx); + &proc->timestamp_rx, + rxp, + fp->samples_per_tti, + fp->nb_antennas_rx); + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ + if (proc->subframe_rx != subframe){ LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); exit_fun("Exiting"); - } + } + if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - exit_fun("Exiting"); - } + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } } else { proc->first_rx = 0; + frame = proc->frame_rx; + subframe = proc->subframe_rx; } - // printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); @@ -974,7 +963,7 @@ static void* eNB_thread_FH( void* param ) { } // node_timing==synch_to_ext_device && node_function == RRU || eNodeB else if ((eNB->node_timing == synch_to_ext_device) && - (eNB->node_function == eNodeB_3GPP_BBU)) { // acquisition from IF + (eNB->node_function == eNodeB_3GPP_BBU)) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); @@ -982,30 +971,30 @@ static void* eNB_thread_FH( void* param ) { proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - + if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - //exit_fun("Exiting"); - } - if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - //exit_fun("Exiting"); - } + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + exit_fun("Exiting"); + } + + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } } else { - proc->first_rx = 0; - } + proc->first_rx = 0; + } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); + } // eNodeB_3GPP_BBU && node_timing == synch_to_ext_device - else if ((eNB->node_timing == synch_to_ext_device) && - (eNB->node_function == NGFI_RCC_IF4)) { + (eNB->node_function == NGFI_RCC_IF4)) { /// **** recv_IF4 of rxdataF from RRU **** /// /// **** recv_IF4 of rxsigF from RRU **** /// - // get frame/subframe information from IF4 interface // timed loop (200 us) symbol_number = 0; @@ -1014,7 +1003,6 @@ static void* eNB_thread_FH( void* param ) { prach_rx = 0; do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); @@ -1025,10 +1013,7 @@ static void* eNB_thread_FH( void* param ) { } else if (packet_type == IF4_PRACH) { // wake up thread for PRACH RX prach_rx = 1; - } - - - + } } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); if (proc->first_rx == 0) { @@ -1047,7 +1032,6 @@ static void* eNB_thread_FH( void* param ) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); - } // node_timing == synch_to_externs, node_function = NGFI_IF4 else { // should not get here @@ -1061,10 +1045,11 @@ static void* eNB_thread_FH( void* param ) { // wake up slave FH thread // lock the FH mutex and make sure the thread is ready if (pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d (IC %d)\n",proc->CC_id,slave_proc->CC_id); - exit_fun( "error locking mutex_rxtx" ); - break; + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d (IC %d)\n",proc->CC_id,slave_proc->CC_id); + exit_fun( "error locking mutex_rxtx" ); + break; } + int cnt_slave = ++slave_proc->instance_cnt_FH; slave_proc->frame_rx = proc->frame_rx; slave_proc->subframe_rx = proc->subframe_rx; @@ -1073,16 +1058,16 @@ static void* eNB_thread_FH( void* param ) { pthread_mutex_unlock( &slave_proc->mutex_FH ); if (cnt_slave == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&slave_proc->cond_FH) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB CCid %d, slave CCid %d\n",proc->CC_id,slave_proc->CC_id); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&slave_proc->cond_FH) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB CCid %d, slave CCid %d\n",proc->CC_id,slave_proc->CC_id); + exit_fun( "ERROR pthread_cond_signal" ); + break; + } } else { - LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_rxtx %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); - exit_fun( "TX thread busy" ); - break; + LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_rxtx %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); + exit_fun( "TX thread busy" ); + break; } } @@ -1102,7 +1087,7 @@ static void* eNB_thread_FH( void* param ) { // We have just received and processed the common part of a subframe, say n. // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_pexr_frame) was n*samples_per_tti, + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, // and proc->subframe_tx = proc->subframe_rx+3 proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); @@ -1124,14 +1109,13 @@ static void* eNB_thread_FH( void* param ) { LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, cnt_rxtx ); exit_fun( "TX thread busy" ); break; - } - + } stop_meas( &softmodem_stats_rxtx_sf ); #ifdef DEADLINE_SCHEDULER if (opp_enabled){ - if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); + if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); } } #endif // DEADLINE_SCHEDULER @@ -1152,7 +1136,6 @@ static void* eNB_thread_FH( void* param ) { } printf( "Exiting FH thread \n"); - eNB_thread_FH_status = 0; return &eNB_thread_FH_status; @@ -1167,8 +1150,6 @@ static void* eNB_thread_FH( void* param ) { static void* eNB_thread_prach( void* param ) { static int eNB_thread_prach_status; - - eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id]; @@ -1315,10 +1296,8 @@ static void* eNB_thread_prach( void* param ) { } } - printf( "Exiting eNB thread PRACH\n"); - eNB_thread_prach_status = 0; return &eNB_thread_prach_status; } From 2e29052ff47b0a75f850cebed1ce07e378de8a40 Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Fri, 22 Jul 2016 19:35:52 +0200 Subject: [PATCH 105/206] correct logging for common/uespec --- openair1/SCHED/phy_procedures_lte_eNb.c | 53 +++++++++++-------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index ecaeb20fa8..28098406f2 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2517,31 +2517,29 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { - int i,l; + int l; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; eNB_proc_t *proc = &eNB->proc; - int subframe = proc->subframe_rx; - int frame = proc->frame_rx; + + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; uint8_t seqno=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); - - start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe); #endif - if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot) - + if (abstraction_flag==0) { if ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == eNodeB_3GPP) || - (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing + (eNB->node_function == eNodeB_3GPP) || + (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing // now do common RX processing for first slot in subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); @@ -2564,7 +2562,6 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl ); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); if (eNB->node_function == NGFI_RRU_IF4) { @@ -2572,10 +2569,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(eNB, proc->frame_rx, proc->subframe_rx, IF4_PULFFT, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); - - } - - + } } else if (eNB->node_function == NGFI_RRU_IF5) { /// **** send_IF5 of rxdata to BBU **** /// @@ -2587,12 +2581,12 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) // check if we have to detect PRACH first if ((eNB->node_function != NGFI_RRU_IF5) && - (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0)) { // any other node must call prach procedure + (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0)) { // any other node must call prach procedure // wake up thread for PRACH RX if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); - exit_fun( "error locking mutex_prach" ); - return; + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); + exit_fun( "error locking mutex_prach" ); + return; } int cnt_prach = ++proc->instance_cnt_prach; @@ -2603,18 +2597,19 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl pthread_mutex_unlock( &proc->mutex_prach ); if (cnt_prach == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&proc->cond_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } } else { - LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach); - exit_fun( "PRACH thread busy" ); - return; + LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach); + exit_fun( "PRACH thread busy" ); + return; } } + } else { // grab transport channel information from network interface } @@ -2641,7 +2636,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe); + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe); #endif T(T_ENB_PHY_UL_TICK, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe)); From 6e4d361eb3af7d7bbae93c5c4bd00862f76e04af Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 23 Jul 2016 01:17:59 -0700 Subject: [PATCH 106/206] commit before merge --- cmake_targets/CMakeLists.txt | 6 + openair1/PHY/defs.h | 12 +- openair1/PHY/extern.h | 3 + openair1/PHY/vars.h | 3 + openair1/SCHED/phy_procedures_lte_eNb.c | 96 ----- openair2/UTIL/OCG/OCG.h | 2 + ...enb.band7.generic.oaisim.local_no_mme.conf | 2 + targets/RT/USER/lte-enb.c | 273 +++++++++----- targets/RT/USER/lte-softmodem.c | 76 ++-- targets/RT/USER/lte-ue.c | 343 +++++------------- targets/SIMU/USER/oaisim.c | 186 +++------- targets/SIMU/USER/oaisim_functions.c | 22 +- 12 files changed, 388 insertions(+), 636 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index a39cf35f6a..56ff74b8d3 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1736,6 +1736,9 @@ add_executable(oaisim ${s1ap_h} ${x2ap_h} ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR_TARGETS}/RT/USER/lte-ue.c + ${OPENAIR_TARGETS}/RT/USER/lte-enb.c + ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c @@ -1779,6 +1782,9 @@ add_executable(oaisim_nos1 ${s1ap_h} ${x2ap_h} ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR_TARGETS}/RT/USER/lte-ue.c + ${OPENAIR_TARGETS}/RT/USER/lte-enb.c + ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c ${OPENAIR_TARGETS}/SIMU/USER/init_lte.c ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 4c46674ecb..e4386c8fdf 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -171,6 +171,7 @@ typedef enum { } eNB_timing_t; + typedef struct UE_SCAN_INFO_s { /// 10 best amplitudes (linear) for each pss signals int32_t amp[3][10]; @@ -310,10 +311,16 @@ typedef struct { uint8_t CC_id; /// Last RX timestamp openair0_timestamp timestamp_rx; + /// pthread attributes for main UE thread + pthread_attr_t attr_ue; + /// scheduling parameters for main UE thread + struct sched_param sched_param_ue; + /// pthread descriptor main UE thread + pthread_t pthread_ue; /// \brief Instance count for synch thread. /// \internal This variable is protected by \ref mutex_synch. int instance_cnt_synch; - /// pthread attributes for prach processing thread + /// pthread attributes for synch processing thread pthread_attr_t attr_synch; /// scheduling parameters for synch thread struct sched_param sched_param_synch; @@ -770,6 +777,9 @@ typedef struct { time_stats_t dlsch_tc_intl2_stats; time_stats_t tx_prach; + /// RF and Interface devices per CC + openair0_device rfdevice; + #if ENABLE_RAL hash_table_t *ral_thresholds_timed; SLIST_HEAD(ral_thresholds_gen_poll_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX]; diff --git a/openair1/PHY/extern.h b/openair1/PHY/extern.h index 4c9e2706c7..2144c4f01d 100755 --- a/openair1/PHY/extern.h +++ b/openair1/PHY/extern.h @@ -111,6 +111,9 @@ extern double p_qam64[8]; extern double beta1_dlsch[6][MCS_COUNT]; extern double beta2_dlsch[6][MCS_COUNT]; +extern char eNB_functions[5][20]; +extern char eNB_timing[2][20]; + #endif /*__PHY_EXTERN_H__ */ diff --git a/openair1/PHY/vars.h b/openair1/PHY/vars.h index 3d940d4a94..85bfe7a2a6 100755 --- a/openair1/PHY/vars.h +++ b/openair1/PHY/vars.h @@ -139,6 +139,9 @@ double beta2_dlsch[6][MCS_COUNT] = { {2.52163, 0.83231, 0.77472, 1.36536, 1.1682 */ +char eNB_functions[5][20]={"eNodeB_3GPP","eNodeB_3GPP_BBU","NGFI_RRU_IF5","NGFI_RRU_IF4","NGFI_RCC_IF4"}; +char eNB_timing[2][20]={"synch_to_ext_device","synch_to_other"}; + #endif /*__PHY_VARS_H__ */ diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index ecaeb20fa8..43edfa807d 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -3236,99 +3236,3 @@ int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, r return do_proc; } #endif -/* -void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t abstraction_flag, - relaying_type_t r_type, PHY_VARS_RN *rn) -{ -#if defined(ENABLE_ITTI) - MessageDef *msg_p; - const char *msg_name; - instance_t instance; - unsigned int Mod_id; - int result; -#endif - - - int CC_id=0; - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, eNB[0]->proc[subframe].frame_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,1); - start_meas(&eNB[0]->phy_proc); - -#if defined(ENABLE_ITTI) - - do { - // Checks if a message has been sent to PHY sub-task - itti_poll_msg (TASK_PHY_ENB, &msg_p); - - if (msg_p != NULL) { - msg_name = ITTI_MSG_NAME (msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); - Mod_id = instance; - - switch (ITTI_MSG_ID(msg_p)) { - - // Messages from eNB app - case PHY_CONFIGURATION_REQ: - LOG_I(PHY, "[eNB %d] Received %s\n", instance, msg_name); - // TODO - - break; - - default: - LOG_E(PHY, "[ENB %d] Received unexpected message %s\n", Mod_id, msg_name); - break; - } - - result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - } - } while(msg_p != NULL); - -#endif - - - for (CC_id=0; CC_idframe_parms.frame_type == TDD)&& - (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_tx)==SF_DL))|| - (eNB[CC_id]->frame_parms.frame_type == FDD))) { -#ifdef Rel10 - - if (phy_procedures_RN_eNB_TX(eNB[CC_id]->proc[0].subframe_rx, eNB[CC_id]->proc[0].subframe_tx, r_type) != 0 ) -#endif - phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn); - } - - if ((((eNB[CC_id]->frame_parms.frame_type == TDD )&& - (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_rx)==SF_UL)) || - (eNB[CC_id]->frame_parms.frame_type == FDD))) { - phy_procedures_eNB_RX(subframe,eNB[CC_id],abstraction_flag,r_type); - } - - if (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_tx)==SF_S) { -#ifdef Rel10 - - if (phy_procedures_RN_eNB_TX(subframe, subframe, r_type) != 0 ) -#endif - phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn); - } - - if ((subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_rx)==SF_S)) { - phy_procedures_eNB_S_RX(subframe,eNB[CC_id],abstraction_flag,r_type); - } - - eNB[CC_id]->proc[0].frame_tx++; - eNB[CC_id]->proc[0].frame_rx++; - - if (eNB[CC_id]->proc[0].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h - eNB[CC_id]->proc[0].frame_tx-=MAX_FRAME_NUMBER; - - if (eNB[CC_id]->proc[0].frame_rx>=MAX_FRAME_NUMBER) - eNB[CC_id]->proc[0].frame_rx-=MAX_FRAME_NUMBER; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,0); - stop_meas(&eNB[0]->phy_proc); -} -*/ diff --git a/openair2/UTIL/OCG/OCG.h b/openair2/UTIL/OCG/OCG.h index cf96de7963..c47cc8e8c7 100644 --- a/openair2/UTIL/OCG/OCG.h +++ b/openair2/UTIL/OCG/OCG.h @@ -707,6 +707,8 @@ typedef struct { // phy related params unsigned int n_frames; unsigned int n_frames_flag; // if set, then let the emulation goes to infinity + node_function_t node_function[MAX_NUM_CCs]; + node_timing_t node_timing[MAX_NUM_CCS]; unsigned char frame_type[MAX_NUM_CCs]; //! LTE frame type (TDD=1, FDD=0). \note this should be converted to \ref lte_frame_type_t (header file reorganization needed) char * frame_type_name[MAX_NUM_CCs]; unsigned char tdd_config[MAX_NUM_CCs]; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf index 50cb6747ac..3ec8ea01da 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf @@ -23,6 +23,8 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "SYNCH_TO_OTHER"; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 3317d289e0..ba7921e408 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -157,7 +157,7 @@ static struct { void exit_fun(const char* s); -void init_eNB(eNB_func_t node_function); +void init_eNB(eNB_func_t node_function,int nb_inst); void stop_eNB(void); @@ -350,7 +350,7 @@ static void* eNB_thread_rxtx( void* param ) { /* Set affinity mask to include CPUs 1 to MAX_CPUS */ /* CPU 0 is reserved for UHD threads */ - /* CPU 1 is reserved for all TX threads */ + /* CPU 1 is reserved for all RX_TX threads */ /* Enable CPU Affinity only if number of CPUs >2 */ CPU_ZERO(&cpuset); @@ -398,7 +398,7 @@ static void* eNB_thread_rxtx( void* param ) { exit_fun("Error getting thread priority"); } - LOG_I(HW, "[SCHED][eNB] TX thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), + LOG_I(HW, "[SCHED][eNB] RXn_TXnp4 thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -644,12 +644,103 @@ static void* eNB_thread_asynch_rx( void* param ) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; openair0_timestamp timestamp_rx; int frame_rx,subframe_rx; - int first_rx = 1; + static int first_rx = 1; uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; int prach_rx; +#ifdef DEADLINE_SCHEDULER + struct sched_attr attr; + unsigned int flags = 0; + uint64_t runtime = 870000 ; + uint64_t deadline = 1 * 1000000; + uint64_t period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0; + + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = runtime; + attr.sched_deadline = deadline; + attr.sched_period = period; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] eNB FH sched_setattr failed\n"); + return &eNB_thread_FH_status; + } + + LOG_I( HW, "[SCHED] eNB asynch RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); +#else // LOW_LATENCY + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD */ + /* CPU 1 is reserved for all TX threads */ + /* CPU 2..MAX_CPUS is reserved for all RX threads */ + /* Set CPU Affinity only if number of CPUs >2 */ + CPU_ZERO(&cpuset); +#ifdef CPU_AFFINITY + if (get_nprocs() >2) { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) { + perror( "pthread_setaffinity_np"); + exit_fun (" Error setting processor affinity :"); + } + } +#endif //CPU_AFFINITY + /* Check the actual affinity mask assigned to the thread */ + + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) { + perror ("pthread_getaffinity_np"); + exit_fun (" Error getting processor affinity :"); + } + memset(cpu_affinity,0, sizeof(cpu_affinity)); + + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } + + memset(&sparam, 0 , sizeof (sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + + policy = SCHED_FIFO ; + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + + memset(&sparam, 0 , sizeof (sparam)); + + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) { + perror("pthread_getschedparam"); + exit_fun("Error getting thread priority"); + } + + LOG_I(HW, "[SCHED][eNB] eNB asynch RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, cpu_affinity); + + +#endif // DEADLINE_SCHEDULER + if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); @@ -772,11 +863,11 @@ static void* eNB_thread_FH( void* param ) { attr.sched_period = period; if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB RX sched_setattr failed\n"); + perror("[SCHED] eNB FH sched_setattr failed\n"); return &eNB_thread_FH_status; } - LOG_I( HW, "[SCHED] eNB RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB FH deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); #else // LOW_LATENCY int policy, s, j; struct sched_param sparam; @@ -835,7 +926,7 @@ static void* eNB_thread_FH( void* param ) { exit_fun("Error getting thread priority"); } - LOG_I(HW, "[SCHED][eNB] RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), + LOG_I(HW, "[SCHED][eNB] FH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), (policy == SCHED_FIFO) ? "SCHED_FIFO" : (policy == SCHED_RR) ? "SCHED_RR" : (policy == SCHED_OTHER) ? "SCHED_OTHER" : @@ -848,8 +939,8 @@ static void* eNB_thread_FH( void* param ) { mlockall(MCL_CURRENT | MCL_FUTURE); - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe of TX and RX threads - printf( "waiting for sync (eNB_thread_rx_common)\n"); + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + printf( "waiting for sync (eNB_thread_FH)\n"); pthread_mutex_lock( &sync_mutex ); while (sync_var<0) @@ -1080,8 +1171,8 @@ static void* eNB_thread_FH( void* param ) { break; } } else { - LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_rxtx %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); - exit_fun( "TX thread busy" ); + LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); + exit_fun( "FH thread busy" ); break; } } @@ -1324,91 +1415,94 @@ static void* eNB_thread_prach( void* param ) { } -void init_eNB_proc(void) { +void init_eNB_proc(int nb_inst) { int i; int CC_id; PHY_VARS_eNB *eNB; eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; + int inst; - for (CC_id=0; CC_idproc; - proc_rxtx = proc->proc_rxtx; + for (inst = 0; inst < nb_inst; inst++) { + for (CC_id=0; CC_idnode_function],eNB_timing[eNB->node_timing]); + proc = &eNB->proc; + proc_rxtx = proc->proc_rxtx; #ifndef DEADLINE_SCHEDULER - /* - pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_TX] setting thread stack size failed\n"); - - pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_RX] setting thread stack size failed\n"); - */ - // set the kernel scheduling policy and priority - proc_rxtx[0].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[0].attr_rxtx, &proc_rxtx[0].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[0].attr_rxtx, SCHED_FIFO); - proc_rxtx[1].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); - - proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_FH, &proc->sched_param_FH); - pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO); - - proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); - pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); - - printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); + /* + pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); + if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) + perror("[ENB_PROC_TX] setting thread stack size failed\n"); + + pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); + if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) + perror("[ENB_PROC_RX] setting thread stack size failed\n"); + */ + // set the kernel scheduling policy and priority + proc_rxtx[0].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc_rxtx[0].attr_rxtx, &proc_rxtx[0].sched_param_rxtx); + pthread_attr_setschedpolicy (&proc_rxtx[0].attr_rxtx, SCHED_FIFO); + proc_rxtx[1].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); + pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); + + proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_FH, &proc->sched_param_FH); + pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO); + + proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); + pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); + + printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); #endif - proc_rxtx[0].instance_cnt_rxtx = -1; - proc_rxtx[1].instance_cnt_rxtx = -1; - proc->instance_cnt_prach = -1; - proc->instance_cnt_FH = -1; - proc->CC_id = CC_id; - - proc->first_rx=4; - - pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); - pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); - pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_FH, NULL); + proc_rxtx[0].instance_cnt_rxtx = -1; + proc_rxtx[1].instance_cnt_rxtx = -1; + proc->instance_cnt_prach = -1; + proc->instance_cnt_FH = -1; + proc->CC_id = CC_id; + + proc->first_rx=4; + + pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); + pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); + pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); + pthread_cond_init( &proc->cond_prach, NULL); + pthread_cond_init( &proc->cond_FH, NULL); #ifndef DEADLINE_SCHEDULER - pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc ); + pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); + pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); + pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); + if (eNB->node_timing == synch_to_other) + pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc ); #else - pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc ); - + pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); + pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); + pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); + if (eNB->node_timing == synch_to_other) + pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc ); + #endif - char name[16]; - snprintf( name, sizeof(name), "RXTX0 %d", i ); - pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); - snprintf( name, sizeof(name), "RXTX1 %d", i ); - pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); - snprintf( name, sizeof(name), "FH %d", i ); - pthread_setname_np( proc->pthread_FH, name ); + char name[16]; + snprintf( name, sizeof(name), "RXTX0 %d", i ); + pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); + snprintf( name, sizeof(name), "RXTX1 %d", i ); + pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); + snprintf( name, sizeof(name), "FH %d", i ); + pthread_setname_np( proc->pthread_FH, name ); + } + + /* setup PHY proc TX sync mechanism */ + pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); + pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); + sync_phy_proc.phy_proc_CC_id = 0; } - - /* setup PHY proc TX sync mechanism */ - pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); - pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); - sync_phy_proc.phy_proc_CC_id = 0; } @@ -1577,14 +1671,15 @@ void print_opp_meas(void) { } -void init_eNB(eNB_func_t node_function) { + void init_eNB(eNB_func_t node_function,int nb_inst) { int CC_id; - - for (CC_id=0;CC_idnode_function = node_function; - - init_eNB_proc(); + int inst; + for (inst=0;instnode_function = node_function; + + init_eNB_proc(nb_inst); sleep(1); LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index eedc641574..d17f7b8599 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -119,14 +119,14 @@ unsigned short config_frames[4] = {2,9,11,13}; // In lte-enb.c extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); -extern void init_eNB(eNB_func_t); +extern void init_eNB(eNB_func_t,int); extern void stop_eNB(void); extern void kill_eNB_proc(void); // In lte-ue.c extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); extern void fill_ue_band_info(void); -extern void init_UE(void); +extern void init_UE(int); #ifdef XFORMS // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) @@ -284,9 +284,6 @@ eth_params_t *eth_params; openair0_config_t openair0_cfg[MAX_CARDS]; -// Change to openair_global to handle UE -openair0_device openair0; - double cpuf; char uecap_xer[1024],uecap_xer_in=0; @@ -1677,40 +1674,15 @@ int main( int argc, char **argv ) } } } - /* device host type is set*/ - openair0.host_type = BBU_HOST; - /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ - openair0.type = NONE_DEV; - /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ - openair0.transp_type = NONE_TP; - - // Legacy BBU - RRH init - //int returns=-1; - ///* BBU can have either a local or a remote radio head */ - //if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active - load library of radio head and initiate it - //if (mode!=loop_through_memory) { - //returns=openair0_device_load(&openair0, &openair0_cfg[0]); - //printf("openair0_device_init returns %d\n",returns); - //if (returns<0) { - //printf("Exiting, cannot initialize device\n"); - //exit(-1); - //} - //} - //else if (mode==loop_through_memory) { - //} - //} else { //remote radio head active - load library of transport protocol and initiate it - //if (mode!=loop_through_memory) { - //returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params); - //printf("openair0_transport_init returns %d\n",returns); - //if (returns<0) { - //printf("Exiting, cannot initialize transport protocol\n"); - //exit(-1); - //} - //} - //else if (mode==loop_through_memory) { - //} - //} - + else { + /* device host type is set*/ + PHY_vars_UE_g[0][0]->rfdevice.host_type = BBU_HOST; + /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ + PHY_vars_UE_g[0][0]->rfdevice.type = NONE_DEV; + /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ + PHY_vars_UE_g[0][0]->rfdevice.transp_type = NONE_TP; + } + int returns=-1; // Handle spatially distributed MIMO antenna ports @@ -1720,7 +1692,7 @@ int main( int argc, char **argv ) if (mode!=loop_through_memory) { returns= (UE_flag == 0) ? openair0_device_load(&(PHY_vars_eNB_g[0][CC_id]->rfdevice), &openair0_cfg[0]) : - openair0_device_load(&openair0, &openair0_cfg[0]); + openair0_device_load(&(PHY_vars_UE_g[0][CC_id]->rfdevice), &openair0_cfg[0]); printf("openair0_device_init returns %d for CC_id %d\n",returns,CC_id); if (returns<0) { @@ -1904,8 +1876,8 @@ int main( int argc, char **argv ) // start the main thread - if (UE_flag == 1) init_UE(); - else init_eNB(node_function); + if (UE_flag == 1) init_UE(1); + else init_eNB(node_function,1); // Sleep to allow all threads to setup sleep(3); @@ -1978,16 +1950,18 @@ int main( int argc, char **argv ) pthread_mutex_destroy(&sync_mutex); // *** Handle per CC_id openair0 - if (UE_flag==1) - openair0.trx_end_func(&openair0); - - for(CC_id=0; CC_idrfdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); - if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + if (UE_flag==1) { + if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func) + PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice); + } + else { + for(CC_id=0; CC_idrfdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + } } - if (ouput_vcd) VCD_SIGNAL_DUMPER_CLOSE(); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 4fa06f1bc8..73e9197588 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -92,9 +92,9 @@ typedef enum { si=2 } sync_mode_t; -void init_UE_threads(void); +void init_UE_threads(int nb_inst); void *UE_thread(void *arg); -void init_UE(void); +void init_UE(int nb_inst); extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; @@ -105,8 +105,6 @@ extern openair0_config_t openair0_cfg[MAX_CARDS]; extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern openair0_rf_map rf_map[MAX_NUM_CCs]; - -extern openair0_device openair0; extern int oai_exit; extern int32_t **rxdata; @@ -176,21 +174,26 @@ pthread_t main_ue_thread; pthread_attr_t attr_UE_thread; struct sched_param sched_param_UE_thread; -void init_UE() { +void init_UE(int nb_inst) { int error_code; - - printf("Intializing UE Threads ...\n"); - init_UE_threads(); - sleep(1); - error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL); - - if (error_code!= 0) { - LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code); - return; - } else { - LOG_D( HW, "[lte-softmodem.c] Allocate UE_thread successful\n" ); - pthread_setname_np( main_ue_thread, "main UE" ); + int inst; + PHY_VARS_UE *UE; + + for (inst=0;instproc.pthread_ue, &UE->proc.attr_ue, UE_thread, NULL); + + if (error_code!= 0) { + LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code); + return; + } else { + LOG_D(HW, "[lte-softmodem.c] Allocate UE_thread successful\n" ); + pthread_setname_np( UE->proc.pthread_ue, "main UE" ); + } } printf("UE threads created\n"); @@ -362,7 +365,7 @@ static void *UE_thread_synch(void *arg) } - if (openair0.trx_start_func(&openair0) != 0 ) { + if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { LOG_E(HW,"Could not start the device\n"); oai_exit=1; } @@ -484,12 +487,12 @@ static void *UE_thread_synch(void *arg) break; } - //openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0); - //openair0.trx_set_gains_func(&openair0,&openair0_cfg[0]); - openair0.trx_stop_func(&openair0); + //UE->rfdevice.trx_set_freq_func(&openair0,&openair0_cfg[0],0); + //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); + UE->rfdevice.trx_stop_func(&UE->rfdevice); sleep(1); init_frame_parms(&UE->frame_parms,1); - if (openair0.trx_start_func(&openair0) != 0 ) { + if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { LOG_E(HW,"Could not start the device\n"); oai_exit=1; } @@ -568,7 +571,7 @@ static void *UE_thread_synch(void *arg) } } - // openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0); + // UE->rfdevice.trx_set_freq_func(&openair0,&openair0_cfg[0],0); if (UE->UE_scan_carrier==1) { for (i=0;iinstance_cnt_tx=-1; - -#ifdef DEADLINE_SCHEDULER - - struct sched_attr attr; - unsigned int flags = 0; - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - // This creates a 1ms reservation every 10ms period - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = 900000; // each tx thread requires .5ms to finish its job - attr.sched_deadline = 1000000; // each tx thread will finish within 1ms - attr.sched_period = 1000000; // each tx thread has a period of 1ms from the starting point - - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] UE_thread_tx thread: sched_setattr failed\n"); - return &UE_thread_tx_retval; - } - -#else - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - // Set affinity mask to include CPUs 1 to MAX_CPUS - // CPU 0 is reserved for UHD threads - CPU_ZERO(&cpuset); - - #ifdef CPU_AFFINITY - if (get_nprocs() >2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } -#endif - - // Check the actual affinity mask assigned to the thread - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity, 0 , sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) - { - char temp[1024]; - sprintf(temp, " CPU_%d ", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) - { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) - { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - - } - - LOG_I( HW, "[SCHED][UE] Started UE thread TX on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - (int) sparam.sched_priority, cpu_affinity); - - -#endif - - printf("waiting for sync (UE_thread_tx)\n"); - - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (UE_thread_tx)\n"); - - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); - - pthread_mutex_unlock(&sync_mutex); - printf("unlocked sync_mutex, waiting (UE_thread_tx)\n"); - - printf("Starting UE TX thread\n"); - - // Lock memory from swapping. This is a process wide call (not constraint to this thread). - mlockall(MCL_CURRENT | MCL_FUTURE); - - while (!oai_exit) { - - if (pthread_mutex_lock(&UE->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE TX\n" ); - exit_fun("nothing to add"); - return &UE_thread_tx_retval; - } - - while (UE->instance_cnt_tx < 0) { - // most of the time, the thread is waiting here - pthread_cond_wait( &UE->cond_tx, &UE->mutex_tx ); - } - - if (pthread_mutex_unlock(&UE->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE TX\n" ); - exit_fun("nothing to add"); - return &UE_thread_tx_retval; - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX, 1 ); - - if ((subframe_select( &UE->frame_parms, UE->slot_tx>>1 ) == SF_UL) || - (UE->frame_parms.frame_type == FDD)) { - phy_procedures_UE_TX( UE, 0, 0, UE->mode, no_relay ); - } - - if ((subframe_select( &UE->frame_parms, UE->slot_tx>>1 ) == SF_S) && - ((UE->slot_tx&1) == 1)) { - phy_procedures_UE_S_TX( UE, 0, 0, no_relay ); - } - - UE->slot_tx += 2; - - if (UE->slot_tx >= 20) { - UE->slot_tx -= 20; - UE->frame_tx++; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_UE, UE->frame_tx ); - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_UE, UE->slot_tx>>1 ); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX, 0 ); - - if (pthread_mutex_lock(&UE->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE TX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_tx_retval; - } - - UE->instance_cnt_tx--; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX, UE->instance_cnt_tx); - - if (pthread_mutex_unlock(&UE->mutex_tx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE TX thread\n" ); - exit_fun("nothing to add"); - return &UE_thread_tx_retval; - } - - } - - return &UE_thread_tx_retval; -} -*/ /*! @@ -804,7 +621,7 @@ static void *UE_thread_tx(void *arg) static void *UE_thread_rxn_txnp4(void *arg) { - static int UE_thread_rx_retval; + static int UE_thread_rxtx_retval; UE_rxtx_proc_t *proc = (UE_rxtx_proc_t *)arg; int ret; PHY_VARS_UE *UE=PHY_vars_UE_g[0][proc->CC_id]; @@ -828,8 +645,8 @@ static void *UE_thread_rxn_txnp4(void *arg) attr.sched_period = 1000000; // each rx thread has a period of 1ms from the starting point if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] UE_thread_rx : sched_setattr failed\n"); - return &UE_thread_rx_retval; + perror("[SCHED] UE_thread_rxtx : sched_setattr failed\n"); + return &UE_thread_rxtx_retval; } #else @@ -914,15 +731,15 @@ static void *UE_thread_rxn_txnp4(void *arg) pthread_cond_wait(&sync_cond, &sync_mutex); pthread_mutex_unlock(&sync_mutex); - printf("unlocked sync_mutex, waiting (UE_thread_rx)\n"); + printf("unlocked sync_mutex, waiting (UE_thread_rxtx)\n"); printf("Starting UE RXN_TXNP4 thread\n"); while (!oai_exit) { if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" ); + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); exit_fun("nothing to add"); - return &UE_thread_rx_retval; + return &UE_thread_rxtx_retval; } while (proc->instance_cnt_rxtx < 0) { @@ -933,7 +750,7 @@ static void *UE_thread_rxn_txnp4(void *arg) if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" ); exit_fun("nothing to add"); - return &UE_thread_rx_retval; + return &UE_thread_rxtx_retval; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 1 ); @@ -976,23 +793,23 @@ static void *UE_thread_rxn_txnp4(void *arg) if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" ); + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); exit_fun("noting to add"); - return &UE_thread_rx_retval; + return &UE_thread_rxtx_retval; } proc->instance_cnt_rxtx--; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, proc->instance_cnt_rxtx); if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" ); + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" ); exit_fun("noting to add"); - return &UE_thread_rx_retval; + return &UE_thread_rxtx_retval; } } // thread finished - return &UE_thread_rx_retval; + return &UE_thread_rxtx_retval; } @@ -1105,11 +922,11 @@ void *UE_thread(void *arg) { rxp[i] = (void*)&rxdata[i][0]; if (UE->mode != loop_through_memory) { - rxs = openair0.trx_read_func(&openair0, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti*10, - UE->frame_parms.nb_antennas_rx); + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti*10, + UE->frame_parms.nb_antennas_rx); } instance_cnt_synch = ++UE->proc.instance_cnt_synch; if (instance_cnt_synch == 0) { @@ -1132,11 +949,11 @@ void *UE_thread(void *arg) { rxp[i] = (void*)&dummy_rx[i][0]; for (int sf=0;sf<10;sf++) { // printf("Reading dummy sf %d\n",sf); - rxs = openair0.trx_read_func(&openair0, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti, - UE->frame_parms.nb_antennas_rx); + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_rx); } } } @@ -1147,11 +964,11 @@ void *UE_thread(void *arg) { start_rx_stream=1; if (UE->mode != loop_through_memory) { LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); - rxs = openair0.trx_read_func(&openair0, - ×tamp, - (void**)rxdata, - UE->rx_offset, - UE->frame_parms.nb_antennas_rx); + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void**)rxdata, + UE->rx_offset, + UE->frame_parms.nb_antennas_rx); if (rxs != UE->rx_offset) { exit_fun("problem in rx"); return &UE_thread_retval; @@ -1161,11 +978,11 @@ void *UE_thread(void *arg) { UE->proc.proc_rxtx[1].frame_rx++; // read in first symbol - rxs = openair0.trx_read_func(&openair0, - ×tamp, - (void**)rxdata, - UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, - UE->frame_parms.nb_antennas_rx); + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void**)rxdata, + UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx); slot_fep(UE, 0, 0, @@ -1192,21 +1009,21 @@ void *UE_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); if (UE->mode != loop_through_memory) { if (sf<9) { - rxs = openair0.trx_read_func(&openair0, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti, - UE->frame_parms.nb_antennas_rx); + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_rx); } else { - rxs = openair0.trx_read_func(&openair0, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0, - UE->frame_parms.nb_antennas_rx); + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx); // read in first symbol of next frame and adjust for timing drift - rxs = openair0.trx_read_func(&openair0, + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp1, (void**)rxdata, UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 - rx_off_diff, @@ -1383,7 +1200,7 @@ void *UE_thread_old(void *arg) if (UE->mode != loop_through_memory) { - rxs = openair0.trx_read_func(&openair0, + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, rxp, spp - ((first_rx==1) ? rx_off_diff : 0), @@ -1413,7 +1230,7 @@ void *UE_thread_old(void *arg) for (int i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void*)&txdata[i][txpos]; - openair0.trx_write_func(&openair0, + UE->rfdevice.trx_write_func(&openair0, (timestamp+openair0_cfg[0].tx_scheduling_advance-openair0_cfg[0].tx_sample_advance), txp, spp - ((first_rx==1) ? rx_off_diff : 0), @@ -1612,7 +1429,7 @@ void *UE_thread_old(void *arg) #ifndef USRP_DEBUG if (UE->mode != loop_through_memory) { LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); - rxs = openair0.trx_read_func(&openair0, + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, (void**)rxdata, UE->rx_offset, @@ -1673,16 +1490,18 @@ void *UE_thread_old(void *arg) * - UE_thread_synch * and the locking between them. */ -void init_UE_threads(void) +void init_UE_threads(int inst) { - PHY_VARS_UE *UE = PHY_vars_UE_g[0][0]; - - pthread_attr_init (&attr_UE_thread); - pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN); + PHY_VARS_UE *UE; + + UE = PHY_vars_UE_g[inst][0]; + pthread_attr_init (&UE->proc.attr_ue); + pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN); + #ifndef LOWLATENCY - sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO); - pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread); + UE->proc.sched_param_ue.sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_attr_setschedparam(&UE->proc.attr_ue,&sched_param_UE_thread); #endif // the threads are not yet active, therefore access is allowed without locking diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c index 2472328c76..f59c7d7f54 100644 --- a/targets/SIMU/USER/oaisim.c +++ b/targets/SIMU/USER/oaisim.c @@ -61,22 +61,15 @@ #include "LAYER2/MAC/proto.h" #include "LAYER2/MAC/vars.h" #include "pdcp.h" -#ifndef CELLULAR #include "RRC/LITE/vars.h" -#endif -#include "PHY_INTERFACE/vars.h" -//#endif #include "RRC/NAS/nas_config.h" -#ifdef IFFT_FPGA -//#include "PHY/LTE_REFSIG/mod_table.h" -#endif //IFFT_FPGA #include "SCHED/defs.h" #include "SCHED/vars.h" -//#ifdef XFORMS + #include "PHY/TOOLS/lte_phy_scope.h" -//#endif + #ifdef SMBV // Rohde&Schwarz SMBV100A vector signal generator @@ -143,6 +136,28 @@ channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs]; //Added for PHY abstraction node_desc_t *enb_data[NUMBER_OF_eNB_MAX]; node_desc_t *ue_data[NUMBER_OF_UE_MAX]; + +pthread_cond_t sync_cond; +pthread_mutex_t sync_mutex; +int sync_var; + + +openair0_config_t openair0_cfg[MAX_CARDS]; +uint32_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +openair0_rf_map rf_map[MAX_NUM_CCs]; + +#if defined(ENABLE_ITTI) +volatile int start_eNB = 0; +volatile int start_UE = 0; +#endif +volatile int oai_exit = 0; + + +//int32_t **rxdata; +//int32_t **txdata; + + // Added for PHY abstraction extern node_list* ue_node_list; extern node_list* enb_node_list; @@ -164,6 +179,9 @@ extern uint16_t Nid_cell; extern LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; +extern Enb_properties_array_t enb_properties; + + //#ifdef XFORMS int otg_enabled; int xforms=0; @@ -728,23 +746,32 @@ l2l1_task (void *args_p) #endif CC_id=0; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc.frame_rx = frame; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc.subframe_rx = sf; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].frame_rx = frame; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].subframe_rx = sf; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].subframe_tx = (sf+4)%10; - PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1].frame_tx = (sf<6) ? frame : frame+1; - phy_procedures_eNB_common_RX(PHY_vars_eNB_g[eNB_inst][CC_id], - abstraction_flag); - phy_procedures_eNB_uespec_RX(PHY_vars_eNB_g[eNB_inst][CC_id], - &PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1], - abstraction_flag, - no_relay); - phy_procedures_eNB_TX(PHY_vars_eNB_g[eNB_inst][CC_id], - &PHY_vars_eNB_g[eNB_inst][CC_id]->proc.proc_rxtx[sf&1], - 0,no_relay,NULL); + // trigger synch event to RAN FH thread for CC_id + eNB_proc_t *proc = &PHY_vars_eNB_g[eNB_inst][CC_id]->proc; + if (pthread_mutex_lock(&proc->mutex_FH) != 0) { + LOG_E( PHY, "error locking mutex for FH\n"); + exit_fun( "error locking mutex" ); + break; + } + int cnt_FH = ++proc->instance_cnt_FH; + proc->frame_rx = frame; + proc->subframe_rx = sf; + proc->timestamp_rx += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti; + + if (proc->instance_cnt_FH == 0) { + if (pthread_cond_signal(&proc->cond_FH) != 0) { + LOG_E(PHY,"ERROR pthread_cond_signal for eNB FH CCid %d\n",proc->CC_id); + exit_fun("ERROR pthread_cond_signal"); + break; + } + } + else { + LOG_W(PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %d)\n",proc->instance_cnt_FH); + exit_fun("FH thread busy"); + break; + } #ifdef PRINT_STATS if((sf==9) && frame%10==0) @@ -780,109 +807,9 @@ l2l1_task (void *args_p) log_set_instance_type (LOG_INSTANCE_UE); #endif + /* clear_UE_transport_info (oai_emulation.info.nb_ue_local); - for (UE_inst = oai_emulation.info.first_ue_local; - (UE_inst < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local)); - UE_inst++) { - if (oai_emulation.info.cli_start_ue[UE_inst] != 0) { -#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME) - -#else - - if (frame >= (UE_inst * 20)) // activate UE only after 20*UE_id frames so that different UEs turn on separately -#endif - { // UE_PROCEDURES - LOG_D(EMU, - "PHY procedures UE %d for frame %d, subframe %d\n", - UE_inst, frame % MAX_FRAME_NUMBER, sf); - - if (PHY_vars_UE_g[UE_inst][0]->UE_mode[0] - != NOT_SYNCHED) { - if (frame > 0) { - PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].frame_rx = frame % MAX_FRAME_NUMBER; - PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].subframe_rx = sf; - PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].frame_tx = ((sf<6) ? frame : frame+1)% MAX_FRAME_NUMBER; - PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1].subframe_tx = (sf+4)%10; - -#ifdef OPENAIR2 - //Application - update_otg_UE (UE_inst, oai_emulation.info.time_ms); - - //Access layer - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, 0, ENB_FLAG_NO, NOT_A_RNTI, frame % MAX_FRAME_NUMBER, sf); - pdcp_run (&ctxt); -#endif - - for (CC_id = 0; CC_id < MAX_NUM_CCs; - CC_id++) { - phy_procedures_UE_RX(PHY_vars_UE_g[UE_inst][CC_id], - &PHY_vars_UE_g[UE_inst][CC_id]->proc.proc_rxtx[sf&1], - 0, abstraction_flag, - normal_txrx, no_relay, - NULL); - phy_procedures_UE_TX(PHY_vars_UE_g[UE_inst][CC_id], - &PHY_vars_UE_g[UE_inst][CC_id]->proc.proc_rxtx[sf&1], - 0, - abstraction_flag, - normal_txrx, - no_relay); - } - - ue_data[UE_inst]->tx_power_dBm = - PHY_vars_UE_g[UE_inst][0]->tx_power_dBm; - } - } else { - if (abstraction_flag == 1) { - LOG_E(EMU, - "sync not supported in abstraction mode (UE%d,mode%d)\n", - UE_inst, - PHY_vars_UE_g[UE_inst][0]->UE_mode[0]); - exit (-1); - } - - if ((frame > 0) - && (sf==9)){ - - initial_sync (PHY_vars_UE_g[UE_inst][0], - normal_txrx); - - /* - write_output("dlchan00.m","dlch00",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][0][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); - if (PHY_vars_UE_g[0]->frame_parms.nb_antennas_rx>1) - write_output("dlchan01.m","dlch01",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][1][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); - write_output("dlchan10.m","dlch10",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][2][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); - if (PHY_vars_UE_g[0]->frame_parms.nb_antennas_rx>1) - write_output("dlchan11.m","dlch11",&(PHY_vars_UE_g[0]->common_vars.dl_ch_estimates[0][3][0]),(6*(PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size)),1,1); - write_output("rxsig.m","rxs",PHY_vars_UE_g[0]->common_vars.rxdata[0],PHY_vars_UE_g[0]->frame_parms.samples_per_tti*10,1,1); - write_output("rxsigF.m","rxsF",PHY_vars_UE_g[0]->common_vars.rxdataF[0],2*PHY_vars_UE_g[0]->frame_parms.symbols_per_tti*PHY_vars_UE_g[0]->frame_parms.ofdm_symbol_size,2,1); - write_output("pbch_rxF_ext0.m","pbch_ext0",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->rxdataF_ext[0],6*12*4,1,1); - write_output("pbch_rxF_comp0.m","pbch_comp0",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->rxdataF_comp[0],6*12*4,1,1); - write_output("pbch_rxF_llr.m","pbch_llr",PHY_vars_UE_g[0]->lte_ue_pbch_vars[0]->llr,(frame_parms->Ncp==0) ? 1920 : 1728,1,4); - */ - } - } - -#ifdef PRINT_STATS - - if((sf==1) && frame%10==0) { - if (UE_stats_th[UE_inst]) { - fprintf(UE_stats_th[UE_inst],"%d %d\n",frame % MAX_FRAME_NUMBER, PHY_vars_UE_g[UE_inst][0]->bitrate[0]/1000); - } - } - - if (UE_stats[UE_inst]) { - len = dump_ue_stats (PHY_vars_UE_g[UE_inst][0], &PHY_vars_UE_g[UE_inst][0]->proc.proc_rxtx[sf&1],stats_buffer, 0, normal_txrx, 0); - rewind (UE_stats[UE_inst]); - fwrite (stats_buffer, 1, len, UE_stats[UE_inst]); - fflush(UE_stats[UE_inst]); - } - -#endif - } // UE_PROCEDURES - } - } // UE_inst - emu_transport (frame % MAX_FRAME_NUMBER, sf<<1, ((sf+4)%10)<<1, subframe_select(&PHY_vars_eNB_g[0][0]->frame_parms,sf), oai_emulation.info.frame_type[0], ethernet_flag); @@ -942,6 +869,7 @@ l2l1_task (void *args_p) stop_meas (&ul_chan_stats); + */ if ((sf == 0) && ((frame % MAX_FRAME_NUMBER) == 0) && (abstraction_flag == 0) && (oai_emulation.info.n_frames == 1)) { @@ -1200,7 +1128,7 @@ main (int argc, char **argv) // oai performance profiler is enabled if (oai_emulation.info.opp_enabled == 1) - reset_opp_meas (); + reset_opp_meas_oaisim (); init_time (); @@ -1242,7 +1170,7 @@ main (int argc, char **argv) } void -reset_opp_meas (void) +reset_opp_meas_oaisim (void) { uint8_t eNB_id = 0, UE_id = 0; @@ -1383,7 +1311,7 @@ reset_opp_meas (void) } void -print_opp_meas (void) +print_opp_meas_oaisim (void) { uint8_t eNB_id = 0, UE_id = 0; @@ -1687,7 +1615,7 @@ oai_shutdown (void) kpi_gen (); } if (oai_emulation.info.opp_enabled == 1) - print_opp_meas (); + print_opp_meas_oaisim (); // relase all rx state if (ethernet_flag == 1) { diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 867d578ce9..c8f42dfdd8 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -772,12 +772,13 @@ void get_simulation_options(int argc, char *argv[]) AssertFatal (oai_emulation.info.nb_enb_local <= enb_properties->number, "Number of eNB is greater than eNB defined in configuration file %s (%d/%d)!", conf_config_file_name, oai_emulation.info.nb_enb_local, enb_properties->number); - + /* Update some simulation parameters */ oai_emulation.info.frame_type[0] = enb_properties->properties[0]->frame_type[0]; oai_emulation.info.tdd_config[0] = enb_properties->properties[0]->tdd_config[0]; oai_emulation.info.tdd_config_S[0] = enb_properties->properties[0]->tdd_config_s[0]; oai_emulation.info.extended_prefix_flag[0] = enb_properties->properties[0]->prefix_type[0]; + } free(conf_config_file_name); @@ -1016,23 +1017,26 @@ void init_openair1(void) } else { PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 0; } - } - } + } // eNB_id + } // CC_id - for (eNB_id=0; eNB_idmac_enabled=0; else PHY_vars_eNB_g[eNB_id][CC_id]->mac_enabled=1; } + } + + init_eNB(eNodeB_3GPP,NB_eNB_INST); // init_ue_status(); - for (UE_id=0; UE_idtx_power_max_dBm=23; - + PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB=100; // update UE_mode for each eNB_id not just 0 @@ -1065,8 +1069,10 @@ void init_openair1(void) #endif + } // CC_id + } // UE_id + init_UE(NB_UE_INST); } -} void init_openair2(void) { From e0f0072023d8f17a4320adaa4531d8cf54104e45 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 24 Jul 2016 01:21:35 -0700 Subject: [PATCH 107/206] oaisim with interfaces for lte-ue/lte-enb threading compiles and runs. --- openair2/ENB_APP/enb_config.c | 5 +- openair2/UTIL/OCG/OCG.h | 5 +- targets/ARCH/COMMON/common_lib.h | 3 + ...enb.band7.generic.oaisim.local_no_mme.conf | 7 +- targets/RT/USER/lte-enb.c | 224 ++++---- targets/RT/USER/lte-softmodem.c | 8 +- targets/SIMU/USER/channel_sim.c | 535 ++++++++---------- targets/SIMU/USER/oaisim.c | 4 +- targets/SIMU/USER/oaisim.h | 10 +- targets/SIMU/USER/oaisim_functions.c | 133 ++++- 10 files changed, 508 insertions(+), 426 deletions(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 35d02f8842..cecdf623ef 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -59,6 +59,7 @@ #include "sctp_default_values.h" #include "SystemInformationBlockType2.h" #include "LAYER2/MAC/extern.h" +#include "PHY/extern.h" #define ENB_CONFIG_STRING_ACTIVE_ENBS "Active_eNBs" @@ -321,8 +322,8 @@ void enb_config_display(void) for (j=0; j< enb_properties.properties[i]->nb_cc; j++) { // CC_ID node function/timing - printf( "\n\tnode_function for CC %d: \t%d:\n",j,enb_properties.properties[i]->cc_node_function[j]); - printf( "\tnode_timing for CC %d: \t%d:\n",j,enb_properties.properties[i]->cc_node_timing[j]); + printf( "\n\tnode_function for CC %d: \t%s:\n",j,eNB_functions[enb_properties.properties[i]->cc_node_function[j]]); + printf( "\tnode_timing for CC %d: \t%s:\n",j,eNB_timing[enb_properties.properties[i]->cc_node_timing[j]]); printf( "\tnode_synch_ref for CC %d: \t%d:\n",j,enb_properties.properties[i]->cc_node_synch_ref[j]); printf( "\teutra band for CC %d: \t%"PRId16":\n",j,enb_properties.properties[i]->eutra_band[j]); diff --git a/openair2/UTIL/OCG/OCG.h b/openair2/UTIL/OCG/OCG.h index c47cc8e8c7..55b55c7e5f 100644 --- a/openair2/UTIL/OCG/OCG.h +++ b/openair2/UTIL/OCG/OCG.h @@ -44,6 +44,7 @@ #ifndef __OCG_H__ #define __OCG_H__ +#include "PHY/defs.h" #include "PHY/impl_defs_top.h" #include "platform_types.h" @@ -707,8 +708,8 @@ typedef struct { // phy related params unsigned int n_frames; unsigned int n_frames_flag; // if set, then let the emulation goes to infinity - node_function_t node_function[MAX_NUM_CCs]; - node_timing_t node_timing[MAX_NUM_CCS]; + eNB_func_t node_function[MAX_NUM_CCs]; + eNB_timing_t node_timing[MAX_NUM_CCs]; unsigned char frame_type[MAX_NUM_CCs]; //! LTE frame type (TDD=1, FDD=0). \note this should be converted to \ref lte_frame_type_t (header file reorganization needed) char * frame_type_name[MAX_NUM_CCs]; unsigned char tdd_config[MAX_NUM_CCs]; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 70f098217a..17d1f7b180 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -248,6 +248,9 @@ typedef struct { struct openair0_device_t { /*!brief Module ID of this device */ int Mod_id; + + /*!brief Component Carrier ID of this device */ + int CC_id; /*!brief Type of this device */ dev_type_t type; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf index 3ec8ea01da..ad3bcfcf92 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf @@ -24,7 +24,8 @@ eNBs = component_carriers = ( { node_function = "eNodeB_3GPP"; - node_timing = "SYNCH_TO_OTHER"; + node_timing = "synch_to_other"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; @@ -37,8 +38,8 @@ eNBs = Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; - tx_gain = 25; - rx_gain = 20; + tx_gain = 25; + rx_gain = 20; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 2ec507e4c3..177291596b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -157,8 +157,8 @@ static struct { void exit_fun(const char* s); -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[]); -void stop_eNB(void); +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst); +void stop_eNB(int nb_inst); void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { @@ -647,6 +647,8 @@ static void* eNB_thread_asynch_rx( void* param ) { uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; int prach_rx; + int dummy_rx[fp->nb_antennas_rx][fp->samples_per_tti]; + int rxs; #ifdef DEADLINE_SCHEDULER struct sched_attr attr; @@ -739,7 +741,34 @@ static void* eNB_thread_asynch_rx( void* param ) { #endif // DEADLINE_SCHEDULER - if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF + + mlockall(MCL_CURRENT | MCL_FUTURE); + + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + printf( "waiting for sync (eNB_thread_asynch_rx)\n"); + pthread_mutex_lock( &sync_mutex ); + + while (sync_var<0) + pthread_cond_wait( &sync_cond, &sync_mutex ); + + pthread_mutex_unlock(&sync_mutex); + + printf( "got sync (eNB_thread_asynch_rx)\n" ); + + if (eNB->node_function == eNodeB_3GPP) { // acquisition from RF + + if (eNB->rfdevice.trx_read_func) + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, + &proc->timestamp_rx, + (void**)dummy_rx, + fp->samples_per_tti, + fp->nb_antennas_rx); + else { + printf("eNB asynch RX\n"); + sleep(1); + } + } + else if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); recv_IF5(eNB, ×tamp_rx, subframe_rx++, IF5_RRH_GW_UL); @@ -938,7 +967,7 @@ static void* eNB_thread_FH( void* param ) { pthread_mutex_unlock(&sync_mutex); - printf( "got sync (eNB_thread)\n" ); + printf( "got sync (eNB_thread FH)\n" ); #if defined(ENABLE_ITTI) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); @@ -1394,108 +1423,106 @@ static void* eNB_thread_prach( void* param ) { } -void init_eNB_proc(int nb_inst) { +void init_eNB_proc(int inst) { int i; int CC_id; PHY_VARS_eNB *eNB; eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; - int inst; - - for (inst = 0; inst < nb_inst; inst++) { - for (CC_id=0; CC_idnode_function],eNB_timing[eNB->node_timing]); - proc = &eNB->proc; - proc_rxtx = proc->proc_rxtx; + + for (CC_id=0; CC_idnode_function],eNB_timing[eNB->node_timing]); + proc = &eNB->proc; + proc_rxtx = proc->proc_rxtx; #ifndef DEADLINE_SCHEDULER - /* - pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_TX] setting thread stack size failed\n"); - - pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_RX] setting thread stack size failed\n"); - */ - // set the kernel scheduling policy and priority - proc_rxtx[0].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[0].attr_rxtx, &proc_rxtx[0].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[0].attr_rxtx, SCHED_FIFO); - proc_rxtx[1].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); - - proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_FH, &proc->sched_param_FH); - pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO); - - proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); - pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); - - printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); -#endif - proc_rxtx[0].instance_cnt_rxtx = -1; - proc_rxtx[1].instance_cnt_rxtx = -1; - proc->instance_cnt_prach = -1; - proc->instance_cnt_FH = -1; - proc->CC_id = CC_id; - - proc->first_rx=4; - - pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); - pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); - pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_FH, NULL); -#ifndef DEADLINE_SCHEDULER - pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc ); -#else - pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc ); - -#endif - char name[16]; - snprintf( name, sizeof(name), "RXTX0 %d", i ); - pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); - snprintf( name, sizeof(name), "RXTX1 %d", i ); - pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); - snprintf( name, sizeof(name), "FH %d", i ); - pthread_setname_np( proc->pthread_FH, name ); - } + /* + pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); + if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) + perror("[ENB_PROC_TX] setting thread stack size failed\n"); + + pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); + if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) + perror("[ENB_PROC_RX] setting thread stack size failed\n"); + */ + // set the kernel scheduling policy and priority + proc_rxtx[0].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc_rxtx[0].attr_rxtx, &proc_rxtx[0].sched_param_rxtx); + pthread_attr_setschedpolicy (&proc_rxtx[0].attr_rxtx, SCHED_FIFO); + proc_rxtx[1].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); + pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); - /* setup PHY proc TX sync mechanism */ - pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); - pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); - sync_phy_proc.phy_proc_CC_id = 0; + proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_FH, &proc->sched_param_FH); + pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO); + + proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); + pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); + + printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); +#endif + proc_rxtx[0].instance_cnt_rxtx = -1; + proc_rxtx[1].instance_cnt_rxtx = -1; + proc->instance_cnt_prach = -1; + proc->instance_cnt_FH = -1; + proc->CC_id = CC_id; + + proc->first_rx=4; + + pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); + pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); + pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); + pthread_cond_init( &proc->cond_prach, NULL); + pthread_cond_init( &proc->cond_FH, NULL); +#ifndef DEADLINE_SCHEDULER + pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); + pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); + pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); + if (eNB->node_timing == synch_to_other) + pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc ); +#else + pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); + pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); + pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); + if (eNB->node_timing == synch_to_other) + pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc ); + +#endif + char name[16]; + snprintf( name, sizeof(name), "RXTX0 %d", i ); + pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); + snprintf( name, sizeof(name), "RXTX1 %d", i ); + pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); + snprintf( name, sizeof(name), "FH %d", i ); + pthread_setname_np( proc->pthread_FH, name ); } + + /* setup PHY proc TX sync mechanism */ + pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); + pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); + sync_phy_proc.phy_proc_CC_id = 0; } + /*! * \brief Terminate eNB TX and RX threads. */ -void kill_eNB_proc(void) { +void kill_eNB_proc(int inst) { int *status; PHY_VARS_eNB *eNB; eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; for (int CC_id=0; CC_idproc; proc_rxtx = &proc->proc_rxtx[0]; @@ -1650,16 +1677,21 @@ void print_opp_meas(void) { } -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[]) { + void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst) { int CC_id; - - for (CC_id=0;CC_idnode_function = node_function[CC_id]; - PHY_vars_eNB_g[0][CC_id]->node_timing = node_timing[CC_id]; - } + int inst; - init_eNB_proc(); + for (inst=0;instnode_function = node_function[CC_id]; + PHY_vars_eNB_g[inst][CC_id]->node_timing = node_timing[CC_id]; + LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]); + } + + init_eNB_proc(inst); + } + sleep(1); LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); @@ -1677,7 +1709,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[]) { } -void stop_eNB() { +void stop_eNB(int nb_inst) { /* #ifdef DEBUG_THREADS @@ -1702,6 +1734,8 @@ void stop_eNB() { #endif // DEBUG_THREADS */ - printf("Killing eNB processing threads\n"); - kill_eNB_proc(); + for (int inst=0;instnb_rx; // number of rx antennas at UE uint8_t nb_antennas_tx = eNB2UE[0][0][CC_id]->nb_tx; // number of tx antennas at eNB - //LTE_DL_FRAME_PARMS *fp; - // int subframe_sched = ((next_slot>>1) == 0) ? 9 : ((next_slot>>1)-1); + double s_re[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + double s_im[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + double r_re0[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + double r_im0[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + - - if (next_slot==0) + if (subframe==0) hold_channel = 0; else hold_channel = 1; @@ -186,19 +192,6 @@ void do_DL_sig(double **r_re0,double **r_im0, } } - /* - if(PHY_vars_UE_g[UE_id]->transmission_mode[att_eNB_id]>=5) - { - lte_ue_measurements(PHY_vars_UE_g[UE_id], - ((next_slot-1)>>1)*frame_parms->samples_per_tti, - 1, - abstraction_flag); - - PHY_vars_eNB_g[att_eNB_id]->dlsch_eNB[0][0]->pmi_alloc = quantize_subband_pmi(&PHY_vars_UE_g[UE_id]->PHY_measurements,0); - // printf("pmi_alloc in channel sim: %d",PHY_vars_eNB_g[att_eNB_id]->dlsch_eNB[0][0]->pmi_alloc); - } - */ - // calculate the SNR for the attached eNB (this assumes eNB always uses PMI stored in eNB_UE_stats; to be improved) init_snr(eNB2UE[att_eNB_id][UE_id][CC_id], enb_data[att_eNB_id], ue_data[UE_id], PHY_vars_UE_g[UE_id][CC_id]->sinr_dB, &PHY_vars_UE_g[UE_id][CC_id]->N0, PHY_vars_UE_g[UE_id][CC_id]->transmission_mode[att_eNB_id], PHY_vars_eNB_g[att_eNB_id][CC_id]->UE_stats[UE_id].DL_pmi_single, @@ -214,52 +207,44 @@ void do_DL_sig(double **r_re0,double **r_im0, } else { //abstraction_flag - /* - Call do_OFDM_mod from phy_procedures_eNB_TX function - */ - // printf("r_re[0] %p\n",r_re[0]); - for (aa=0; aasamples_per_tti>>1)*sizeof(double)); - memset((void*)r_im[aa],0,(frame_parms->samples_per_tti>>1)*sizeof(double)); + + pthread_mutex_lock(&eNB_output_mutex[UE_id]); + if (eNB_output_mask[UE_id] == 0) { // This is the first eNodeB for this UE, clear the buffer + + for (aa=0; aasamples_per_tti)*sizeof(double)); + memset((void*)r_im_DL[UE_id][aa],0,(frame_parms->samples_per_tti)*sizeof(double)); + } } + pthread_mutex_unlock(&eNB_output_mutex[UE_id]); - /* - for (i=0;i<16;i++) - printf("%f, %X\n",r_re[aa][i],(unsigned long long)r_re[aa][i]); - */ for (eNB_id=0; eNB_idtx_power_dBm + - // eNB2UE[eNB_id][UE_id]->path_loss_dB) <= -107.0) - // break; - txdata = PHY_vars_eNB_g[eNB_id][CC_id]->common_vars.txdata[0]; - slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); - slot_offset_meas = ((next_slot&1)==0) ? slot_offset : (slot_offset-(frame_parms->samples_per_tti>>1)); - tx_pwr = dac_fixed_gain(s_re, - s_im, + sf_offset = subframe*frame_parms->samples_per_tti; + tx_pwr = dac_fixed_gain((double**)s_re, + (double**)s_im, txdata, - slot_offset, + sf_offset, nb_antennas_tx, - frame_parms->samples_per_tti>>1, - slot_offset_meas, + frame_parms->samples_per_tti, + sf_offset, frame_parms->ofdm_symbol_size, 14, - // enb_data[eNB_id]->tx_power_dBm); frame_parms->pdsch_config_common.referenceSignalPower, // dBm/RE frame_parms->N_RB_DL*12); #ifdef DEBUG_SIM - LOG_D(OCM,"[SIM][DL] eNB %d (CCid %d): tx_pwr %.1f dBm/RE (target %d dBm/RE), for slot %d (subframe %d)\n", + LOG_D(OCM,"[SIM][DL] eNB %d (CCid %d): tx_pwr %.1f dBm/RE (target %d dBm/RE), for subframe %d\n", eNB_id,CC_id, 10*log10(tx_pwr), frame_parms->pdsch_config_common.referenceSignalPower, - next_slot, - next_slot>>1); + subframe); + #endif //eNB2UE[eNB_id][UE_id]->path_loss_dB = 0; - multipath_channel(eNB2UE[eNB_id][UE_id][CC_id],s_re,s_im,r_re0,r_im0, - frame_parms->samples_per_tti>>1,hold_channel); + multipath_channel(eNB2UE[eNB_id][UE_id][CC_id],(double**)s_re,(double**)s_im,(double**)r_re0,(double**)r_im0, + frame_parms->samples_per_tti,hold_channel); #ifdef DEBUG_SIM rx_pwr = signal_energy_fp2(eNB2UE[eNB_id][UE_id][CC_id]->ch[0], eNB2UE[eNB_id][UE_id][CC_id]->channel_length)*eNB2UE[eNB_id][UE_id][CC_id]->channel_length; @@ -281,17 +266,17 @@ void do_DL_sig(double **r_re0,double **r_im0, eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB); #ifdef DEBUG_SIM - rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx, + rx_pwr = signal_energy_fp((double**)r_re0,(double**)r_im0,nb_antennas_rx, frame_parms->ofdm_symbol_size, - slot_offset_meas)/(12.0*frame_parms->N_RB_DL); - LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr %f dBm/RE (%f dBm RSSI)for slot %d (subframe %d)\n",UE_id, + sf_offset)/(12.0*frame_parms->N_RB_DL); + LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr %f dBm/RE (%f dBm RSSI)for subframe %d\n",UE_id, 10*log10(rx_pwr), - 10*log10(rx_pwr*(double)frame_parms->N_RB_DL*12),next_slot,next_slot>>1); + 10*log10(rx_pwr*(double)frame_parms->N_RB_DL*12),subframe); LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (noise) -132 dBm/RE (N0fs = %.1f dBm, N0B = %.1f dBm) for slot %d (subframe %d)\n", UE_id, 10*log10(eNB2UE[eNB_id][UE_id][CC_id]->sampling_rate*1e6)-174, 10*log10(eNB2UE[eNB_id][UE_id][CC_id]->sampling_rate*1e6*12*frame_parms->N_RB_DL/(double)frame_parms->ofdm_symbol_size)-174, - next_slot,next_slot>>1); + subframe); #endif if (eNB2UE[eNB_id][UE_id][CC_id]->first_run == 1) @@ -300,96 +285,85 @@ void do_DL_sig(double **r_re0,double **r_im0, // RF model #ifdef DEBUG_SIM - LOG_D(OCM,"[SIM][DL] UE %d (CCid %d): rx_gain %d dB (-ADC %f) for slot %d (subframe %d)\n",UE_id,CC_id,PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB, - PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB-66.227,next_slot,next_slot>>1); + LOG_D(OCM,"[SIM][DL] UE %d (CCid %d): rx_gain %d dB (-ADC %f) for subframe %d\n",UE_id,CC_id,PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB, + PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB-66.227,subframe); #endif - /* - rf_rx(r_re0, - r_im0, - NULL, - NULL, - 0, - nb_antennas_rx, - frame_parms->samples_per_tti>>1, - 1e3/eNB2UE[eNB_id][UE_id]->BW, // sampling time (ns) - 0.0, // freq offset (Hz) (-20kHz..20kHz) - 0.0, // drift (Hz) NOT YET IMPLEMENTED - ue_data[UE_id]->rx_noise_level, // noise_figure NOT YET IMPLEMENTED - (double)PHY_vars_UE_g[UE_id]->rx_total_gain_dB - 66.227, // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) - 200.0, // IP3_dBm (dBm) - &eNB2UE[eNB_id][UE_id]->ip, // initial phase - 30.0e3, // pn_cutoff (kHz) - -500.0, // pn_amp (dBc) default: 50 - 0.0, // IQ imbalance (dB), - 0.0); // IQ phase imbalance (rad) - */ - rf_rx_simple(r_re0, - r_im0, + rf_rx_simple((double**)r_re0, + (double**)r_im0, nb_antennas_rx, - frame_parms->samples_per_tti>>1, + frame_parms->samples_per_tti, 1e3/eNB2UE[eNB_id][UE_id][CC_id]->sampling_rate, // sampling time (ns) (double)PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) #ifdef DEBUG_SIM - rx_pwr = signal_energy_fp(r_re0,r_im0, + rx_pwr = signal_energy_fp((double**)r_re0,(double**)r_im0, nb_antennas_rx, frame_parms->ofdm_symbol_size, - slot_offset_meas)/(12.0*frame_parms->N_RB_DL); - LOG_D(OCM,"[SIM][DL] UE %d : ADC in (eNB %d) %f dBm/RE for slot %d (subframe %d)\n", + sf_offset)/(12.0*frame_parms->N_RB_DL); + LOG_D(OCM,"[SIM][DL] UE %d : ADC in (eNB %d) %f dBm/RE for subframe %d\n", UE_id,eNB_id, - 10*log10(rx_pwr),next_slot,next_slot>>1); + 10*log10(rx_pwr),subframe); #endif - - for (i=0; i<(frame_parms->samples_per_tti>>1); i++) { + + pthread_mutex_lock(&eNB_output_mutex[UE_id]); + for (i=0; isamples_per_tti; i++) { for (aa=0; aaofdm_symbol_size,slot_offset_meas)/(12.0*frame_parms->N_RB_DL); - LOG_D(OCM,"[SIM][DL] UE %d : ADC in %f dBm for slot %d (subframe %d)\n",UE_id,10*log10(rx_pwr),next_slot,next_slot>>1); + rx_pwr = signal_energy_fp((double**)r_re_DL[UE_id],(double**)r_im_DL[UE_id],nb_antennas_rx,frame_parms->ofdm_symbol_size,sf_offset)/(12.0*frame_parms->N_RB_DL); + LOG_D(OCM,"[SIM][DL] UE %d : ADC in %f dBm for subframe %d\n",UE_id,10*log10(rx_pwr),subframe); #endif - - rxdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.rxdata; - slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); - - adc(r_re, - r_im, - 0, - slot_offset, - rxdata, - nb_antennas_rx, - frame_parms->samples_per_tti>>1, - 12); - + + rxdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.rxdata; + sf_offset = subframe*frame_parms->samples_per_tti; + + adc((double**)r_re_DL[UE_id], + (double**)r_im_DL[UE_id], + 0, + sf_offset, + rxdata, + nb_antennas_rx, + frame_parms->samples_per_tti, + 12); + #ifdef DEBUG_SIM - rx_pwr2 = signal_energy(rxdata[0]+slot_offset,frame_parms->ofdm_symbol_size)/(12.0*frame_parms->N_RB_DL); - LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (ADC out) %f dB/RE (%d) for slot %d (subframe %d), writing to %p\n",UE_id, 10*log10((double)rx_pwr2),rx_pwr2,next_slot,next_slot>>1,rxdata); + rx_pwr2 = signal_energy(rxdata[0]+sf_offset,frame_parms->ofdm_symbol_size)/(12.0*frame_parms->N_RB_DL); + LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (ADC out) %f dB/RE (%d) for subframe %d, writing to %p\n",UE_id, 10*log10((double)rx_pwr2),rx_pwr2,subframe,rxdata); #else - UNUSED_VARIABLE(rx_pwr2); - UNUSED_VARIABLE(tx_pwr); - UNUSED_VARIABLE(rx_pwr); + UNUSED_VARIABLE(rx_pwr2); + UNUSED_VARIABLE(tx_pwr); + UNUSED_VARIABLE(rx_pwr); #endif - //}// UE_index loop + + } // eNB_output_mask + pthread_mutex_unlock(&eNB_output_mutex[UE_id]); + } // eNB_id + } } -void do_UL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double **s_re,double **s_im,channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs], - node_desc_t *enb_data[NUMBER_OF_eNB_MAX],node_desc_t *ue_data[NUMBER_OF_UE_MAX],uint16_t next_slot,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms, uint32_t frame,uint8_t CC_id) +void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs], + node_desc_t *enb_data[NUMBER_OF_eNB_MAX],node_desc_t *ue_data[NUMBER_OF_UE_MAX], + uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms, + uint32_t frame,int eNB_id,uint8_t CC_id) { int32_t **txdata,**rxdata; #ifdef PHY_ABSTRACTION_UL int32_t att_eNB_id=-1; #endif - uint8_t eNB_id=0,UE_id=0; + uint8_t UE_id=0; uint8_t nb_antennas_rx = UE2eNB[0][0][CC_id]->nb_rx; // number of rx antennas at eNB uint8_t nb_antennas_tx = UE2eNB[0][0][CC_id]->nb_tx; // number of tx antennas at UE @@ -397,7 +371,7 @@ void do_UL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double double tx_pwr, rx_pwr; int32_t rx_pwr2; uint32_t i,aa; - uint32_t slot_offset,slot_offset_meas; + uint32_t sf_offset; uint8_t hold_channel=0; @@ -408,192 +382,149 @@ void do_UL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double int ulnbrb2 ; int ulfrrb2 ; uint8_t harq_pid; - int subframe = (next_slot>>1); #endif - - /* - if (next_slot==4) - hold_channel = 0; - else - hold_channel = 1; - */ + double s_re[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_im[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_re0[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_im0[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; if (abstraction_flag!=0) { #ifdef PHY_ABSTRACTION_UL - for (eNB_id=0; eNB_idN_RB_UL,frame_parms->N_RB_UL*12+1); - - // REceived power at the eNB - rx_pwr = signal_energy_fp2(UE2eNB[UE_id][eNB_id][CC_id]->ch[0], - UE2eNB[UE_id][eNB_id][CC_id]->channel_length)*UE2eNB[UE_id][att_eNB_id][CC_id]->channel_length; // calculate the rx power at the eNB - } - - // write_output("SINRch.m","SINRch",PHY_vars_eNB_g[att_eNB_id]->sinr_dB_eNB,frame_parms->N_RB_UL*12+1,1,1); - if(subframe>1 && subframe <5) { - harq_pid = subframe2harq_pid(frame_parms,frame,subframe); - ul_nb_rb = PHY_vars_eNB_g[att_eNB_id][CC_id]->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->nb_rb; - ul_fr_rb = PHY_vars_eNB_g[att_eNB_id][CC_id]->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->first_rb; - } - - if(ul_nb_rb>1 && (ul_fr_rb < 25 && ul_fr_rb > -1)) { - number_rb_ul = ul_nb_rb; - first_rbUL = ul_fr_rb; - init_snr_up(UE2eNB[UE_id][att_eNB_id][CC_id],enb_data[att_eNB_id], ue_data[UE_id],PHY_vars_eNB_g[att_eNB_id][CC_id]->sinr_dB,&PHY_vars_UE_g[att_eNB_id][CC_id]->N0,ul_nb_rb,ul_fr_rb); - - } - } //UE_id - } //eNB_id + for (UE_id=0; UE_idN_RB_UL,frame_parms->N_RB_UL*12+1); + + // REceived power at the eNB + rx_pwr = signal_energy_fp2(UE2eNB[UE_id][eNB_id][CC_id]->ch[0], + UE2eNB[UE_id][eNB_id][CC_id]->channel_length)*UE2eNB[UE_id][att_eNB_id][CC_id]->channel_length; // calculate the rx power at the eNB + } + + // write_output("SINRch.m","SINRch",PHY_vars_eNB_g[att_eNB_id]->sinr_dB_eNB,frame_parms->N_RB_UL*12+1,1,1); + if(subframe>1 && subframe <5) { + harq_pid = subframe2harq_pid(frame_parms,frame,subframe); + ul_nb_rb = PHY_vars_eNB_g[att_eNB_id][CC_id]->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->nb_rb; + ul_fr_rb = PHY_vars_eNB_g[att_eNB_id][CC_id]->ulsch_eNB[(uint8_t)UE_id]->harq_processes[harq_pid]->first_rb; + } + + if(ul_nb_rb>1 && (ul_fr_rb < 25 && ul_fr_rb > -1)) { + number_rb_ul = ul_nb_rb; + first_rbUL = ul_fr_rb; + init_snr_up(UE2eNB[UE_id][att_eNB_id][CC_id],enb_data[att_eNB_id], ue_data[UE_id],PHY_vars_eNB_g[att_eNB_id][CC_id]->sinr_dB,&PHY_vars_UE_g[att_eNB_id][CC_id]->N0,ul_nb_rb,ul_fr_rb); + + } + } //UE_id #else - /* the following functions are not needed */ - /* - if (abstraction_flag!=0) { - for (eNB_id=0;eNB_idN_RB_UL,2); - } - } - } - */ + #endif } else { //without abstraction - for (eNB_id=0; eNB_idsamples_per_tti>>1); i++) { - for (aa=0; aasamples_per_tti; i++) { + for (aa=0; aacommon_vars.txdata; + sf_offset = subframe*frame_parms->samples_per_tti; + + if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm + + UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB) <= -125.0) { + // don't simulate a UE that is too weak + } else { + + tx_pwr = dac_fixed_gain((double**)s_re, + (double**)s_im, + txdata, + sf_offset, + nb_antennas_tx, + frame_parms->samples_per_tti, + sf_offset, + frame_parms->ofdm_symbol_size, + 14, + (double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE), + PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE); // This make the previous argument the total power + LOG_D(OCM,"[SIM][UL] UE %d tx_pwr %f dBm (target %d dBm, num_RE %d) for subframe %d (sf_offset %d)\n", + UE_id, + 10*log10(tx_pwr), + PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm, + PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE, + subframe,sf_offset); + + + multipath_channel(UE2eNB[UE_id][eNB_id][CC_id],(double**)s_re,(double**)s_im,(double**)r_re0,(double**)r_im0, + frame_parms->samples_per_tti,hold_channel); + - txdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.txdata; - slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); - slot_offset_meas = ((next_slot&1)==0) ? slot_offset : (slot_offset-(frame_parms->samples_per_tti>>1)); + rx_pwr = signal_energy_fp2(UE2eNB[UE_id][eNB_id][CC_id]->ch[0], + UE2eNB[UE_id][eNB_id][CC_id]->channel_length)*UE2eNB[UE_id][eNB_id][CC_id]->channel_length; - if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm + - UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB) <= -125.0) { - - // don't simulate a UE that is too weak - } else { - - tx_pwr = dac_fixed_gain(s_re, - s_im, - txdata, - slot_offset, - nb_antennas_tx, - frame_parms->samples_per_tti>>1, - slot_offset_meas, - frame_parms->ofdm_symbol_size, - 14, - (double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE), - PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE); // This make the previous argument the total power - //ue_data[UE_id]->tx_power_dBm); - //#ifdef DEBUG_SIM - LOG_D(OCM,"[SIM][UL] UE %d tx_pwr %f dBm (target %d dBm, num_RE %d) for slot %d (subframe %d, slot_offset %d, slot_offset_meas %d)\n", - UE_id, - 10*log10(tx_pwr), - PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm, - PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE, - next_slot,next_slot>>1,slot_offset,slot_offset_meas); - //#endif - - multipath_channel(UE2eNB[UE_id][eNB_id][CC_id],s_re,s_im,r_re0,r_im0, - frame_parms->samples_per_tti>>1,hold_channel); - - //#ifdef DEBUG_SIM - rx_pwr = signal_energy_fp2(UE2eNB[UE_id][eNB_id][CC_id]->ch[0], - UE2eNB[UE_id][eNB_id][CC_id]->channel_length)*UE2eNB[UE_id][eNB_id][CC_id]->channel_length; - LOG_D(OCM,"[SIM][UL] slot %d Channel UE %d => eNB %d : %f dB (hold %d,length %d, PL %f)\n",next_slot,UE_id,eNB_id,10*log10(rx_pwr), - hold_channel,UE2eNB[UE_id][eNB_id][CC_id]->channel_length, - UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB); - //#endif - - //#ifdef DEBUG_SIM - rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx,frame_parms->samples_per_tti>>1,0); - LOG_D(OCM,"[SIM][UL] eNB %d : rx_pwr %f dBm (%f) for slot %d (subframe %d), sptti %d\n", - eNB_id,10*log10(rx_pwr),rx_pwr,next_slot,next_slot>>1,frame_parms->samples_per_tti); - //#endif - - - if (UE2eNB[UE_id][eNB_id][CC_id]->first_run == 1) - UE2eNB[UE_id][eNB_id][CC_id]->first_run = 0; - - - - for (aa=0; aasamples_per_tti>>1); i++) { - r_re[aa][i]+=r_re0[aa][i]; - r_im[aa][i]+=r_im0[aa][i]; - } - } - } - } //UE_id - - // RF model - /* - rf_rx(r_re0, - r_im0, - NULL, - NULL, - 0, - frame_parms->nb_antennas_rx, - frame_parms->samples_per_tti>>1, - 1e3/UE2eNB[UE_id][eNB_id]->BW, // sampling time (ns) - 0.0, // freq offset (Hz) (-20kHz..20kHz) - 0.0, // drift (Hz) NOT YET IMPLEMENTED - enb_data[eNB_id]->rx_noise_level, // noise_figure NOT YET IMPLEMENTED - (double)PHY_vars_eNB_g[eNB_id]->rx_total_gain_eNB_dB - 66.227, // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) - 200.0, // IP3_dBm (dBm) - &UE2eNB[UE_id][eNB_id]->ip, // initial phase - 30.0e3, // pn_cutoff (kHz) - -500.0, // pn_amp (dBc) default: 50 - 0.0, // IQ imbalance (dB), - 0.0); // IQ phase imbalance (rad) - */ - - rf_rx_simple(r_re, - r_im, - nb_antennas_rx, - frame_parms->samples_per_tti>>1, - 1e3/UE2eNB[0][eNB_id][CC_id]->sampling_rate, // sampling time (ns) - (double)PHY_vars_eNB_g[eNB_id][CC_id]->rx_total_gain_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) + LOG_D(OCM,"[SIM][UL] subframe %d Channel UE %d => eNB %d : %f dB (hold %d,length %d, PL %f)\n",subframe,UE_id,eNB_id,10*log10(rx_pwr), + hold_channel,UE2eNB[UE_id][eNB_id][CC_id]->channel_length, + UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB); + rx_pwr = signal_energy_fp((double**)r_re0,(double**)r_im0,nb_antennas_rx,frame_parms->samples_per_tti,0); + LOG_D(OCM,"[SIM][UL] eNB %d : rx_pwr %f dBm (%f) for subframe %d, sptti %d\n", + eNB_id,10*log10(rx_pwr),rx_pwr,subframe,frame_parms->samples_per_tti); + + + if (UE2eNB[UE_id][eNB_id][CC_id]->first_run == 1) + UE2eNB[UE_id][eNB_id][CC_id]->first_run = 0; + + + pthread_mutex_lock(&UE_output_mutex[eNB_id]); + for (aa=0; aasamples_per_tti; i++) { + r_re_UL[eNB_id][aa][i]+=r_re0[aa][i]; + r_im_UL[eNB_id][aa][i]+=r_im0[aa][i]; + } + } + pthread_mutex_unlock(&UE_output_mutex[eNB_id]); + } + } //UE_id + + rf_rx_simple((double**)r_re_UL[eNB_id], + (double**)r_im_UL[eNB_id], + nb_antennas_rx, + frame_parms->samples_per_tti, + 1e3/UE2eNB[0][eNB_id][CC_id]->sampling_rate, // sampling time (ns) + (double)PHY_vars_eNB_g[eNB_id][CC_id]->rx_total_gain_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) + #ifdef DEBUG_SIM - rx_pwr = signal_energy_fp(r_re,r_im,nb_antennas_rx,frame_parms->samples_per_tti>>1,0)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); - LOG_D(OCM,"[SIM][UL] rx_pwr (ADC in) %f dB for slot %d (subframe %d)\n",10*log10(rx_pwr),next_slot,next_slot>>1); + rx_pwr = signal_energy_fp((double**)r_re_UL[eNB_id],(double**)r_im_UL[eNB_id],nb_antennas_rx,frame_parms->samples_per_tti,0)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); + LOG_D(OCM,"[SIM][UL] rx_pwr (ADC in) %f dB for subframe %d\n",10*log10(rx_pwr),subframe); #endif - - rxdata = PHY_vars_eNB_g[eNB_id][CC_id]->common_vars.rxdata[0]; - slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); - - adc(r_re, - r_im, - 0, - slot_offset, - rxdata, - nb_antennas_rx, - frame_parms->samples_per_tti>>1, - 12); - + + rxdata = PHY_vars_eNB_g[eNB_id][CC_id]->common_vars.rxdata[0]; + sf_offset = subframe*frame_parms->samples_per_tti; + + adc((double**)r_re_UL[eNB_id], + (double**)r_im_UL[eNB_id], + 0, + sf_offset, + rxdata, + nb_antennas_rx, + frame_parms->samples_per_tti, + 12); + #ifdef DEBUG_SIM - rx_pwr2 = signal_energy(rxdata[0]+slot_offset,frame_parms->samples_per_tti>>1)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); - LOG_D(OCM,"[SIM][UL] eNB %d rx_pwr (ADC out) %f dB (%d) for slot %d (subframe %d)\n",eNB_id,10*log10((double)rx_pwr2),rx_pwr2,next_slot,next_slot>>1); + rx_pwr2 = signal_energy(rxdata[0]+sf_offset,frame_parms->samples_per_tti)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); + LOG_D(OCM,"[SIM][UL] eNB %d rx_pwr (ADC out) %f dB (%d) for subframe %d\n",eNB_id,10*log10((double)rx_pwr2),rx_pwr2,subframe); #else - UNUSED_VARIABLE(tx_pwr); - UNUSED_VARIABLE(rx_pwr); - UNUSED_VARIABLE(rx_pwr2); + UNUSED_VARIABLE(tx_pwr); + UNUSED_VARIABLE(rx_pwr); + UNUSED_VARIABLE(rx_pwr2); #endif - - } // eNB_id + } // abstraction_flag==0 } @@ -604,29 +535,13 @@ void init_channel_vars(LTE_DL_FRAME_PARMS *frame_parms, double ***s_re,double ** int i; - *s_re = malloc(2*sizeof(double*)); - *s_im = malloc(2*sizeof(double*)); - *r_re = malloc(2*sizeof(double*)); - *r_im = malloc(2*sizeof(double*)); - *r_re0 = malloc(2*sizeof(double*)); - *r_im0 = malloc(2*sizeof(double*)); + memset(eNB_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX); + for (i=0;iframe_rx = frame; proc->subframe_rx = sf; proc->timestamp_rx += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti; + pthread_mutex_unlock( &proc->mutex_FH ); - if (proc->instance_cnt_FH == 0) { + if (cnt_FH == 0) { if (pthread_cond_signal(&proc->cond_FH) != 0) { LOG_E(PHY,"ERROR pthread_cond_signal for eNB FH CCid %d\n",proc->CC_id); exit_fun("ERROR pthread_cond_signal"); diff --git a/targets/SIMU/USER/oaisim.h b/targets/SIMU/USER/oaisim.h index 6fb16b82db..47eefe472c 100644 --- a/targets/SIMU/USER/oaisim.h +++ b/targets/SIMU/USER/oaisim.h @@ -50,11 +50,13 @@ eNB_MAC_INST* get_eNB_mac_inst(module_id_t module_idP); OAI_Emulation* get_OAI_emulation(void); void init_channel_vars(LTE_DL_FRAME_PARMS *frame_parms, double ***s_re,double ***s_im,double ***r_re,double ***r_im,double ***r_re0,double ***r_im0); -void do_UL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double **s_re,double **s_im,channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs], - node_desc_t *enb_data[NUMBER_OF_eNB_MAX],node_desc_t *ue_data[NUMBER_OF_UE_MAX],uint16_t next_slot,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms, uint32_t,uint8_t); +void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_NUM_CCs], + node_desc_t *enb_data[NUMBER_OF_eNB_MAX],node_desc_t *ue_data[NUMBER_OF_UE_MAX], + uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms, + uint32_t frame,int eNB_id,uint8_t CC_id); -void do_DL_sig(double **r_re0,double **r_im0,double **r_re,double **r_im,double **s_re,double **s_im,channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs], - node_desc_t *enb_data[NUMBER_OF_eNB_MAX],node_desc_t *ue_data[NUMBER_OF_UE_MAX],uint16_t next_slot,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms,uint8_t UE_id,int CC_id); +void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs], + node_desc_t *enb_data[NUMBER_OF_eNB_MAX],node_desc_t *ue_data[NUMBER_OF_UE_MAX],uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms,uint8_t UE_id,int CC_id); void init_ue(node_desc_t *ue_data, UE_Antenna ue_ant);//Abstraction changes void init_enb(node_desc_t *enb_data, eNB_Antenna enb_ant);//Abstraction changes diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 8148730a24..c4a70f8716 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -173,6 +173,12 @@ extern time_stats_t ul_chan_stats; extern int xforms; +extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; +extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst); +void stop_eNB(int nb_inst); + void get_simulation_options(int argc, char *argv[]) { int option; @@ -774,11 +780,15 @@ void get_simulation_options(int argc, char *argv[]) conf_config_file_name, oai_emulation.info.nb_enb_local, enb_properties->number); /* Update some simulation parameters */ - oai_emulation.info.frame_type[0] = enb_properties->properties[0]->frame_type[0]; - oai_emulation.info.tdd_config[0] = enb_properties->properties[0]->tdd_config[0]; - oai_emulation.info.tdd_config_S[0] = enb_properties->properties[0]->tdd_config_s[0]; + oai_emulation.info.frame_type[0] = enb_properties->properties[0]->frame_type[0]; + oai_emulation.info.tdd_config[0] = enb_properties->properties[0]->tdd_config[0]; + oai_emulation.info.tdd_config_S[0] = enb_properties->properties[0]->tdd_config_s[0]; oai_emulation.info.extended_prefix_flag[0] = enb_properties->properties[0]->prefix_type[0]; + oai_emulation.info.node_function[0] = enb_properties->properties[0]->cc_node_function[0]; + oai_emulation.info.node_timing[0] = enb_properties->properties[0]->cc_node_timing[0]; + downlink_frequency[0][0] = enb_properties->properties[0]->downlink_frequency[0]; + uplink_frequency_offset[0][0] = enb_properties->properties[0]->uplink_frequency_offset[0]; } free(conf_config_file_name); @@ -939,6 +949,119 @@ void init_seed(uint8_t set_seed) } } +int eNB_trx_start(openair0_device *device) { + return(0); +} + +void eNB_trx_end(openair0_device *device) { + return; +} + +int eNB_trx_stop(openair0_device *device) { + return(0); +} +int UE_trx_start(openair0_device *device) { + return(0); +} +int UE_trx_end(openair0_device *device) { + return(0); +} +int UE_trx_stop(openair0_device *device) { + return(0); +} +int eNB_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) { + return(0); +} +int eNB_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { + return(0); +} +int UE_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) { + return(0); +} +int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { + return(0); +} + +int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + return(0); +} + +int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + return(0); +} + +int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + + int eNB_id = device->Mod_id; + int CC_id = device->CC_id; + int UE_id; + int subframe = (timestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10; + + for (UE_id=0;UE_id<=NB_UE_INST;UE_id++) { + do_DL_sig(eNB2UE, + enb_data, + ue_data, + subframe, + 0, //abstraction_flag, + &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms, + UE_id, + CC_id); + } + return(0); +} + +int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + + int UE_id = device->Mod_id; + int CC_id = device->CC_id; + int eNB_id; + int subframe = (timestamp/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10; + + for (eNB_id=0;eNB_id<=NB_eNB_INST;eNB_id++) { + do_UL_sig(UE2eNB, + enb_data, + ue_data, + subframe, + 0, // abstraction_flag + &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms, + 0, // frame is only used for abstraction + eNB_id, + CC_id); + } + return(0); +} + +void init_devices(void){ + + module_id_t UE_id, eNB_id; + uint8_t CC_id; + + for (CC_id=0; CC_idrfdevice.Mod_id = eNB_id; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.CC_id = CC_id; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_start_func = eNB_trx_start; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_read_func = eNB_trx_read; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_write_func = eNB_trx_write; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_end_func = eNB_trx_end; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_stop_func = eNB_trx_stop; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_freq_func = eNB_trx_set_freq; + PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_gains_func = eNB_trx_set_gains; + } + for (UE_id=0;UE_idrfdevice.Mod_id = UE_id; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.CC_id = CC_id; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_start_func = UE_trx_start; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_read_func = UE_trx_read; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_write_func = UE_trx_write; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_end_func = UE_trx_end; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_stop_func = UE_trx_stop; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_freq_func = UE_trx_set_freq; + PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_gains_func = UE_trx_set_gains; + } + } +} + void init_openair1(void) { module_id_t UE_id, eNB_id; @@ -1029,7 +1152,9 @@ void init_openair1(void) } } - init_eNB(eNodeB_3GPP,NB_eNB_INST); + init_devices (); + + init_eNB(oai_emulation.info.node_function,oai_emulation.info.node_timing,NB_eNB_INST); // init_ue_status(); for (UE_id=0; UE_id Date: Sun, 24 Jul 2016 02:31:29 -0700 Subject: [PATCH 108/206] bug fixes from Laurent on IF5 interface. 8-bit conversion for Mobipass. --- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 545c892c2a..052e4d9174 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -46,8 +46,8 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe, uint8_t *seqno, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - void *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; - void *tx_buffer=NULL; + int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; + int32_t *tx_buffer=NULL; uint16_t packet_id=0, i=0; @@ -115,8 +115,8 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe data_block = data_block_head; for (i=0; i>3; i+=2) { - t0 = _mm_srli_epi16(*txp128++, 4); - t1 = _mm_srli_epi16(*txp128++, 4); + t0 = _mm_srai_epi16(*txp128++, 4); + t1 = _mm_srai_epi16(*txp128++, 4); *data_block++ = _mm_packs_epi16(t0, t1); } @@ -147,8 +147,8 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - void *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; - void *rx_buffer=NULL; + int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; + uint16_t packet_id=0, i=0; @@ -203,6 +203,5 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type); } - free(rx_buffer); return; } From e035bc3e1c45a5aa386535a0ebac661961c1e778 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 24 Jul 2016 17:37:22 +0200 Subject: [PATCH 109/206] Result of testing as eNodeB. modifications for .vcd logging, bugfix in eNB_thread_FH (subframe counter), update of .conf file for new threading parameters. Updates to gtkwave configuration file for new threading. --- openair1/SCHED/phy_procedures_lte_eNb.c | 12 +++--- openair2/UTIL/LOG/vcd_signal_dumper.c | 24 +++++++----- openair2/UTIL/LOG/vcd_signal_dumper.h | 18 +++++---- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 3 ++ targets/RT/USER/eNB_usrp.gtkw | 37 +++++++++++-------- targets/RT/USER/lte-enb.c | 29 +++++++-------- targets/RT/USER/lte-softmodem.c | 1 + 7 files changed, 70 insertions(+), 54 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index ca7b5ec559..6966c3cb90 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1105,7 +1105,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, uint8_t smbv_alloc_cnt = 1; #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),1); start_meas(&eNB->phy_proc_tx); for (i=0; iphy_proc_tx); } @@ -2515,7 +2515,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl uint8_t seqno=0; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 1 ); start_meas(&eNB->phy_proc_rx); @@ -2602,7 +2602,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 0 ); } @@ -2621,7 +2621,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 1 ); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe); @@ -3183,7 +3183,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const phy_procedures_emos_eNB_RX(subframe,eNB); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 0 ); stop_meas(&eNB->phy_proc_rx); diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index a643874444..db00a8c35f 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -75,10 +75,14 @@ struct vcd_module_s { } vcd_module_s; const char* eurecomVariablesNames[] = { - "frame_number_TX_eNB", - "frame_number_RX_eNB", - "subframe_number_TX_eNB", - "subframe_number_RX_eNB", + "frame_number_TX0_eNB", + "frame_number_TX1_eNB", + "frame_number_RX0_eNB", + "frame_number_RX1_eNB", + "subframe_number_TX0_eNB", + "subframe_number_TX1_eNB", + "subframe_number_RX0_eNB", + "subframe_number_RX1_eNB", "runtime_TX_eNB", "runtime_RX_eNB", "frame_number_TX0_UE", @@ -187,8 +191,6 @@ const char* eurecomFunctionsNames[] = { "trx_write", "eNB_thread_rxtx0", "eNB_thread_rxtx1", - "eNB_thread_rx", - "eNB_thread_prach", "ue_thread_synch", "ue_thread_rxtx0", "ue_thread_rxtx1", @@ -213,10 +215,12 @@ const char* eurecomFunctionsNames[] = { "lte_ue_measurement_procedures", "lte_ue_pdcch_procedures", "lte_ue_pbch_procedures", - "phy_procedures_eNb_tx", - "phy_procedures_eNb_rx", - "phy_procedures_eNb_rx_common", - "phy_procedures_eNb_rx_uespec", + "phy_procedures_eNb_tx0", + "phy_procedures_eNb_tx1", + "phy_procedures_eNb_rx_common0", + "phy_procedures_eNb_rx_common1", + "phy_procedures_eNb_rx_uespec0", + "phy_procedures_eNb_rx_uespec1", "phy_eNB_slot_fep", "phy_procedures_ue_tx", "phy_procedures_ue_rx", diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index 1b72002f25..433d155a6c 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -47,10 +47,14 @@ /* WARNING: if you edit the enums below, update also string definitions in vcd_signal_dumper.c */ typedef enum { - VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB = 0, - VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, - VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_ENB, - VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB = 0, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX1_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB, + VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_ENB, VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB, VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE, @@ -161,8 +165,6 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0, VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX1, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, - VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_PRACH, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX1, @@ -188,9 +190,11 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX, - VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX, + VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX1, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, + VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON1, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, + VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC1, VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index d00482edca..b6ba5213ef 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/RT/USER/eNB_usrp.gtkw b/targets/RT/USER/eNB_usrp.gtkw index 474d2d1cf3..44401bd25e 100644 --- a/targets/RT/USER/eNB_usrp.gtkw +++ b/targets/RT/USER/eNB_usrp.gtkw @@ -1,17 +1,17 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sun May 29 20:10:01 2016 +[*] Sun Jul 24 14:21:37 2016 [*] [dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Sun May 29 20:07:25 2016" -[dumpfile_size] 16398004 +[dumpfile_mtime] "Sun Jul 24 14:18:00 2016" +[dumpfile_size] 7104337 [savefile] "/home/papillon/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw" -[timestart] 10806270000 +[timestart] 10621768000 [size] 1535 724 [pos] 309 0 -*-18.793451 10806918339 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +*-19.793451 29026062100 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [sst_width] 284 -[signals_width] 254 +[signals_width] 262 [sst_expanded] 1 [sst_vpaned_height] 294 @28 @@ -20,19 +20,24 @@ functions.trx_write @24 variables.trx_ts[63:0] variables.trx_tst[63:0] -variables.frame_number_TX_eNB[63:0] -variables.frame_number_RX_eNB[63:0] -variables.subframe_number_TX_eNB[63:0] -variables.subframe_number_RX_eNB[63:0] @28 -functions.eNB_thread_rx0 -functions.eNB_thread_tx0 -functions.phy_procedures_eNb_tx +functions.eNB_thread_rxtx0 +@24 +variables.frame_number_RX0_eNB[63:0] +variables.subframe_number_RX0_eNB[63:0] +variables.frame_number_TX0_eNB[63:0] +variables.subframe_number_TX0_eNB[63:0] +@28 +functions.eNB_thread_rxtx1 +@24 +variables.frame_number_RX1_eNB[63:0] +variables.subframe_number_RX1_eNB[63:0] +variables.frame_number_TX1_eNB[63:0] +@25 +variables.subframe_number_TX1_eNB[63:0] +@28 functions.phy_enb_sfgen -@29 functions.phy_eNB_slot_fep -@28 -functions.phy_procedures_eNb_rx functions.phy_enb_prach_rx @24 variables.dci_info[63:0] diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 177291596b..ff302ec80d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -435,6 +435,9 @@ static void* eNB_thread_rxtx( void* param ) { if (oai_exit) break; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->subframe_rx ); + // Common procedures phy_procedures_eNB_common_RX(PHY_vars_eNB_g[0][proc->CC_id], 0); @@ -473,8 +476,8 @@ static void* eNB_thread_rxtx( void* param ) { exit_fun("nothing to add"); } - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_ENB, proc->subframe_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->subframe_tx ); if (oai_exit) break; @@ -1004,6 +1007,14 @@ static void* eNB_thread_FH( void* param ) { if (oai_exit) break; + if (subframe==9) { + subframe=0; + frame++; + frame&=1023; + } else { + subframe++; + } + // This case is for synchronization to another thread if ((eNB->node_timing == synch_to_other) && ((eNB->node_function == NGFI_RCC_IF4) || @@ -1037,13 +1048,7 @@ static void* eNB_thread_FH( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - if (subframe==9) { - subframe=0; - frame++; - frame&=1023; - } else { - subframe++; - } + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, &proc->timestamp_rx, @@ -1073,8 +1078,6 @@ static void* eNB_thread_FH( void* param ) { //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); if (rxs != fp->samples_per_tti) exit_fun( "problem receiving samples" ); @@ -1107,8 +1110,6 @@ static void* eNB_thread_FH( void* param ) { } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); } // eNodeB_3GPP_BBU && node_timing == synch_to_ext_device else if ((eNB->node_timing == synch_to_ext_device) && @@ -1150,8 +1151,6 @@ static void* eNB_thread_FH( void* param ) { } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx ); } // node_timing == synch_to_externs, node_function = NGFI_IF4 else { // should not get here diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 8d073d310b..5db0451c4c 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -526,6 +526,7 @@ static void *scope_thread(void *arg) for(UE_id=0; UE_iddlsch[UE_id][0]->rnti>0) && (ue_cnt Date: Mon, 25 Jul 2016 12:04:25 +0200 Subject: [PATCH 110/206] if4 tx works again with FH thread changes --- targets/RT/USER/lte-enb.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index ff302ec80d..427f69180f 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -301,6 +301,7 @@ static void* eNB_thread_rxtx( void* param ) { uint16_t packet_type; uint32_t symbol_number=0; + uint32_t symbol_mask, symbol_mask_full; uint8_t seqno=0; @@ -502,10 +503,16 @@ static void* eNB_thread_rxtx( void* param ) { } } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) { /// **** recv_IF4 of txdataF from RCC **** /// + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<CC_id]->frame_parms.symbols_per_tti)-1; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); do { recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); - } while (symbol_number < PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti-1); + symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; } else if (packet_type == IF4_PRACH) { - // wake up thread for PRACH RX - prach_rx = 1; + prach_rx = 0; } - } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); + } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); if (proc->first_rx == 0) { if (subframe_rx < proc->subframe_rx+2){ @@ -1122,32 +1128,33 @@ static void* eNB_thread_FH( void* param ) { symbol_mask = 0; symbol_mask_full = (1<symbols_per_tti)-1; prach_rx = 0; - + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); if (packet_type == IF4_PULFFT) { - symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; } else if (packet_type == IF4_PRACH) { - // wake up thread for PRACH RX - prach_rx = 1; - } - } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0)); + prach_rx = 0; + } + } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); if (proc->first_rx == 0) { if (proc->subframe_rx != subframe){ LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - //exit_fun("Exiting"); + exit_fun("Exiting"); } if (proc->frame_rx != frame) { LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - //exit_fun("Exiting"); + exit_fun("Exiting"); } } else { proc->first_rx = 0; + frame = proc->frame_rx; + subframe = proc->subframe_rx; } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); From 81506be64c4e8876ac46f0fc48ccba6ae855613a Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Mon, 25 Jul 2016 17:40:46 +0200 Subject: [PATCH 111/206] if4 working --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 4 ++-- openair1/PHY/LTE_TRANSPORT/prach.c | 21 +-------------------- targets/RT/USER/lte-enb.c | 2 +- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 572bcd73b7..d492af16a7 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -96,7 +96,7 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, } else if (packet_type == IF4_PULFFT) { db_fulllength = 12*fp->N_RB_UL; db_halflength = (db_fulllength)>>1; - slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; IF4_header_t *ul_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); @@ -212,7 +212,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ } else if (*packet_type == IF4_PULFFT) { *symbol_number = ((packet_header->frame_status)>>26)&0x000f; - slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; + slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; for (element_id=0; element_idcommon_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_tti-eNB->N_TA_offset]; } - - int energy = dB_fixed(signal_energy(prach[0], eNB->frame_parms.samples_per_tti)); - //if (energy >= 45) { - // printf("prach subframe energy %d\n",energy); - //} - + // First compute physical root sequence if (restricted_set == 0) { if (Ncs_config>15) { @@ -1290,13 +1285,6 @@ void rx_prach(PHY_VARS_eNB *eNB, send_IF4(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4_PRACH, k); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); - energy = dB_fixed(signal_energy(&rxsigF[0][k], 839)); - if (energy >=45) { - printf(" prach freq-domain energy %d\n",eNB->proc.frame_rx, energy); - //write_output("beforecomp.m","rxF",&rxsigF[0][k],839*2,1,0); - //exit(1); - } - return; } else if (eNB->node_function == NGFI_RCC_IF4) { k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; @@ -1313,13 +1301,6 @@ void rx_prach(PHY_VARS_eNB *eNB, memmove((&rxsigF[0][k]), (&rxsigF[0][0]), 839*2*sizeof(int16_t)); - - energy = dB_fixed(signal_energy(&rxsigF[0][k], 839)); - if (energy >=45) { - printf(" prach freq-domain energy %d\n",eNB->proc.frame_rx, energy); - //write_output("aftercomp.m","rxF",&rxsigF[0][k],839*2,1,0); - //exit(1); - } } // in case of RCC and prach received rx_thread wakes up prach diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 427f69180f..6ed97c0f65 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -976,7 +976,7 @@ static void* eNB_thread_FH( void* param ) { pthread_mutex_unlock(&sync_mutex); - printf( "got sync (eNB_thread FH)\n" ); + printf( "got sync (eNB_thread_FH)\n" ); #if defined(ENABLE_ITTI) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); From fb2a4529d556ea7db50aa36884260c363594c7a1 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 25 Jul 2016 21:17:05 +0200 Subject: [PATCH 112/206] updated config files for NGFI RRH interface --- .../CONF/enb.band7.tm1.bladerfx40.conf | 3 +++ .../CONF/enb.band7.tm1.exmimo2.conf | 3 +++ .../CONF/enb.band7.tm1.lmssdr.conf | 3 +++ .../CONF/enb.band7.tm1.usrpb210.conf | 17 ++++++++++------- .../CONF/enb.band7.tm1.usrpx310.conf | 3 +++ 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf index 5a6a9a462b..8ae0ddeb06 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf index f1160e78ca..7bf097875d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf index 47e2179d18..a407aaecf1 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index ae2b076a49..21c1a80efc 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -17,12 +17,15 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "93"; + mobile_network_code = "92"; ////////// Physical parameters: component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; @@ -31,7 +34,7 @@ eNBs = downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; - N_RB_DL = 25; + N_RB_DL = 50; Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; @@ -130,7 +133,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "127.0.0.3"; + mme_ip_address = ( { ipv4 = "192.168.12.26"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -139,11 +142,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.147/24"; - ENB_INTERFACE_NAME_FOR_S1U = "lo"; - ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.147/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf index d4b88383e2..65f58fe33f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -22,6 +22,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; From 491c23c3ebebb0b6acdf558088170a8b90720f4e Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 26 Jul 2016 02:37:44 -0700 Subject: [PATCH 113/206] removed a debugging print in dft60 --- openair1/PHY/TOOLS/lte_dfts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/lte_dfts.c index 4fc332704b..00e1b0b5ce 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/lte_dfts.c @@ -6817,7 +6817,7 @@ void dft60(int16_t *x,int16_t *y,unsigned char scale) for (i=0; i<60; i++) { y128[i] = mulhi_int16(y128[i],norm128); - printf("y[%d] = (%d,%d)\n",i,((int16_t*)&y128[i])[0],((int16_t*)&y128[i])[1]); +// printf("y[%d] = (%d,%d)\n",i,((int16_t*)&y128[i])[0],((int16_t*)&y128[i])[1]); } } From 64121aaf15054b797f71610bb7fd4ee229a1e183 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 26 Jul 2016 12:40:52 +0200 Subject: [PATCH 114/206] configuration files, minor changes in RF interface --- targets/ARCH/COMMON/common_lib.h | 2 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 35 +++++------- .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 24 +++++---- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 2 +- .../CONF/enb.band7.tm1.usrpb210.conf | 3 ++ targets/RT/USER/lte-enb.c | 53 +++++++++++-------- 6 files changed, 64 insertions(+), 55 deletions(-) diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 17d1f7b180..99350a4c1e 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -152,8 +152,8 @@ typedef struct { int mmapped_dma; //! offset in samples between TX and RX paths int tx_sample_advance; + //! samples per packet on the fronthaul interface int samples_per_packet; - int tx_scheduling_advance; //! number of RX channels (=RX antennas) int rx_num_channels; //! number of TX channels (=TX antennas) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index d8a65dc2ca..fc4f8d5d39 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -172,25 +172,32 @@ static void trx_usrp_end(openair0_device *device) */ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + int ret; usrp_state_t *s = (usrp_state_t*)device->priv; + s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); - + if(flags) s->tx_md.has_time_spec = true; else s->tx_md.has_time_spec = false; - + if (cc>1) { std::vector buff_ptrs; for (int i=0;itx_stream->send(buff_ptrs, nsamps, s->tx_md); + ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3); } else - s->tx_stream->send(buff[0], nsamps, s->tx_md); + ret = (int)s->tx_stream->send(buff[0], nsamps, s->tx_md,1e-3); + s->tx_md.start_of_burst = false; - return 0; + if (ret != nsamps) { + printf("[xmit] tx samples %d != %d\n",ret,nsamps); + } + + return ret; } /*! \brief Receive samples from hardware. @@ -551,28 +558,24 @@ extern "C" { openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 15360000: openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 45; openair0_cfg[0].tx_bw = 10e6; openair0_cfg[0].rx_bw = 10e6; - openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 7680000: openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].tx_bw = 5e6; openair0_cfg[0].rx_bw = 5e6; - openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 1920000: openair0_cfg[0].samples_per_packet = 256; openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].tx_bw = 1.25e6; openair0_cfg[0].rx_bw = 1.25e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; default: printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); @@ -607,44 +610,34 @@ extern "C" { switch ((int)openair0_cfg[0].sample_rate) { case 30720000: - s->usrp->set_master_clock_rate(30.72e6); - openair0_cfg[0].samples_per_packet = 4096; + s->usrp->set_master_clock_rate(61.44e6); openair0_cfg[0].tx_sample_advance = 115; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; - openair0_cfg[0].tx_scheduling_advance = 11*openair0_cfg[0].samples_per_packet; break; case 23040000: s->usrp->set_master_clock_rate(23.04e6); //to be checked - openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 113; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 15360000: s->usrp->set_master_clock_rate(30.72e06); - openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 103; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; - openair0_cfg[0].tx_scheduling_advance = 10240; break; case 7680000: s->usrp->set_master_clock_rate(30.72e6); - openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 80; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; - openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 1920000: - s->usrp->set_master_clock_rate(7.68e6); - openair0_cfg[0].samples_per_packet = 256; + s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].tx_sample_advance = 40; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; default: printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index 7d34889f67..a2187d402f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -23,12 +23,15 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 100; @@ -46,7 +49,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -26; + pdsch_referenceSignalPower = -29; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; @@ -64,9 +67,9 @@ eNBs = srs_ackNackST =; srs_MaxUpPts =;*/ - pusch_p0_Nominal = -90; + pusch_p0_Nominal = -96; pusch_alpha = "AL1"; - pucch_p0_Nominal = -100; + pucch_p0_Nominal = -103; msg3_delta_Preamble = 6; pucch_deltaF_Format1 = "deltaF2"; pucch_deltaF_Format1b = "deltaF3"; @@ -82,7 +85,7 @@ eNBs = rach_messagePowerOffsetGroupB = ; */ rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; + rach_preambleInitialReceivedTargetPower = -104; rach_preambleTransMax = 10; rach_raResponseWindowSize = 10; rach_macContentionResolutionTimer = 48; @@ -130,7 +133,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.11"; + mme_ip_address = ( { ipv4 = "127.0.0.3"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -139,11 +142,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; @@ -164,6 +167,5 @@ eNBs = rrc_log_level ="info"; rrc_log_verbosity ="medium"; }; - } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index b6ba5213ef..d2e99a3481 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -25,7 +25,7 @@ eNBs = { node_function = "eNodeB_3GPP"; node_timing = "synch_to_ext_device"; - node_synch_ref = 0; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index ae2b076a49..c73c4ef809 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index ff302ec80d..93795c7220 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -298,7 +298,8 @@ static void* eNB_thread_rxtx( void* param ) { FILE *tx_time_file = NULL; char tx_time_name[101]; void *txp[PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx]; - + int txs; + uint16_t packet_type; uint32_t symbol_number=0; @@ -553,18 +554,21 @@ static void* eNB_thread_rxtx( void* param ) { for (i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; - // if symb_written < spp ==> error - PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, - (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), - txp, - PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, - PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, - 1); + txs = PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, + (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), + txp, + PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, + PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, + 1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + if (txs != PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti) { + LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti); + exit_fun( "problem transmitting samples" ); + } } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { /// **** send_IF5 of txdata to RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); @@ -651,7 +655,7 @@ static void* eNB_thread_asynch_rx( void* param ) { uint32_t symbol_mask, symbol_mask_full; int prach_rx; int dummy_rx[fp->nb_antennas_rx][fp->samples_per_tti]; - int rxs; + int rxs=0; #ifdef DEADLINE_SCHEDULER struct sched_attr attr; @@ -770,6 +774,9 @@ static void* eNB_thread_asynch_rx( void* param ) { printf("eNB asynch RX\n"); sleep(1); } + if (rxs!=fp->samples_per_tti) { + exit_fun("error receiving samples\n"); + } } else if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// @@ -1031,7 +1038,7 @@ static void* eNB_thread_FH( void* param ) { while (proc->instance_cnt_FH < 0) { // most of the time the thread is waiting here - // proc->instance_cnt_prach is -1 + // proc->instance_cnt_FH is -1 pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); // this unlocks mutex_rxtx while waiting and then locks it again } proc->instance_cnt_FH++; @@ -1243,15 +1250,19 @@ static void* eNB_thread_FH( void* param ) { print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - } + - if (eNB->node_timing == synch_to_ext_device) { - proc->instance_cnt_FH--; - - if (pthread_mutex_unlock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for FH\n"); - exit_fun( "error unlocking mutex" ); + if (eNB->node_timing == synch_to_ext_device) { + proc->instance_cnt_FH--; + + if (pthread_mutex_unlock(&proc->mutex_FH) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for FH\n"); + exit_fun( "error unlocking mutex" ); + } } + + if (eNB->frame_parms.N_RB_DL==6) + rt_sleep_ns(800000LL); } printf( "Exiting FH thread \n"); @@ -1271,12 +1282,12 @@ static void* eNB_thread_prach( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id]; - + /* struct timespec wait; wait.tv_sec=0; wait.tv_nsec=5000000L; - + */ // set default return value eNB_thread_prach_status = 0; @@ -1378,7 +1389,7 @@ static void* eNB_thread_prach( void* param ) { if (oai_exit) break; - if (pthread_mutex_timedlock(&proc->mutex_prach,&wait) != 0) { + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n"); exit_fun( "error locking mutex" ); break; @@ -1400,7 +1411,7 @@ static void* eNB_thread_prach( void* param ) { prach_procedures(eNB,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); - if (pthread_mutex_timedlock(&proc->mutex_prach,&wait) != 0) { + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); exit_fun( "error locking mutex" ); break; From 986dfecc83b4a5eb372c5ed3d12ff49a44ebc5df Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Tue, 26 Jul 2016 18:56:43 +0200 Subject: [PATCH 115/206] testing if5-rrh_gw tx working --- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 57 ++++++++++--------- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 3 - targets/RT/USER/eNB_transport_IQ.c | 3 +- targets/RT/USER/lte-enb.c | 8 +-- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 052e4d9174..59a3e70cd6 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -50,36 +50,35 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe int32_t *tx_buffer=NULL; uint16_t packet_id=0, i=0; + + uint32_t spp_eth = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_packet; + uint32_t spsf = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10; - if (packet_type == IF5_RRH_GW_DL) { - unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; - unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; - + if (packet_type == IF5_RRH_GW_DL) { + for (i=0; i < fp->nb_antennas_tx; i++) txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] += packet_id*spp_eth; - + eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), txp, spp_eth, fp->nb_antennas_tx, 0); + + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] += spp_eth; + } } else if (packet_type == IF5_RRH_GW_UL) { - unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; - unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; - + for (i=0; i < fp->nb_antennas_rx; i++) rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] += packet_id*spp_eth; eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), @@ -87,6 +86,10 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe spp_eth, fp->nb_antennas_rx, 0); + + for (i=0; i < fp->nb_antennas_rx; i++) + rxp[i] += spp_eth; + } } else if (packet_type == IF5_MOBIPASS) { @@ -149,49 +152,49 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; - uint16_t packet_id=0, i=0; + + int32_t spp_eth = (int32_t) eNB->ifdevice.openair0_cfg->samples_per_packet; + int32_t spsf = (int32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10; + + openair0_timestamp timestamp[spsf / spp_eth]; if (packet_type == IF5_RRH_GW_DL) { - unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; - unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; - - openair0_timestamp timestamp[spsf / spp_eth]; - + for (i=0; i < fp->nb_antennas_tx; i++) txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] += packet_id*spp_eth; eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], txp, spp_eth, fp->nb_antennas_tx); + + for (i=0; i < fp->nb_antennas_tx; i++) + txp[i] += spp_eth; + } *proc_timestamp = timestamp[0]; - } else if (packet_type == IF5_RRH_GW_UL) { - unsigned int spp_eth = eNB->ifdevice.openair0_cfg->samples_per_packet; - unsigned int spsf = eNB->ifdevice.openair0_cfg->samples_per_frame/10; - - openair0_timestamp timestamp[spsf / spp_eth]; + } else if (packet_type == IF5_RRH_GW_UL) { for (i=0; i < fp->nb_antennas_rx; i++) rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - for (i=0; i < fp->nb_antennas_tx; i++) - rxp[i] += packet_id*spp_eth; eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], rxp, spp_eth, fp->nb_antennas_rx); + + for (i=0; i < fp->nb_antennas_rx; i++) + rxp[i] += spp_eth; + } *proc_timestamp = timestamp[0]; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index f29375dac3..252bdbb47c 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -411,7 +411,6 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth exit(-1); break; } - openair0_cfg[0].tx_scheduling_advance = eth_params->tx_scheduling_advance*openair0_cfg[0].samples_per_packet; } device->openair0_cfg=&openair0_cfg[0]; @@ -454,8 +453,6 @@ void dump_dev(openair0_device *device) { printf(" Log level is %i :\n" ,device->openair0_cfg->log_level); printf(" RB number: %i, sample rate: %lf \n" , device->openair0_cfg->num_rb_dl, device->openair0_cfg->sample_rate); - printf(" Scheduling_advance: %i, Sample_advance: %u \n" , - device->openair0_cfg->tx_scheduling_advance, device->openair0_cfg->tx_sample_advance); printf(" BBU configured for %i tx/%i rx channels)\n", device->openair0_cfg->tx_num_channels,device->openair0_cfg->rx_num_channels); printf(" Running flags: %s %s %s\n", diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index 86080c2c33..f09bdcaadc 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -710,14 +710,13 @@ static void check_dev_config( rrh_module_t *mod_enb) { printf("\n---------------------RF device configuration parameters---------------------\n"); - printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_scheduling_advance=%d\n \ttx_sample_advance=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n", + printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_sample_advance=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n", mod_enb->devs->openair0_cfg->Mod_id, mod_enb->devs->openair0_cfg->log_level, mod_enb->devs->openair0_cfg->num_rb_dl, mod_enb->devs->openair0_cfg->samples_per_frame, mod_enb->devs->openair0_cfg->sample_rate, mod_enb->devs->openair0_cfg->samples_per_packet, - mod_enb->devs->openair0_cfg->tx_scheduling_advance, mod_enb->devs->openair0_cfg->tx_sample_advance, mod_enb->devs->openair0_cfg->rx_num_channels, mod_enb->devs->openair0_cfg->tx_num_channels, diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 0d9002d849..d6103d709e 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1061,8 +1061,6 @@ static void* eNB_thread_FH( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - - rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, &proc->timestamp_rx, rxp, @@ -1102,7 +1100,7 @@ static void* eNB_thread_FH( void* param ) { (eNB->node_function == eNodeB_3GPP_BBU)) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); + recv_IF5(eNB, &proc->timestamp_rx, subframe, IF5_RRH_GW_UL); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; @@ -1113,13 +1111,15 @@ static void* eNB_thread_FH( void* param ) { LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); exit_fun("Exiting"); } - + if (proc->frame_rx != frame) { LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); exit_fun("Exiting"); } } else { proc->first_rx = 0; + frame = proc->frame_rx; + subframe = proc->subframe_rx; } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); From 032806725ec79e5b0911d8bab96c7a032bbfb96c Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 27 Jul 2016 08:43:35 +0200 Subject: [PATCH 116/206] moving of trx_write in eNB_thread_FH to avoit conflicts with trx_read --- openair1/SCHED/phy_procedures_lte_eNb.c | 2 +- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 2 +- .../CONF/enb.band7.tm1.usrpb210.conf | 14 +++---- targets/RT/USER/lte-enb.c | 38 +++++++++++++++++-- targets/RT/USER/lte-softmodem.c | 4 +- 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6966c3cb90..2407061f8e 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1931,7 +1931,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits eNB->UE_stats[(uint32_t)UE_id].sector = 0; - LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, frame, diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index d2e99a3481..0a9b61546b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -31,7 +31,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2660000000L; + downlink_frequency = 2680000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 50; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index 7ec2264444..c73c4ef809 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "92"; + mobile_network_code = "93"; ////////// Physical parameters: @@ -34,7 +34,7 @@ eNBs = downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; - N_RB_DL = 50; + N_RB_DL = 25; Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; @@ -133,7 +133,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.26"; + mme_ip_address = ( { ipv4 = "127.0.0.3"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -142,11 +142,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.147/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth1"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.147/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 0d9002d849..fc0b8b8cf5 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -550,6 +550,7 @@ static void* eNB_thread_rxtx( void* param ) { */ + /* // eNodeB_3GPP, RRU write to RF device if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) || @@ -576,13 +577,15 @@ static void* eNB_thread_rxtx( void* param ) { LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti); exit_fun( "problem transmitting samples" ); } - } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { + } + */ + if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { /// **** send_IF5 of txdata to RRH **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); - } else { + } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4) { /// **** send_IF4 of txdataF to RRU **** /// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0); @@ -854,8 +857,8 @@ static void* eNB_thread_FH( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - void *rxp[fp->nb_antennas_rx]; - unsigned int rxs; + void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; + unsigned int rxs,txs; FILE *rx_time_file = NULL; char rx_time_name[101]; struct timespec wait; @@ -1055,7 +1058,34 @@ static void* eNB_thread_FH( void* param ) { ((eNB->node_function == NGFI_RRU_IF4) || (eNB->node_function == NGFI_RRU_IF5) || (eNB->node_function == eNodeB_3GPP))) { // acquisition from RF + + if (proc->first_rx==0) { + + // Transmit TX buffer based on timestamp from RX + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + + for (i=0; iframe_parms.nb_antennas_tx; i++) + txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti]; + + txs = PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, + proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, + txp, + fp->samples_per_tti, + fp->nb_antennas_tx, + 1); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + + + if (txs != PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti) { + LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, fp->samples_per_tti); + exit_fun( "problem transmitting samples" ); + } + } + for (i=0; inb_antennas_rx; i++) rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 5db0451c4c..a3984f75d9 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -525,8 +525,8 @@ static void *scope_thread(void *arg) ue_cnt=0; for(UE_id=0; UE_iddlsch[UE_id][0]->rnti>0) && (ue_cntdlsch[UE_id][0]->rnti>0) && (ue_cnt Date: Wed, 27 Jul 2016 11:36:25 +0200 Subject: [PATCH 117/206] removed debugging trace for Detection of hypothesized PRACH preamble --- openair1/SCHED/phy_procedures_lte_eNb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 2407061f8e..6966c3cb90 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1931,7 +1931,7 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits eNB->UE_stats[(uint32_t)UE_id].sector = 0; - LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", + LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, frame, From bf6428cf38012b3dab14072bed3e2d69f454b5fa Mon Sep 17 00:00:00 2001 From: Sandeep Kumar Date: Wed, 27 Jul 2016 17:16:05 +0200 Subject: [PATCH 118/206] add rcc/rru conf files --- .../CONF/rcc.band7.tm1.usrpb210.conf | 190 ++++++++++++++++++ .../CONF/rru.band7.tm1.usrpb210.conf | 190 ++++++++++++++++++ 2 files changed, 380 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf new file mode 100644 index 0000000000..20cc9189bb --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "127.0.0.3"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth2"; + remote_address = "00:13:95:1f:a0:af"; + local_address = "90:e2:ba:c5:fc:04"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf new file mode 100644 index 0000000000..f828dfb1c7 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF4"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "90:e2:ba:c5:fc:04"; + local_address = "00:13:95:1f:a0:af"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); From a2ea484cd8e2a26b0a90599f6f15e24c8a68f6e9 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jul 2016 22:59:27 +0200 Subject: [PATCH 119/206] remove gitlab CI detection of error logging --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2f2d95d4b7..a7605ea29b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,5 +33,4 @@ job1: - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR - cat $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml - exce_log=`egrep -i 'warning|error|critical|exception' $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log |cat ` - - if [ -n "$exce_log" ]; then echo -e "\e[31mThere are errors in $NFS_TEST_RESULTS_DIR/log/python_autotest.log. Please check the logs\e[0m" ; fi From 60f0d9ad46264c6b57126d78b5b9ead70ad6ff83 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 28 Jul 2016 12:27:54 +0200 Subject: [PATCH 120/206] bugfix --- openair1/SCHED/phy_procedures_lte_eNb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6966c3cb90..3f5c46e9ab 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1249,6 +1249,8 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, // Now loop again over the DCIs for UL configuration for (i=0; iNum_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) { + dci_alloc = &DCI_pdu->dci_alloc[i]; + if (dci_alloc->format == format0) { // this is a ULSCH allocation if (eNB->mac_enabled==1) UE_id = find_ue((int16_t)dci_alloc->rnti,eNB); From 313acc6e96ab3fd8a58eb788b8602c59ed234a38 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 28 Jul 2016 15:58:54 +0200 Subject: [PATCH 121/206] fixes for the T --- .../LTE_ESTIMATION/lte_ul_channel_estimation.c | 2 +- openair1/PHY/LTE_TRANSPORT/phich.c | 2 +- openair1/PHY/LTE_TRANSPORT/pucch.c | 4 ++-- openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c | 4 ++-- openair1/SCHED/phy_procedures_lte_eNb.c | 17 +++++++++++------ targets/RT/USER/lte-enb.c | 2 ++ targets/RT/USER/lte-softmodem.c | 5 +++-- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 3112350d85..68bbf3e001 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -335,7 +335,7 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, #if T_TRACER if (aa == 0) T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(eNB_id), T_INT(UE_id), - T_INT(phy_vars_eNB->proc[sched_subframe].frame_rx), T_INT(subframe), + T_INT(proc->frame_rx), T_INT(subframe), T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4)); #endif diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index e0aa5d3ee0..d5dff4ef30 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -1511,7 +1511,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, if ((ulsch[UE_id]->harq_processes[harq_pid]->dci_alloc == 0) && (ulsch[UE_id]->harq_processes[harq_pid]->rar_alloc == 0) ) { if (ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK==0 ) { - T(T_ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION, T_INT(eNB->Mod_id), T_INT(eNB->proc->frame_tx), + T(T_ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION, T_INT(eNB->Mod_id), T_INT(proc->frame_tx), T_INT(subframe), T_INT(UE_id), T_INT(ulsch[UE_id]->rnti), T_INT(harq_pid)); LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d, subframe %d : PHICH NACK / (no format0 DCI) Setting subframe_scheduling_flag\n", eNB->Mod_id,harq_pid,proc->frame_tx,subframe); diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index cb7803fbfc..9b9693c82f 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -802,7 +802,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, eNB->pucch1_stats_thres[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres; eNB->pucch1_stats_cnt[UE_id][subframe] = (eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023; - T(T_ENB_PHY_PUCCH_1_ENERGY, T_INT(phy_vars_eNB->Mod_id), T_INT(UE_id), T_INT(frame), T_INT(subframe), + T(T_ENB_PHY_PUCCH_1_ENERGY, T_INT(eNB->Mod_id), T_INT(UE_id), T_INT(frame), T_INT(subframe), T_INT(stat_max), T_INT(sigma2_dB+pucch1_thres)); /* @@ -1047,7 +1047,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; /* frame not available here - set to -1 for the moment */ - T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(phy_vars_eNB->Mod_id), T_INT(UE_id), T_INT(-1), T_INT(subframe), T_INT(stat_re), T_INT(stat_im)); + T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(eNB->Mod_id), T_INT(UE_id), T_INT(-1), T_INT(subframe), T_INT(stat_re), T_INT(stat_im)); *payload = (stat_re<0) ? 1 : 0; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index c396cdf6fa..16cd847016 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1842,10 +1842,10 @@ void rx_ulsch(PHY_VARS_eNB *eNB, llrp = (int16_t*)&pusch_vars->llr[0]; - T(T_ENB_PHY_PUSCH_IQ, T_INT(eNB_id), T_INT(UE_id), T_INT(phy_vars_eNB->proc[sched_subframe].frame_rx), + T(T_ENB_PHY_PUSCH_IQ, T_INT(eNB_id), T_INT(UE_id), T_INT(proc->frame_rx), T_INT(subframe), T_INT(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb), T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_tti), - T_BUFFER(eNB_pusch_vars->rxdataF_comp[eNB_id][0], + T_BUFFER(pusch_vars->rxdataF_comp[eNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_tti*2)); for (l=0; lsymbols_per_tti-ulsch[UE_id]->harq_processes[harq_pid]->srs_active; l++) { diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 3f5c46e9ab..314aaa4de9 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -767,6 +767,10 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe); + T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id), + T_INT(dci_alloc->rnti), T_INT(dci_alloc->format), + T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid)); + eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE; LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe, @@ -858,6 +862,9 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC else eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + T(T_ENB_PHY_ULSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id), + T_INT(dci_alloc->rnti), T_INT(harq_pid)); + } void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols,int abstraction_flag) { @@ -997,11 +1004,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d #ifdef DEBUG_DLSCH LOG_T(PHY,"eNB DLSCH SDU: \n"); - T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id), - T_INT(DCI_pdu->dci_alloc[i].rnti), T_INT(DCI_pdu->dci_alloc[i].format), - T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid)); - - eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; + //eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe, DCI_pdu->dci_alloc[i].rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->dci_alloc[i].firstCCE); @@ -1108,6 +1111,8 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),1); start_meas(&eNB->phy_proc_tx); + T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe)); + for (i=0; iMod_id), T_INT(frame), T_INT(subframe)); T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0), - T_BUFFER(&eNB->lte_eNB_common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti], + T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti * 4)); eNB->rb_mask_ul[0]=0; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 94afcb15f7..5be00337af 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1201,6 +1201,8 @@ static void* eNB_thread_FH( void* param ) { AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); } + T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); + // At this point, all information for subframe has been received on FH interface // If this proc is to provide synchronization, do so for (i=0;inum_slaves;i++) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index a3984f75d9..9c3ec6fb99 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -682,11 +682,11 @@ static void get_options (int argc, char **argv) LONG_OPTION_DUMP_FRAME, LONG_OPTION_LOOPMEMORY, LONG_OPTION_PHYTEST, - LONG_OPTION_MMAPPED_DMA + LONG_OPTION_MMAPPED_DMA, #if T_TRACER - , LONG_OPTION_T_PORT, LONG_OPTION_T_NOWAIT, + LONG_OPTION_T_DONT_FORK, #endif }; @@ -710,6 +710,7 @@ static void get_options (int argc, char **argv) #if T_TRACER {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, + {"T_dont_fork", no_argument, 0, LONG_OPTION_T_DONT_FORK}, #endif {NULL, 0, NULL, 0} }; From f9d43daa3a0df3500e2630c522968baf434f51f3 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 29 Jul 2016 11:39:24 +0200 Subject: [PATCH 122/206] bugfix --- targets/RT/USER/lte-enb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 5be00337af..f18e1090cc 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -109,6 +109,8 @@ unsigned short config_frames[4] = {2,9,11,13}; # endif #endif +#include "T.h" + //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 From f33e9a702791f949d161e9a0f40fac7a0382b3af Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 29 Jul 2016 21:56:40 +0200 Subject: [PATCH 123/206] do not exit immediately in case of busy thread 5ms by default, easy to change (change the 10 in the loops) if the behavior is worse than before, do git revert [commit ID] --- openair1/SCHED/phy_procedures_lte_eNb.c | 31 +++++++++++++---------- targets/RT/USER/lte-enb.c | 33 ++++++++++++++----------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 314aaa4de9..6be9ff2080 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2577,6 +2577,17 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl // check if we have to detect PRACH first if ((eNB->node_function != NGFI_RRU_IF5) && (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0)) { // any other node must call prach procedure + /* accept some delay in processing - up to 5ms */ + int i; + for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) { + LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach); + usleep(500); + } + if (proc->instance_cnt_prach == 0) { + exit_fun( "PRACH thread busy" ); + return; + } + // wake up thread for PRACH RX if (pthread_mutex_lock(&proc->mutex_prach) != 0) { LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); @@ -2584,25 +2595,19 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl return; } - int cnt_prach = ++proc->instance_cnt_prach; + ++proc->instance_cnt_prach; // set timing for prach thread proc->frame_prach = proc->frame_rx; proc->subframe_prach = proc->subframe_rx; - pthread_mutex_unlock( &proc->mutex_prach ); - - if (cnt_prach == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - } else { - LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach); - exit_fun( "PRACH thread busy" ); + // the thread can now be woken up + if (pthread_cond_signal(&proc->cond_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); return; } + + pthread_mutex_unlock( &proc->mutex_prach ); } } else { // grab transport channel information from network interface diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index f18e1090cc..ac552e82fe 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1242,6 +1242,16 @@ static void* eNB_thread_FH( void* param ) { // choose even or odd thread for RXn-TXnp4 processing eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[proc->subframe_rx&1]; + /* accept some delay in processing - up to 5ms */ + for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) { + LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->instance_cnt_rxtx); + usleep(500); + } + if (proc_rxtx->instance_cnt_rxtx == 0) { + exit_fun( "TX thread busy" ); + break; + } + // wake up TX for subframe n+4 // lock the TX mutex and make sure the thread is ready if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) { @@ -1249,7 +1259,8 @@ static void* eNB_thread_FH( void* param ) { exit_fun( "error locking mutex_rxtx" ); break; } - int cnt_rxtx = ++proc_rxtx->instance_cnt_rxtx; + + ++proc_rxtx->instance_cnt_rxtx; // We have just received and processed the common part of a subframe, say n. // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired @@ -1263,20 +1274,14 @@ static void* eNB_thread_FH( void* param ) { proc_rxtx->frame_tx = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx; proc_rxtx->subframe_tx = (proc_rxtx->subframe_rx + 4)%10; - pthread_mutex_unlock( &proc_rxtx->mutex_rxtx ); - - if (cnt_rxtx == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, cnt_rxtx ); - exit_fun( "TX thread busy" ); + // the thread can now be woken up + if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); break; - } + } + + pthread_mutex_unlock( &proc_rxtx->mutex_rxtx ); stop_meas( &softmodem_stats_rxtx_sf ); #ifdef DEADLINE_SCHEDULER From 025f56d28b6c085ef0e4ab433f8c4b08bc72c71a Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 10:28:56 +0200 Subject: [PATCH 124/206] node function interfaces via function pointers. Suggestions from L. Thomas, B. Mongazon, C. Roux. --- openair1/PHY/INIT/lte_init.c | 20 +- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 98 +- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 26 +- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 10 +- openair1/PHY/LTE_TRANSPORT/phich.c | 5 +- openair1/PHY/LTE_TRANSPORT/pmch.c | 8 +- openair1/PHY/LTE_TRANSPORT/prach.c | 12 +- openair1/PHY/LTE_TRANSPORT/proto.h | 9 +- openair1/PHY/defs.h | 40 +- openair1/SCHED/defs.h | 17 +- openair1/SCHED/phy_procedures_lte_eNb.c | 288 +++--- openair2/ENB_APP/enb_config.c | 10 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 32 +- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 32 +- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 8 +- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 12 +- targets/RT/USER/lte-enb.c | 877 ++++++++++-------- targets/RT/USER/lte-softmodem.c | 8 +- 18 files changed, 788 insertions(+), 724 deletions(-) diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index a453b8eb8d..d583381781 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -1167,7 +1167,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, frame_parms->phich_config_common.phich_duration); LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_eNB][MOD %02"PRIu8"][]\n", eNB->Mod_id); - if (eNB->node_function != NGFI_RRU_IF4) { + if (eNB->node_function != NGFI_RRU_IF4p5) { lte_gold(frame_parms,eNB->lte_gold_table,frame_parms->Nid_cell); generate_pcfich_reg_mapping(frame_parms); generate_phich_reg_mapping(frame_parms); @@ -1191,12 +1191,12 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, if (abstraction_flag==0) { // TX vars - if (eNB->node_function != NGFI_RCC_IF4) + if (eNB->node_function != NGFI_RCC_IF4p5) common_vars->txdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); common_vars->txdataF[eNB_id] = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); for (i=0; inb_antennas_tx; i++) { - if (eNB->node_function != NGFI_RCC_IF4) + if (eNB->node_function != NGFI_RCC_IF4p5) common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); #ifdef DEBUG_PHY @@ -1208,14 +1208,14 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, } // RX vars - if (eNB->node_function != NGFI_RCC_IF4) { + if (eNB->node_function != NGFI_RCC_IF4p5) { common_vars->rxdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); } common_vars->rxdataF[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); for (i=0; inb_antennas_rx; i++) { - if (eNB->node_function != NGFI_RCC_IF4) { + if (eNB->node_function != NGFI_RCC_IF4p5) { common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->samples_per_tti*sizeof(int32_t) ); } @@ -1227,7 +1227,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, #endif } - if (eNB->node_function != NGFI_RRU_IF4) { + if (eNB->node_function != NGFI_RRU_IF4p5) { // Channel estimates for SRS for (UE_id=0; UE_idnode_function != NGFI_RRU_IF4) { + if (eNB->node_function != NGFI_RRU_IF4p5) { generate_ul_ref_sigs_rx(); // SRS @@ -1264,7 +1264,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, // ULSCH VARS, skip if NFGI_RRU_IF4 - if (eNB->node_function!=NGFI_RRU_IF4) + if (eNB->node_function!=NGFI_RRU_IF4p5) prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) ); /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ @@ -1277,7 +1277,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, #endif } - if (eNB->node_function != NGFI_RRU_IF4) { + if (eNB->node_function != NGFI_RRU_IF4p5) { AssertFatal(frame_parms->nb_antennas_rx <= sizeof(prach_vars->prach_ifft) / sizeof(prach_vars->prach_ifft[0]), "nb_antennas_rx too large"); for (i=0; inb_antennas_rx; i++) { @@ -1399,7 +1399,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, eNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration init_prach_tables(839); - } // node_function != NGFI_RRU_IF4 + } // node_function != NGFI_RRU_IF4p5 return (0); } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index d492af16a7..738fe842b6 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -42,9 +42,9 @@ #include "PHY/TOOLS/alaw_lut.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" +#include "UTIL/LOG/vcd_signal_dumper.h" - -void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int k) { +void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int k) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -57,16 +57,18 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, uint16_t *data_block=NULL, *i=NULL; - if (packet_type == IF4_PDLFFT) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); + + if (packet_type == IF4p5_PDLFFT) { db_fulllength = 12*fp->N_RB_DL; db_halflength = (db_fulllength)>>1; slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - IF4_header_t *dl_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); + IF4p5_header_t *dl_header = (IF4p5_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t); - gen_IF4_dl_header(dl_header, frame, subframe); + gen_IF4p5_dl_header(dl_header, frame, subframe); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { @@ -86,23 +88,23 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, &tx_buffer, db_fulllength, 1, - IF4_PDLFFT)) < 0) { - perror("ETHERNET write for IF4_PDLFFT\n"); + IF4p5_PDLFFT)) < 0) { + perror("ETHERNET write for IF4p5_PDLFFT\n"); } slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } - } else if (packet_type == IF4_PULFFT) { + } else if (packet_type == IF4p5_PULFFT) { db_fulllength = 12*fp->N_RB_UL; db_halflength = (db_fulllength)>>1; slotoffsetF = 1; blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; - IF4_header_t *ul_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); + IF4p5_header_t *ul_header = (IF4p5_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t); - gen_IF4_ul_header(ul_header, frame, subframe); + gen_IF4p5_ul_header(ul_header, frame, subframe); for (symbol_id=0; symbol_idsymbols_per_tti; symbol_id++) { @@ -122,23 +124,23 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, &tx_buffer, db_fulllength, 1, - IF4_PULFFT)) < 0) { - perror("ETHERNET write for IF4_PULFFT\n"); + IF4p5_PULFFT)) < 0) { + perror("ETHERNET write for IF4p5_PULFFT\n"); } slotoffsetF += fp->ofdm_symbol_size; blockoffsetF += fp->ofdm_symbol_size; } - } else if (packet_type == IF4_PRACH) { + } else if (packet_type == IF4p5_PRACH) { // FIX: hard coded prach samples length db_fulllength = 839*2; - IF4_header_t *prach_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t); + IF4p5_header_t *prach_header = (IF4p5_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); + data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t); - gen_IF4_prach_header(prach_header, frame, subframe); + gen_IF4p5_prach_header(prach_header, frame, subframe); - memcpy((int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t), + memcpy((int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t), (&rxsigF[0][k]), db_fulllength*sizeof(int16_t)); @@ -147,18 +149,19 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, &tx_buffer, db_fulllength, 1, - IF4_PRACH)) < 0) { - perror("ETHERNET write for IF4_PRACH\n"); + IF4p5_PRACH)) < 0) { + perror("ETHERNET write for IF4p5_PRACH\n"); } } else { - AssertFatal(1==0, "send_IF4 - Unknown packet_type %x", packet_type); + AssertFatal(1==0, "send_IF4p5 - Unknown packet_type %x", packet_type); } - + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); return; } -void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) { +void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int32_t **txdataF = eNB->common_vars.txdataF[0]; int32_t **rxdataF = eNB->common_vars.rxdataF[0]; @@ -168,15 +171,17 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ uint16_t element_id; uint16_t db_fulllength, db_halflength; int slotoffsetF=0, blockoffsetF=0; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - if (eNB->node_function == NGFI_RRU_IF4) { + if (eNB->node_function == NGFI_RRU_IF4p5) { db_fulllength = (12*fp->N_RB_DL); } else { db_fulllength = (12*fp->N_RB_UL); } db_halflength = db_fulllength>>1; - IF4_header_t *packet_header=NULL; + IF4p5_header_t *packet_header=NULL; uint16_t *data_block=NULL, *i=NULL; if (eNB->ifdevice.trx_read_func(&eNB->ifdevice, @@ -187,13 +192,13 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ perror("ETHERNET read"); } - packet_header = (IF4_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES); - data_block = (uint16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t); + packet_header = (IF4p5_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES); + data_block = (uint16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t); *frame = ((packet_header->frame_status)>>6)&0xffff; *subframe = ((packet_header->frame_status)>>22)&0x000f; - if (*packet_type == IF4_PDLFFT) { + if (*packet_type == IF4p5_PDLFFT) { *symbol_number = ((packet_header->frame_status)>>26)&0x000f; slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1; @@ -209,7 +214,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ]; } - } else if (*packet_type == IF4_PULFFT) { + } else if (*packet_type == IF4p5_PULFFT) { *symbol_number = ((packet_header->frame_status)>>26)&0x000f; slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + 1; @@ -225,25 +230,26 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ]; } - } else if (*packet_type == IF4_PRACH) { + } else if (*packet_type == IF4p5_PRACH) { // FIX: hard coded prach samples length db_fulllength = 839*2; memcpy((&rxsigF[0][0]), - (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t), + (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t), db_fulllength*sizeof(int16_t)); } else { - AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type); + AssertFatal(1==0, "recv_IF4p5 - Unknown packet_type %x", *packet_type); } - + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); return; } -void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) { - dl_packet->type = IF4_PACKET_TYPE; - dl_packet->sub_type = IF4_PDLFFT; +void gen_IF4p5_dl_header(IF4p5_header_t *dl_packet, int frame, int subframe) { + dl_packet->type = IF4p5_PACKET_TYPE; + dl_packet->sub_type = IF4p5_PDLFFT; dl_packet->rsvd = 0; @@ -254,9 +260,9 @@ void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) { } -void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) { - ul_packet->type = IF4_PACKET_TYPE; - ul_packet->sub_type = IF4_PULFFT; +void gen_IF4p5_ul_header(IF4p5_header_t *ul_packet, int frame, int subframe) { + ul_packet->type = IF4p5_PACKET_TYPE; + ul_packet->sub_type = IF4p5_PULFFT; ul_packet->rsvd = 0; @@ -267,9 +273,9 @@ void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) { } -void gen_IF4_prach_header(IF4_header_t *prach_packet, int frame, int subframe) { - prach_packet->type = IF4_PACKET_TYPE; - prach_packet->sub_type = IF4_PRACH; +void gen_IF4p5_prach_header(IF4p5_header_t *prach_packet, int frame, int subframe) { + prach_packet->type = IF4p5_PACKET_TYPE; + prach_packet->sub_type = IF4p5_PRACH; prach_packet->rsvd = 0; @@ -280,8 +286,8 @@ void gen_IF4_prach_header(IF4_header_t *prach_packet, int frame, int subframe) { } -void malloc_IF4_buffer(PHY_VARS_eNB *eNB) { +void malloc_IF4p5_buffer(PHY_VARS_eNB *eNB) { // Keep the size large enough - eNB->ifbuffer.tx = malloc(RAW_IF4_PRACH_SIZE_BYTES); - eNB->ifbuffer.rx = malloc(RAW_IF4_PRACH_SIZE_BYTES); + eNB->ifbuffer.tx = malloc(RAW_IF4p5_PRACH_SIZE_BYTES); + eNB->ifbuffer.rx = malloc(RAW_IF4p5_PRACH_SIZE_BYTES); } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 7276d97efa..95798e5bb8 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -41,12 +41,12 @@ #include "PHY/defs.h" /// Macro for IF4 packet type -#define IF4_PACKET_TYPE 0x080A -#define IF4_PULFFT 0x0019 -#define IF4_PDLFFT 0x0020 -#define IF4_PRACH 0x0021 +#define IF4p5_PACKET_TYPE 0x080A +#define IF4p5_PULFFT 0x0019 +#define IF4p5_PDLFFT 0x0020 +#define IF4p5_PRACH 0x0021 -struct IF4_header { +struct IF4p5_header { /// Type uint16_t type; /// Sub-Type @@ -58,17 +58,17 @@ struct IF4_header { } __attribute__ ((__packed__)); -typedef struct IF4_header IF4_header_t; -#define sizeof_IF4_header_t 12 +typedef struct IF4p5_header IF4p5_header_t; +#define sizeof_IF4p5_header_t 12 -void gen_IF4_dl_header(IF4_header_t*, int, int); +void gen_IF4p5_dl_header(IF4p5_header_t*, int, int); -void gen_IF4_ul_header(IF4_header_t*, int, int); +void gen_IF4p5_ul_header(IF4p5_header_t*, int, int); -void gen_IF4_prach_header(IF4_header_t*, int, int); +void gen_IF4p5_prach_header(IF4p5_header_t*, int, int); -void send_IF4(PHY_VARS_eNB*, int, int, uint16_t, int); +void send_IF4p5(PHY_VARS_eNB*, int, int, uint16_t, int); -void recv_IF4(PHY_VARS_eNB*, int*, int*, uint16_t*, uint32_t*); +void recv_IF4p5(PHY_VARS_eNB*, int*, int*, uint16_t*, uint32_t*); -void malloc_IF4_buffer(PHY_VARS_eNB*); +void malloc_IF4p5_buffer(PHY_VARS_eNB*); diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 59a3e70cd6..92d516d7e8 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -41,7 +41,7 @@ #include "PHY/defs.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" - +#include "UTIL/LOG/vcd_signal_dumper.h" void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe, uint8_t *seqno, uint16_t packet_type) { @@ -54,6 +54,8 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe uint32_t spp_eth = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_packet; uint32_t spsf = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); + if (packet_type == IF5_RRH_GW_DL) { for (i=0; i < fp->nb_antennas_tx; i++) @@ -143,6 +145,8 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe } free(tx_buffer); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); + return; } @@ -158,6 +162,8 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram int32_t spsf = (int32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10; openair0_timestamp timestamp[spsf / spp_eth]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); if (packet_type == IF5_RRH_GW_DL) { @@ -205,6 +211,8 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram } else { AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type); } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); return; } diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index d5dff4ef30..b3b4545350 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -1424,8 +1424,7 @@ void rx_phich(PHY_VARS_UE *ue, void generate_phich_top(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, int16_t amp, - uint8_t sect_id, - uint8_t abstraction_flag) + uint8_t sect_id) { @@ -1486,7 +1485,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, ulsch[UE_id]->harq_processes[harq_pid]->first_rb); } - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { generate_phich(frame_parms, amp,//amp*2, nseq_PHICH, diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 325e0918a5..93922207bb 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -190,7 +190,7 @@ int is_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_par return(0); } -void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx, int abstraction_flag) +void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx) { LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_MCH; @@ -227,7 +227,7 @@ void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx, int abstrac break; } - if (abstraction_flag) { + if (eNB->abstraction_flag) { eNB_transport_info[eNB->Mod_id][eNB->CC_id].cntl.pmch_flag=1; eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_pmch=1; // assumption: there is always one pmch in each SF eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_common_dci=0; @@ -286,13 +286,13 @@ void fill_UE_dlsch_MCH(PHY_VARS_UE *ue,int mcs,int ndi,int rvidx,int eNB_id) } } -void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a,int abstraction_flag) +void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a) { int G; int subframe = proc->subframe_tx; - if (abstraction_flag != 0) { + if (eNB->abstraction_flag != 0) { if (eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]!=0) printf("[PHY][EMU] PMCH transport block position is different than zero %d \n", eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]); diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 471b572a56..dfdf4ed470 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1183,7 +1183,7 @@ void rx_prach(PHY_VARS_eNB *eNB, if ((eNB->node_function == eNodeB_3GPP) || - (eNB->node_function == NGFI_RRU_IF4)) { // compute the DFTs of the PRACH temporal resources + (eNB->node_function == NGFI_RRU_IF4p5)) { // compute the DFTs of the PRACH temporal resources // Do forward transform for (aa=0; aanode_function == NGFI_RRU_IF4) { + if (eNB->node_function == NGFI_RRU_IF4p5) { k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; if (k<0) { @@ -1281,12 +1281,10 @@ void rx_prach(PHY_VARS_eNB *eNB, k*=2; /// **** send_IF4 of rxsigF to RCC **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - send_IF4(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4_PRACH, k); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + send_IF4p5(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4p5_PRACH, k); return; - } else if (eNB->node_function == NGFI_RCC_IF4) { + } else if (eNB->node_function == NGFI_RCC_IF4p5) { k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; if (k<0) { @@ -1305,7 +1303,7 @@ void rx_prach(PHY_VARS_eNB *eNB, // in case of RCC and prach received rx_thread wakes up prach - // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4 + // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4p5 preamble_offset_old = 99; diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 6993dd18c0..c3922b13d5 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -232,7 +232,7 @@ int mch_modulation(int32_t **txdataF, @param abstraction_flag */ -void generate_mch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t *a,int abstraction_flag); +void generate_mch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t *a); /** \brief This function generates the frequency-domain pilots (cell-specific downlink reference signals) @param phy_vars_eNB Pointer to eNB variables @@ -240,10 +240,8 @@ void generate_mch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t *a,in @param mcs MCS for MBSFN @param ndi new data indicator @param rdvix - @param abstraction_flag - */ -void fill_eNB_dlsch_MCH(PHY_VARS_eNB *phy_vars_eNB,int mcs,int ndi,int rvidx,int abstraction_flag); +void fill_eNB_dlsch_MCH(PHY_VARS_eNB *phy_vars_eNB,int mcs,int ndi,int rvidx); /** \brief This function generates the frequency-domain pilots (cell-specific downlink reference signals) @param phy_vars_ue Pointer to UE variables @@ -1546,8 +1544,7 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB, eNB_rxtx_proc_t *proc, int16_t amp, - uint8_t sect_id, - uint8_t abstraction_flag); + uint8_t sect_id); /* \brief This routine demodulates the PHICH and updates PUSCH/ULSCH parameters. @param phy_vars_ue Pointer to UE variables diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 3b3f277894..7bcc3810ae 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -161,8 +161,9 @@ typedef enum { eNodeB_3GPP=0, // classical eNodeB function eNodeB_3GPP_BBU, // eNodeB with NGFI IF5 NGFI_RRU_IF5, // NGFI_RRU with IF5 - NGFI_RRU_IF4, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) - NGFI_RCC_IF4 // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) + NGFI_RRU_IF4p5, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4p5) + NGFI_RCC_IF4p5, // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4p5) + NGFI_RAU_IF4p5 } eNB_func_t; typedef enum { @@ -187,6 +188,20 @@ typedef struct ral_threshold_phy_s { } ral_threshold_phy_t; #endif +/// Top-level PHY Data Structure for RN +typedef struct { + /// Module ID indicator for this instance + uint8_t Mod_id; + uint32_t frame; + // phy_vars_eNB + // phy_vars ue + // cuurently only used to store and forward the PMCH + uint8_t mch_avtive[10]; + uint8_t sync_area[10]; // num SF + LTE_UE_DLSCH_t *dlsch_rn_MCH[10]; + +} PHY_VARS_RN; + /// Context data structure for RX/TX portion of subframe processing typedef struct { /// Component Carrier index @@ -340,6 +355,15 @@ typedef struct PHY_VARS_eNB_s { eNB_proc_t proc; eNB_func_t node_function; eNB_timing_t node_timing; + int abstraction_flag; + void (*do_prach)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc); + void (*fep)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc); + void (*proc_uespec_rx)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type); + void (*proc_tx)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type,PHY_VARS_RN *rn); + void (*tx_fh)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc); + void (*rx_fh)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc,int *frame, int *subframe); + int (*start_rf)(struct PHY_VARS_eNB_s *eNB); + int (*start_if)(struct PHY_VARS_eNB_s *eNB); uint8_t local_flag; uint32_t rx_total_gain_dB; LTE_DL_FRAME_PARMS frame_parms; @@ -785,19 +809,7 @@ typedef struct { #endif } PHY_VARS_UE; -/// Top-level PHY Data Structure for RN -typedef struct { - /// Module ID indicator for this instance - uint8_t Mod_id; - uint32_t frame; - // phy_vars_eNB - // phy_vars ue - // cuurently only used to store and forward the PMCH - uint8_t mch_avtive[10]; - uint8_t sync_area[10]; // num SF - LTE_UE_DLSCH_t *dlsch_rn_MCH[10]; -} PHY_VARS_RN; #include "PHY/INIT/defs.h" #include "PHY/LTE_REFSIG/defs.h" diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index 279703b78a..a9f8633e30 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -164,20 +164,18 @@ void phy_procedures_UE_S_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abst @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param phy_vars_rn pointer to the RN variables */ -void phy_procedures_eNB_TX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); +void phy_procedures_eNB_TX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); /*! \brief Scheduling for eNB RX UE-specific procedures in normal subframes. @param phy_vars_eNB Pointer to eNB variables on which to act @param proc Pointer to RXn-TXnp4 proc information - @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type); /*! \brief Scheduling for eNB TX procedures in TDD S-subframes. @param phy_vars_eNB Pointer to eNB variables on which to act @param proc Pointer to RXn-TXnp4 proc information - @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ @@ -185,29 +183,26 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *pr @param phy_vars_eNB Pointer to eNB variables on which to act @param abstraction_flag Indicator of PHY abstraction */ -void phy_procedures_eNB_common_RX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag); +void phy_procedures_eNB_common_RX(PHY_VARS_eNB *phy_vars_eNB); /*! \brief Scheduling for eNB TX procedures in TDD S-subframes. @param phy_vars_eNB Pointer to eNB variables on which to act - @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_S_TX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_S_TX(PHY_VARS_eNB *phy_vars_eNB,relaying_type_t r_type); /*! \brief Scheduling for eNB RX procedures in TDD S-subframes. @param phy_vars_eNB Pointer to eNB variables on which to act - @param abstraction_flag Indicator of PHY abstraction @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type); +void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type); /*! \brief Scheduling for eNB PRACH RX procedures @param phy_vars_eNB Pointer to eNB variables on which to act @param proc Pointer to RXn-TXnp4 proc information - @param abstraction_flag Indicator of PHY abstraction */ -void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag); +void prach_procedures(PHY_VARS_eNB *eNB); /*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. @param frame_parms Pointer to DL frame parameter descriptor diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6be9ff2080..593d2b61fb 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -180,7 +180,7 @@ int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB) int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) { uint8_t i; - int j,CC_id; + int CC_id; PHY_VARS_eNB *eNB; for (CC_id=0;CC_idsubframe_rx; @@ -305,7 +305,7 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t abs #endif - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { lte_eNB_I0_measurements(eNB, subframe, 0, @@ -392,7 +392,7 @@ unsigned int taus(void); DCI_PDU DCI_pdu_tmp; -void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) { +void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) { #ifdef Rel10 @@ -403,7 +403,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, in int subframe = proc->subframe_tx; - if (abstraction_flag==0) { + if (eNB->abstraction_flag==0) { // This is DL-Cell spec pilots in Control region generate_pilots_slot(eNB, eNB->common_vars.txdataF[0], @@ -464,9 +464,9 @@ void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, in }// switch if (mch_pduP) { - fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0, abstraction_flag); + fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0); // Generate PMCH - generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload,abstraction_flag); + generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload); } else { LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe); } @@ -474,7 +474,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, in #endif } -void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstraction_flag) { +void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int **txdataF = eNB->common_vars.txdataF[0]; @@ -483,7 +483,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr int frame = proc->frame_tx; // generate Cell-Specific Reference Signals for both slots - if (abstraction_flag==0) { + if (eNB->abstraction_flag==0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1); generate_pilots_slot(eNB, txdataF, @@ -502,7 +502,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr // First half of PSS/SSS (FDD, slot 0) if (subframe == 0) { if ((fp->frame_type == FDD) && - (abstraction_flag==0)) { + (eNB->abstraction_flag==0)) { generate_pss(txdataF, AMP, fp, @@ -585,7 +585,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr /// First half of SSS (TDD, slot 1) if ((fp->frame_type == TDD)&& - (abstraction_flag==0)){ + (eNB->abstraction_flag==0)){ generate_sss(txdataF, AMP, fp, @@ -594,7 +594,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr } /// generate PBCH - if (abstraction_flag==0) { + if (eNB->abstraction_flag==0) { generate_pbch(&eNB->pbch, txdataF, AMP, @@ -611,7 +611,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr } else if ((subframe == 1) && (fp->frame_type == TDD)&& - (abstraction_flag==0)) { + (eNB->abstraction_flag==0)) { generate_pss(txdataF, AMP, fp, @@ -622,7 +622,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr // Second half of PSS/SSS (FDD, slot 10) else if ((subframe == 5) && (fp->frame_type == FDD) && - (abstraction_flag==0)) { + (eNB->abstraction_flag==0)) { generate_pss(txdataF, AMP, &eNB->frame_parms, @@ -639,7 +639,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr // Second-half of SSS (TDD, slot 11) else if ((subframe == 5) && (fp->frame_type == TDD) && - (abstraction_flag==0)) { + (eNB->abstraction_flag==0)) { generate_sss(txdataF, AMP, fp, @@ -650,7 +650,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr // Second half of PSS (TDD, slot 12) else if ((subframe == 6) && (fp->frame_type == TDD) && - (abstraction_flag==0)) { + (eNB->abstraction_flag==0)) { generate_pss(txdataF, AMP, fp, @@ -867,7 +867,7 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC } -void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols,int abstraction_flag) { +void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols) { int frame=proc->frame_tx; int subframe=proc->subframe_tx; @@ -1025,7 +1025,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d #endif } - if (abstraction_flag==0) { + if (eNB->abstraction_flag==0) { LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag); // 36-212 @@ -1083,7 +1083,6 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, - uint8_t abstraction_flag, relaying_type_t r_type, PHY_VARS_RN *rn) { @@ -1145,7 +1144,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, } // clear the transmit data array for the current subframe - if (abstraction_flag==0) { + if (eNB->abstraction_flag==0) { for (aa=0; aanb_antennas_tx_eNB; aa++) { memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)], 0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t)); @@ -1153,11 +1152,11 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, } if (is_pmch_subframe(frame,subframe,fp)) { - pmch_procedures(eNB,proc,rn,abstraction_flag,r_type); + pmch_procedures(eNB,proc,rn,r_type); } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH - common_signal_procedures(eNB,proc,abstraction_flag); + common_signal_procedures(eNB,proc); } #if defined(SMBV) @@ -1283,7 +1282,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, eNB->num_common_dci[(subframe)&1]=0; } - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) { LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,frame, subframe, @@ -1316,7 +1315,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) { - pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols); #if defined(SMBV) @@ -1349,7 +1348,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, eNB->ulsch[(uint32_t)UE_id]->Msg3_frame, eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe); - pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols); eNB->dlsch_ra->active = 0; @@ -1362,7 +1361,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&& (eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) { - pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols,abstraction_flag); + pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols); } @@ -1385,8 +1384,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, generate_phich_top(eNB, proc, AMP, - 0, - abstraction_flag); + 0); } @@ -1395,24 +1393,6 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, phy_procedures_emos_eNB_TX(subframe, eNB); #endif -#if !(defined(EXMIMO) || defined(OAI_USRP) || defined (CPRIGW)) - - if (abstraction_flag==0) - { - start_meas(&eNB->ofdm_mod_stats); - do_OFDM_mod(eNB->common_vars.txdataF[0], - eNB->common_vars.txdata[0], - frame,subframe<<1, - fp); - do_OFDM_mod(eNB->common_vars.txdataF[0], - eNB->common_vars.txdata[0], - frame,1+(subframe<<1), - fp); - stop_meas(&eNB->ofdm_mod_stats); - } - -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),0); stop_meas(&eNB->phy_proc_tx); @@ -1869,8 +1849,7 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, } } -void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) -{ +void prach_procedures(PHY_VARS_eNB *eNB) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint16_t preamble_energy_list[64],preamble_delay_list[64]; @@ -1881,10 +1860,11 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) int frame = eNB->proc.frame_prach; uint8_t CC_id = eNB->CC_id; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); memset(&preamble_energy_list[0],0,64*sizeof(uint16_t)); memset(&preamble_delay_list[0],0,64*sizeof(uint16_t)); - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id, frame,subframe,dB_fixed(signal_energy(&eNB->common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_dB); @@ -1984,9 +1964,10 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag) eNB->Mod_id,frame, subframe); } } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } -void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0}; @@ -2059,7 +2040,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq eNB->UE_stats[UE_id].sr_total++; - if (abstraction_flag == 0) + if (eNB->abstraction_flag == 0) metric0_SR = rx_pucch(eNB, pucch_format1, UE_id, @@ -2115,7 +2096,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload); - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { @@ -2160,7 +2141,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload); - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { @@ -2236,7 +2217,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format); #endif - if (abstraction_flag == 0) + if (eNB->abstraction_flag == 0) metric0_SR = rx_pucch(eNB, format, UE_id, @@ -2268,7 +2249,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq // Check n1_pucch0 metric if (n1_pucch0 != -1) { - if (abstraction_flag == 0) + if (eNB->abstraction_flag == 0) metric0 = rx_pucch(eNB, format, UE_id, @@ -2293,7 +2274,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq // Check n1_pucch1 metric if (n1_pucch1 != -1) { - if (abstraction_flag == 0) + if (eNB->abstraction_flag == 0) metric1 = rx_pucch(eNB, format, UE_id, @@ -2350,7 +2331,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq } -void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) { +void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) { uint8_t access_mode; int num_active_cba_groups; @@ -2375,7 +2356,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]); #endif - if (abstraction_flag==0) { + if (eNB->abstraction_flag==0) { rx_ulsch(eNB,proc, eNB->UE_stats[UE_id].sector, // this is the effective sector id UE_id, @@ -2392,7 +2373,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p #endif - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { ret = ulsch_decoding(eNB,proc, UE_id, 0, // control_only_flag @@ -2509,116 +2490,121 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p } - -void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) { +void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { int l; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); + remove_7_5_kHz(eNB,proc->subframe_rx<<1); + remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1)); + for (l=0; lsymbols_per_tti/2; l++) { + slot_fep_ul(fp, + &eNB->common_vars, + l, + proc->subframe_rx<<1, + 0, + 0 + ); + slot_fep_ul(fp, + &eNB->common_vars, + l, + 1+(proc->subframe_rx<<1), + 0, + 0 + ); + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); + + if (eNB->node_function == NGFI_RRU_IF4p5) { + /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); + send_IF4p5(eNB, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT, 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + } +} + +void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { + + uint8_t seqno=0; + + /// **** send_IF5 of rxdata to BBU **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); + send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); + +} + +void do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { + + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + // check if we have to detect PRACH first + if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) { + /* accept some delay in processing - up to 5ms */ + int i; + for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) { + LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach); + usleep(500); + } + if (proc->instance_cnt_prach == 0) { + exit_fun( "PRACH thread busy" ); + return; + } + + // wake up thread for PRACH RX + if (pthread_mutex_lock(&proc->mutex_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); + exit_fun( "error locking mutex_prach" ); + return; + } + + ++proc->instance_cnt_prach; + // set timing for prach thread + proc->frame_prach = proc->frame_rx; + proc->subframe_prach = proc->subframe_rx; + + // the thread can now be woken up + if (pthread_cond_signal(&proc->cond_prach) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + + pthread_mutex_unlock( &proc->mutex_prach ); + } + +} + +void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){ + + eNB_proc_t *proc = &eNB->proc; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; - uint8_t seqno=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 1 ); start_meas(&eNB->phy_proc_rx); -#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe); -#endif - if (abstraction_flag==0) { - if ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == eNodeB_3GPP) || - (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing + if (eNB->fep) eNB->fep(eNB,proc); - // now do common RX processing for first slot in subframe - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); - remove_7_5_kHz(eNB,proc->subframe_rx<<1); - remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1)); - for (l=0; lsymbols_per_tti/2; l++) { - slot_fep_ul(fp, - &eNB->common_vars, - l, - proc->subframe_rx<<1, - 0, - 0 - ); - slot_fep_ul(fp, - &eNB->common_vars, - l, - 1+(proc->subframe_rx<<1), - 0, - 0 - ); - } + if (eNB->do_prach) eNB->do_prach(eNB,proc); + - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); - - if (eNB->node_function == NGFI_RRU_IF4) { - /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - send_IF4(eNB, proc->frame_rx, proc->subframe_rx, IF4_PULFFT, 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); - } - } - else if (eNB->node_function == NGFI_RRU_IF5) { - /// **** send_IF5 of rxdata to BBU **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); - } - - /// **** send_IF4 of prach to RCC **** /// done in prach thread (below) - // check if we have to detect PRACH first - if ((eNB->node_function != NGFI_RRU_IF5) && - (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0)) { // any other node must call prach procedure - /* accept some delay in processing - up to 5ms */ - int i; - for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) { - LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach); - usleep(500); - } - if (proc->instance_cnt_prach == 0) { - exit_fun( "PRACH thread busy" ); - return; - } - - // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach ); - exit_fun( "error locking mutex_prach" ); - return; - } - - ++proc->instance_cnt_prach; - // set timing for prach thread - proc->frame_prach = proc->frame_rx; - proc->subframe_prach = proc->subframe_rx; - - // the thread can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - - pthread_mutex_unlock( &proc->mutex_prach ); - } - - } else { // grab transport channel information from network interface - - } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 0 ); } -void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const uint8_t abstraction_flag,const relaying_type_t r_type) +void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type) { //RX processing for ue-specific resources (i UNUSED(r_type); @@ -2664,7 +2650,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const // Do PUCCH processing first for (i=0; ipusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->mcs; start_meas(&eNB->ulsch_demodulation_stats); - if (abstraction_flag==0) { + if (eNB->abstraction_flag==0) { rx_ulsch(eNB,proc, eNB->UE_stats[i].sector, // this is the effective sector id i, @@ -2770,7 +2756,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const start_meas(&eNB->ulsch_decoding_stats); - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { ret = ulsch_decoding(eNB,proc, i, 0, // control_only_flag @@ -3082,7 +3068,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const } // Msg3_flag == 0 // estimate timing advance for MAC - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { sync_pos = lte_est_timing_advance_pusch(eNB,i); eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check } @@ -3169,10 +3155,10 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const } // CBA (non-LTE) - cba_procedures(eNB,proc,i,harq_pid,abstraction_flag); + cba_procedures(eNB,proc,i,harq_pid); } // loop i=0 ... NUMBER_OF_UE_MAX-1 - if (abstraction_flag == 0) { + if (eNB->abstraction_flag == 0) { lte_eNB_I0_measurements(eNB, subframe, 0, diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index cecdf623ef..770b4afa25 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -887,10 +887,12 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->cc_node_function[j] = eNodeB_3GPP; } else if (strcmp(cc_node_function, "eNodeB_3GPP_BBU") == 0) { enb_properties.properties[enb_properties_index]->cc_node_function[j] = eNodeB_3GPP_BBU; - } else if (strcmp(cc_node_function, "NGFI_RCC_IF4") == 0) { - enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RCC_IF4; - } else if (strcmp(cc_node_function, "NGFI_RRU_IF4") == 0) { - enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF4; + } else if (strcmp(cc_node_function, "NGFI_RCC_IF4p5") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RCC_IF4p5; + } else if (strcmp(cc_node_function, "NGFI_RAU_IF4p5") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RAU_IF4p5; + } else if (strcmp(cc_node_function, "NGFI_RRU_IF4p5") == 0) { + enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF4p5; } else if (strcmp(cc_node_function, "NGFI_RRU_IF5") == 0) { enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF5; } else { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index faf19c9fda..02ca6ee7eb 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -201,7 +201,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi -int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { +int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { int nblocks = nsamps; int bytes_sent = 0; @@ -211,14 +211,14 @@ int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, ssize_t packet_size; - if (flags == IF4_PDLFFT) { - packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks); - } else if (flags == IF4_PULFFT) { - packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks); + if (flags == IF4p5_PDLFFT) { + packet_size = RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks); + } else if (flags == IF4p5_PULFFT) { + packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks); } else if (flags == IF5_MOBIPASS) { packet_size = RAW_IF5_MOBIPASS_SIZE_BYTES; } else { - packet_size = RAW_IF4_PRACH_SIZE_BYTES; + packet_size = RAW_IF4p5_PRACH_SIZE_BYTES; } eth->tx_nsamps = nblocks; @@ -304,7 +304,7 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi -int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { +int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { // Read nblocks info from packet itself int nblocks = nsamps; @@ -312,8 +312,8 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t; - IF4_header_t *test_header = (IF4_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES); + ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t; + IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES); bytes_received = recv(eth->sockfd[Mod_id], buff[0], @@ -327,12 +327,12 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, *timestamp = test_header->sub_type; - if (test_header->sub_type == IF4_PDLFFT) { - packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks); - } else if (test_header->sub_type == IF4_PULFFT) { - packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks); + if (test_header->sub_type == IF4p5_PDLFFT) { + packet_size = RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks); + } else if (test_header->sub_type == IF4p5_PULFFT) { + packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks); } else { - packet_size = RAW_IF4_PRACH_SIZE_BYTES; + packet_size = RAW_IF4p5_PRACH_SIZE_BYTES; } while(bytes_received < packet_size) { @@ -387,7 +387,7 @@ int eth_set_dev_conf_raw(openair0_device *device) { -int eth_set_dev_conf_raw_IF4(openair0_device *device) { +int eth_set_dev_conf_raw_IF4p5(openair0_device *device) { // use for cc_id info int Mod_id = device->Mod_id; @@ -448,7 +448,7 @@ int eth_get_dev_conf_raw(openair0_device *device) { } -int eth_get_dev_conf_raw_IF4(openair0_device *device) { +int eth_get_dev_conf_raw_IF4p5(openair0_device *device) { // use for cc_id info eth_state_t *eth = (eth_state_t*)device->priv; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 252bdbb47c..f2c69985bf 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -73,27 +73,27 @@ int trx_eth_start(openair0_device *device) { /* adjust MTU wrt number of samples per packet */ if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; - } else if (eth->flags == ETH_RAW_IF4_MODE) { + } else if (eth->flags == ETH_RAW_IF4p5_MODE) { if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ if (device->host_type == BBU_HOST) { - if(eth_set_dev_conf_raw_IF4(device)!=0) return -1; + if(eth_set_dev_conf_raw_IF4p5(device)!=0) return -1; } else { - if(eth_get_dev_conf_raw_IF4(device)!=0) return -1; + if(eth_get_dev_conf_raw_IF4p5(device)!=0) return -1; } /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,RAW_IF4_PRACH_SIZE_BYTES)!=0) return -1; + if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; - } else if (eth->flags == ETH_UDP_IF4_MODE) { + } else if (eth->flags == ETH_UDP_IF4p5_MODE) { } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ //if (device->host_type == BBU_HOST) { - //if(eth_set_dev_conf_raw_IF4(device)!=0) return -1; + //if(eth_set_dev_conf_raw_IF4p5(device)!=0) return -1; //} else { - //if(eth_get_dev_conf_raw_IF4(device)!=0) return -1; + //if(eth_get_dev_conf_raw_IF4p5(device)!=0) return -1; // /* adjust MTU wrt number of samples per packet */ // if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; @@ -339,9 +339,9 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth } else if (eth_params->transp_preference == 0) { eth->flags = ETH_UDP_MODE; } else if (eth_params->transp_preference == 3) { - eth->flags = ETH_RAW_IF4_MODE; + eth->flags = ETH_RAW_IF4p5_MODE; } else if (eth_params->transp_preference == 2) { - eth->flags = ETH_UDP_IF4_MODE; + eth->flags = ETH_UDP_IF4p5_MODE; } else if (eth_params->transp_preference == 4) { eth->flags = ETH_RAW_IF5_MOBIPASS; } else { @@ -368,15 +368,15 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth } else if (eth->flags == ETH_UDP_MODE) { device->trx_write_func = trx_eth_write_udp; device->trx_read_func = trx_eth_read_udp; - } else if (eth->flags == ETH_RAW_IF4_MODE) { - device->trx_write_func = trx_eth_write_raw_IF4; - device->trx_read_func = trx_eth_read_raw_IF4; + } else if (eth->flags == ETH_RAW_IF4p5_MODE) { + device->trx_write_func = trx_eth_write_raw_IF4p5; + device->trx_read_func = trx_eth_read_raw_IF4p5; } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - device->trx_write_func = trx_eth_write_raw_IF4; - device->trx_read_func = trx_eth_read_raw_IF4; + device->trx_write_func = trx_eth_write_raw_IF4p5; + device->trx_read_func = trx_eth_read_raw_IF4p5; } else { - //device->trx_write_func = trx_eth_write_udp_IF4; - //device->trx_read_func = trx_eth_read_udp_IF4; + //device->trx_write_func = trx_eth_write_udp_IF4p5; + //device->trx_read_func = trx_eth_read_udp_IF4p5; } eth->if_name[device->Mod_id] = eth_params->local_if_name; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index f7753fb517..3adb0f45cb 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -222,11 +222,11 @@ int eth_set_dev_conf_udp(openair0_device *device); int eth_socket_init_raw(openair0_device *device); int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); -int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); -int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); int eth_get_dev_conf_raw(openair0_device *device); int eth_set_dev_conf_raw(openair0_device *device); -int eth_get_dev_conf_raw_IF4(openair0_device *device); -int eth_set_dev_conf_raw_IF4(openair0_device *device); +int eth_get_dev_conf_raw_IF4p5(openair0_device *device); +int eth_set_dev_conf_raw_IF4p5(openair0_device *device); #endif diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 038129cf36..e118e9f99f 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -47,8 +47,8 @@ // ETH transport preference modes #define ETH_UDP_MODE 0 #define ETH_RAW_MODE 1 -#define ETH_UDP_IF4_MODE 2 -#define ETH_RAW_IF4_MODE 3 +#define ETH_UDP_IF4p5_MODE 2 +#define ETH_RAW_IF4p5_MODE 3 #define ETH_RAW_IF5_MOBIPASS 4 // Time domain RRH packet sizes @@ -58,13 +58,13 @@ #define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) #define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) -// Packet sizes for IF4 interface format +// Packet sizes for IF4p5 interface format #define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(uint16_t)*scaled_nblocks) #define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839*2) // FIX hard coded prach size (uncompressed) -#define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) -#define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) -#define RAW_IF4_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + PRACH_BLOCK_SIZE_BYTES) +#define RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define RAW_IF4p5_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + PRACH_BLOCK_SIZE_BYTES) // Mobipass packet sizes #define RAW_IF5_MOBIPASS_BLOCK_SIZE_BYTES 1280 diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index ac552e82fe..150a29e342 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -173,6 +173,8 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { int len,len2; int16_t *txdata; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); + slot_offset_F = (subframe<<1)*slot_sizeF; slot_offset = subframe*phy_vars_eNB->frame_parms.samples_per_tti; @@ -284,8 +286,101 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { } } } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); } +void tx_fh_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { + uint8_t seqno; + send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL); +} + +void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { + send_IF4p5(eNB,proc->frame_tx, proc->subframe_tx, IF4p5_PDLFFT, 0); +} + +void proc_tx_full(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, + uint8_t abstraction_flag, + relaying_type_t r_type, + PHY_VARS_RN *rn) { + + phy_procedures_eNB_TX(eNB,proc,r_type,rn); + + /* we're done, let the next one proceed */ + if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n"); + exit_fun("nothing to add"); + } + sync_phy_proc.phy_proc_CC_id++; + sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs; + pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); + if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n"); + exit_fun("nothing to add"); + } + + + do_OFDM_mod_rt(proc->subframe_tx,eNB); + + if (eNB->tx_fh) eNB->tx_fh(eNB,proc); + + + +} + +void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { + + uint32_t symbol_number=0; + uint32_t symbol_mask, symbol_mask_full; + uint16_t packet_type; + + /// **** recv_IF4 of txdataF from RCC **** /// + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<frame_parms.symbols_per_tti)-1; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); + do { + recv_IF4p5(eNB, &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); + symbol_mask = symbol_mask | (1<subframe_tx, eNB); +} + +void proc_tx_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { + /// **** recv_IF5 of txdata from BBU **** /// + recv_IF5(eNB, &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL); +} + +int wait_CCs(eNB_rxtx_proc_t *proc) { + + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(&sync_phy_proc.mutex_phy_proc_tx,&wait) != 0) { + LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n"); + exit_fun("nothing to add"); + return(-1); + } + + // wait for our turn or oai_exit + while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) { + pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx, + &sync_phy_proc.mutex_phy_proc_tx); + } + + if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { + LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX\n"); + exit_fun("nothing to add"); + return(-1); + } + return(0); +} /*! * \brief The RX UE-specific and TX thread of eNB. @@ -297,14 +392,16 @@ static void* eNB_thread_rxtx( void* param ) { static int eNB_thread_rxtx_status; eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param; + PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + FILE *tx_time_file = NULL; char tx_time_name[101]; - void *txp[PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx]; + void *txp[fp->nb_antennas_tx]; int txs; - uint16_t packet_type; - uint32_t symbol_number=0; - uint32_t symbol_mask, symbol_mask_full; + + uint8_t seqno=0; @@ -435,6 +532,7 @@ static void* eNB_thread_rxtx( void* param ) { } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); + start_meas( &softmodem_stats_rxtx_sf ); if (oai_exit) break; @@ -443,158 +541,31 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->subframe_rx ); // Common procedures - phy_procedures_eNB_common_RX(PHY_vars_eNB_g[0][proc->CC_id], 0); - - // UE-specific RX processing for subframe n - if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4)) { - - // this is the ue-specific processing for the subframe and can be multi-threaded later - phy_procedures_eNB_uespec_RX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay ); - } + phy_procedures_eNB_common_RX(eNB); + // Do UE-specific RX processing for subframe n if any + if (eNB->proc_uespec_rx) eNB->proc_uespec_rx(eNB, proc, no_relay ); // TX processing for subframe n+4 - if (((PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.frame_type == TDD) && - ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_DL) || - (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_S))) || - (PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.frame_type == FDD)) { + if (((fp->frame_type == TDD) && + ((subframe_select(fp,proc->subframe_tx) == SF_DL) || + (subframe_select(fp,proc->subframe_tx) == SF_S))) || + (fp->frame_type == FDD)) { /* run PHY TX procedures the one after the other for all CCs to avoid race conditions * (may be relaxed in the future for performance reasons) */ - - if (pthread_mutex_timedlock(&sync_phy_proc.mutex_phy_proc_tx,&wait) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n"); - exit_fun("nothing to add"); - break; - } - - // wait for our turn or oai_exit - while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) { - pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx, - &sync_phy_proc.mutex_phy_proc_tx); - } - if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX\n"); - exit_fun("nothing to add"); - } + if (wait_CCs(proc)<0) break; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->frame_tx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->subframe_tx ); if (oai_exit) break; - - if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4)) { - phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay, NULL ); - /* we're done, let the next one proceed */ - if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; - } - sync_phy_proc.phy_proc_CC_id++; - sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs; - pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); - if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) { - LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; - } - } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) { - /// **** recv_IF4 of txdataF from RCC **** /// - symbol_number = 0; - symbol_mask = 0; - symbol_mask_full = (1<CC_id]->frame_parms.symbols_per_tti)-1; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - do { - recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); - symbol_mask = symbol_mask | (1<CC_id]->node_function == NGFI_RRU_IF5) { - /// **** recv_IF5 of txdata from BBU **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - recv_IF5(PHY_vars_eNB_g[0][proc->CC_id], &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - - } - } - - // eNodeB_3GPP, _BBU and RRU create txdata - if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 ); - do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 ); - } - - /* - short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti]; - int i; - for (i=0;iCC_id]->frame_parms.samples_per_tti*2;i+=8) { - txdata[i] = 2047; - txdata[i+1] = 0; - txdata[i+2] = 0; - txdata[i+3] = 2047; - txdata[i+4] = -2047; - txdata[i+5] = 0; - txdata[i+6] = 0; - txdata[i+7] = -2047; } - */ - - - /* - // eNodeB_3GPP, RRU write to RF device - if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) || - (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5)) { - // Transmit TX buffer based on timestamp from RX - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - int i; - for (i=0; iframe_parms.nb_antennas_tx; i++) - txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti]; - - txs = PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, - (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance), - txp, - PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti, - PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx, - 1); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff ); - - if (txs != PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti) { - LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti); - exit_fun( "problem transmitting samples" ); - } - } - */ - if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) { - /// **** send_IF5 of txdata to RRH **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); - - } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4) { - /// **** send_IF4 of txdataF to RRU **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); - send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); + if (eNB->proc_tx) eNB->proc_tx(eNB, proc, no_relay, NULL ); } + if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n"); exit_fun("nothing to add"); @@ -611,13 +582,14 @@ static void* eNB_thread_rxtx( void* param ) { stop_meas( &softmodem_stats_rxtx_sf ); -#ifdef DEADLINE_SCHEDULER if (opp_enabled){ + +#ifdef DEADLINE_SCHEDULER if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); - } + } #endif - + } print_meas_now(&softmodem_stats_rxtx_sf,"eNB_TX_SF",tx_time_file); } @@ -807,10 +779,10 @@ static void* eNB_thread_asynch_rx( void* param ) { } } // eNodeB_3GPP_BBU - else if (eNB->node_function == NGFI_RCC_IF4) { - /// **** recv_IF4 of rxdataF from RRU **** /// - /// **** recv_IF4 of rxsigF from RRU **** /// - // get frame/subframe information from IF4 interface + else if (eNB->node_function == NGFI_RCC_IF4p5) { + /// **** recv_IF4p5 of rxdataF from RRU **** /// + /// **** recv_IF4p5 of rxsigF from RRU **** /// + // get frame/subframe information from IF4p5 interface // timed loop (200 us) symbol_number = 0; @@ -819,14 +791,12 @@ static void* eNB_thread_asynch_rx( void* param ) { prach_rx = 0; do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - recv_IF4(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); + recv_IF4p5(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number); - if (packet_type == IF4_PULFFT) { + if (packet_type == IF4p5_PULFFT) { symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; - } else if (packet_type == IF4_PRACH) { + } else if (packet_type == IF4p5_PRACH) { prach_rx = 0; } } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); @@ -845,6 +815,248 @@ static void* eNB_thread_asynch_rx( void* param ) { } +void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { + + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; + unsigned int rxs,txs; + int i; + + if (proc->first_rx==0) { + + // Transmit TX buffer based on timestamp from RX + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + + for (i=0; inb_antennas_tx; i++) + txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti]; + + txs = eNB->rfdevice.trx_write_func(&eNB->rfdevice, + proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, + txp, + fp->samples_per_tti, + fp->nb_antennas_tx, + 1); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + + + + if (txs != fp->samples_per_tti) { + LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, fp->samples_per_tti); + exit_fun( "problem transmitting samples" ); + } + } + + for (i=0; inb_antennas_rx; i++) + rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][*subframe*fp->samples_per_tti]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); + + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, + &(proc->timestamp_rx), + rxp, + fp->samples_per_tti, + fp->nb_antennas_rx); + + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + + if (proc->first_rx == 0) { + if (proc->subframe_rx != *subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + exit_fun("Exiting"); + } + + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *subframe = proc->subframe_rx; + } + + //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + + if (rxs != fp->samples_per_tti) + exit_fun( "problem receiving samples" ); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + +} + +void rx_fh_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame, int *subframe) { + + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + + recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); + + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + + if (proc->first_rx == 0) { + if (proc->subframe_rx != subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + exit_fun("Exiting"); + } + + if (proc->frame_rx != frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + frame = proc->frame_rx; + subframe = proc->subframe_rx; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + +} + +void rx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *subframe,int *frame) { + + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + + int prach_rx; + + uint16_t packet_type; + uint32_t symbol_number=0; + uint32_t symbol_mask, symbol_mask_full; + + symbol_mask = 0; + symbol_mask_full = (1<symbols_per_tti)-1; + prach_rx = 0; + + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); + recv_IF4p5(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); + + if (packet_type == IF4p5_PULFFT) { + symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; + } else if (packet_type == IF4p5_PRACH) { + prach_rx = 0; + } + } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); + + if (proc->first_rx == 0) { + if (proc->subframe_rx != *subframe){ + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + exit_fun("Exiting"); + } + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *subframe = proc->subframe_rx; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + +} + +int wakeup_rxtx(eNB_proc_t *proc,eNB_rxtx_proc_t *proc_rxtx,LTE_DL_FRAME_PARMS *fp) { + + int i; + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + /* accept some delay in processing - up to 5ms */ + for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) { + LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->instance_cnt_rxtx); + usleep(500); + } + if (proc_rxtx->instance_cnt_rxtx == 0) { + exit_fun( "TX thread busy" ); + return(-1); + } + + // wake up TX for subframe n+4 + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx ); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + + ++proc_rxtx->instance_cnt_rxtx; + + // We have just received and processed the common part of a subframe, say n. + // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired + // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, + // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+3 + proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); + proc_rxtx->frame_rx = proc->frame_rx; + proc_rxtx->subframe_rx = proc->subframe_rx; + proc_rxtx->frame_tx = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx; + proc_rxtx->subframe_tx = (proc_rxtx->subframe_rx + 4)%10; + + // the thread can now be woken up + if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return(-1); + } + + pthread_mutex_unlock( &proc_rxtx->mutex_rxtx ); + + return(0); +} + +void wakeup_slaves(eNB_proc_t *proc) { + + int i; + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + for (i=0;inum_slaves;i++) { + eNB_proc_t *slave_proc = proc->slave_proc[i]; + // wake up slave FH thread + // lock the FH mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d (IC %d)\n",proc->CC_id,slave_proc->CC_id); + exit_fun( "error locking mutex_rxtx" ); + break; + } + + int cnt_slave = ++slave_proc->instance_cnt_FH; + slave_proc->frame_rx = proc->frame_rx; + slave_proc->subframe_rx = proc->subframe_rx; + slave_proc->timestamp_rx = proc->timestamp_rx; + + pthread_mutex_unlock( &slave_proc->mutex_FH ); + + if (cnt_slave == 0) { + // the thread was presumably waiting where it should and can now be woken up + if (pthread_cond_signal(&slave_proc->cond_FH) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB CCid %d, slave CCid %d\n",proc->CC_id,slave_proc->CC_id); + exit_fun( "ERROR pthread_cond_signal" ); + break; + } + } else { + LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); + exit_fun( "FH thread busy" ); + break; + } + } +} + /*! * \brief The Fronthaul thread of RRU/RAU/RCC/eNB * In the case of RRU/eNB, handles interface with external RF @@ -859,19 +1071,15 @@ static void* eNB_thread_FH( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; - unsigned int rxs,txs; + FILE *rx_time_file = NULL; char rx_time_name[101]; - struct timespec wait; - int i; - int prach_rx; - uint16_t packet_type; - uint32_t symbol_number=0; - uint32_t symbol_mask, symbol_mask_full; + int i; int subframe=0, frame=0; + + struct timespec wait; wait.tv_sec=0; wait.tv_nsec=5000000L; @@ -994,32 +1202,16 @@ static void* eNB_thread_FH( void* param ) { wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif - // Create buffer for IF device and free when stopping - if (eNB->node_function == NGFI_RCC_IF4 || eNB->node_function == NGFI_RRU_IF4) { - malloc_IF4_buffer(eNB); - - } else if (eNB->node_function == NGFI_RRU_IF5 || eNB->node_function == eNodeB_3GPP_BBU) { - //malloc_IF5_buffer(eNB); - - } else { - eNB->ifbuffer.tx = NULL; - eNB->ifbuffer.rx = NULL; - } - - // Start IF device for this CC - if (eNB->node_function != eNodeB_3GPP) { - if (eNB->ifdevice.trx_start_func(&eNB->ifdevice) != 0 ) - LOG_E(HW,"Could not start the IF device\n"); - } - - // Start RF device for this CC - if ((eNB->node_function == eNodeB_3GPP) || - (eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == NGFI_RRU_IF5)) { - if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) + // Start RF device if any + if (eNB->start_rf) + if (eNB->start_rf(eNB) != 0) LOG_E(HW,"Could not start the RF device\n"); - } - + + // Start IF device if any + if (eNB->start_if) + if (eNB->start_if(eNB) != 0) + LOG_E(HW,"Could not start the IF device\n"); + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { @@ -1035,7 +1227,7 @@ static void* eNB_thread_FH( void* param ) { // This case is for synchronization to another thread if ((eNB->node_timing == synch_to_other) && - ((eNB->node_function == NGFI_RCC_IF4) || + ((eNB->node_function == NGFI_RCC_IF4p5) || (eNB->node_function == eNodeB_3GPP_BBU))) { //wait for event @@ -1056,232 +1248,24 @@ static void* eNB_thread_FH( void* param ) { } // Remaining cases are all for synchronization on FH interface - else if ((eNB->node_timing == synch_to_ext_device) && - ((eNB->node_function == NGFI_RRU_IF4) || - (eNB->node_function == NGFI_RRU_IF5) || - (eNB->node_function == eNodeB_3GPP))) { // acquisition from RF + else if ((eNB->node_timing == synch_to_ext_device) && + (eNB->rx_fh)) + eNB->rx_fh(eNB,proc,&frame,&subframe); - if (proc->first_rx==0) { - - // Transmit TX buffer based on timestamp from RX - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - - for (i=0; iframe_parms.nb_antennas_tx; i++) - txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti]; - - txs = PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice, - proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, - txp, - fp->samples_per_tti, - fp->nb_antennas_tx, - 1); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - - - - if (txs != PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti) { - LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, fp->samples_per_tti); - exit_fun( "problem transmitting samples" ); - } - } - - for (i=0; inb_antennas_rx; i++) - rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - - rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, - &proc->timestamp_rx, - rxp, - fp->samples_per_tti, - fp->nb_antennas_rx); - - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; - proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - - if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - exit_fun("Exiting"); - } - - if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - frame = proc->frame_rx; - subframe = proc->subframe_rx; - } - - //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - - if (rxs != fp->samples_per_tti) - exit_fun( "problem receiving samples" ); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - - } // node_timing==synch_to_ext_device && node_function == RRU || eNodeB - else if ((eNB->node_timing == synch_to_ext_device) && - (eNB->node_function == eNodeB_3GPP_BBU)) { // acquisition from IF - /// **** recv_IF5 of rxdata from RRH **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - recv_IF5(eNB, &proc->timestamp_rx, subframe, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; - proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - - if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - exit_fun("Exiting"); - } - - if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - frame = proc->frame_rx; - subframe = proc->subframe_rx; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - - } // eNodeB_3GPP_BBU && node_timing == synch_to_ext_device - else if ((eNB->node_timing == synch_to_ext_device) && - (eNB->node_function == NGFI_RCC_IF4)) { - /// **** recv_IF4 of rxdataF from RRU **** /// - /// **** recv_IF4 of rxsigF from RRU **** /// - // timed loop (200 us) - - symbol_number = 0; - symbol_mask = 0; - symbol_mask_full = (1<symbols_per_tti)-1; - prach_rx = 0; - - do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); - recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); - - if (packet_type == IF4_PULFFT) { - symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; - } else if (packet_type == IF4_PRACH) { - prach_rx = 0; - } - } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); - - if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); - exit_fun("Exiting"); - } - if (proc->frame_rx != frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - frame = proc->frame_rx; - subframe = proc->subframe_rx; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - - } // node_timing == synch_to_externs, node_function = NGFI_IF4 else { // should not get here - AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); + AssertFatal(1==0, "Unknown fronthaul interface : eNB->node_function %d",eNB->node_function); } T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); // At this point, all information for subframe has been received on FH interface // If this proc is to provide synchronization, do so - for (i=0;inum_slaves;i++) { - eNB_proc_t *slave_proc = proc->slave_proc[i]; - // wake up slave FH thread - // lock the FH mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d (IC %d)\n",proc->CC_id,slave_proc->CC_id); - exit_fun( "error locking mutex_rxtx" ); - break; - } - - int cnt_slave = ++slave_proc->instance_cnt_FH; - slave_proc->frame_rx = proc->frame_rx; - slave_proc->subframe_rx = proc->subframe_rx; - slave_proc->timestamp_rx = proc->timestamp_rx; - - pthread_mutex_unlock( &slave_proc->mutex_FH ); - - if (cnt_slave == 0) { - // the thread was presumably waiting where it should and can now be woken up - if (pthread_cond_signal(&slave_proc->cond_FH) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB CCid %d, slave CCid %d\n",proc->CC_id,slave_proc->CC_id); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - } else { - LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); - exit_fun( "FH thread busy" ); - break; - } - } + wakeup_slaves(proc); // wake up RXn_TXnp4 thread for the subframe // choose even or odd thread for RXn-TXnp4 processing - eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[proc->subframe_rx&1]; - - /* accept some delay in processing - up to 5ms */ - for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) { - LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->instance_cnt_rxtx); - usleep(500); - } - if (proc_rxtx->instance_cnt_rxtx == 0) { - exit_fun( "TX thread busy" ); + if (wakeup_rxtx(proc,&proc->proc_rxtx[proc->subframe_rx&1],fp) < 0) break; - } - - // wake up TX for subframe n+4 - // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx ); - exit_fun( "error locking mutex_rxtx" ); - break; - } - - ++proc_rxtx->instance_cnt_rxtx; - - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, - // and proc->subframe_tx = proc->subframe_rx+3 - proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); - proc_rxtx->frame_rx = proc->frame_rx; - proc_rxtx->subframe_rx = proc->subframe_rx; - proc_rxtx->frame_tx = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx; - proc_rxtx->subframe_tx = (proc_rxtx->subframe_rx + 4)%10; - - // the thread can now be woken up - if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - break; - } - - pthread_mutex_unlock( &proc_rxtx->mutex_rxtx ); stop_meas( &softmodem_stats_rxtx_sf ); #ifdef DEADLINE_SCHEDULER @@ -1453,9 +1437,8 @@ static void* eNB_thread_prach( void* param ) { break; } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); - prach_procedures(eNB,0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); + + prach_procedures(eNB); if (pthread_mutex_lock(&proc->mutex_prach) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); @@ -1732,17 +1715,95 @@ void print_opp_meas(void) { } } +int start_if(PHY_VARS_eNB *eNB) { + return(eNB->ifdevice.trx_start_func(&eNB->ifdevice)); +} - void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst) { +int start_rf(PHY_VARS_eNB *eNB) { + return(eNB->rfdevice.trx_start_func(&eNB->rfdevice)); +} +extern eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc); +extern eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc); +extern do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc); + +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst) { + int CC_id; int inst; - + PHY_VARS_eNB *eNB; for (inst=0;instnode_function = node_function[CC_id]; - PHY_vars_eNB_g[inst][CC_id]->node_timing = node_timing[CC_id]; + eNB = PHY_vars_eNB_g[inst][CC_id]; + eNB->node_function = node_function[CC_id]; + eNB->node_timing = node_timing[CC_id]; + eNB->abstraction_flag = 0; LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]); + switch (node_function[CC_id]) { + case NGFI_RRU_IF5: + eNB->do_prach = NULL; + eNB->fep = eNB_fep_rru_if5; + eNB->proc_uespec_rx = NULL; + eNB->proc_tx = NULL; + eNB->tx_fh = NULL; + eNB->rx_fh = rx_rf; + eNB->start_rf = start_rf; + eNB->start_if = start_if; + break; + case NGFI_RRU_IF4p5: + eNB->do_prach = do_prach; + eNB->fep = eNB_fep_full; + eNB->proc_uespec_rx = NULL; + eNB->proc_tx = proc_tx_rru_if4p5; + eNB->tx_fh = NULL; + eNB->rx_fh = rx_rf; + eNB->start_rf = start_rf; + eNB->start_if = start_if; + malloc_IF4p5_buffer(eNB); + break; + case eNodeB_3GPP: + eNB->do_prach = do_prach; + eNB->fep = eNB_fep_full; + eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; + eNB->proc_tx = proc_tx_full; + eNB->tx_fh = NULL; + eNB->rx_fh = rx_rf; + eNB->start_rf = start_rf; + eNB->start_if = NULL; + break; + case eNodeB_3GPP_BBU: + eNB->do_prach = do_prach; + eNB->fep = eNB_fep_full; + eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; + eNB->proc_tx = proc_tx_full; + eNB->tx_fh = tx_fh_if5; + eNB->rx_fh = rx_fh_if5; + eNB->start_rf = NULL; + eNB->start_if = start_if; + break; + case NGFI_RCC_IF4p5: + eNB->do_prach = do_prach; + eNB->fep = eNB_fep_full; + eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; + eNB->proc_tx = proc_tx_full; + eNB->tx_fh = tx_fh_if4p5; + eNB->rx_fh = rx_fh_if4p5; + eNB->start_rf = NULL; + eNB->start_if = start_if; + malloc_IF4p5_buffer(eNB); + break; + case NGFI_RAU_IF4p5: + eNB->do_prach = do_prach; + eNB->fep = eNB_fep_full; + eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; + eNB->proc_tx = proc_tx_full; + eNB->tx_fh = tx_fh_if4p5; + eNB->rx_fh = rx_fh_if4p5; + eNB->start_rf = NULL; + eNB->start_if = start_if; + malloc_IF4p5_buffer(eNB); + break; + } } init_eNB_proc(inst); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 9c3ec6fb99..38c95a4122 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1056,9 +1056,9 @@ static void get_options (int argc, char **argv) if (enb_properties->properties[i]->rrh_gw_config[j].raw == 1) { (eth_params+j)->transp_preference = ETH_RAW_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4 == 1) { - (eth_params+j)->transp_preference = ETH_RAW_IF4_MODE; + (eth_params+j)->transp_preference = ETH_RAW_IF4p5_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4 == 1) { - (eth_params+j)->transp_preference = ETH_UDP_IF4_MODE; + (eth_params+j)->transp_preference = ETH_UDP_IF4p5_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif5_mobipass == 1) { (eth_params+j)->transp_preference = ETH_RAW_IF5_MOBIPASS; } else { @@ -1645,7 +1645,7 @@ int main( int argc, char **argv ) if (UE_flag == 0) { for (CC_id=0; CC_idrfdevice.host_type = RRH_HOST; PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = RRH_HOST; } else { @@ -1667,7 +1667,7 @@ int main( int argc, char **argv ) // Load RF device and initialize for (CC_id=0; CC_idrfdevice), &openair0_cfg[0]) : From d6377f1acd1db0348270c15a2ae6a52f9fb409ef Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 10:41:09 +0200 Subject: [PATCH 125/206] correction for RCC/RAU initialization --- targets/RT/USER/lte-enb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 150a29e342..c9df826908 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1783,7 +1783,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case NGFI_RCC_IF4p5: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; + eNB->fep = NULL; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = tx_fh_if4p5; @@ -1794,7 +1794,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case NGFI_RAU_IF4p5: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; + eNB->fep = NULL; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = tx_fh_if4p5; From 5309b71e94607509b1f8336aa8b0041308dfa15f Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 12:26:41 +0200 Subject: [PATCH 126/206] more separation for RRU/RCC --- targets/RT/USER/lte-enb.c | 74 ++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index c9df826908..43ae984197 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -298,11 +298,10 @@ void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { send_IF4p5(eNB,proc->frame_tx, proc->subframe_tx, IF4p5_PDLFFT, 0); } -void proc_tx_full(PHY_VARS_eNB *eNB, - eNB_rxtx_proc_t *proc, - uint8_t abstraction_flag, - relaying_type_t r_type, - PHY_VARS_RN *rn) { +void proc_tx_high0(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, + relaying_type_t r_type, + PHY_VARS_RN *rn) { phy_procedures_eNB_TX(eNB,proc,r_type,rn); @@ -319,16 +318,42 @@ void proc_tx_full(PHY_VARS_eNB *eNB, exit_fun("nothing to add"); } +} +void proc_tx_high(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, + relaying_type_t r_type, + PHY_VARS_RN *rn) { + + // do PHY high + proc_tx_high0(eNB,proc,r_type,rn); + + // if TX fronthaul go ahead + if (eNB->tx_fh) eNB->tx_fh(eNB,proc); + +} + +void proc_tx_full(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, + relaying_type_t r_type, + PHY_VARS_RN *rn) { + + + // do PHY high + proc_tx_high0(eNB,proc,r_type,rn); + // do OFDM modulation do_OFDM_mod_rt(proc->subframe_tx,eNB); - + // if TX fronthaul go ahead if (eNB->tx_fh) eNB->tx_fh(eNB,proc); } -void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { +void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB, + eNB_rxtx_proc_t *proc, + relaying_type_t r_type, + PHY_VARS_RN *rn) { uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; @@ -397,13 +422,7 @@ static void* eNB_thread_rxtx( void* param ) { FILE *tx_time_file = NULL; char tx_time_name[101]; - void *txp[fp->nb_antennas_tx]; - int txs; - - - - uint8_t seqno=0; if (opp_enabled == 1) { snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf", "eNB"); @@ -628,6 +647,8 @@ static void wait_system_ready (char *message, volatile int *start_flag) { */ static void* eNB_thread_asynch_rx( void* param ) { + static int eNB_thread_asynch_rx_status; + eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; @@ -813,6 +834,8 @@ static void* eNB_thread_asynch_rx( void* param ) { AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); } + eNB_thread_asynch_rx_status=0; + return(&eNB_thread_asynch_rx_status); } void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { @@ -900,19 +923,19 @@ void rx_fh_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame, int *subframe) { proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; if (proc->first_rx == 0) { - if (proc->subframe_rx != subframe){ + if (proc->subframe_rx != *subframe){ LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); exit_fun("Exiting"); } - if (proc->frame_rx != frame) { + if (proc->frame_rx != *frame) { LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); exit_fun("Exiting"); } } else { proc->first_rx = 0; - frame = proc->frame_rx; - subframe = proc->subframe_rx; + *frame = proc->frame_rx; + *subframe = proc->subframe_rx; } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); @@ -1075,15 +1098,8 @@ static void* eNB_thread_FH( void* param ) { FILE *rx_time_file = NULL; char rx_time_name[101]; - int i; - int subframe=0, frame=0; - struct timespec wait; - - wait.tv_sec=0; - wait.tv_nsec=5000000L; - if (opp_enabled == 1) { snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB"); rx_time_file = fopen(rx_time_name,"w"); @@ -1723,9 +1739,9 @@ int start_rf(PHY_VARS_eNB *eNB) { return(eNB->rfdevice.trx_start_func(&eNB->rfdevice)); } -extern eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc); -extern eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc); -extern do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc); +extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc); +extern void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc); +extern void do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc); void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst) { @@ -1785,7 +1801,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = do_prach; eNB->fep = NULL; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; - eNB->proc_tx = proc_tx_full; + eNB->proc_tx = proc_tx_high; eNB->tx_fh = tx_fh_if4p5; eNB->rx_fh = rx_fh_if4p5; eNB->start_rf = NULL; @@ -1796,7 +1812,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = do_prach; eNB->fep = NULL; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; - eNB->proc_tx = proc_tx_full; + eNB->proc_tx = proc_tx_high; eNB->tx_fh = tx_fh_if4p5; eNB->rx_fh = rx_fh_if4p5; eNB->start_rf = NULL; From dbae061e72f6db0c2b2ca5642fb26b1ba358beca Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 15:31:45 +0200 Subject: [PATCH 127/206] modifications for if5 --- .../CONF/rcc.band7.tm1.usrpb210.conf | 2 +- .../CONF/rru.band7.tm1.usrpb210.conf | 2 +- targets/RT/USER/lte-enb.c | 129 +++++++++++++----- targets/RT/USER/lte-softmodem.c | 62 +-------- targets/RT/USER/lte-ue.c | 5 + 5 files changed, 107 insertions(+), 93 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf index 20cc9189bb..06ecae228b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf @@ -23,7 +23,7 @@ eNBs = component_carriers = ( { - node_function = "NGFI_RCC_IF4"; + node_function = "NGFI_RCC_IF4p5"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; frame_type = "FDD"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf index f828dfb1c7..5fbdad1fa6 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.usrpb210.conf @@ -23,7 +23,7 @@ eNBs = component_carriers = ( { - node_function = "NGFI_RRU_IF4"; + node_function = "NGFI_RRU_IF4p5"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; frame_type = "FDD"; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 43ae984197..5f0c033826 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -159,7 +159,7 @@ static struct { void exit_fun(const char* s); -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst); +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *); void stop_eNB(int nb_inst); @@ -1218,16 +1218,17 @@ static void* eNB_thread_FH( void* param ) { wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif - // Start RF device if any - if (eNB->start_rf) - if (eNB->start_rf(eNB) != 0) - LOG_E(HW,"Could not start the RF device\n"); // Start IF device if any if (eNB->start_if) if (eNB->start_if(eNB) != 0) LOG_E(HW,"Could not start the IF device\n"); + // Start RF device if any + if (eNB->start_rf) + if (eNB->start_rf(eNB) != 0) + LOG_E(HW,"Could not start the RF device\n"); + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { @@ -1743,11 +1744,13 @@ extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc); extern void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc); extern void do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc); -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst) { +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params) { int CC_id; int inst; PHY_VARS_eNB *eNB; + int ret; + for (inst=0;instnode_timing = node_timing[CC_id]; eNB->abstraction_flag = 0; LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]); + switch (node_function[CC_id]) { case NGFI_RRU_IF5: - eNB->do_prach = NULL; - eNB->fep = eNB_fep_rru_if5; - eNB->proc_uespec_rx = NULL; - eNB->proc_tx = NULL; - eNB->tx_fh = NULL; - eNB->rx_fh = rx_rf; - eNB->start_rf = start_rf; - eNB->start_if = start_if; + eNB->do_prach = NULL; + eNB->fep = eNB_fep_rru_if5; + eNB->proc_uespec_rx = NULL; + eNB->proc_tx = proc_tx_rru_if5;; + eNB->tx_fh = NULL; + eNB->rx_fh = rx_rf; + eNB->start_rf = start_rf; + eNB->start_if = start_if; + ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[0]); + if (ret<0) { + printf("Exiting, cannot initialize rf device\n"); + exit(-1); + } + eNB->rfdevice.host_type = RRH_HOST; + eNB->ifdevice.host_type = RRH_HOST; + ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[0], (eth_params+CC_id)); + printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id); + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } break; case NGFI_RRU_IF4p5: - eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; - eNB->proc_uespec_rx = NULL; - eNB->proc_tx = proc_tx_rru_if4p5; - eNB->tx_fh = NULL; - eNB->rx_fh = rx_rf; - eNB->start_rf = start_rf; - eNB->start_if = start_if; + eNB->do_prach = do_prach; + eNB->fep = eNB_fep_full; + eNB->proc_uespec_rx = NULL; + eNB->proc_tx = proc_tx_rru_if4p5; + eNB->tx_fh = NULL; + eNB->rx_fh = rx_rf; + eNB->start_rf = start_rf; + eNB->start_if = start_if; + ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[0]); + if (ret<0) { + printf("Exiting, cannot initialize rf device\n"); + exit(-1); + } + eNB->rfdevice.host_type = RRH_HOST; + eNB->ifdevice.host_type = RRH_HOST; + ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[0], (eth_params+CC_id)); + printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id); + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + malloc_IF4p5_buffer(eNB); + break; case eNodeB_3GPP: - eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; - eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; - eNB->proc_tx = proc_tx_full; - eNB->tx_fh = NULL; - eNB->rx_fh = rx_rf; - eNB->start_rf = start_rf; - eNB->start_if = NULL; + eNB->do_prach = do_prach; + eNB->fep = eNB_fep_full; + eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; + eNB->proc_tx = proc_tx_full; + eNB->tx_fh = NULL; + eNB->rx_fh = rx_rf; + eNB->start_rf = start_rf; + eNB->start_if = NULL; + ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[0]); + if (ret<0) { + printf("Exiting, cannot initialize rf device\n"); + exit(-1); + } + eNB->rfdevice.host_type = BBU_HOST; + eNB->ifdevice.host_type = BBU_HOST; break; case eNodeB_3GPP_BBU: eNB->do_prach = do_prach; @@ -1796,6 +1835,15 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->rx_fh = rx_fh_if5; eNB->start_rf = NULL; eNB->start_if = start_if; + eNB->rfdevice.host_type = BBU_HOST; + + eNB->ifdevice.host_type = BBU_HOST; + ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[0], (eth_params+CC_id)); + printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id); + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } break; case NGFI_RCC_IF4p5: eNB->do_prach = do_prach; @@ -1806,7 +1854,16 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->rx_fh = rx_fh_if4p5; eNB->start_rf = NULL; eNB->start_if = start_if; + eNB->rfdevice.host_type = BBU_HOST; + eNB->ifdevice.host_type = BBU_HOST; + ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[0], (eth_params+CC_id)); + printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id); + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } malloc_IF4p5_buffer(eNB); + break; case NGFI_RAU_IF4p5: eNB->do_prach = do_prach; @@ -1817,8 +1874,18 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->rx_fh = rx_fh_if4p5; eNB->start_rf = NULL; eNB->start_if = start_if; - malloc_IF4p5_buffer(eNB); + + eNB->rfdevice.host_type = BBU_HOST; + eNB->ifdevice.host_type = BBU_HOST; + ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[0], (eth_params+CC_id)); + printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id); + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } break; + malloc_IF4p5_buffer(eNB); + } } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 38c95a4122..f2c3614850 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -119,7 +119,7 @@ unsigned short config_frames[4] = {2,9,11,13}; // In lte-enb.c extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); -extern void init_eNB(eNB_func_t *, eNB_timing_t *,int); +extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *); extern void stop_eNB(int); extern void kill_eNB_proc(void); @@ -1643,64 +1643,6 @@ int main( int argc, char **argv ) openair0_cfg[0].log_level = glog_level; - if (UE_flag == 0) { - for (CC_id=0; CC_idrfdevice.host_type = RRH_HOST; - PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = RRH_HOST; - } else { - PHY_vars_eNB_g[0][CC_id]->rfdevice.host_type = BBU_HOST; - PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = BBU_HOST; - } - } - } - else { - /* device host type is set*/ - PHY_vars_UE_g[0][0]->rfdevice.host_type = BBU_HOST; - /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ - PHY_vars_UE_g[0][0]->rfdevice.type = NONE_DEV; - /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ - PHY_vars_UE_g[0][0]->rfdevice.transp_type = NONE_TP; - } - - int returns=-1; - - // Load RF device and initialize - for (CC_id=0; CC_idrfdevice), &openair0_cfg[0]) : - openair0_device_load(&(PHY_vars_UE_g[0][CC_id]->rfdevice), &openair0_cfg[0]); - - printf("openair0_device_init returns %d for CC_id %d\n",returns,CC_id); - if (returns<0) { - printf("Exiting, cannot initialize device\n"); - exit(-1); - } - } else if (mode==loop_through_memory) { - - } - } - } - - // Load transport protocol and initialize - for (CC_id=0; CC_idifdevice), &openair0_cfg[0], (eth_params+CC_id)); - printf("openair0_transport_init returns %d for CC_id %d\n",returns,CC_id); - if (returns<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - } else if (mode==loop_through_memory) { - - } - } - } - - printf("Done initializing RF and IF devices\n"); mac_xface = malloc(sizeof(MAC_xface)); @@ -1854,7 +1796,7 @@ int main( int argc, char **argv ) // start the main thread if (UE_flag == 1) init_UE(1); - else init_eNB(node_function,node_timing,1); + else init_eNB(node_function,node_timing,1,eth_params); // Sleep to allow all threads to setup sleep(3); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 73e9197588..3fda5d735f 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -179,12 +179,17 @@ void init_UE(int nb_inst) { int error_code; int inst; PHY_VARS_UE *UE; + int ret; for (inst=0;instrfdevice), &openair0_cfg[0]); + UE->rfdevice.host_type = BBU_HOST; + UE->rfdevice.type = NONE_DEV; error_code = pthread_create(&UE->proc.pthread_ue, &UE->proc.attr_ue, UE_thread, NULL); if (error_code!= 0) { From 2a621d319cad4cc2dbfe8f275cb8253ed06c8480 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 15:50:05 +0200 Subject: [PATCH 128/206] rcc if5 configuration file --- .../GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf index 20cc9189bb..bba251f2d9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.usrpb210.conf @@ -23,7 +23,7 @@ eNBs = component_carriers = ( { - node_function = "NGFI_RCC_IF4"; + node_function = "NGFI_RCC_IF4p5"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; frame_type = "FDD"; @@ -155,13 +155,13 @@ eNBs = rrh_gw_config = ( { - local_if_name = "eth2"; - remote_address = "00:13:95:1f:a0:af"; - local_address = "90:e2:ba:c5:fc:04"; + local_if_name = "eth0"; + remote_address = "74:d4:35:cc:8d:15"; + local_address = "34:e6:d7:3c:ae:fc"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; rrh_gw_active = "yes"; - tr_preference = "raw_if4"; + tr_preference = "raw_if4p5"; rf_preference = "usrp_b200"; iq_txshift = 4; tx_sample_advance = 80; From 5817a62c37ddb0bfe10af8ecac0552ec45d38410 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 17:02:43 +0200 Subject: [PATCH 129/206] vcd dumping for send/recv IF5 --- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 15 +++++++++------ openair2/UTIL/LOG/vcd_signal_dumper.c | 2 ++ openair2/UTIL/LOG/vcd_signal_dumper.h | 2 ++ targets/RT/USER/lte-enb.c | 17 ++++++++++------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 92d516d7e8..1f3c76ddd4 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -62,14 +62,15 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe txp[i] = (void*)&eNB->common_vars.txdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), txp, spp_eth, fp->nb_antennas_tx, 0); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); for (i=0; i < fp->nb_antennas_tx; i++) txp[i] += spp_eth; @@ -82,13 +83,14 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), rxp, spp_eth, fp->nb_antennas_rx, 0); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); for (i=0; i < fp->nb_antennas_rx; i++) rxp[i] += spp_eth; @@ -172,12 +174,13 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], txp, spp_eth, fp->nb_antennas_tx); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); for (i=0; i < fp->nb_antennas_tx; i++) txp[i] += spp_eth; @@ -191,13 +194,13 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], rxp, spp_eth, fp->nb_antennas_rx); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); for (i=0; i < fp->nb_antennas_rx; i++) rxp[i] += spp_eth; diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index db00a8c35f..7779fe5290 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -189,6 +189,8 @@ const char* eurecomFunctionsNames[] = { "rt_sleep", "trx_read", "trx_write", + "trx_read_if", + "trx_write_if", "eNB_thread_rxtx0", "eNB_thread_rxtx1", "ue_thread_synch", diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index 433d155a6c..4c5e5cc1b8 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -163,6 +163,8 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP=0, VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, + VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, + VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0, VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX1, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 5f0c033826..ed8cfefecb 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -291,6 +291,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { void tx_fh_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { uint8_t seqno; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, proc->timestamp_tx&0xffffffff ); send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL); } @@ -847,7 +848,7 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { if (proc->first_rx==0) { - // Transmit TX buffer based on timestamp from RX + // Transmit TX buffer based on timestamp from RX VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers @@ -882,6 +883,8 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { rxp, fp->samples_per_tti, fp->nb_antennas_rx); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; @@ -906,11 +909,11 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - if (rxs != fp->samples_per_tti) - exit_fun( "problem receiving samples" ); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - + if (rxs != fp->samples_per_tti) + exit_fun( "problem receiving samples" ); + + + } void rx_fh_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame, int *subframe) { @@ -1764,7 +1767,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = NULL; eNB->fep = eNB_fep_rru_if5; eNB->proc_uespec_rx = NULL; - eNB->proc_tx = proc_tx_rru_if5;; + eNB->proc_tx = proc_tx_rru_if5; eNB->tx_fh = NULL; eNB->rx_fh = rx_rf; eNB->start_rf = start_rf; From ec209bd43e053e471611015972800251a9004389 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 19:33:39 +0200 Subject: [PATCH 130/206] if5 modifications. Use of asynchronous RX thread for RCC->RRU IF5 link --- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 10 +- openair1/PHY/defs.h | 18 ++-- targets/RT/USER/lte-enb.c | 134 ++++++++++++++++--------- 3 files changed, 104 insertions(+), 58 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 1f3c76ddd4..8f5b7b32fe 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -66,7 +66,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), - txp, + (void**)txp, spp_eth, fp->nb_antennas_tx, 0); @@ -86,7 +86,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); eNB->ifdevice.trx_write_func(&eNB->ifdevice, (proc_timestamp + packet_id*spp_eth), - rxp, + (void**)rxp, spp_eth, fp->nb_antennas_rx, 0); @@ -131,7 +131,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe // Write the packet to the fronthaul if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice, packet_id, - &tx_buffer, + (void**)&tx_buffer, db_fulllength, 1, IF5_MOBIPASS)) < 0) { @@ -177,7 +177,7 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], - txp, + (void**)txp, spp_eth, fp->nb_antennas_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); @@ -197,7 +197,7 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 1 ); eNB->ifdevice.trx_read_func(&eNB->ifdevice, ×tamp[packet_id], - rxp, + (void**)rxp, spp_eth, fp->nb_antennas_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF, 0 ); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 7bcc3810ae..8e88fba00d 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -252,10 +252,12 @@ typedef struct eNB_proc_t_s { /// \brief Instance count for rx processing thread. /// \internal This variable is protected by \ref mutex_prach. int instance_cnt_prach; + /// \internal This variable is protected by \ref mutex_asynch_rxtx. + int instance_cnt_asynch_rxtx; /// pthread structure for FH processing thread pthread_t pthread_FH; - /// pthread structure for asychronous RX processing thread - pthread_t pthread_asynch_rx; + /// pthread structure for asychronous RX/TX processing thread + pthread_t pthread_asynch_rxtx; /// flag to indicate first RX acquisition int first_rx; /// pthread attributes for FH processing thread @@ -263,23 +265,27 @@ typedef struct eNB_proc_t_s { /// pthread attributes for prach processing thread pthread_attr_t attr_prach; /// pthread attributes for asynchronous RX thread - pthread_attr_t attr_asynch_rx; + pthread_attr_t attr_asynch_rxtx; /// scheduling parameters for FH thread struct sched_param sched_param_FH; /// scheduling parameters for prach thread struct sched_param sched_param_prach; - /// scheduling parameters for asynch_rx thread - struct sched_param sched_param_asynch_rx; - /// condition variable for FH thread + /// scheduling parameters for asynch_rxtx thread + struct sched_param sched_param_asynch_rxtx; + /// pthread structure for PRACH thread pthread_t pthread_prach; /// condition variable for FH thread pthread_cond_t cond_FH; /// condition variable for PRACH processing thread; pthread_cond_t cond_prach; + /// condition variable for asynch RX/TX thread + pthread_cond_t cond_asynch_rxtx; /// mutex for FH pthread_mutex_t mutex_FH; /// mutex for PRACH thread pthread_mutex_t mutex_prach; + /// mutex for asynch RX/TX thread + pthread_mutex_t mutex_asynch_rxtx; /// set of scheduling variables RXn-TXnp4 threads eNB_rxtx_proc_t proc_rxtx[2]; /// number of slave threads diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index ed8cfefecb..732fec7a4f 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -641,21 +641,22 @@ static void wait_system_ready (char *message, volatile int *start_flag) { #endif /*! - * \brief The Asynchronous RX FH thread of RAU/RCC/eNB. + * \brief The Asynchronous RX/TX FH thread of RAU/RCC/eNB/RRU. * This handles the RX FH for an asynchronous RRU/UE * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ -static void* eNB_thread_asynch_rx( void* param ) { +static void* eNB_thread_asynch_rxtx( void* param ) { - static int eNB_thread_asynch_rx_status; + static int eNB_thread_asynch_rxtx_status; eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - openair0_timestamp timestamp_rx; - int frame_rx,subframe_rx; + openair0_timestamp timestamp_rx,timestamp_tx; + int frame_rx,subframe_rx=0,subframe_tx=0; static int first_rx = 1; + static int first_tx = 1; uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask, symbol_mask_full; @@ -768,40 +769,67 @@ static void* eNB_thread_asynch_rx( void* param ) { printf( "got sync (eNB_thread_asynch_rx)\n" ); - if (eNB->node_function == eNodeB_3GPP) { // acquisition from RF - if (eNB->rfdevice.trx_read_func) - rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, - &proc->timestamp_rx, - (void**)dummy_rx, - fp->samples_per_tti, - fp->nb_antennas_rx); - else { - printf("eNB asynch RX\n"); - sleep(1); + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + printf( "waiting for devices (eNB_thread_asynch_rx)\n"); + pthread_mutex_lock( &proc->mutex_asynch_rxtx); + + while (proc->instance_cnt_asynch_rxtx<0) + pthread_cond_wait( &proc->cond_asynch_rxtx, &proc->mutex_asynch_rxtx ); + + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + + printf( "devices ok (eNB_thread_asynch_rx)\n"); + + while (!oai_exit) { + if (eNB->node_function == eNodeB_3GPP) { // acquisition from RF + + if (eNB->rfdevice.trx_read_func) + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, + &proc->timestamp_rx, + (void**)dummy_rx, + fp->samples_per_tti, + fp->nb_antennas_rx); + else { + printf("eNB asynch RX\n"); + sleep(1); + } + if (rxs!=fp->samples_per_tti) { + exit_fun("error receiving samples\n"); + } } - if (rxs!=fp->samples_per_tti) { - exit_fun("error receiving samples\n"); - } - } - else if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF + else if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF /// **** recv_IF5 of rxdata from RRH **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - recv_IF5(eNB, ×tamp_rx, subframe_rx++, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - if (first_rx == 1) { - first_rx = 0; - subframe_rx = (timestamp_rx/fp->samples_per_tti)%10; - } - else { - // check timestamp - if ((timestamp_rx - proc->timestamp_rx) < (2*fp->samples_per_tti)) - printf("RX overflow ...\n"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); + recv_IF5(eNB, ×tamp_rx, subframe_rx++, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); + if (first_rx == 1) { + first_rx = 0; + subframe_rx = (timestamp_rx/fp->samples_per_tti)%10; + } + else { + // check timestamp + if ((timestamp_rx - proc->timestamp_rx) < (2*fp->samples_per_tti)) + printf("RX overflow ...\n"); + + } + } // eNodeB_3GPP_BBU + + else if (eNB->node_function == NGFI_RRU_IF5) { + /// **** recv_IF5 of rxdata from RRH **** /// + subframe_tx = (subframe_tx+1)%10; + + recv_IF5(eNB, ×tamp_tx, subframe_tx, IF5_RRH_GW_DL); + printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); + if (first_tx == 1) { + first_tx = 0; + subframe_tx = (timestamp_tx/fp->samples_per_tti)%10; + + } + } - } // eNodeB_3GPP_BBU - - else if (eNB->node_function == NGFI_RCC_IF4p5) { + else if (eNB->node_function == NGFI_RCC_IF4p5) { /// **** recv_IF4p5 of rxdataF from RRU **** /// /// **** recv_IF4p5 of rxsigF from RRU **** /// // get frame/subframe information from IF4p5 interface @@ -811,10 +839,10 @@ static void* eNB_thread_asynch_rx( void* param ) { symbol_mask = 0; symbol_mask_full = (1<symbols_per_tti)-1; prach_rx = 0; - + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number); - + if (packet_type == IF4p5_PULFFT) { symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; @@ -834,9 +862,9 @@ static void* eNB_thread_asynch_rx( void* param ) { else { // should not get here AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); } - - eNB_thread_asynch_rx_status=0; - return(&eNB_thread_asynch_rx_status); + } + eNB_thread_asynch_rxtx_status=0; + return(&eNB_thread_asynch_rxtx_status); } void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { @@ -848,16 +876,17 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { if (proc->first_rx==0) { - // Transmit TX buffer based on timestamp from RX + // Transmit TX buffer based on timestamp from RX + printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers for (i=0; inb_antennas_tx; i++) - txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti]; + txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+2)%10)*fp->samples_per_tti]; txs = eNB->rfdevice.trx_write_func(&eNB->rfdevice, - proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, + proc->timestamp_rx+(2*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, txp, fp->samples_per_tti, fp->nb_antennas_tx, @@ -877,7 +906,7 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][*subframe*fp->samples_per_tti]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - + rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, &(proc->timestamp_rx), rxp, @@ -888,6 +917,7 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + printf("trx_read <- USRP TS %llu (sf %d, first_rx %d)\n", proc->timestamp_rx,proc->subframe_rx,proc->first_rx); if (proc->first_rx == 0) { if (proc->subframe_rx != *subframe){ @@ -1232,6 +1262,12 @@ static void* eNB_thread_FH( void* param ) { if (eNB->start_rf(eNB) != 0) LOG_E(HW,"Could not start the RF device\n"); + // unlock asnych_rxtx thread + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx=0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { @@ -1527,6 +1563,7 @@ void init_eNB_proc(int inst) { proc_rxtx[1].instance_cnt_rxtx = -1; proc->instance_cnt_prach = -1; proc->instance_cnt_FH = -1; + proc->instance_cnt_asynch_rxtx = -1; proc->CC_id = CC_id; proc->first_rx=4; @@ -1534,24 +1571,27 @@ void init_eNB_proc(int inst) { pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); pthread_cond_init( &proc->cond_prach, NULL); pthread_cond_init( &proc->cond_FH, NULL); + pthread_cond_init( &proc->cond_asynch_rxtx, NULL); #ifndef DEADLINE_SCHEDULER pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc ); + if ((eNB->node_timing == synch_to_other) || + (eNB->node_function == NGFI_RRU_IF5)) + pthread_create( &proc->pthread_asynch_rxtx, &proc->attr_asynch_rxtx, eNB_thread_asynch_rxtx, &eNB->proc ); #else pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc ); + pthread_create( &proc->pthread_asynch_rxtx, NULL, eNB_thread_asynch_rxtx, &eNB->proc ); #endif char name[16]; @@ -1767,7 +1807,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = NULL; eNB->fep = eNB_fep_rru_if5; eNB->proc_uespec_rx = NULL; - eNB->proc_tx = proc_tx_rru_if5; + eNB->proc_tx = NULL; eNB->tx_fh = NULL; eNB->rx_fh = rx_rf; eNB->start_rf = start_rf; From 4b6da53f6d0b311e40b228b4e84d3d2dce15d07f Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 19:41:31 +0200 Subject: [PATCH 131/206] added timeout on ETHERNET recv --- targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index f2c69985bf..d530558816 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -72,7 +72,7 @@ int trx_eth_start(openair0_device *device) { } /* adjust MTU wrt number of samples per packet */ if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; - + if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_RAW_IF4p5_MODE) { if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ @@ -83,7 +83,8 @@ int trx_eth_start(openair0_device *device) { } /* adjust MTU wrt number of samples per packet */ if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; - + if(ethernet_tune (device,RCV_TIMEOUT,5000)!=0) return -1; + } else if (eth->flags == ETH_UDP_IF4p5_MODE) { @@ -225,15 +226,15 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { break; case RCV_TIMEOUT: - timeout.tv_sec = value/1000000000; - timeout.tv_usec = value%1000000000;//less than rt_period? + timeout.tv_sec = value/1000000; + timeout.tv_usec = value%1000000;//less than rt_period? if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,sizeof(timeout))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "receive timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec); + printf( "receive timeout= %u usec\n",timeout.tv_usec); } break; From b2c21c624642462ccd76bee437285846a2b1d91f Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 21:19:26 +0200 Subject: [PATCH 132/206] configuration files for IF5 rru (5,10 MHz) --- .../rru.band7.tm1.50PRB.if5.usrpb210.conf | 190 ++++++++++++++++++ .../CONF/rru.band7.tm1.if5.usrpb210.conf | 190 ++++++++++++++++++ targets/RT/USER/lte-enb.c | 8 +- 3 files changed, 384 insertions(+), 4 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.50PRB.if5.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.50PRB.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.50PRB.if5.usrpb210.conf new file mode 100644 index 0000000000..902420ae08 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.50PRB.if5.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "34:e6:d7:3c:ae:fc"; + local_address = "74:d4:35:cc:8d:15"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf new file mode 100644 index 0000000000..8e1e1441bf --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if5.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "34:e6:d7:3c:ae:fc"; + local_address = "74:d4:35:cc:8d:15"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 732fec7a4f..da40b58379 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -821,7 +821,7 @@ static void* eNB_thread_asynch_rxtx( void* param ) { subframe_tx = (subframe_tx+1)%10; recv_IF5(eNB, ×tamp_tx, subframe_tx, IF5_RRH_GW_DL); - printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); + // printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); if (first_tx == 1) { first_tx = 0; subframe_tx = (timestamp_tx/fp->samples_per_tti)%10; @@ -877,8 +877,8 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { if (proc->first_rx==0) { // Transmit TX buffer based on timestamp from RX - printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + // printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(2*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers @@ -917,7 +917,7 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - printf("trx_read <- USRP TS %llu (sf %d, first_rx %d)\n", proc->timestamp_rx,proc->subframe_rx,proc->first_rx); + // printf("trx_read <- USRP TS %llu (sf %d, first_rx %d)\n", proc->timestamp_rx,proc->subframe_rx,proc->first_rx); if (proc->first_rx == 0) { if (proc->subframe_rx != *subframe){ From 56e85db773f3600dd7c7aac0ffcea78c2d493581 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 31 Jul 2016 21:30:13 +0200 Subject: [PATCH 133/206] configuration files for RCC IF5 5,10 MHz --- openair1/PHY/LTE_TRANSPORT/prach.c | 1 + openair1/SCHED/phy_procedures_lte_eNb.c | 2 +- .../rcc.band7.tm1.50PRB.if5.usrpb210.conf | 190 ++++++++++++++++++ .../CONF/rcc.band7.tm1.if5.usrpb210.conf | 190 ++++++++++++++++++ 4 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if5.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index dfdf4ed470..0adb8685f0 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1183,6 +1183,7 @@ void rx_prach(PHY_VARS_eNB *eNB, if ((eNB->node_function == eNodeB_3GPP) || + (eNB->node_function == eNodeB_3GPP_BBU) || (eNB->node_function == NGFI_RRU_IF4p5)) { // compute the DFTs of the PRACH temporal resources // Do forward transform for (aa=0; aaUE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits eNB->UE_stats[(uint32_t)UE_id].sector = 0; - LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, frame, diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if5.usrpb210.conf new file mode 100644 index 0000000000..4929f39b3b --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if5.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP_BBU"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "127.0.0.3"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "74:d4:35:cc:8d:15"; + local_address = "34:e6:d7:3c:ae:fc"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf new file mode 100644 index 0000000000..b9030cf439 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP_BBU"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "127.0.0.3"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "74:d4:35:cc:8d:15"; + local_address = "34:e6:d7:3c:ae:fc"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); From 9ec462e8802b5418c31cd0619cc8def512eb73e5 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 1 Aug 2016 20:30:42 +0200 Subject: [PATCH 134/206] debugging for IF4p5 --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 1 + openair1/PHY/defs.h | 8 +- .../CONF/rru.band7.tm1.if4p5.usrpb210.conf | 190 ++++++++++++++++++ targets/RT/USER/lte-enb.c | 38 +--- targets/RT/USER/lte-softmodem.c | 11 +- 5 files changed, 205 insertions(+), 43 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 738fe842b6..217492dba6 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -261,6 +261,7 @@ void gen_IF4p5_dl_header(IF4p5_header_t *dl_packet, int frame, int subframe) { void gen_IF4p5_ul_header(IF4p5_header_t *ul_packet, int frame, int subframe) { + ul_packet->type = IF4p5_PACKET_TYPE; ul_packet->sub_type = IF4p5_PULFFT; diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 8e88fba00d..dd78e575bb 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -160,10 +160,10 @@ enum transmission_access_mode { typedef enum { eNodeB_3GPP=0, // classical eNodeB function eNodeB_3GPP_BBU, // eNodeB with NGFI IF5 - NGFI_RRU_IF5, // NGFI_RRU with IF5 - NGFI_RRU_IF4p5, // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4p5) - NGFI_RCC_IF4p5, // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4p5) - NGFI_RAU_IF4p5 + NGFI_RCC_IF4p5, // NGFI_RCC (NGFI radio cloud center) + NGFI_RAU_IF4p5, + NGFI_RRU_IF5, // NGFI_RRU (NGFI remote radio-unit,IF5) + NGFI_RRU_IF4p5 // NGFI_RRU (NGFI remote radio-unit,IF4p5) } eNB_func_t; typedef enum { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf new file mode 100644 index 0000000000..f99cdab2a2 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "34:e6:d7:3c:ae:fc"; + local_address = "74:d4:35:cc:8d:15"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index da40b58379..b0d1eb3d0e 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1248,7 +1248,8 @@ static void* eNB_thread_FH( void* param ) { printf( "got sync (eNB_thread_FH)\n" ); #if defined(ENABLE_ITTI) - wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); + if (eNB->node_function < NGFI_RRU_IF5) + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif @@ -1938,45 +1939,12 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst sleep(1); LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); - /* - printf("Creating main eNB_thread \n"); - error_code = pthread_create( &main_eNB_thread, &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); - } else { - LOG_D( HW, "[lte-softmodem.c] Allocate eNB_thread successful\n" ); - pthread_setname_np( main_eNB_thread, "main eNB" ); - } - */ + } void stop_eNB(int nb_inst) { - /* -#ifdef DEBUG_THREADS - printf("Joining eNB_thread ..."); -#endif - - int *eNB_thread_status_p; - int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p ); - -#ifdef DEBUG_THREADS - if (result != 0) { - printf( "\nError joining main_eNB_thread.\n" ); - } else { - if (eNB_thread_status_p) { - printf( "status %d\n", *eNB_thread_status_p ); - } else { - printf( "The thread was killed. No status available.\n"); - } - } -#else - UNUSED(result); -#endif // DEBUG_THREADS - */ - for (int inst=0;inst Date: Mon, 1 Aug 2016 20:39:01 +0200 Subject: [PATCH 135/206] debugging for IF4p5 --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 3 +- openair2/ENB_APP/enb_config.c | 10 +- openair2/ENB_APP/enb_config.h | 4 +- .../CONF/enb.band7.tm1.exmimo2.conf | 12 +- .../CONF/rcc.band7.tm1.if4p5.usrpb210.conf | 190 ++++++++++++++++++ targets/RT/USER/lte-softmodem.c | 4 +- 6 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.usrpb210.conf diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 738fe842b6..4a4448ef76 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -197,7 +197,8 @@ void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_t *frame = ((packet_header->frame_status)>>6)&0xffff; *subframe = ((packet_header->frame_status)>>22)&0x000f; - + + if (*packet_type == IF4p5_PDLFFT) { *symbol_number = ((packet_header->frame_status)>>26)&0x000f; diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 770b4afa25..02e61711b8 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -303,7 +303,7 @@ void enb_config_display(void) printf( "\ttx_scheduling_advance :\t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_scheduling_advance); printf( "\ttx_sample_advance : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_sample_advance); printf( "\tiq_txshift : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].iq_txshift); - printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : (enb_properties.properties[i]->rrh_gw_config[j].rawif4 == 1)? "RAW_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].udpif4 == 1)? "UDP_IF4" : (enb_properties.properties[i]->rrh_gw_config[j].rawif5_mobipass == 1)? "RAW_IF5_MOBIPASS" : "UDP"); + printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : (enb_properties.properties[i]->rrh_gw_config[j].rawif4p5 == 1)? "RAW_IF4p5" : (enb_properties.properties[i]->rrh_gw_config[j].udpif4p5 == 1)? "UDP_IF4p5" : (enb_properties.properties[i]->rrh_gw_config[j].rawif5_mobipass == 1)? "RAW_IF5_MOBIPASS" : "UDP"); if (enb_properties.properties[i]->rrh_gw_config[j].exmimo == 1) { printf( "\tRF target : \tEXMIMO:\n"); } else if (enb_properties.properties[i]->rrh_gw_config[j].usrp_b200 == 1) { @@ -2296,10 +2296,10 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; } else if (strcmp(tr_preference, "raw") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; - } else if (strcmp(tr_preference, "udp_if4") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udpif4 = 1; - } else if (strcmp(tr_preference, "raw_if4") == 0) { - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif4 = 1; + } else if (strcmp(tr_preference, "udp_if4p5") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udpif4p5 = 1; + } else if (strcmp(tr_preference, "raw_if4p5") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif4p5 = 1; } else if (strcmp(tr_preference, "raw_if5_mobipass") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].rawif5_mobipass = 1; } else {//if (strcmp(preference, "no") == 0) diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 6a8483c3d0..62418197f0 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -87,8 +87,8 @@ typedef struct rrh_gw_config_s { char *remote_address; uint16_t local_port; uint16_t remote_port; - uint8_t udpif4; - uint8_t rawif4; + uint8_t udpif4p5; + uint8_t rawif4p5; uint8_t rawif5_mobipass; int tx_scheduling_advance; int tx_sample_advance; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf index 7bf097875d..4cec39bdc7 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf @@ -134,7 +134,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.171"; + mme_ip_address = ( { ipv4 = "127.0.0.3"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -143,17 +143,17 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth2"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.80/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth2"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.80/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; log_config : { - global_log_level ="debug"; + global_log_level ="info"; global_log_verbosity ="medium"; hw_log_level ="info"; hw_log_verbosity ="medium"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.usrpb210.conf new file mode 100644 index 0000000000..e8ffde20b6 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "127.0.0.3"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "74:d4:35:cc:8d:15"; + local_address = "34:e6:d7:3c:ae:fc"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index f2c3614850..8ac5a8307f 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1055,9 +1055,9 @@ static void get_options (int argc, char **argv) if (enb_properties->properties[i]->rrh_gw_config[j].raw == 1) { (eth_params+j)->transp_preference = ETH_RAW_MODE; - } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4 == 1) { + } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4p5 == 1) { (eth_params+j)->transp_preference = ETH_RAW_IF4p5_MODE; - } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4 == 1) { + } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4p5 == 1) { (eth_params+j)->transp_preference = ETH_UDP_IF4p5_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif5_mobipass == 1) { (eth_params+j)->transp_preference = ETH_RAW_IF5_MOBIPASS; From 350465fdef1a8be56155f35f2b03ddda52ae08e7 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 3 Aug 2016 21:14:38 +0200 Subject: [PATCH 136/206] fix 20 MHz config file --- .../GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf index 210c7ea740..534ed62dfd 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf @@ -22,6 +22,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; From 714bae4ffd766bb7d17e210dc2be59350c508936 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 3 Aug 2016 21:17:41 +0200 Subject: [PATCH 137/206] minor fix for installation --- cmake_targets/tools/build_helper | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index ac8d9f34c1..c91de1ea77 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -205,10 +205,8 @@ install_gnutls_from_source(){ cd /tmp echo "Downloading gnutls archive" $SUDO rm -rf /tmp/gnutls-3.1.23.tar.xz* /tmp/gnutls-3.1.23 - wget http://mirrors.dotsrc.org/gcrypt/gnutls/v3.1/gnutls-3.1.23.tar.xz - if [ $? -ne 0 ]; then + wget http://mirrors.dotsrc.org/gcrypt/gnutls/v3.1/gnutls-3.1.23.tar.xz || \ wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.1/gnutls-3.1.23.tar.xz - fi if [ ! -f gnutls-3.1.23.tar.xz ]; then echo_error "Could not download gnutls source files" cd - From dc124abbad5d63105c3587f2eb51f3c896bc666a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 30 Jul 2016 20:57:37 +0200 Subject: [PATCH 138/206] remove nano from test setup --- cmake_targets/autotests/test_case_list.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 2fecd2b292..0bc09f261a 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,6 +1,6 @@ -mozart tique stevens nano amerique +mozart tique stevens amerique /mnt/sradio/TEST_RESULTS/ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git @@ -12,7 +12,7 @@ 36000 010141 0102+ 010304 010305 0104+ 015502 015505 015506 015507 015508 015509 015510 015511 015514 015517 015602 015605 015702 015705 015802 015805 015808 015811 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 018502 018505 025502 025505 025508 025511 3 - mozart tique stevens nano amerique + mozart tique stevens amerique compilation Build oaisim.Rel8 From 5056134772bcf574edfc87f66c7c6774fe5d175e Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 4 Aug 2016 00:58:19 +0200 Subject: [PATCH 139/206] debugging of IF4p5 RRU --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 2 +- openair1/PHY/LTE_TRANSPORT/prach.c | 28 +- openair1/PHY/defs.h | 9 +- openair1/PHY/vars.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 21 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 3 +- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 2 +- targets/RT/USER/lte-enb.c | 376 +++++++++++------- targets/RT/USER/lte-softmodem.c | 347 ++++++++-------- targets/SIMU/USER/init_lte.c | 1 + 10 files changed, 464 insertions(+), 327 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 8f01fc5369..655c61c15c 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -133,7 +133,7 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type } } else if (packet_type == IF4p5_PRACH) { // FIX: hard coded prach samples length - db_fulllength = 839*2; + db_fulllength = 840*2; IF4p5_header_t *prach_header = (IF4p5_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES); data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t); diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 0adb8685f0..df28dfd6fa 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1065,7 +1065,7 @@ void rx_prach(PHY_VARS_eNB *eNB, int i; lte_frame_type_t frame_type = eNB->frame_parms.frame_type; - int subframe = eNB->proc.subframe_rx; + int subframe = eNB->proc.subframe_prach; uint16_t rootSequenceIndex = eNB->frame_parms.prach_config_common.rootSequenceIndex; uint8_t prach_ConfigIndex = eNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex; uint8_t Ncs_config = eNB->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; @@ -1101,6 +1101,8 @@ void rx_prach(PHY_VARS_eNB *eNB, int fft_size,log2_ifft_size; uint8_t nb_ant_rx = 1; //eNB->frame_parms.nb_antennas_rx; + // int en; + for (aa=0; aacommon_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_tti-eNB->N_TA_offset]; } @@ -1282,8 +1284,11 @@ void rx_prach(PHY_VARS_eNB *eNB, k*=2; /// **** send_IF4 of rxsigF to RCC **** /// - send_IF4p5(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4p5_PRACH, k); + send_IF4p5(eNB, eNB->proc.frame_prach, eNB->proc.subframe_prach, IF4p5_PRACH, k); + // en = dB_fixed(signal_energy(&rxsigF[0][k],840)); + // if (en>60) + // printf("PRACH: Frame %d, Subframe %d => %d dB\n",eNB->proc.frame_rx,eNB->proc.subframe_rx,en); return; } else if (eNB->node_function == NGFI_RCC_IF4p5) { k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; @@ -1469,11 +1474,24 @@ void rx_prach(PHY_VARS_eNB *eNB, #endif // if (aa=1) write_output("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1); }// antennas_rx + #ifdef PRACH_DEBUG - write_output("prach_ifft0.m","prach_t0",prach_ifft[0],2048,1,1); + if (en>40) { + k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; + + if (k<0) + k+=(eNB->frame_parms.ofdm_symbol_size); + + k*=12; + k+=13; + k*=2; + printf("Dumping prach, k = %d (n_ra_prb %d)\n",k,n_ra_prb); + write_output("rxsigF.m","prach_rxF",&rxsigF[0][k],840,1,1); + write_output("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); + write_output("prach_ifft0.m","prach_t0",prach_ifft[0],1024,1,1); + exit(-1); + } #endif - // write_output("prach_ifft1.m","prach_t1",prach_ifft[1],2048,1,1); - } // new dft // check energy in nth time shift diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index dd78e575bb..9b5db4b421 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -260,6 +260,8 @@ typedef struct eNB_proc_t_s { pthread_t pthread_asynch_rxtx; /// flag to indicate first RX acquisition int first_rx; + /// flag to indicate first TX transmission + int first_tx; /// pthread attributes for FH processing thread pthread_attr_t attr_FH; /// pthread attributes for prach processing thread @@ -362,14 +364,15 @@ typedef struct PHY_VARS_eNB_s { eNB_func_t node_function; eNB_timing_t node_timing; int abstraction_flag; - void (*do_prach)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc); - void (*fep)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc); + void (*do_prach)(struct PHY_VARS_eNB_s *eNB); + void (*fep)(struct PHY_VARS_eNB_s *eNB); void (*proc_uespec_rx)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type); void (*proc_tx)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type,PHY_VARS_RN *rn); void (*tx_fh)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc); - void (*rx_fh)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc,int *frame, int *subframe); + void (*rx_fh)(struct PHY_VARS_eNB_s *eNB,int *frame, int *subframe); int (*start_rf)(struct PHY_VARS_eNB_s *eNB); int (*start_if)(struct PHY_VARS_eNB_s *eNB); + void (*fh_asynch)(struct PHY_VARS_eNB_s *eNB,int *frame, int *subframe); uint8_t local_flag; uint32_t rx_total_gain_dB; LTE_DL_FRAME_PARMS frame_parms; diff --git a/openair1/PHY/vars.h b/openair1/PHY/vars.h index 85bfe7a2a6..b8cb33239d 100755 --- a/openair1/PHY/vars.h +++ b/openair1/PHY/vars.h @@ -139,7 +139,7 @@ double beta2_dlsch[6][MCS_COUNT] = { {2.52163, 0.83231, 0.77472, 1.36536, 1.1682 */ -char eNB_functions[5][20]={"eNodeB_3GPP","eNodeB_3GPP_BBU","NGFI_RRU_IF5","NGFI_RRU_IF4","NGFI_RCC_IF4"}; +char eNB_functions[6][20]={"eNodeB_3GPP","eNodeB_3GPP_BBU","NGFI_RCC_IF4p5","NGFI_RAI_IF4p5","NGFI_RRU_IF5","NGFI_RRU_IF4p5",}; char eNB_timing[2][20]={"synch_to_ext_device","synch_to_other"}; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6bf9273776..b1c37e9579 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1950,12 +1950,14 @@ void prach_procedures(PHY_VARS_eNB *eNB) { break; } + /* mac_xface->initiate_ra_proc(eNB->Mod_id, eNB->CC_id, frame, preamble_max, preamble_delay_list[preamble_max]*update_TA, 0,subframe,0); + */ } } else { @@ -2490,8 +2492,9 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p } -void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { +void eNB_fep_full(PHY_VARS_eNB *eNB) { + eNB_proc_t *proc = &eNB->proc; int l; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -2503,7 +2506,7 @@ void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { &eNB->common_vars, l, proc->subframe_rx<<1, - 0, + 0, 0 ); slot_fep_ul(fp, @@ -2519,14 +2522,13 @@ void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { if (eNB->node_function == NGFI_RRU_IF4p5) { /// **** send_IF4 of rxdataF to RCC (no prach now) **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 ); send_IF4p5(eNB, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT, 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 ); - } + } } -void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { +void eNB_fep_rru_if5(PHY_VARS_eNB *eNB) { + eNB_proc_t *proc=&eNB->proc; uint8_t seqno=0; /// **** send_IF5 of rxdata to BBU **** /// @@ -2536,8 +2538,9 @@ void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { } -void do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc) { +void do_prach(PHY_VARS_eNB *eNB) { + eNB_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; // check if we have to detect PRACH first @@ -2594,9 +2597,9 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){ LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe); - if (eNB->fep) eNB->fep(eNB,proc); + if (eNB->fep) eNB->fep(eNB); - if (eNB->do_prach) eNB->do_prach(eNB,proc); + if (eNB->do_prach) eNB->do_prach(eNB); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 02ca6ee7eb..3e06cf0356 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -224,7 +224,8 @@ int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestam eth->tx_nsamps = nblocks; memcpy(buff[0], (void*)ð->eh, MAC_HEADER_SIZE_BYTES); - + + bytes_sent = send(eth->sockfd[Mod_id], buff[0], packet_size, diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index d530558816..869777b6bf 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -83,7 +83,7 @@ int trx_eth_start(openair0_device *device) { } /* adjust MTU wrt number of samples per packet */ if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; - if(ethernet_tune (device,RCV_TIMEOUT,5000)!=0) return -1; + if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_UDP_IF4p5_MODE) { diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index b0d1eb3d0e..d6e262a4d5 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -365,13 +365,11 @@ void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB, symbol_mask = 0; symbol_mask_full = (1<frame_parms.symbols_per_tti)-1; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); + do { recv_IF4p5(eNB, &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number); symbol_mask = symbol_mask | (1<subframe_tx, eNB); } @@ -640,6 +638,151 @@ static void wait_system_ready (char *message, volatile int *start_flag) { } #endif + +// asynchronous UL with IF4p5 (RCC,RAU,eNodeB_BBU) +void fh_if5_asynch_UL(PHY_VARS_eNB *eNB,int *frame,int *subframe) { + + eNB_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + + recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); + + proc->subframe_rx = (proc->timestamp_rx/fp->samples_per_tti)%10; + proc->frame_rx = (proc->timestamp_rx/(10*fp->samples_per_tti))&1023; + + if (proc->first_rx != 0) { + proc->first_rx = 0; + *subframe = proc->subframe_rx; + *frame = proc->frame_rx; + } + else { + if (proc->subframe_rx != *subframe) { + LOG_E(PHY,"subframe_rx %d is not what we expect %d\n",proc->subframe_rx,*subframe); + exit_fun("Exiting"); + } + if (proc->frame_rx != *frame) { + LOG_E(PHY,"subframe_rx %d is not what we expect %d\n",proc->frame_rx,*frame); + exit_fun("Exiting"); + } + } +} // eNodeB_3GPP_BBU + +// asynchronous UL with IF4p5 (RCC,RAU,eNodeB_BBU) +void fh_if4p5_asynch_UL(PHY_VARS_eNB *eNB,int *frame,int *subframe) { + + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc; + + uint16_t packet_type; + uint32_t symbol_number,symbol_mask,symbol_mask_full,prach_rx; + + + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<symbols_per_tti)-1; + prach_rx = 0; + + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! + recv_IF4p5(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); + if (proc->first_rx != 0) { + *frame = proc->frame_rx; + *subframe = proc->subframe_rx; + proc->first_rx = 0; + } + else { + if (proc->frame_rx != *frame) { + LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame); + exit_fun("Exiting"); + } + if (proc->subframe_rx != *subframe) { + LOG_E(PHY,"subframe_rx %d is not what we expect %d\n",proc->subframe_rx,*subframe); + exit_fun("Exiting"); + } + } + if (packet_type == IF4p5_PULFFT) { + symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; + } else if (packet_type == IF4p5_PRACH) { + prach_rx = 0; + } + } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); + + +} + + +void fh_if5_asynch_DL(PHY_VARS_eNB *eNB,int *frame,int *subframe) { + + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc; + int subframe_tx,frame_tx; + openair0_timestamp timestamp_tx; + + recv_IF5(eNB, ×tamp_tx, *subframe, IF5_RRH_GW_DL); + // printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); + + subframe_tx = (timestamp_tx/fp->samples_per_tti)%10; + frame_tx = (timestamp_tx/(fp->samples_per_tti*10))&1023; + + if (proc->first_tx != 0) { + *subframe = subframe_tx; + *frame = frame_tx; + proc->first_tx = 0; + } + else { + if (subframe_tx != *subframe) { + LOG_E(PHY,"subframe_tx %d is not what we expect %d\n",subframe_tx,*subframe); + exit_fun("Exiting"); + } + if (frame_tx != *frame) { + LOG_E(PHY,"frame_tx %d is not what we expect %d\n",frame_tx,*frame); + exit_fun("Exiting"); + } + } +} + +void fh_if4p5_asynch_DL(PHY_VARS_eNB *eNB,int *frame,int *subframe) { + + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc; + + uint16_t packet_type; + uint32_t symbol_number,symbol_mask,symbol_mask_full; + int subframe_tx,frame_tx; + + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<symbols_per_tti)-1; + + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! + recv_IF4p5(eNB, &frame_tx, &subframe_tx, &packet_type, &symbol_number); + if (proc->first_tx != 0) { + *frame = frame_tx; + *subframe = subframe_tx; + proc->first_tx = 0; + } + else { + if (frame_tx != *frame) { + LOG_E(PHY,"frame_tx %d is not what we expect %d\n",frame_tx,*frame); + exit_fun("Exiting"); + } + if (subframe_tx != *subframe) { + LOG_E(PHY,"subframe_tx %d is not what we expect %d\n",subframe_tx,*subframe); + exit_fun("Exiting"); + } + } + if (packet_type == IF4p5_PDLFFT) { + symbol_mask = symbol_mask | (1<CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - openair0_timestamp timestamp_rx,timestamp_tx; - int frame_rx,subframe_rx=0,subframe_tx=0; - static int first_rx = 1; - static int first_tx = 1; - uint16_t packet_type; - uint32_t symbol_number=0; - uint32_t symbol_mask, symbol_mask_full; - int prach_rx; - int dummy_rx[fp->nb_antennas_rx][fp->samples_per_tti]; - int rxs=0; + + int subframe=0, frame=0; + #ifdef DEADLINE_SCHEDULER struct sched_attr attr; @@ -781,94 +917,35 @@ static void* eNB_thread_asynch_rxtx( void* param ) { printf( "devices ok (eNB_thread_asynch_rx)\n"); + while (!oai_exit) { - if (eNB->node_function == eNodeB_3GPP) { // acquisition from RF - - if (eNB->rfdevice.trx_read_func) - rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice, - &proc->timestamp_rx, - (void**)dummy_rx, - fp->samples_per_tti, - fp->nb_antennas_rx); - else { - printf("eNB asynch RX\n"); - sleep(1); - } - if (rxs!=fp->samples_per_tti) { - exit_fun("error receiving samples\n"); - } - } - else if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF - /// **** recv_IF5 of rxdata from RRH **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); - recv_IF5(eNB, ×tamp_rx, subframe_rx++, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); - if (first_rx == 1) { - first_rx = 0; - subframe_rx = (timestamp_rx/fp->samples_per_tti)%10; - } - else { - // check timestamp - if ((timestamp_rx - proc->timestamp_rx) < (2*fp->samples_per_tti)) - printf("RX overflow ...\n"); - - } - } // eNodeB_3GPP_BBU + + if (oai_exit) break; + + if (subframe==9) { + subframe=0; + frame++; + frame&=1023; + } else { + subframe++; + } + + if (eNB->fh_asynch) eNB->fh_asynch(eNB,&frame,&subframe); + else AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); - else if (eNB->node_function == NGFI_RRU_IF5) { - /// **** recv_IF5 of rxdata from RRH **** /// - - subframe_tx = (subframe_tx+1)%10; - - recv_IF5(eNB, ×tamp_tx, subframe_tx, IF5_RRH_GW_DL); - // printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); - if (first_tx == 1) { - first_tx = 0; - subframe_tx = (timestamp_tx/fp->samples_per_tti)%10; - - } - - } - else if (eNB->node_function == NGFI_RCC_IF4p5) { - /// **** recv_IF4p5 of rxdataF from RRU **** /// - /// **** recv_IF4p5 of rxsigF from RRU **** /// - // get frame/subframe information from IF4p5 interface - // timed loop (200 us) - - symbol_number = 0; - symbol_mask = 0; - symbol_mask_full = (1<symbols_per_tti)-1; - prach_rx = 0; - - do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - recv_IF4p5(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number); - - if (packet_type == IF4p5_PULFFT) { - symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; - } else if (packet_type == IF4p5_PRACH) { - prach_rx = 0; - } - } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); - - if (proc->first_rx == 0) { - if (subframe_rx < proc->subframe_rx+2){ - LOG_E(PHY,"RX overflow (proc->subframe_rx %d, subframe_rx %d)\n",proc->subframe_rx,subframe_rx); - } - } else { - proc->first_rx = 0; - } - } // node_timing == synch_to_externs, node_function = NGFI_IF4 - else { // should not get here - AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function); - } } + eNB_thread_asynch_rxtx_status=0; return(&eNB_thread_asynch_rxtx_status); } -void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { + + + +void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { + + eNB_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; unsigned int rxs,txs; @@ -883,10 +960,10 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { // prepare tx buffer pointers for (i=0; inb_antennas_tx; i++) - txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+2)%10)*fp->samples_per_tti]; + txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti]; txs = eNB->rfdevice.trx_write_func(&eNB->rfdevice, - proc->timestamp_rx+(2*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, + proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, txp, fp->samples_per_tti, fp->nb_antennas_tx, @@ -946,9 +1023,10 @@ void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { } -void rx_fh_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame, int *subframe) { +void rx_fh_if5(PHY_VARS_eNB *eNB,int *frame, int *subframe) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + eNB_proc_t *proc = &eNB->proc; recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); @@ -975,7 +1053,9 @@ void rx_fh_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame, int *subframe) { } -void rx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *subframe,int *frame) { +void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *subframe,int *frame) { + + eNB_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; @@ -990,9 +1070,7 @@ void rx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *subframe,int *frame) { prach_rx = 0; do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); recv_IF4p5(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); if (packet_type == IF4p5_PULFFT) { symbol_mask = symbol_mask | (1<proc; + + if (pthread_mutex_lock(&proc->mutex_FH) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH Slave\n"); + exit_fun( "error locking mutex" ); + } + + while (proc->instance_cnt_FH < 0) { + pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); + } + proc->instance_cnt_FH++; + + pthread_mutex_unlock( &proc->mutex_FH ); + +} + + int wakeup_rxtx(eNB_proc_t *proc,eNB_rxtx_proc_t *proc_rxtx,LTE_DL_FRAME_PARMS *fp) { int i; @@ -1263,7 +1361,7 @@ static void* eNB_thread_FH( void* param ) { if (eNB->start_rf(eNB) != 0) LOG_E(HW,"Could not start the RF device\n"); - // unlock asnych_rxtx thread + // wakeup asnych_rxtx thread pthread_mutex_lock(&proc->mutex_asynch_rxtx); proc->instance_cnt_asynch_rxtx=0; pthread_mutex_unlock(&proc->mutex_asynch_rxtx); @@ -1274,6 +1372,8 @@ static void* eNB_thread_FH( void* param ) { if (oai_exit) break; + + // this is to check that we are in synch with the fronthaul timing if (subframe==9) { subframe=0; frame++; @@ -1282,36 +1382,10 @@ static void* eNB_thread_FH( void* param ) { subframe++; } - // This case is for synchronization to another thread - if ((eNB->node_timing == synch_to_other) && - ((eNB->node_function == NGFI_RCC_IF4p5) || - (eNB->node_function == eNodeB_3GPP_BBU))) { - //wait for event - - // how long should we wait here, for MOBIPASS this could be long - // if (pthread_mutex_timedlock(&proc->mutex_FH,&wait) != 0) { - if (pthread_mutex_lock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH\n"); - exit_fun( "error locking mutex" ); - break; - } - - while (proc->instance_cnt_FH < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_FH is -1 - pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); // this unlocks mutex_rxtx while waiting and then locks it again - } - proc->instance_cnt_FH++; - - } - // Remaining cases are all for synchronization on FH interface - else if ((eNB->node_timing == synch_to_ext_device) && - (eNB->rx_fh)) - eNB->rx_fh(eNB,proc,&frame,&subframe); - - else { // should not get here - AssertFatal(1==0, "Unknown fronthaul interface : eNB->node_function %d",eNB->node_function); - } + + // synchronization on FH interface, acquire signals/data and block + if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe); + else AssertFatal(1==0, "No fronthaul interface : eNB->node_function %d",eNB->node_function); T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); @@ -1494,7 +1568,7 @@ static void* eNB_thread_prach( void* param ) { break; } - + prach_procedures(eNB); if (pthread_mutex_lock(&proc->mutex_prach) != 0) { @@ -1567,8 +1641,9 @@ void init_eNB_proc(int inst) { proc->instance_cnt_asynch_rxtx = -1; proc->CC_id = CC_id; - proc->first_rx=4; - + proc->first_rx=1; + proc->first_tx=1; + pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); pthread_mutex_init( &proc->mutex_prach, NULL); @@ -1584,7 +1659,8 @@ void init_eNB_proc(int inst) { pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); if ((eNB->node_timing == synch_to_other) || - (eNB->node_function == NGFI_RRU_IF5)) + (eNB->node_function == NGFI_RRU_IF5) || + (eNB->node_function == NGFI_RRU_IF4p5)) pthread_create( &proc->pthread_asynch_rxtx, &proc->attr_asynch_rxtx, eNB_thread_asynch_rxtx, &eNB->proc ); #else pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); @@ -1784,9 +1860,9 @@ int start_rf(PHY_VARS_eNB *eNB) { return(eNB->rfdevice.trx_start_func(&eNB->rfdevice)); } -extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc); -extern void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc); -extern void do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc); +extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB); +extern void eNB_fep_full(PHY_VARS_eNB *eNB); +extern void do_prach(PHY_VARS_eNB *eNB); void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params) { @@ -1813,6 +1889,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->rx_fh = rx_rf; eNB->start_rf = start_rf; eNB->start_if = start_if; + eNB->fh_asynch = fh_if5_asynch_DL; ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[0]); if (ret<0) { printf("Exiting, cannot initialize rf device\n"); @@ -1831,9 +1908,10 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = do_prach; eNB->fep = eNB_fep_full; eNB->proc_uespec_rx = NULL; - eNB->proc_tx = proc_tx_rru_if4p5; + eNB->proc_tx = NULL;//proc_tx_rru_if4p5; eNB->tx_fh = NULL; eNB->rx_fh = rx_rf; + eNB->fh_asynch = fh_if4p5_asynch_DL; eNB->start_rf = start_rf; eNB->start_if = start_if; ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[0]); @@ -1862,6 +1940,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->rx_fh = rx_rf; eNB->start_rf = start_rf; eNB->start_if = NULL; + eNB->fh_asynch = NULL; ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[0]); if (ret<0) { printf("Exiting, cannot initialize rf device\n"); @@ -1877,11 +1956,14 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->proc_tx = proc_tx_full; eNB->tx_fh = tx_fh_if5; eNB->rx_fh = rx_fh_if5; + eNB->fh_asynch = (eNB->node_timing == synch_to_other) ? fh_if5_asynch_UL : NULL; + eNB->start_rf = NULL; eNB->start_if = start_if; eNB->rfdevice.host_type = BBU_HOST; eNB->ifdevice.host_type = BBU_HOST; + ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[0], (eth_params+CC_id)); printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id); if (ret<0) { @@ -1890,14 +1972,15 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst } break; case NGFI_RCC_IF4p5: - eNB->do_prach = do_prach; - eNB->fep = NULL; - eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; - eNB->proc_tx = proc_tx_high; - eNB->tx_fh = tx_fh_if4p5; - eNB->rx_fh = rx_fh_if4p5; - eNB->start_rf = NULL; - eNB->start_if = start_if; + eNB->do_prach = do_prach; + eNB->fep = NULL; + eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; + eNB->proc_tx = proc_tx_high; + eNB->tx_fh = tx_fh_if4p5; + eNB->rx_fh = rx_fh_if4p5; + eNB->start_rf = NULL; + eNB->start_if = start_if; + eNB->fh_asynch = (eNB->node_timing == synch_to_other) ? fh_if4p5_asynch_UL : NULL; eNB->rfdevice.host_type = BBU_HOST; eNB->ifdevice.host_type = BBU_HOST; ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[0], (eth_params+CC_id)); @@ -1916,6 +1999,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->proc_tx = proc_tx_high; eNB->tx_fh = tx_fh_if4p5; eNB->rx_fh = rx_fh_if4p5; + eNB->fh_asynch = (eNB->node_timing == synch_to_other) ? fh_if4p5_asynch_UL : NULL; eNB->start_rf = NULL; eNB->start_if = start_if; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index cf5528598f..fc16d11e7d 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1088,6 +1088,8 @@ static void get_options (int argc, char **argv) } for (CC_id=0; CC_idproperties[i]->cc_node_function[CC_id]; node_timing[CC_id] = enb_properties->properties[i]->cc_node_timing[CC_id]; node_synch_ref[CC_id] = enb_properties->properties[i]->cc_node_synch_ref[CC_id]; @@ -1104,6 +1106,13 @@ static void get_options (int argc, char **argv) frame_parms[CC_id]->nb_antennas_tx = enb_properties->properties[i]->nb_antennas_tx[CC_id]; frame_parms[CC_id]->nb_antennas_tx_eNB = enb_properties->properties[i]->nb_antennas_tx[CC_id]; frame_parms[CC_id]->nb_antennas_rx = enb_properties->properties[i]->nb_antennas_rx[CC_id]; + + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = enb_properties->properties[i]->prach_config_index[CC_id]; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset = enb_properties->properties[i]->prach_freq_offset[CC_id]; + + frame_parms[CC_id]->mode1_flag = (transmission_mode == 1) ? 1 : 0; + frame_parms[CC_id]->threequarter_fs = threequarter_fs; + //} // j } @@ -1182,6 +1191,156 @@ int T_port = 2021; /* default port to listen to to wait for the tracer */ int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */ #endif +void set_default_frame_parms() { + + int CC_id; + + for (CC_id=0; CC_idframe_type = FDD; + frame_parms[CC_id]->tdd_config = 3; + frame_parms[CC_id]->tdd_config_S = 0; + frame_parms[CC_id]->N_RB_DL = 100; + frame_parms[CC_id]->N_RB_UL = 100; + frame_parms[CC_id]->Ncp = NORMAL; + frame_parms[CC_id]->Ncp_UL = NORMAL; + frame_parms[CC_id]->Nid_cell = 0; + frame_parms[CC_id]->num_MBSFN_config = 0; + frame_parms[CC_id]->nb_antennas_tx_eNB = 1; + frame_parms[CC_id]->nb_antennas_tx = 1; + frame_parms[CC_id]->nb_antennas_rx = 1; + + frame_parms[CC_id]->nushift = 0; + + frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; + frame_parms[CC_id]->phich_config_common.phich_duration = normal; + // UL RS Config + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + + frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + + downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31. + downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; + downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; + downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; + //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); + + } + +} + +void init_openair0() { + + int card; + int i; + + for (card=0; cardN_RB_DL == 100) { + if (frame_parms[0]->threequarter_fs) { + openair0_cfg[card].sample_rate=23.04e6; + openair0_cfg[card].samples_per_frame = 230400; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } + else { + openair0_cfg[card].sample_rate=30.72e6; + openair0_cfg[card].samples_per_frame = 307200; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } + } else if(frame_parms[0]->N_RB_DL == 50) { + openair0_cfg[card].sample_rate=15.36e6; + openair0_cfg[card].samples_per_frame = 153600; + openair0_cfg[card].tx_bw = 5e6; + openair0_cfg[card].rx_bw = 5e6; + } else if (frame_parms[0]->N_RB_DL == 25) { + openair0_cfg[card].sample_rate=7.68e6; + openair0_cfg[card].samples_per_frame = 76800; + openair0_cfg[card].tx_bw = 2.5e6; + openair0_cfg[card].rx_bw = 2.5e6; + } else if (frame_parms[0]->N_RB_DL == 6) { + openair0_cfg[card].sample_rate=1.92e6; + openair0_cfg[card].samples_per_frame = 19200; + openair0_cfg[card].tx_bw = 1.5e6; + openair0_cfg[card].rx_bw = 1.5e6; + } + + if (frame_parms[0]->frame_type==TDD) + openair0_cfg[card].duplex_mode = duplex_mode_TDD; + else //FDD + openair0_cfg[card].duplex_mode = duplex_mode_FDD; + + + if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) { + openair0_cfg[card].remote_addr = eth_params->remote_addr; + openair0_cfg[card].remote_port = eth_params->remote_port; + openair0_cfg[card].my_addr = eth_params->my_addr; + openair0_cfg[card].my_port = eth_params->my_port; + } + + printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, + ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx), + ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); + openair0_cfg[card].Mod_id = 0; + + if (UE_flag) { + printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port); + openair0_cfg[card].remote_addr = &rrh_UE_ip[0]; + openair0_cfg[card].remote_port = rrh_UE_port; + } + + openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; + + + openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx)); + openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); + + for (i=0; i<4; i++) { + + if (irx_total_gain_dB; + } + else { + openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB; + } + + + } + + + } +} + int main( int argc, char **argv ) { int i,aa,card=0; @@ -1190,8 +1349,7 @@ int main( int argc, char **argv ) #endif int CC_id; - uint16_t Nid_cell = 0; - uint8_t cooperation_flag=0, abstraction_flag=0; + uint8_t abstraction_flag=0; uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; #if defined (XFORMS) @@ -1211,39 +1369,18 @@ int main( int argc, char **argv ) memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); set_latency_target(); - // det defaults - for (CC_id=0; CC_idframe_type = FDD; - frame_parms[CC_id]->tdd_config = 3; - frame_parms[CC_id]->tdd_config_S = 0; - frame_parms[CC_id]->N_RB_DL = 100; - frame_parms[CC_id]->N_RB_UL = 100; - frame_parms[CC_id]->Ncp = NORMAL; - frame_parms[CC_id]->Ncp_UL = NORMAL; - frame_parms[CC_id]->Nid_cell = Nid_cell; - frame_parms[CC_id]->num_MBSFN_config = 0; - frame_parms[CC_id]->nb_antennas_tx_eNB = 1; - frame_parms[CC_id]->nb_antennas_tx = 1; - frame_parms[CC_id]->nb_antennas_rx = 1; - } + // set default parameters + set_default_frame_parms(frame_parms); - for (CC_id=0; CC_idnushift = 0; - if (UE_flag==0) { - - } else { - //UE_flag==1 + if (UE_flag==1) { frame_parms[CC_id]->nb_antennas_tx = 1; frame_parms[CC_id]->nb_antennas_rx = 1; frame_parms[CC_id]->nb_antennas_tx_eNB = (transmission_mode == 1) ? 1 : 2; //initial value overwritten by initial sync later } - - frame_parms[CC_id]->mode1_flag = (transmission_mode == 1) ? 1 : 0; - frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; - frame_parms[CC_id]->phich_config_common.phich_duration = normal; - // UL RS Config - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; - frame_parms[CC_id]->threequarter_fs = threequarter_fs; init_ul_hopping(frame_parms[CC_id]); init_frame_parms(frame_parms[CC_id],1); // phy_init_top(frame_parms[CC_id]); @@ -1392,11 +1515,7 @@ int main( int argc, char **argv ) for (CC_id=0; CC_idprach_config_common.rootSequenceIndex=22; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; - frame_parms[CC_id]->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; } @@ -1457,7 +1576,7 @@ int main( int argc, char **argv ) PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*)); for (CC_id=0; CC_idNid_cell,cooperation_flag,transmission_mode,abstraction_flag); + PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,0,transmission_mode,abstraction_flag); PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id; if (phy_test==1) PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0; @@ -1497,107 +1616,9 @@ int main( int argc, char **argv ) dump_frame_parms(frame_parms[0]); - for (card=0; cardN_RB_DL == 100) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } - else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } - } else if(frame_parms[0]->N_RB_DL == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - openair0_cfg[card].tx_bw = 5e6; - openair0_cfg[card].rx_bw = 5e6; - } else if (frame_parms[0]->N_RB_DL == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - openair0_cfg[card].tx_bw = 2.5e6; - openair0_cfg[card].rx_bw = 2.5e6; - } else if (frame_parms[0]->N_RB_DL == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - openair0_cfg[card].tx_bw = 1.5e6; - openair0_cfg[card].rx_bw = 1.5e6; - } - - if (frame_parms[0]->frame_type==TDD) - openair0_cfg[card].duplex_mode = duplex_mode_TDD; - else //FDD - openair0_cfg[card].duplex_mode = duplex_mode_FDD; - - - if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) { - openair0_cfg[card].remote_addr = eth_params->remote_addr; - openair0_cfg[card].remote_port = eth_params->remote_port; - openair0_cfg[card].my_addr = eth_params->my_addr; - openair0_cfg[card].my_port = eth_params->my_port; - } - - printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, - ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx), - ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); - openair0_cfg[card].Mod_id = 0; -#ifdef ETHERNET - - if (UE_flag) { - printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port); - openair0_cfg[card].remote_addr = &rrh_UE_ip[0]; - openair0_cfg[card].remote_port = rrh_UE_port; - } - - openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; -#endif - - // in the case of the USRP, the following variables need to be initialized before the init - // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC. - // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer - - openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx)); - openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); - - for (i=0; i<4; i++) { - - if (irx_total_gain_dB; - } - else { - openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB; - } + init_openair0(); - } - - - } #ifndef DEADLINE_SCHEDULER @@ -1644,15 +1665,21 @@ int main( int argc, char **argv ) openair0_cfg[0].log_level = glog_level; - mac_xface = malloc(sizeof(MAC_xface)); + int eMBMS_active=0; - - l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL, - 0,// cba_group_active - 0); // HO flag - - mac_xface->macphy_exit = &exit_fun; + if (node_function[0] >=NGFI_RAU_IF4p5) { // don't initialize L2 for RRU + mac_xface = malloc(sizeof(MAC_xface)); + l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL, + 0,// cba_group_active + 0); // HO flag + mac_xface->macphy_exit = &exit_fun; + } + else if (node_function[0] == NGFI_RRU_IF4p5) { // Initialize PRACH in this case + + } + + #if defined(ENABLE_ITTI) @@ -1672,7 +1699,7 @@ int main( int argc, char **argv ) printf("Filling UE band info\n"); fill_ue_band_info(); mac_xface->dl_phy_sync_success (0, 0, 0, 1); - } else + } else if (node_function[0]>NGFI_RRU_IF4p5) mac_xface->mrbch_phy_sync_failure (0, 0, 0); } diff --git a/targets/SIMU/USER/init_lte.c b/targets/SIMU/USER/init_lte.c index 583891f1ac..756d705870 100644 --- a/targets/SIMU/USER/init_lte.c +++ b/targets/SIMU/USER/init_lte.c @@ -70,6 +70,7 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, NUMBER_OF_UE_MAX, NUMBER_OF_eNB_MAX, NUMBER_OF_HARQ_PID_MAX); LOG_I(PHY,"init eNB: N_RB_DL %d\n", frame_parms->N_RB_DL); LOG_I(PHY,"init eNB: Transmission mode %d\n", transmission_mode); + LOG_I(PHY,"init eNB: prach_config_index %d\n", frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex); for (i=0; i Date: Thu, 4 Aug 2016 01:14:33 +0200 Subject: [PATCH 140/206] modifications for RRC IF4p5 --- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 2 +- openair1/PHY/LTE_TRANSPORT/prach.c | 26 ++++++++++++++++--- openair1/SCHED/phy_procedures_lte_eNb.c | 3 ++- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 12 +++++---- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 8 ++++-- targets/RT/USER/lte-enb.c | 14 +++++----- 6 files changed, 45 insertions(+), 20 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index 8f01fc5369..fb3e11780f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -233,7 +233,7 @@ void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_t } else if (*packet_type == IF4p5_PRACH) { // FIX: hard coded prach samples length - db_fulllength = 839*2; + db_fulllength = 840*2; memcpy((&rxsigF[0][0]), (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t), diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 0adb8685f0..4d29ba55e7 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1101,6 +1101,8 @@ void rx_prach(PHY_VARS_eNB *eNB, int fft_size,log2_ifft_size; uint8_t nb_ant_rx = 1; //eNB->frame_parms.nb_antennas_rx; + // int en; + for (aa=0; aacommon_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_tti-eNB->N_TA_offset]; } @@ -1299,7 +1301,12 @@ void rx_prach(PHY_VARS_eNB *eNB, // Adjust received rxsigF offset memmove((&rxsigF[0][k]), (&rxsigF[0][0]), - 839*2*sizeof(int16_t)); + 839*2*sizeof(int16_t)); + + //en = dB_fixed(signal_energy(&rxsigF[0][k],840)); + // if (en>60) + //printf("PRACH: Frame %d, Subframe %d => %d dB\n",eNB->proc.frame_rx,eNB->proc.subframe_rx,en); + } // in case of RCC and prach received rx_thread wakes up prach @@ -1470,9 +1477,22 @@ void rx_prach(PHY_VARS_eNB *eNB, // if (aa=1) write_output("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1); }// antennas_rx #ifdef PRACH_DEBUG - write_output("prach_ifft0.m","prach_t0",prach_ifft[0],2048,1,1); + + if (en>40) { + k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL; + + if (k<0) + k+=(eNB->frame_parms.ofdm_symbol_size); + + k*=12; + k+=13; + k*=2; + printf("Dumping prach, k = %d (n_ra_prb %d)\n",k,n_ra_prb); + write_output("rxsigF.m","prach_rxF",&rxsigF[0][k],840,1,1); + write_output("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); + write_output("prach_ifft0.m","prach_t0",prach_ifft[0],1024,1,1); + } #endif - // write_output("prach_ifft1.m","prach_t1",prach_ifft[1],2048,1,1); } // new dft diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6bf9273776..8385d97f41 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1949,13 +1949,14 @@ void prach_procedures(PHY_VARS_eNB *eNB) { update_TA = 1; break; } - + mac_xface->initiate_ra_proc(eNB->Mod_id, eNB->CC_id, frame, preamble_max, preamble_delay_list[preamble_max]*update_TA, 0,subframe,0); + } } else { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 02ca6ee7eb..0b73324080 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -274,7 +274,7 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi if (bytes_received ==-1) { eth->num_rx_errors++; - perror("ETHERNET READ: "); + perror("ETHERNET IF5 READ: "); exit(-1); } else { /* store the timestamp value from packet's header */ @@ -314,14 +314,15 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t; IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES); - + + bytes_received = recv(eth->sockfd[Mod_id], buff[0], packet_size, MSG_PEEK); if (bytes_received ==-1) { eth->num_rx_errors++; - perror("ETHERNET READ: "); + perror("ETHERNET IF4p5 READ (header): "); exit(-1); } @@ -334,7 +335,8 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam } else { packet_size = RAW_IF4p5_PRACH_SIZE_BYTES; } - + + while(bytes_received < packet_size) { bytes_received = recv(eth->sockfd[Mod_id], buff[0], @@ -342,7 +344,7 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam 0); if (bytes_received ==-1) { eth->num_rx_errors++; - perror("ETHERNET READ: "); + perror("ETHERNET IF4p5 READ (payload): "); exit(-1); } else { eth->rx_actual_nsamps = bytes_received>>1; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index d530558816..38a6d5a571 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -63,6 +63,7 @@ int trx_eth_start(openair0_device *device) { /* initialize socket */ if (eth->flags == ETH_RAW_MODE) { + printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n"); if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ if (device->host_type == BBU_HOST) { @@ -74,6 +75,8 @@ int trx_eth_start(openair0_device *device) { if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_RAW_IF4p5_MODE) { + + printf("Setting ETHERNET to ETH_RAW_IF4p5_MODE\n"); if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ if (device->host_type == BBU_HOST) { @@ -83,12 +86,13 @@ int trx_eth_start(openair0_device *device) { } /* adjust MTU wrt number of samples per packet */ if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; - if(ethernet_tune (device,RCV_TIMEOUT,5000)!=0) return -1; + if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_UDP_IF4p5_MODE) { - + printf("Setting ETHERNET to UDP_IF4p5_MODE\n"); } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { + printf("Setting ETHERNET to RAW_IF5_MODE\n"); if (eth_socket_init_raw(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ //if (device->host_type == BBU_HOST) { diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index b0d1eb3d0e..231b1bceb0 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -975,7 +975,7 @@ void rx_fh_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame, int *subframe) { } -void rx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *subframe,int *frame) { +void rx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; @@ -988,27 +988,25 @@ void rx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *subframe,int *frame) { symbol_mask = 0; symbol_mask_full = (1<symbols_per_tti)-1; prach_rx = 0; - + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 ); recv_IF4p5(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 ); - if (packet_type == IF4p5_PULFFT) { symbol_mask = symbol_mask | (1<frame_rx, proc->subframe_rx)>0) ? 1 : 0; } else if (packet_type == IF4p5_PRACH) { prach_rx = 0; } + } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); if (proc->first_rx == 0) { if (proc->subframe_rx != *subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe); exit_fun("Exiting"); } if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); exit_fun("Exiting"); } } else { @@ -1271,7 +1269,7 @@ static void* eNB_thread_FH( void* param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - + if (oai_exit) break; if (subframe==9) { From 1ec0c5bf63e6b9a4f6e3fd79eda5fd9897205119 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 4 Aug 2016 16:41:14 +0200 Subject: [PATCH 141/206] modifications for EXMIMO2 targets --- openair1/PHY/INIT/lte_init.c | 13 +- openair1/PHY/defs.h | 3 + openair1/SCHED/phy_procedures_lte_eNb.c | 7 ++ .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 26 ++-- .../CONF/enb.band38.tm1.exmimo2.conf | 7 +- .../CONF/enb.band7.exmimo2.conf | 3 + targets/RT/USER/lte-enb.c | 19 +-- targets/RT/USER/lte-softmodem.c | 114 +++++++++--------- targets/RT/USER/lte-ue.c | 80 ++++++------ 9 files changed, 152 insertions(+), 120 deletions(-) diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index d583381781..2fa9c36d69 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -43,10 +43,6 @@ #include "assertions.h" #include -#ifdef EXMIMO -extern openair0_rf_map rf_map[MAX_NUM_CCs]; -#endif - extern uint16_t prach_root_sequence_map0_3[838]; extern uint16_t prach_root_sequence_map4[138]; uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10}; @@ -672,7 +668,7 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, int CC_id) { - //PHY_VARS_eNB *eNB = PHY_vars_eNB_g[Mod_id][CC_id]; + uint8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][0]); struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10 = sCellToAddMod_r10->radioResourceConfigDedicatedSCell_r10->physicalConfigDedicatedSCell_r10; //struct RadioResourceConfigCommonSCell_r10 *physicalConfigCommonSCell_r10 = sCellToAddMod_r10->radioResourceConfigCommonSCell_r10; @@ -682,13 +678,14 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, #ifdef EXMIMO #ifdef DRIVER2013 - exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[rf_map[CC_id].card].exmimo_config_ptr; + // exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[rf_map[CC_id].card].exmimo_config_ptr; #endif #endif if ((dl_CarrierFreq_r10>=36000) && (dl_CarrierFreq_r10<=36199)) { carrier_freq_local = 1900000000 + (dl_CarrierFreq_r10-36000)*100000; //band 33 from 3GPP 36.101 v 10.9 Table 5.7.3-1 LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); + /* #ifdef EXMIMO #ifdef DRIVER2013 //carrier_freq[CC_id] = carrier_freq_local; @@ -700,11 +697,12 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, p_exmimo_config->rf.rf_local[rf_map[CC_id].chain] = 8255063; //this should be taken form calibration file p_exmimo_config->rf.rffe_band_mode[rf_map[CC_id].chain] = B19G_TDD; #endif -#endif +#endif*/ } else if ((dl_CarrierFreq_r10>=6150) && (dl_CarrierFreq_r10<=6449)) { carrier_freq_local = 832000000 + (dl_CarrierFreq_r10-6150)*100000; //band 20 from 3GPP 36.101 v 10.9 Table 5.7.3-1 // this is actually for the UL only, but we use it for DL too, since there is no TDD mode for this band LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); +/* #ifdef EXMIMO #ifdef DRIVER2013 //carrier_freq[CC_id] = carrier_freq_local; @@ -717,6 +715,7 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, p_exmimo_config->rf.rffe_band_mode[rf_map[CC_id].chain] = DD_TDD; #endif #endif +*/ } else { LOG_E(PHY,"[eNB %d] Frame %d: ARFCN %d of SCell %d for UE %d not supported\n",Mod_id,/*eNB->frame*/0,dl_CarrierFreq_r10,CC_id,UE_id); } diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 9b5db4b421..46679c7f7c 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -363,6 +363,7 @@ typedef struct PHY_VARS_eNB_s { eNB_proc_t proc; eNB_func_t node_function; eNB_timing_t node_timing; + openair0_rf_map rf_map; int abstraction_flag; void (*do_prach)(struct PHY_VARS_eNB_s *eNB); void (*fep)(struct PHY_VARS_eNB_s *eNB); @@ -579,6 +580,8 @@ typedef struct { uint8_t Mod_id; /// \brief Component carrier ID for this PHY instance uint8_t CC_id; + /// \brief Mapping of CC_id antennas to cards + openair0_rf_map rf_map; //uint8_t local_flag; /// \brief Indicator of current run mode of UE (normal_txrx, rx_calib_ue, no_L2_connect, debug_prach) runmode_t mode; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6fcd41ec28..164c21ce21 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1107,6 +1107,8 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, uint8_t smbv_alloc_cnt = 1; #endif + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_DL)) return; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),1); start_meas(&eNB->phy_proc_tx); @@ -2582,11 +2584,14 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){ eNB_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 1 ); start_meas(&eNB->phy_proc_rx); @@ -2620,6 +2625,8 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 1 ); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index 736e126ccb..17a1d18ce6 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -501,6 +501,7 @@ int trx_exmimo_start(openair0_device *device) { printf("Starting ...\n"); openair0_config(device->openair0_cfg,0); openair0_start_rt_acquisition(0); + printf("Setting state to running\n"); exm->daq_state = running; exm->wait_first_read = 1; return(0); @@ -508,7 +509,8 @@ int trx_exmimo_start(openair0_device *device) { int trx_exmimo_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc, int flags) { - return(0); + + return(nsamps); } @@ -521,12 +523,12 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi struct timespec sleep_time; unsigned long tv_nsec; int i; - struct timespec wait; int n,n1,n2,ntot,first_len; int ret; - wait.tv_sec=0; - wait.tv_nsec=50000000L; + // struct timespec wait; + // wait.tv_sec=0; + // wait.tv_nsec=50000000L; if (exm->watchdog_exit == 1) return(0); @@ -535,7 +537,6 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi tv_nsec=(unsigned long)((double)(nsamps)*1e9/cfg->sample_rate); return(0); } - ret = pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); switch (ret) { @@ -564,6 +565,9 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi return(0); break; } + + ret = pthread_mutex_lock(&exm->watchdog_mutex); + ts = exm->ts; if (exm->wait_first_read==1) { exm->wait_first_read=0; @@ -603,7 +607,7 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi printf("back\n"); #endif // get new timestamp, in case we have to sleep again - pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); + pthread_mutex_lock(&exm->watchdog_mutex); ts = exm->ts; pthread_mutex_unlock(&exm->watchdog_mutex); if (old_ts == ts) { @@ -638,7 +642,7 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi } } } - pthread_mutex_timedlock(&exm->watchdog_mutex,&wait); + pthread_mutex_lock(&exm->watchdog_mutex); exm->last_ts_rx += n; pthread_mutex_unlock(&exm->watchdog_mutex); if (n==n1) { @@ -712,6 +716,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { exmimo_id_t *p_exmimo_id; int ret; exmimo_state_t *exm = (exmimo_state_t *)malloc(sizeof(exmimo_state_t)); + int card,ant; ret = openair0_open(); @@ -763,6 +768,13 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->priv = (void *)exm; + printf("EXMIMO2: Getting addresses for memory-mapped DMA\n"); + for (card=0; cardfirst_rx == 0) { if (proc->subframe_rx != *subframe){ - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe); + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe); exit_fun("Exiting"); } if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame); + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); exit_fun("Exiting"); } } else { @@ -1740,7 +1740,7 @@ void kill_eNB_proc(int inst) { Each rf chain is is addressed by the card number and the chain on the card. The rf_map specifies for each CC, on which rf chain the mapping should start. Multiple antennas are mapped to successive RF chains on the same card. */ -int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) { +int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg) { int i, CC_id; int j; @@ -1808,17 +1808,17 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c for (i=0; inb_antennas_rx; i++) { free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); - rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory - memset(rxdata[i], 0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); + memset(rxdata[i], 0, openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t)); printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset); } for (i=0; inb_antennas_tx; i++) { free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); - txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i]; - memset(txdata[i],0, openair0_cfg[rf_map[CC_id].card].samples_per_frame*sizeof(int32_t)); + memset(txdata[i],0, openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t)); printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); } } @@ -2018,6 +2018,11 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst } } + if (setup_eNB_buffers(PHY_vars_eNB_g[inst],&openair0_cfg[inst])!=0) { + printf("Exiting, cannot initialize eNodeB Buffers\n"); + exit(-1); + } + init_eNB_proc(inst); } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 38629b8ff4..4849e63807 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -118,13 +118,13 @@ unsigned short config_frames[4] = {2,9,11,13}; #endif // In lte-enb.c -extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); +extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg); extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *); extern void stop_eNB(int); extern void kill_eNB_proc(void); // In lte-ue.c -extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]); +extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg); extern void fill_ue_band_info(void); extern void init_UE(int); @@ -177,7 +177,6 @@ static char threequarter_fs=0; uint32_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -openair0_rf_map rf_map[MAX_NUM_CCs]; static char *conf_config_file_name = NULL; #if defined(ENABLE_ITTI) @@ -272,10 +271,10 @@ int16_t osa_log_verbosity = LOG_MED; #endif -#ifdef ETHERNET + char *rrh_UE_ip = "127.0.0.1"; int rrh_UE_port = 51000; -#endif + /* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */ uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; @@ -1704,60 +1703,7 @@ int main( int argc, char **argv ) mac_xface->mrbch_phy_sync_failure (0, 0, 0); } - number_of_cards = 1; - for(CC_id=0; CC_idhw_timing_advance = timing_advance; -#else - UE[CC_id]->hw_timing_advance = 160; -#endif - } - if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) { - printf("Error setting up eNB buffer\n"); - exit(-1); - } - - - - if (input_fd) { - printf("Reading in from file to antenna buffer %d\n",0); - if (fread(UE[0]->common_vars.rxdata[0], - sizeof(int32_t), - frame_parms[0]->samples_per_tti*10, - input_fd) != frame_parms[0]->samples_per_tti*10) - printf("error reading from file\n"); - } - //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; - } else { - - - - if (setup_eNB_buffers(PHY_vars_eNB_g[0],&openair0_cfg[0],rf_map)!=0) { - printf("Error setting up eNB buffer\n"); - exit(-1); - } - - printf("Setting eNB buffer to all-RX\n"); - - // Set LSBs for antenna switch (ExpressMIMO) - for (CC_id=0; CC_idhw_timing_advance = 0; - for (i=0; isamples_per_tti*10; i++) - for (aa=0; aanb_antennas_tx; aa++) - PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; - } - } mlockall(MCL_CURRENT | MCL_FUTURE); @@ -1829,6 +1775,58 @@ int main( int argc, char **argv ) if (UE_flag == 1) init_UE(1); else init_eNB(node_function,node_timing,1,eth_params); // Sleep to allow all threads to setup + + number_of_cards = 1; + + for(CC_id=0; CC_idrf_map.card=0; + PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; + } + + // connect the TX/RX buffers + if (UE_flag==1) { + + for (CC_id=0;CC_idhw_timing_advance = timing_advance; +#else + UE[CC_id]->hw_timing_advance = 160; +#endif + } + if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) { + printf("Error setting up eNB buffer\n"); + exit(-1); + } + + + + if (input_fd) { + printf("Reading in from file to antenna buffer %d\n",0); + if (fread(UE[0]->common_vars.rxdata[0], + sizeof(int32_t), + frame_parms[0]->samples_per_tti*10, + input_fd) != frame_parms[0]->samples_per_tti*10) + printf("error reading from file\n"); + } + //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; + } else { + + + + + + printf("Setting eNB buffer to all-RX\n"); + + // Set LSBs for antenna switch (ExpressMIMO) + for (CC_id=0; CC_idhw_timing_advance = 0; + for (i=0; isamples_per_tti*10; i++) + for (aa=0; aanb_antennas_tx; aa++) + PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; + } + } sleep(3); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 3fda5d735f..88bce26d6c 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -104,7 +104,6 @@ extern int sync_var; extern openair0_config_t openair0_cfg[MAX_CARDS]; extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -extern openair0_rf_map rf_map[MAX_NUM_CCs]; extern int oai_exit; extern int32_t **rxdata; @@ -1559,56 +1558,59 @@ void fill_ue_band_info(void) } #endif -int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]) +int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) { int i, CC_id; LTE_DL_FRAME_PARMS *frame_parms; - - for (CC_id=0; CC_idframe_parms); - } else { - printf("phy_vars_UE[%d] not initialized\n", CC_id); - return(-1); - } + openair0_rf_map *rf_map; - /* - if (frame_parms->frame_type == TDD) { - if (frame_parms->N_RB_DL == 100) + for (CC_id=0; CC_idrf_map; + + if (phy_vars_ue[CC_id]) { + frame_parms = &(phy_vars_ue[CC_id]->frame_parms); + } else { + printf("phy_vars_UE[%d] not initialized\n", CC_id); + return(-1); + } + + /* + if (frame_parms->frame_type == TDD) { + if (frame_parms->N_RB_DL == 100) N_TA_offset = 624; else if (frame_parms->N_RB_DL == 50) - N_TA_offset = 624/2; + N_TA_offset = 624/2; else if (frame_parms->N_RB_DL == 25) - N_TA_offset = 624/4; - } - */ - + N_TA_offset = 624/4; + } + */ + // replace RX signal buffers with mmaped HW versions - rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - printf( "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); - free( phy_vars_ue[CC_id]->common_vars.rxdata[i] ); + rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + + for (i=0; inb_antennas_rx; i++) { + printf( "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i ); + free( phy_vars_ue[CC_id]->common_vars.rxdata[i] ); rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD printf("rxdata[%d] : %p\n",i,rxdata[i]); - } - - for (i=0; inb_antennas_tx; i++) { - printf( "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i ); - free( phy_vars_ue[CC_id]->common_vars.txdata[i] ); - txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); - phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i]; - printf("txdata[%d] : %p\n",i,txdata[i]); - } - - // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x] - // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x] - // be careful when releasing memory! - // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes) - + } + + for (i=0; inb_antennas_tx; i++) { + printf( "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i ); + free( phy_vars_ue[CC_id]->common_vars.txdata[i] ); + txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) ); + phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i]; + printf("txdata[%d] : %p\n",i,txdata[i]); + } + + // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x] + // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x] + // be careful when releasing memory! + // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes) + } return 0; From 6e1d81bef32f7e6a9002b8a5f363b32cb7f31db0 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 4 Aug 2016 18:19:54 +0200 Subject: [PATCH 142/206] band 38 tx gain exmimo2 --- .../PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.exmimo2.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.exmimo2.conf index d4300301f8..3c608776d6 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.exmimo2.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.exmimo2.conf @@ -38,7 +38,7 @@ eNBs = Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; - tx_gain = 25; + tx_gain = 10;//25; rx_gain = 120; prach_root = 0; prach_config_index = 0; From 3608e5bc9e84bb0b95ab2181b628abc40ad0df15 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 4 Aug 2016 19:13:48 +0200 Subject: [PATCH 143/206] Gitlab CI: fix for 20MHz tests --- cmake_targets/autotests/test_case_list.xml | 112 ++++++++++++--------- 1 file changed, 62 insertions(+), 50 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index e50c651fa3..11a0c172db 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -10,7 +10,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_huaweiE398_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue; uname -a; sudo -E dmesg 36000 - 010141 0102+ 010304 010305 0104+ 015502 015505 015506 015507 015508 015509 015510 015511 015514 015517 015602 015605 015702 015705 015802 015805 015808 015811 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 018502 018505 025502 025505 025508 025511 + 010141 0102+ 010304 010305 0104+ 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 018502 018505 3 mozart tique stevens amerique @@ -1078,7 +1078,7 @@ lte-softmodem - calisson + tique stevens amerique 390 @@ -1090,15 +1090,16 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -32 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c @@ -1120,7 +1121,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 14M -B 192.172.0.2 @@ -1298,7 +1299,7 @@ lte-softmodem - calisson + tique stevens amerique 390 @@ -1312,13 +1313,14 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -32 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c @@ -1340,9 +1342,9 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m - throughput_test min=0.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec + throughput_test min=0.0Mbits/sec max=10.0Mbits/sec average=10.0Mbits/sec False sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue @@ -1361,7 +1363,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -u -c 192.172.0.2 -b 10Mbits/s + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -u -c 192.172.0.2 -b 33M -i 1 -f m -u False @@ -1966,7 +1968,7 @@ lte-softmodem - calisson + tique stevens amerique 390 @@ -1980,13 +1982,14 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -32 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c @@ -2186,7 +2189,7 @@ lte-softmodem - calisson + tique stevens amerique 390 @@ -2200,13 +2203,14 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -32 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c @@ -3485,6 +3489,7 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf pdsch_referenceSignalPower -23 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_tx 1 @@ -3513,7 +3518,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 17Mbits/s -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 17Mbits/s @@ -3699,6 +3704,7 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf pdsch_referenceSignalPower -23 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_tx 1 @@ -3747,7 +3753,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -u -c 192.172.0.2 -b 10Mbits/s + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -u -c 192.172.0.2 -b 33Mbits/s False @@ -3913,6 +3919,7 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf pdsch_referenceSignalPower -23 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_tx 1 @@ -4127,6 +4134,7 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf pdsch_referenceSignalPower -23 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf nb_antennas_tx 1 @@ -4175,7 +4183,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 75 lo -c 192.172.0.2 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 False @@ -7156,7 +7164,7 @@ c lte-softmodem - calisson + tique stevens amerique 390 @@ -7168,15 +7176,16 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -29 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c @@ -7198,7 +7207,7 @@ c sleep 50; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script_phone 1 YT9115PX1E -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script_phone 1 YT9115PX1E -u -c 192.172.0.1 -b 14Mbits/s -B 192.172.0.2 @@ -7378,7 +7387,7 @@ c lte-softmodem - calisson + tique stevens amerique 390 @@ -7390,15 +7399,16 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -29 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c @@ -7441,7 +7451,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -b 40Mbits/s -i 1 -f m -u + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -b 33M -i 1 -f m -u False @@ -7601,7 +7611,7 @@ c lte-softmodem - calisson + tique stevens amerique 390 @@ -7613,15 +7623,16 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -29 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c @@ -7823,7 +7834,7 @@ c lte-softmodem - calisson + tique stevens amerique 390 @@ -7835,15 +7846,16 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf pdsch_referenceSignalPower -29 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c From 8014a94020693ba21f0ed3a53d399af12da1e271 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 5 Aug 2016 09:58:57 +0200 Subject: [PATCH 144/206] IF4p5 with UDP. --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 19 +--- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 103 +++++++++++++++++- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 41 ++++--- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 5 +- targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h | 3 + 5 files changed, 133 insertions(+), 38 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index cfff2158a7..126030d3d4 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -65,23 +65,18 @@ int eth_socket_init_raw(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; const char *local_mac, *remote_mac; - int local_port=0, remote_port=0; int sock_dom=0; int sock_type=0; int sock_proto=0; if (device->host_type == RRH_HOST ) { /* RRH doesn't know remote MAC(will be retrieved from first packet send from BBU) and remote port(don't care) */ local_mac = device->openair0_cfg->my_addr; - local_port = device->openair0_cfg->my_port; remote_mac = malloc(ETH_ALEN); - memset(remote_mac,0,ETH_ALEN); - remote_port = 0; + memset((void*)remote_mac,0,ETH_ALEN); printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac); } else { local_mac = device->openair0_cfg->my_addr; - local_port = device->openair0_cfg->my_port; remote_mac = device->openair0_cfg->remote_addr; - remote_port = device->openair0_cfg->remote_port; printf("[%s] local MAC addr %s remote MAC addr %s\n","BBU", local_mac,remote_mac); } @@ -182,7 +177,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi printf("------- TX ------: nu=%x an_id=%d ts%d bytes_sent=%d\n", *(uint8_t *)(buff2+ETH_ALEN), *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)), - *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), bytes_sent); dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps), TX_FLAG); #endif @@ -343,10 +338,10 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam buff[0], packet_size, 0); - if (bytes_received ==-1) { - eth->num_rx_errors++; - perror("ETHERNET IF4p5 READ (payload): "); - exit(-1); + if (bytes_received ==-1) { + eth->num_rx_errors++; + perror("ETHERNET IF4p5 READ (payload): "); + exit(-1); } else { eth->rx_actual_nsamps = bytes_received>>1; eth->rx_count++; @@ -425,7 +420,6 @@ int eth_get_dev_conf_raw(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - char str[INET_ADDRSTRLEN]; void *msg; ssize_t msg_len; @@ -456,7 +450,6 @@ int eth_get_dev_conf_raw_IF4p5(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - char str[INET_ADDRSTRLEN]; void *msg; ssize_t msg_len; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index a9706c73bd..863b0d02d2 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -63,7 +63,7 @@ uint16_t pck_seq_num = 1; uint16_t pck_seq_num_cur=0; uint16_t pck_seq_num_prev=0; - int eth_socket_init_udp(openair0_device *device) { +int eth_socket_init_udp(openair0_device *device) { int i = 0; eth_state_t *eth = (eth_state_t*)device->priv; @@ -138,6 +138,103 @@ uint16_t pck_seq_num_prev=0; return 0; } +int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + + // Read nblocks info from packet itself + int nblocks = nsamps; + int bytes_received=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + + ssize_t packet_size = sizeof_IF4p5_header_t; + IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0]); + + + bytes_received = recvfrom(eth->sockfd[Mod_id], + buff[0], + packet_size, + 0, + (struct sockaddr *)&dest_addr[Mod_id], + (socklen_t *)&addr_len[Mod_id]); + + if (bytes_received ==-1) { + eth->num_rx_errors++; + perror("ETHERNET IF4p5 READ (header): "); + exit(-1); + } + + *timestamp = test_header->sub_type; + + if (test_header->sub_type == IF4p5_PDLFFT) { + packet_size = UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks); + } else if (test_header->sub_type == IF4p5_PULFFT) { + packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks); + } else { + packet_size = UDP_IF4p5_PRACH_SIZE_BYTES; + } + + + while(bytes_received < packet_size) { + bytes_received = recvfrom(eth->sockfd[Mod_id], + buff[0], + packet_size, + 0, + (struct sockaddr *)&dest_addr[Mod_id], + (socklen_t *)&addr_len[Mod_id]); + if (bytes_received ==-1) { + eth->num_rx_errors++; + perror("ETHERNET IF4p5 READ (payload): "); + exit(-1); + } else { + eth->rx_actual_nsamps = bytes_received>>1; + eth->rx_count++; + } + } + + eth->rx_nsamps = nsamps; + return(bytes_received); +} + +int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + + int nblocks = nsamps; + int bytes_sent = 0; + + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + + ssize_t packet_size; + + if (flags == IF4p5_PDLFFT) { + packet_size = UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks); + } else if (flags == IF4p5_PULFFT) { + packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks); + } else { + printf("trx_eth_write_udp_IF4p5: unknown flags %d\n",flags); + return(-1); + } + + eth->tx_nsamps = nblocks; + + bytes_sent = sendto(eth->sockfd[Mod_id], + buff[0], + packet_size, + 0, + (struct sockaddr*)&dest_addr[Mod_id], + addr_len[Mod_id]); + + if (bytes_sent == -1) { + eth->num_tx_errors++; + perror("ETHERNET WRITE: "); + exit(-1); + } else { + eth->tx_actual_nsamps = bytes_sent>>1; + eth->tx_count++; + } + + return (bytes_sent); +} + int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { int bytes_sent=0; @@ -216,7 +313,7 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi int bytes_received=0; eth_state_t *eth = (eth_state_t*)device->priv; - openair0_timestamp prev_timestamp = -1; + // openair0_timestamp prev_timestamp = -1; int Mod_id = device->Mod_id; int rcvfrom_flag =0; int block_cnt=0; @@ -298,7 +395,7 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi pck_seq_num_cur = *(uint16_t *)buff2; //printf("cur=%d prev=%d buff=%d\n",pck_seq_num_cur,pck_seq_num_prev,*(uint16_t *)(buff2)); if ( ( pck_seq_num_cur != (pck_seq_num_prev + 1) ) && !((pck_seq_num_prev==75) && (pck_seq_num_cur==1 ))){ - printf("out of order packet received1! %d|%d|%d\n",pck_seq_num_cur,pck_seq_num_prev, *timestamp); + printf("out of order packet received1! %d|%d|%d\n",pck_seq_num_cur,pck_seq_num_prev,(int)*timestamp); } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,pck_seq_num_cur); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,pck_seq_num_prev); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index e5d606f2d7..6079781ba1 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -90,19 +90,15 @@ int trx_eth_start(openair0_device *device) { if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_UDP_IF4p5_MODE) { printf("Setting ETHERNET to UDP_IF4p5_MODE\n"); - + if (eth_socket_init_udp(device)!=0) return -1; + if (device->host_type == BBU_HOST) { + if(eth_set_dev_conf_udp(device)!=0) return -1; + } else { + if(eth_get_dev_conf_udp(device)!=0) return -1; + } } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { printf("Setting ETHERNET to RAW_IF5_MODE\n"); if (eth_socket_init_raw(device)!=0) return -1; - /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ - //if (device->host_type == BBU_HOST) { - //if(eth_set_dev_conf_raw_IF4p5(device)!=0) return -1; - //} else { - //if(eth_get_dev_conf_raw_IF4p5(device)!=0) return -1; -// - /* adjust MTU wrt number of samples per packet */ - // if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; - } else { if (eth_socket_init_udp(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ @@ -171,7 +167,7 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { -int trx_eth_stop(int card) { +int trx_eth_stop(openair0_device *device) { return(0); } @@ -199,11 +195,11 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { struct timeval timeout; struct ifreq ifr; char system_cmd[256]; - char* if_name=DEFAULT_IF; - struct in_addr ia; - struct if_nameindex *ids; + // char* if_name=DEFAULT_IF; + // struct in_addr ia; + // struct if_nameindex *ids; int ret=0; - int i=0; + // int i=0; /****************** socket level options ************************/ switch(option) { @@ -238,7 +234,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { (char *)&timeout,sizeof(timeout))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "receive timeout= %u usec\n",timeout.tv_usec); + printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec); } break; @@ -251,7 +247,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { (char *)&timeout,sizeof(timeout))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "send timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec); + printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec); } break; @@ -311,7 +307,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { break; case RING_PAR: - ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx %d tx %d",eth->if_name[Mod_id],value); + ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s val %d",eth->if_name[Mod_id],value); if (ret > 0) { ret=system(system_cmd); if (ret == -1) { @@ -376,6 +372,9 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth } else if (eth->flags == ETH_RAW_IF4p5_MODE) { device->trx_write_func = trx_eth_write_raw_IF4p5; device->trx_read_func = trx_eth_read_raw_IF4p5; + } else if (eth->flags == ETH_UDP_IF4p5_MODE) { + device->trx_write_func = trx_eth_write_udp_IF4p5; + device->trx_read_func = trx_eth_read_udp_IF4p5; } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { device->trx_write_func = trx_eth_write_raw_IF4p5; device->trx_read_func = trx_eth_read_raw_IF4p5; @@ -460,7 +459,7 @@ void dump_dev(openair0_device *device) { device->openair0_cfg->num_rb_dl, device->openair0_cfg->sample_rate); printf(" BBU configured for %i tx/%i rx channels)\n", device->openair0_cfg->tx_num_channels,device->openair0_cfg->rx_num_channels); - printf(" Running flags: %s %s %s\n", + printf(" Running flags: %s %s (\n", ((eth->flags & ETH_RAW_MODE) ? "RAW socket mode - ":""), ((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":"")); printf(" Number of iqs dumped when displaying packets: %i\n\n",eth->iqdumpcnt); @@ -470,14 +469,14 @@ void dump_dev(openair0_device *device) { void inline dump_txcounters(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; printf(" Ethernet device interface %i, tx counters:\n" ,device->openair0_cfg->Mod_id); - printf(" Sent packets: %llu send errors: %i\n", eth->tx_count, eth->num_tx_errors); + printf(" Sent packets: %llu send errors: %i\n", (long long unsigned int)eth->tx_count, eth->num_tx_errors); } void inline dump_rxcounters(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; printf(" Ethernet device interface %i rx counters:\n" ,device->openair0_cfg->Mod_id); - printf(" Received packets: %llu missed packets errors: %i\n", eth->rx_count, eth->num_underflows); + printf(" Received packets: %llu missed packets errors: %i\n", (long long unsigned int)eth->rx_count, eth->num_underflows); } void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag, int nsamps) { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 3adb0f45cb..0d80dbd023 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -176,9 +176,10 @@ typedef struct { void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag); unsigned short calc_csum (unsigned short *buf, int nwords); void dump_dev(openair0_device *device); -void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag,int nsamps); +/*void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag,int nsamps); void inline dump_rxcounters(openair0_device *device); void inline dump_txcounters(openair0_device *device); +*/ void dump_iqs(char * buff, int iq_cnt); @@ -224,6 +225,8 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); int eth_get_dev_conf_raw(openair0_device *device); int eth_set_dev_conf_raw(openair0_device *device); int eth_get_dev_conf_raw_IF4p5(openair0_device *device); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index e118e9f99f..855ff49704 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -65,6 +65,9 @@ #define RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) #define RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) #define RAW_IF4p5_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + PRACH_BLOCK_SIZE_BYTES) +#define UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks) (sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks) (sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks)) +#define UDP_IF4p5_PRACH_SIZE_BYTES (sizeof_IF4p5_header_t + PRACH_BLOCK_SIZE_BYTES) // Mobipass packet sizes #define RAW_IF5_MOBIPASS_BLOCK_SIZE_BYTES 1280 From 121e33e608773baefeb5245a4b7cbd1b2f997629 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 5 Aug 2016 03:21:34 -0700 Subject: [PATCH 145/206] minor changes in dlsim. --- openair1/SIMULATION/LTE_PHY/dlsim.c | 7 ++++--- targets/RT/USER/lte-enb.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 23a453b941..f7824773e0 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -2515,8 +2515,9 @@ int main(int argc, char **argv) proc_eNB->subframe_tx = subframe; - - phy_procedures_eNB_TX(eNB,proc_eNB,0,no_relay,NULL); + eNB->abstraction_flag=0; + + phy_procedures_eNB_TX(eNB,proc_eNB,no_relay,NULL); start_meas(&eNB->ofdm_mod_stats); @@ -2538,7 +2539,7 @@ int main(int argc, char **argv) proc_eNB->subframe_tx = subframe+1; - phy_procedures_eNB_TX(eNB,proc_eNB,0,no_relay,NULL); + phy_procedures_eNB_TX(eNB,proc_eNB,no_relay,NULL); do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], eNB->common_vars.txdata[eNB_id], diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index ed8cfefecb..b5cdf68934 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -682,7 +682,7 @@ static void* eNB_thread_asynch_rx( void* param ) { if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB FH sched_setattr failed\n"); - return &eNB_thread_FH_status; + return &eNB_thread_asynch_rx_status; } LOG_I( HW, "[SCHED] eNB asynch RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); From a0170b8e0f8a2c8b794f613e85f4051947aebdad Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 5 Aug 2016 09:34:45 -0700 Subject: [PATCH 146/206] more cleanup for lte-enb.c --- targets/RT/USER/lte-enb.c | 720 +++++++++-------------------------- targets/RT/USER/rt_wrapper.c | 11 +- targets/RT/USER/rt_wrapper.h | 29 +- 3 files changed, 202 insertions(+), 558 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 36eba0efe3..d55c2d0586 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -163,6 +163,163 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst void stop_eNB(int nb_inst); +inline void thread_top_init(char *thread_name, + uint64_t runtime, + uint64_t deadline, + uint64_t period) { + + MSC_START_USE(); + +#ifdef DEADLINE_SCHEDULER + struct sched_attr attr; + + unsigned int flags = 0; + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0; + + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = runtime; + attr.sched_deadline = deadline; + attr.sched_period = period; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] eNB tx thread: sched_setattr failed\n"); + return &eNB_thread_rxtx_status; + } + + LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); + +#else //LOW_LATENCY + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD threads */ + /* CPU 1 is reserved for all RX_TX threads */ + /* Enable CPU Affinity only if number of CPUs >2 */ + CPU_ZERO(&cpuset); + +#ifdef CPU_AFFINITY + if (get_nprocs() > 2) + { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_setaffinity_np"); + exit_fun("Error setting processor affinity"); + } + } +#endif //CPU_AFFINITY + + /* Check the actual affinity mask assigned to the thread */ + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) { + perror( "pthread_getaffinity_np"); + exit_fun("Error getting processor affinity "); + } + memset(cpu_affinity,0,sizeof(cpu_affinity)); + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } + + memset(&sparam, 0, sizeof(sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + policy = SCHED_FIFO ; + + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) { + perror("pthread_getschedparam : "); + exit_fun("Error getting thread priority"); + } + + LOG_I(HW, "[SCHED][eNB] %s started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(),gettid(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, cpu_affinity ); + +#endif //LOW_LATENCY + + mlockall(MCL_CURRENT | MCL_FUTURE); + +} + +inline void wait_sync(char *thread_name) { + + printf( "waiting for sync (%s)\n",thread_name); + pthread_mutex_lock( &sync_mutex ); + + while (sync_var<0) + pthread_cond_wait( &sync_cond, &sync_mutex ); + + pthread_mutex_unlock(&sync_mutex); + + printf( "got sync (%s)\n", thread_name); + +} + +inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { + + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(mutex,&wait) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + + while (*instance_cnt < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_rxtx is -1 + pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again + } + + if (pthread_mutex_unlock(mutex) != 0) { + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + return(0); +} + +inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { + + if (pthread_mutex_lock(mutex) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + + *instance_cnt=*instance_cnt-1; + + if (pthread_mutex_unlock(mutex) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + return(0); +} + void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { unsigned int aa,slot_offset, slot_offset_F; @@ -419,135 +576,19 @@ static void* eNB_thread_rxtx( void* param ) { PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - FILE *tx_time_file = NULL; - char tx_time_name[101]; + char thread_name[100]; + - - if (opp_enabled == 1) { - snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf", "eNB"); - tx_time_file = fopen(tx_time_name,"w"); - } // set default return value eNB_thread_rxtx_status = 0; - MSC_START_USE(); - -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - - unsigned int flags = 0; - uint64_t runtime = 850000 ; - uint64_t deadline = 1 * 1000000 ; // each tx thread will finish within 1ms - uint64_t period = 1 * 10000000; // each tx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB tx thread: sched_setattr failed\n"); - return &eNB_thread_rxtx_status; - } - - LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); - -#else //LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - struct timespec wait; - - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ - /* CPU 1 is reserved for all RX_TX threads */ - /* Enable CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); - -#ifdef CPU_AFFINITY - if (get_nprocs() > 2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } -#endif //CPU_AFFINITY - - /* Check the actual affinity mask assigned to the thread */ - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity,0,sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0, sizeof(sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - } - - LOG_I(HW, "[SCHED][eNB] RXn_TXnp4 thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity ); - -#endif //LOW_LATENCY - - mlockall(MCL_CURRENT | MCL_FUTURE); + sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1); + thread_top_init(thread_name,850000L,1000000L,2000000L); while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - if (pthread_mutex_timedlock(&proc->mutex_rxtx,&wait) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RXn-TXnp4\n"); - exit_fun("nothing to add"); - break; - } - - while (proc->instance_cnt_rxtx < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_rxtx is -1 - pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX\n"); - exit_fun("nothing to add"); - break; - } + if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); @@ -583,33 +624,10 @@ static void* eNB_thread_rxtx( void* param ) { } - - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; - } - - proc->instance_cnt_rxtx--; - - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; - } + if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break; stop_meas( &softmodem_stats_rxtx_sf ); - - if (opp_enabled){ - -#ifdef DEADLINE_SCHEDULER - if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); - } -#endif - } - print_meas_now(&softmodem_stats_rxtx_sf,"eNB_TX_SF",tx_time_file); - } + } // while !oai_exit VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); @@ -795,125 +813,20 @@ static void* eNB_thread_asynch_rxtx( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; - LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + int subframe=0, frame=0; - -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 870000 ; - uint64_t deadline = 1 * 1000000; - uint64_t period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB FH sched_setattr failed\n"); - return &eNB_thread_asynch_rx_status; - } - - LOG_I( HW, "[SCHED] eNB asynch RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); -#else // LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD */ - /* CPU 1 is reserved for all TX threads */ - /* CPU 2..MAX_CPUS is reserved for all RX threads */ - /* Set CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); -#ifdef CPU_AFFINITY - if (get_nprocs() >2) { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_setaffinity_np"); - exit_fun (" Error setting processor affinity :"); - } - } -#endif //CPU_AFFINITY - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); - } - memset(cpu_affinity,0, sizeof(cpu_affinity)); - - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - - policy = SCHED_FIFO ; - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - memset(&sparam, 0 , sizeof (sparam)); - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } - - LOG_I(HW, "[SCHED][eNB] eNB asynch RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity); - - -#endif // DEADLINE_SCHEDULER - - - mlockall(MCL_CURRENT | MCL_FUTURE); + thread_top_init("thread_asynch",870000L,1000000L,1000000L); // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for sync (eNB_thread_asynch_rx)\n"); - pthread_mutex_lock( &sync_mutex ); - - while (sync_var<0) - pthread_cond_wait( &sync_cond, &sync_mutex ); - - pthread_mutex_unlock(&sync_mutex); - - printf( "got sync (eNB_thread_asynch_rx)\n" ); + wait_sync("thread_asynch"); // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe printf( "waiting for devices (eNB_thread_asynch_rx)\n"); - pthread_mutex_lock( &proc->mutex_asynch_rxtx); - while (proc->instance_cnt_asynch_rxtx<0) - pthread_cond_wait( &proc->cond_asynch_rxtx, &proc->mutex_asynch_rxtx ); - - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); printf( "devices ok (eNB_thread_asynch_rx)\n"); @@ -1105,17 +1018,11 @@ void rx_fh_slave(PHY_VARS_eNB *eNB,int *frame,int *subframe) { // it just waits for an external event. The actual rx_rh is handle by the asynchronous RX thread eNB_proc_t *proc=&eNB->proc; - if (pthread_mutex_lock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH Slave\n"); - exit_fun( "error locking mutex" ); - } - - while (proc->instance_cnt_FH < 0) { - pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); - } - proc->instance_cnt_FH++; - - pthread_mutex_unlock( &proc->mutex_FH ); + if (wait_on_condition(&proc->mutex_FH,&proc->cond_FH,&proc->instance_cnt_FH,"rx_fh_slave") < 0) + return; + + release_thread(&proc->mutex_FH,&proc->instance_cnt_FH,"rx_fh_slave"); + } @@ -1219,6 +1126,7 @@ void wakeup_slaves(eNB_proc_t *proc) { * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ + static void* eNB_thread_FH( void* param ) { static int eNB_thread_FH_status; @@ -1227,131 +1135,20 @@ static void* eNB_thread_FH( void* param ) { PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - FILE *rx_time_file = NULL; - char rx_time_name[101]; - int subframe=0, frame=0; - if (opp_enabled == 1) { - snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB"); - rx_time_file = fopen(rx_time_name,"w"); - } // set default return value eNB_thread_FH_status = 0; - MSC_START_USE(); + thread_top_init("eNB_thread_FH",870000,1000000,1000000); -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 870000 ; - uint64_t deadline = 1 * 1000000; - uint64_t period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; + wait_sync("eNB_thread_FH"); - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB FH sched_setattr failed\n"); - return &eNB_thread_FH_status; - } - - LOG_I( HW, "[SCHED] eNB FH deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); -#else // LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD */ - /* CPU 1 is reserved for all TX threads */ - /* CPU 2..MAX_CPUS is reserved for all RX threads */ - /* Set CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); -#ifdef CPU_AFFINITY - if (get_nprocs() >2) { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_setaffinity_np"); - exit_fun (" Error setting processor affinity :"); - } - } -#endif //CPU_AFFINITY - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); - } - memset(cpu_affinity,0, sizeof(cpu_affinity)); - - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - - policy = SCHED_FIFO ; - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - memset(&sparam, 0 , sizeof (sparam)); - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } - - LOG_I(HW, "[SCHED][eNB] FH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity); - - -#endif // DEADLINE_SCHEDULER - - - mlockall(MCL_CURRENT | MCL_FUTURE); - - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for sync (eNB_thread_FH)\n"); - pthread_mutex_lock( &sync_mutex ); - - while (sync_var<0) - pthread_cond_wait( &sync_cond, &sync_mutex ); - - pthread_mutex_unlock(&sync_mutex); - - printf( "got sync (eNB_thread_FH)\n" ); - #if defined(ENABLE_ITTI) if (eNB->node_function < NGFI_RRU_IF5) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif - // Start IF device if any if (eNB->start_if) if (eNB->start_if(eNB) != 0) @@ -1362,7 +1159,7 @@ static void* eNB_thread_FH( void* param ) { if (eNB->start_rf(eNB) != 0) LOG_E(HW,"Could not start the RF device\n"); - // wakeup asnych_rxtx thread + // wakeup asnych_rxtx thread because the devices are ready at this point pthread_mutex_lock(&proc->mutex_asynch_rxtx); proc->instance_cnt_asynch_rxtx=0; pthread_mutex_unlock(&proc->mutex_asynch_rxtx); @@ -1371,10 +1168,8 @@ static void* eNB_thread_FH( void* param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - if (oai_exit) break; - - - // this is to check that we are in synch with the fronthaul timing + // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. + // They are set on the first rx/tx in the underly FH routines. if (subframe==9) { subframe=0; frame++; @@ -1399,30 +1194,7 @@ static void* eNB_thread_FH( void* param ) { if (wakeup_rxtx(proc,&proc->proc_rxtx[proc->subframe_rx&1],fp) < 0) break; - stop_meas( &softmodem_stats_rxtx_sf ); -#ifdef DEADLINE_SCHEDULER - if (opp_enabled){ - if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); - } - } -#endif // DEADLINE_SCHEDULER - print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - - print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - - - if (eNB->node_timing == synch_to_ext_device) { - proc->instance_cnt_FH--; - - if (pthread_mutex_unlock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for FH\n"); - exit_fun( "error unlocking mutex" ); - } - } - + // artifical sleep for very slow fronthaul if (eNB->frame_parms.N_RB_DL==6) rt_sleep_ns(800000LL); } @@ -1444,147 +1216,21 @@ static void* eNB_thread_prach( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id]; - /* - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - */ // set default return value eNB_thread_prach_status = 0; - MSC_START_USE(); - -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 870000 ; - uint64_t deadline = 1 * 1000000; - uint64_t period = 1 * 10000000; // each prach thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB PRACH sched_setattr failed\n"); - return &eNB_thread_prach_status; - } - - LOG_I( HW, "[SCHED] eNB PRACH deadline thread (TID %ld) started on CPU %d\n", 0, gettid(), sched_getcpu() ); -#else // LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD */ - /* CPU 1 is reserved for all TX threads */ - /* CPU 2..MAX_CPUS is reserved for all RX threads */ - /* Set CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); -#ifdef CPU_AFFINITY - if (get_nprocs() >2) { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_setaffinity_np"); - exit_fun (" Error setting processor affinity :"); - } - } -#endif //CPU_AFFINITY - - /* Check the actual affinity mask assigned to the thread */ - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); - } - memset(cpu_affinity,0, sizeof(cpu_affinity)); - - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-2; - - policy = SCHED_FIFO ; - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - memset(&sparam, 0 , sizeof (sparam)); - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } - - LOG_I(HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, IC %d, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(),proc->instance_cnt_prach, - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity); - -#endif // DEADLINE_SCHEDULER - - mlockall(MCL_CURRENT | MCL_FUTURE); + thread_top_init("eNB_thread_prach",500000L,1000000L,20000000L); while (!oai_exit) { if (oai_exit) break; - - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n"); - exit_fun( "error locking mutex" ); - break; - } - while (proc->instance_cnt_prach < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_prach is -1 - pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH\n"); - exit_fun( "error unlocking mutex" ); - break; - } - + if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; prach_procedures(eNB); - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); - exit_fun( "error locking mutex" ); - break; - } - - proc->instance_cnt_prach--; - - if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n"); - exit_fun( "error unlocking mutex" ); - break; - } + if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; } printf( "Exiting eNB thread PRACH\n"); diff --git a/targets/RT/USER/rt_wrapper.c b/targets/RT/USER/rt_wrapper.c index ed9eb4e798..d80de635a6 100644 --- a/targets/RT/USER/rt_wrapper.c +++ b/targets/RT/USER/rt_wrapper.c @@ -78,8 +78,6 @@ void set_latency_target(void) { } -#ifndef RTAI - struct timespec interval, next, now, res; clockid_t clock_id = CLOCK_MONOTONIC; //other options are CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID RTIME rt_get_time_ns (void) @@ -257,12 +255,7 @@ int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned #endif -#else -int rt_sleep_ns(RTIME x) -{ - rt_sleep(nano2count(x)); - return(0); -} -#endif + + diff --git a/targets/RT/USER/rt_wrapper.h b/targets/RT/USER/rt_wrapper.h index d67632054b..ae668945fe 100644 --- a/targets/RT/USER/rt_wrapper.h +++ b/targets/RT/USER/rt_wrapper.h @@ -28,7 +28,7 @@ *******************************************************************************/ /*! \file rt_wrapper.h -* \brief provides a wrapper for the timing function for real-time opeartions depending on weather RTAI is used or not. It also implements an API for the SCHED_DEADLINE kernel scheduler. +* \brief provides a wrapper for the timing function for real-time opeartions. It also implements an API for the SCHED_DEADLINE kernel scheduler. * \author F. Kaltenberger and Navid Nikaein * \date 2013 * \version 0.1 @@ -39,9 +39,8 @@ */ -void set_latency_target(void); -#ifndef RTAI +#define _GNU_SOURCE #include #include #include @@ -52,11 +51,26 @@ void set_latency_target(void); #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "UTIL/LOG/log_extern.h" +#include "msc.h" #define RTIME long long int #define rt_printk printf +void set_latency_target(void); + RTIME rt_get_time_ns (void); int rt_sleep_ns (RTIME x); @@ -115,12 +129,3 @@ int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned #define gettid() syscall(__NR_gettid) // for gettid -#else -#include -#include -#include -#include - -int rt_sleep_ns(RTIME x); - -#endif From f3e084e005fd3bc7562ec5aabdc2adaa3be2c037 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 5 Aug 2016 15:41:34 -0700 Subject: [PATCH 147/206] single-thread. --- openair1/PHY/defs.h | 7 + openair1/SCHED/phy_procedures_lte_eNb.c | 28 ++- targets/RT/USER/lte-enb.c | 245 +++++++++++++++--------- targets/RT/USER/lte-softmodem.c | 16 +- 4 files changed, 190 insertions(+), 106 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 46679c7f7c..8a6c827ff8 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -256,6 +256,8 @@ typedef struct eNB_proc_t_s { int instance_cnt_asynch_rxtx; /// pthread structure for FH processing thread pthread_t pthread_FH; + /// pthread structure for eNB single processing thread + pthread_t pthread_single; /// pthread structure for asychronous RX/TX processing thread pthread_t pthread_asynch_rxtx; /// flag to indicate first RX acquisition @@ -264,12 +266,16 @@ typedef struct eNB_proc_t_s { int first_tx; /// pthread attributes for FH processing thread pthread_attr_t attr_FH; + /// pthread attributes for single eNB processing thread + pthread_attr_t attr_single; /// pthread attributes for prach processing thread pthread_attr_t attr_prach; /// pthread attributes for asynchronous RX thread pthread_attr_t attr_asynch_rxtx; /// scheduling parameters for FH thread struct sched_param sched_param_FH; + /// scheduling parameters for single eNB thread + struct sched_param sched_param_single; /// scheduling parameters for prach thread struct sched_param sched_param_prach; /// scheduling parameters for asynch_rxtx thread @@ -363,6 +369,7 @@ typedef struct PHY_VARS_eNB_s { eNB_proc_t proc; eNB_func_t node_function; eNB_timing_t node_timing; + int single_thread_flag; openair0_rf_map rf_map; int abstraction_flag; void (*do_prach)(struct PHY_VARS_eNB_s *eNB); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 164c21ce21..0623ae02d5 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2583,30 +2583,27 @@ void do_prach(PHY_VARS_eNB *eNB) { void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){ - eNB_proc_t *proc = &eNB->proc; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - - const int subframe = proc->subframe_rx; - const int frame = proc->frame_rx; - + eNB_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + int offset = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1; if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+offset, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+offset, proc->subframe_rx ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 1 ); start_meas(&eNB->phy_proc_rx); - - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe); if (eNB->fep) eNB->fep(eNB); if (eNB->do_prach) eNB->do_prach(eNB); - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 ); } @@ -2623,11 +2620,12 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; const int subframe = proc->subframe_rx; - const int frame = proc->frame_rx; + const int frame = proc->frame_rx; + int offset = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1; if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 ); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe); @@ -3189,7 +3187,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const phy_procedures_emos_eNB_RX(subframe,eNB); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 ); stop_meas(&eNB->phy_proc_rx); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index d55c2d0586..3d6bb61c0e 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -159,14 +159,14 @@ static struct { void exit_fun(const char* s); -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *); +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *,int); void stop_eNB(int nb_inst); -inline void thread_top_init(char *thread_name, - uint64_t runtime, - uint64_t deadline, - uint64_t period) { +static inline void thread_top_init(char *thread_name, + uint64_t runtime, + uint64_t deadline, + uint64_t period) { MSC_START_USE(); @@ -261,7 +261,7 @@ inline void thread_top_init(char *thread_name, } -inline void wait_sync(char *thread_name) { +static inline void wait_sync(char *thread_name) { printf( "waiting for sync (%s)\n",thread_name); pthread_mutex_lock( &sync_mutex ); @@ -275,7 +275,7 @@ inline void wait_sync(char *thread_name) { } -inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { +static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { struct timespec wait; @@ -302,7 +302,7 @@ inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *in return(0); } -inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { +static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { if (pthread_mutex_lock(mutex) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); @@ -461,6 +461,11 @@ void proc_tx_high0(PHY_VARS_eNB *eNB, relaying_type_t r_type, PHY_VARS_RN *rn) { + int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); + phy_procedures_eNB_TX(eNB,proc,r_type,rn); /* we're done, let the next one proceed */ @@ -483,6 +488,7 @@ void proc_tx_high(PHY_VARS_eNB *eNB, relaying_type_t r_type, PHY_VARS_RN *rn) { + // do PHY high proc_tx_high0(eNB,proc,r_type,rn); @@ -517,6 +523,11 @@ void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB, uint32_t symbol_mask, symbol_mask_full; uint16_t packet_type; + int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); + /// **** recv_IF4 of txdataF from RCC **** /// symbol_number = 0; symbol_mask = 0; @@ -532,6 +543,10 @@ void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB, } void proc_tx_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { + int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); /// **** recv_IF5 of txdata from BBU **** /// recv_IF5(eNB, &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL); } @@ -563,6 +578,34 @@ int wait_CCs(eNB_rxtx_proc_t *proc) { return(0); } +static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) { + + start_meas(&softmodem_stats_rxtx_sf); + // **************************************** + // Common RX procedures subframe n + phy_procedures_eNB_common_RX(eNB); + + // UE-specific RX processing for subframe n + if (eNB->proc_uespec_rx) eNB->proc_uespec_rx(eNB, proc, no_relay ); + + // ***************************************** + // TX processing for subframe n+4 + // run PHY TX procedures the one after the other for all CCs to avoid race conditions + // (may be relaxed in the future for performance reasons) + // ***************************************** + if (wait_CCs(proc)<0) return(-1); + + if (oai_exit) return(-1); + + if (eNB->proc_tx) eNB->proc_tx(eNB, proc, no_relay, NULL ); + + if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1); + + stop_meas( &softmodem_stats_rxtx_sf ); + + return(0); +} + /*! * \brief The RX UE-specific and TX thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. @@ -574,7 +617,6 @@ static void* eNB_thread_rxtx( void* param ) { eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; char thread_name[100]; @@ -592,41 +634,12 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); - start_meas( &softmodem_stats_rxtx_sf ); + if (oai_exit) break; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->subframe_rx ); + if (rxtx(eNB,proc,thread_name) < 0) break; - // Common procedures - phy_procedures_eNB_common_RX(eNB); - // Do UE-specific RX processing for subframe n if any - if (eNB->proc_uespec_rx) eNB->proc_uespec_rx(eNB, proc, no_relay ); - - // TX processing for subframe n+4 - if (((fp->frame_type == TDD) && - ((subframe_select(fp,proc->subframe_tx) == SF_DL) || - (subframe_select(fp,proc->subframe_tx) == SF_S))) || - (fp->frame_type == FDD)) { - /* run PHY TX procedures the one after the other for all CCs to avoid race conditions - * (may be relaxed in the future for performance reasons) - */ - - if (wait_CCs(proc)<0) break; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->subframe_tx ); - - if (oai_exit) break; - - if (eNB->proc_tx) eNB->proc_tx(eNB, proc, no_relay, NULL ); - - } - - if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break; - - stop_meas( &softmodem_stats_rxtx_sf ); } // while !oai_exit VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); @@ -1239,6 +1252,84 @@ static void* eNB_thread_prach( void* param ) { return &eNB_thread_prach_status; } +static void* eNB_thread_single( void* param ) { + + static int eNB_thread_single_status; + + eNB_proc_t *proc = (eNB_proc_t*)param; + eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0]; + PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; + + int subframe=0, frame=0; + + // set default return value + eNB_thread_single_status = 0; + + thread_top_init("eNB_thread_single",870000,1000000,1000000); + + wait_sync("eNB_thread_single"); + +#if defined(ENABLE_ITTI) + if (eNB->node_function < NGFI_RRU_IF5) + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); +#endif + + // Start IF device if any + if (eNB->start_if) + if (eNB->start_if(eNB) != 0) + LOG_E(HW,"Could not start the IF device\n"); + + // Start RF device if any + if (eNB->start_rf) + if (eNB->start_rf(eNB) != 0) + LOG_E(HW,"Could not start the RF device\n"); + + // wakeup asnych_rxtx thread because the devices are ready at this point + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx=0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + + // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. + // They are set on the first rx/tx in the underly FH routines. + if (subframe==9) { + subframe=0; + frame++; + frame&=1023; + } else { + subframe++; + } + + + // synchronization on FH interface, acquire signals/data and block + if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe); + else AssertFatal(1==0, "No fronthaul interface : eNB->node_function %d",eNB->node_function); + + T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); + + // At this point, all information for subframe has been received on FH interface + // If this proc is to provide synchronization, do so + wakeup_slaves(proc); + + proc_rxtx->subframe_rx = proc->subframe_rx; + proc_rxtx->frame_rx = proc->frame_rx; + proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10; + proc_rxtx->frame_tx = (proc->frame_rx < 6) ? proc->frame_rx : (proc->frame_rx+1); + + if (rxtx(eNB,proc_rxtx,"eNB_thread_single") < 0) break; + } + + + printf( "Exiting eNB_single thread \n"); + + eNB_thread_single_status = 0; + return &eNB_thread_single_status; + +} + void init_eNB_proc(int inst) { @@ -1247,40 +1338,14 @@ void init_eNB_proc(int inst) { PHY_VARS_eNB *eNB; eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; - + pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL; + for (CC_id=0; CC_idnode_function],eNB_timing[eNB->node_timing]); proc = &eNB->proc; + proc_rxtx = proc->proc_rxtx; -#ifndef DEADLINE_SCHEDULER - /* - pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_TX] setting thread stack size failed\n"); - - pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_RX] setting thread stack size failed\n"); - */ - // set the kernel scheduling policy and priority - proc_rxtx[0].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[0].attr_rxtx, &proc_rxtx[0].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[0].attr_rxtx, SCHED_FIFO); - proc_rxtx[1].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); - - proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_FH, &proc->sched_param_FH); - pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO); - - proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); - pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); - - printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); -#endif proc_rxtx[0].instance_cnt_rxtx = -1; proc_rxtx[1].instance_cnt_rxtx = -1; proc->instance_cnt_prach = -1; @@ -1293,31 +1358,38 @@ void init_eNB_proc(int inst) { pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); + + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); + pthread_cond_init( &proc->cond_prach, NULL); pthread_cond_init( &proc->cond_FH, NULL); pthread_cond_init( &proc->cond_asynch_rxtx, NULL); #ifndef DEADLINE_SCHEDULER - pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); + attr0 = &proc_rxtx[0].attr_rxtx; + attr1 = &proc_rxtx[1].attr_rxtx; + attr_FH = &proc->attr_FH; + attr_prach = &proc->attr_prach; + attr_asynch = &proc->attr_asynch_rxtx; + attr_single = &proc->attr_single; +#endif + + if (eNB->single_thread_flag==0) { + pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] ); + pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc ); + } + else + pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc); + + pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc ); if ((eNB->node_timing == synch_to_other) || (eNB->node_function == NGFI_RRU_IF5) || (eNB->node_function == NGFI_RRU_IF4p5)) - pthread_create( &proc->pthread_asynch_rxtx, &proc->attr_asynch_rxtx, eNB_thread_asynch_rxtx, &eNB->proc ); -#else - pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rxtx, NULL, eNB_thread_asynch_rxtx, &eNB->proc ); - -#endif + pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, eNB_thread_asynch_rxtx, &eNB->proc ); + char name[16]; snprintf( name, sizeof(name), "RXTX0 %d", i ); pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); @@ -1511,7 +1583,7 @@ extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB); extern void eNB_fep_full(PHY_VARS_eNB *eNB); extern void do_prach(PHY_VARS_eNB *eNB); -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params) { +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params,int single_thread_flag) { int CC_id; int inst; @@ -1524,6 +1596,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->node_function = node_function[CC_id]; eNB->node_timing = node_timing[CC_id]; eNB->abstraction_flag = 0; + eNB->single_thread_flag = single_thread_flag; LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]); switch (node_function[CC_id]) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4849e63807..852147f462 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -119,7 +119,7 @@ unsigned short config_frames[4] = {2,9,11,13}; // In lte-enb.c extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg); -extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *); +extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int); extern void stop_eNB(int); extern void kill_eNB_proc(void); @@ -163,14 +163,14 @@ uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, volatile int start_eNB = 0; volatile int start_UE = 0; #endif -volatile int oai_exit = 0; +volatile int oai_exit = 0; -static char UE_flag=0; +static char UE_flag=0; unsigned int mmapped_dma=0; -//static uint8_t eNB_id=0,UE_id=0; +int single_thread_flag=0; static char threequarter_fs=0; @@ -682,6 +682,7 @@ static void get_options (int argc, char **argv) LONG_OPTION_LOOPMEMORY, LONG_OPTION_PHYTEST, LONG_OPTION_MMAPPED_DMA, + LONG_OPTION_SINGLE_THREAD, #if T_TRACER LONG_OPTION_T_PORT, LONG_OPTION_T_NOWAIT, @@ -706,6 +707,7 @@ static void get_options (int argc, char **argv) {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY}, {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST}, {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA}, + {"single-thread", no_argument, NULL, LONG_OPTION_SINGLE_THREAD}, #if T_TRACER {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, @@ -802,6 +804,10 @@ static void get_options (int argc, char **argv) case LONG_OPTION_MMAPPED_DMA: mmapped_dma = 1; break; + + case LONG_OPTION_SINGLE_THREAD: + single_thread_flag = 1; + break; #if T_TRACER case LONG_OPTION_T_PORT: { @@ -1773,7 +1779,7 @@ int main( int argc, char **argv ) // start the main thread if (UE_flag == 1) init_UE(1); - else init_eNB(node_function,node_timing,1,eth_params); + else init_eNB(node_function,node_timing,1,eth_params,single_thread_flag); // Sleep to allow all threads to setup number_of_cards = 1; From 5055e3e6882217935919c5be0d3355b7f0ca8930 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 6 Aug 2016 01:50:08 +0200 Subject: [PATCH 148/206] bugfixing for single-thread and cleanup --- openair1/SCHED/phy_procedures_lte_eNb.c | 5 +++-- targets/RT/USER/lte-enb.c | 26 +++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 0623ae02d5..8d54e92834 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1104,7 +1104,8 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #if defined(SMBV) // counts number of allocations in subframe // there is at least one allocation for PDCCH - uint8_t smbv_alloc_cnt = 1; + uint8_t smbv_alloc_cnt = 1;Exiting eNB thread RXn_TXnp4 + #endif if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_DL)) return; @@ -2587,7 +2588,7 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){ LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; - int offset = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1; + int offset = (eNB->single_thread_flag==1) ? 0 : (subframe&1); if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 3d6bb61c0e..832e35465e 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -464,7 +464,7 @@ void proc_tx_high0(PHY_VARS_eNB *eNB, int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx ); phy_procedures_eNB_TX(eNB,proc,r_type,rn); @@ -526,7 +526,7 @@ void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB, int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx ); /// **** recv_IF4 of txdataF from RCC **** /// symbol_number = 0; @@ -546,7 +546,7 @@ void proc_tx_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_tx ); /// **** recv_IF5 of txdata from BBU **** /// recv_IF5(eNB, &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL); } @@ -1317,7 +1317,7 @@ static void* eNB_thread_single( void* param ) { proc_rxtx->subframe_rx = proc->subframe_rx; proc_rxtx->frame_rx = proc->frame_rx; proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10; - proc_rxtx->frame_tx = (proc->frame_rx < 6) ? proc->frame_rx : (proc->frame_rx+1); + proc_rxtx->frame_tx = (proc->subframe_rx < 6) ? proc->frame_rx : (proc->frame_rx+1); if (rxtx(eNB,proc_rxtx,"eNB_thread_single") < 0) break; } @@ -1391,12 +1391,18 @@ void init_eNB_proc(int inst) { pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, eNB_thread_asynch_rxtx, &eNB->proc ); char name[16]; - snprintf( name, sizeof(name), "RXTX0 %d", i ); - pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); - snprintf( name, sizeof(name), "RXTX1 %d", i ); - pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); - snprintf( name, sizeof(name), "FH %d", i ); - pthread_setname_np( proc->pthread_FH, name ); + if (eNB->single_thread_flag == 0) { + snprintf( name, sizeof(name), "RXTX0 %d", i ); + pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); + snprintf( name, sizeof(name), "RXTX1 %d", i ); + pthread_setname_np( proc_rxtx[1].pthread_rxtx, name ); + snprintf( name, sizeof(name), "FH %d", i ); + pthread_setname_np( proc->pthread_FH, name ); + } + else { + snprintf( name, sizeof(name), " %d", i ); + pthread_setname_np( proc->pthread_single, name ); + } } /* setup PHY proc TX sync mechanism */ From b9e550812a1dcd61d22299640e252d4318306c77 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 6 Aug 2016 19:28:45 +0200 Subject: [PATCH 149/206] addition of handling of UE list MAC when RRC cannot add a UE context. --- openair1/PHY/INIT/lte_init.c | 22 +++++++++---------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 16 ++++++++++++++ openair2/RRC/LITE/rrc_eNB.c | 3 ++- .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 2 +- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 2 +- targets/RT/USER/lte-enb.c | 10 ++++----- 6 files changed, 36 insertions(+), 19 deletions(-) diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 2fa9c36d69..4386ca5d47 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -965,7 +965,7 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, int i,j,k; int eNB_id; - msg("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,frame_parms->nb_antennas_tx,frame_parms->nb_antennas_rx); + printf("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,frame_parms->nb_antennas_tx,frame_parms->nb_antennas_rx); LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", ue->Mod_id+NB_eNB_INST); // many memory allocation sizes are hard coded @@ -1199,8 +1199,8 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p\n",eNB_id,i,common_vars->txdata[eNB_id][i]); - msg("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%d bytes)\n", + printf("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p\n",eNB_id,i,common_vars->txdata[eNB_id][i]); + printf("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%d bytes)\n", eNB_id,i,common_vars->txdataF[eNB_id][i], FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); #endif @@ -1221,8 +1221,8 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti) ); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata[eNB_id][i]); - msg("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i]); + printf("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata[eNB_id][i]); + printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i]); #endif } @@ -1272,7 +1272,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, for (i=0; inb_antennas_rx; i++) { prach_vars->rxsigF[i] = (int16_t*)malloc16_clear( frame_parms->ofdm_symbol_size*12*2*sizeof(int16_t) ); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]); + printf("[openair][LTE_PHY][INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]); #endif } @@ -1282,7 +1282,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, for (i=0; inb_antennas_rx; i++) { prach_vars->prach_ifft[i] = (int16_t*)malloc16_clear(1024*2*sizeof(int16_t)); #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] prach_vars->prach_ifft[%d] = %p\n",i,prach_vars->prach_ifft[i]); + printf("[openair][LTE_PHY][INIT] prach_vars->prach_ifft[%d] = %p\n",i,prach_vars->prach_ifft[i]); #endif } @@ -1365,11 +1365,11 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, if (eNB->dl_precoder_SeNB[eNB_id]) { #ifdef DEBUG_PHY - msg("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] allocated at %p\n",eNB_id, + printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] allocated at %p\n",eNB_id, eNB->dl_precoder_SeNB[eNB_id]); #endif } else { - msg("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] not allocated\n",eNB_id); + printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] not allocated\n",eNB_id); return(-1); } @@ -1378,12 +1378,12 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, if (eNB->dl_precoder_SeNB[eNB_id][j]) { #ifdef DEBUG_PHY - msg("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j, + printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j, eNB->dl_precoder_SeNB[eNB_id][j]); #endif memset(eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(eNB->frame_parms.ofdm_symbol_size)); } else { - msg("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j); + printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j); return(-1); } } //for(j=...nb_antennas_tx diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index b78856b15c..41f8d35327 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -367,6 +367,22 @@ int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) mac_phy_remove_ue(mod_idP,rntiP); + // check if this has an RA process active + RA_TEMPLATE *RA_template; + for (i=0;iRA_active == TRUE) && + (RA_template->rnti == rntiP)){ + RA_template->RA_active=FALSE; + RA_template->generate_rar=0; + RA_template->generate_Msg4=0; + RA_template->wait_ack_Msg4=0; + RA_template->timing_offset=0; + RA_template->RRC_timer=20; + RA_template->rnti = 0; + break; + } + } if (ret == 0) { return (0); } diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index 59ee560b8a..ed1f18db27 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -3880,6 +3880,7 @@ rrc_eNB_decode_ccch( LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Can't create new context for UE random UE identity (0x%" PRIx64 ")\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), random_value); + rrc_mac_remove_ue(ctxt_pP->module_id,ctxt_pP->rnti); return -1; } } @@ -4220,7 +4221,7 @@ rrc_eNB_decode_dcch( #ifdef RRC_MSG_PRINT LOG_F(RRC,"[MSG] RRC Security Mode Complete\n"); - for (i = 0; i < sdu_sizeP; i++) { + for (i = 0; i < sdu_sizeP; i++) eNB->pusch_vars[UE_id]{ LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]); } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index a2187d402f..8144147ea5 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -31,7 +31,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2660000000L; + downlink_frequency = 2645000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 100; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index 0a9b61546b..d2e99a3481 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -31,7 +31,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 50; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 832e35465e..a3dc3179d3 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -876,20 +876,20 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; unsigned int rxs,txs; int i; - + int tx_sfoffset = (eNB->single_thread_flag == 1) ? 3 : 3; if (proc->first_rx==0) { // Transmit TX buffer based on timestamp from RX // printf("trx_write -> USRP TS %llu (sf %d)\n", (proc->timestamp_rx+(3*fp->samples_per_tti)),(proc->subframe_rx+2)%10); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(2*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(tx_sfoffset*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers for (i=0; inb_antennas_tx; i++) - txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti]; + txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+tx_sfoffset)%10)*fp->samples_per_tti]; txs = eNB->rfdevice.trx_write_func(&eNB->rfdevice, - proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, + proc->timestamp_rx+(tx_sfoffset*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance, txp, fp->samples_per_tti, fp->nb_antennas_tx, @@ -1317,7 +1317,7 @@ static void* eNB_thread_single( void* param ) { proc_rxtx->subframe_rx = proc->subframe_rx; proc_rxtx->frame_rx = proc->frame_rx; proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10; - proc_rxtx->frame_tx = (proc->subframe_rx < 6) ? proc->frame_rx : (proc->frame_rx+1); + proc_rxtx->frame_tx = (proc->subframe_rx < 6) ? proc->frame_rx : (proc->frame_rx+1)&1023; if (rxtx(eNB,proc_rxtx,"eNB_thread_single") < 0) break; } From a483534f9ab32ce03a46efa24890f759c9fd96c6 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 6 Aug 2016 20:01:29 +0200 Subject: [PATCH 150/206] rru configuration files for if4p5 (50/100 PRBs). rru gtkwave configuration files. --- .../rru.band7.tm1.if4p5.100PRB.usrpb210.conf | 190 ++++++++++++++++++ .../rru.band7.tm1.if4p5.50PRB.usrpb210.conf | 190 ++++++++++++++++++ targets/RT/USER/rru_if4p5_usrp.gtkw | 160 +++++++++++++++ targets/RT/USER/rru_if5_usrp.gtkw | 161 +++++++++++++++ 4 files changed, 701 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf create mode 100644 targets/RT/USER/rru_if4p5_usrp.gtkw create mode 100644 targets/RT/USER/rru_if5_usrp.gtkw diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf new file mode 100644 index 0000000000..b1c4298104 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.100PRB.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "34:e6:d7:3c:ae:fc"; + local_address = "74:d4:35:cc:8d:15"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf new file mode 100644 index 0000000000..831010a89a --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.band7.tm1.if4p5.50PRB.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RRU_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth3"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "34:e6:d7:3c:ae:fc"; + local_address = "74:d4:35:cc:8d:15"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/RT/USER/rru_if4p5_usrp.gtkw b/targets/RT/USER/rru_if4p5_usrp.gtkw new file mode 100644 index 0000000000..df8de754db --- /dev/null +++ b/targets/RT/USER/rru_if4p5_usrp.gtkw @@ -0,0 +1,160 @@ +[*] +[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI +[*] Mon Aug 1 18:43:22 2016 +[*] +[dumpfile] "/tmp/openair_dump_eNB.vcd" +[dumpfile_mtime] "Mon Aug 1 18:41:49 2016" +[dumpfile_size] 22622 +[savefile] "/home/papillon/openairinterface5g/targets/RT/USER/rru_if4p5_usrp.gtkw" +[timestart] 0 +[size] 1301 716 +[pos] 309 0 +*-19.793451 29983948856 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[sst_width] 284 +[signals_width] 262 +[sst_expanded] 1 +[sst_vpaned_height] 294 +@28 +functions.trx_read +functions.trx_write +functions.trx_write_if +functions.send_if4 +functions.trx_read_if +@29 +functions.recv_if4 +@24 +variables.trx_ts[63:0] +variables.trx_tst[63:0] +@28 +functions.eNB_thread_rxtx0 +@24 +variables.frame_number_RX0_eNB[63:0] +variables.subframe_number_RX0_eNB[63:0] +variables.frame_number_TX0_eNB[63:0] +variables.subframe_number_TX0_eNB[63:0] +@28 +functions.eNB_thread_rxtx1 +@24 +variables.frame_number_RX1_eNB[63:0] +variables.subframe_number_RX1_eNB[63:0] +variables.frame_number_TX1_eNB[63:0] +variables.subframe_number_TX1_eNB[63:0] +@28 +functions.phy_enb_sfgen +functions.phy_eNB_slot_fep +functions.phy_enb_prach_rx +@24 +variables.dci_info[63:0] +variables.ue0_BO[63:0] +@420 +variables.ue0_BSR[63:0] +variables.ue0_timing_advance[63:0] +@28 +functions.macxface_initiate_ra_proc +functions.macxface_terminate_ra_proc +functions.phy_enb_ulsch_msg3 +functions.macxface_SR_indication +@420 +variables.ue0_SR_ENERGY[63:0] +variables.ue0_SR_THRES[63:0] +@28 +functions.phy_enb_ulsch_decoding0 +@24 +variables.ue0_res0[63:0] +@420 +variables.ue0_rssi0[63:0] +variables.ue0_MCS0[63:0] +variables.ue0_RB0[63:0] +@24 +variables.ue0_ROUND0[63:0] +variables.ue0_SFN0[63:0] +@28 +functions.phy_enb_ulsch_decoding1 +@24 +variables.ue0_res1[63:0] +@420 +variables.ue0_rssi1[63:0] +variables.ue0_MCS1[63:0] +variables.ue0_RB1[63:0] +@24 +variables.ue0_ROUND1[63:0] +variables.ue0_SFN1[63:0] +@28 +functions.phy_enb_ulsch_decoding2 +@24 +variables.ue0_res2[63:0] +@420 +variables.ue0_rssi2[63:0] +variables.ue0_MCS2[63:0] +variables.ue0_RB2[63:0] +@24 +variables.ue0_ROUND2[63:0] +variables.ue0_SFN2[63:0] +@28 +functions.phy_enb_ulsch_decoding3 +@24 +variables.ue0_res3[63:0] +@420 +variables.ue0_rssi3[63:0] +variables.ue0_MCS3[63:0] +variables.ue0_RB3[63:0] +@24 +variables.ue0_ROUND3[63:0] +variables.ue0_SFN3[63:0] +@28 +functions.phy_enb_ulsch_decoding4 +@420 +variables.ue0_rssi4[63:0] +@24 +variables.ue0_res4[63:0] +@420 +variables.ue0_MCS4[63:0] +variables.ue0_RB4[63:0] +@24 +variables.ue0_ROUND4[63:0] +variables.ue0_SFN4[63:0] +@28 +functions.phy_enb_ulsch_decoding5 +@24 +variables.ue0_res5[63:0] +@420 +variables.ue0_rssi5[63:0] +variables.ue0_MCS5[63:0] +variables.ue0_RB5[63:0] +@24 +variables.ue0_ROUND5[63:0] +variables.ue0_SFN5[63:0] +@28 +functions.phy_enb_ulsch_decoding6 +@24 +variables.ue0_res6[63:0] +@420 +variables.ue0_rssi6[63:0] +variables.ue0_MCS6[63:0] +variables.ue0_RB6[63:0] +@24 +variables.ue0_ROUND6[63:0] +variables.ue0_SFN6[63:0] +@28 +functions.phy_enb_ulsch_decoding7 +@24 +variables.ue0_res7[63:0] +@420 +variables.ue0_rssi7[63:0] +variables.ue0_MCS7[63:0] +variables.ue0_RB7[63:0] +@24 +variables.ue0_ROUND7[63:0] +variables.ue0_SFN7[63:0] +@28 +functions.phy_enb_prach_rx +functions.phy_eNB_dlsch_encoding +functions.phy_eNB_dlsch_modulation +functions.phy_eNB_dlsch_scrambling +functions.phy_enb_pdcch_tx +functions.phy_enb_rs_tx +functions.rrc_mac_config_req +functions.rlc_data_req +functions.udp_enb_task +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/targets/RT/USER/rru_if5_usrp.gtkw b/targets/RT/USER/rru_if5_usrp.gtkw new file mode 100644 index 0000000000..ff0c116434 --- /dev/null +++ b/targets/RT/USER/rru_if5_usrp.gtkw @@ -0,0 +1,161 @@ +[*] +[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI +[*] Sun Jul 31 17:45:23 2016 +[*] +[dumpfile] "/tmp/openair_dump_eNB.vcd" +[dumpfile_mtime] "Sun Jul 31 17:44:51 2016" +[dumpfile_size] 26766405 +[savefile] "/home/papillon/openairinterface5g/targets/RT/USER/rru_if5_usrp.gtkw" +[timestart] 0 +[size] 1301 716 +[pos] 309 0 +*-19.793451 29983948856 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[sst_width] 284 +[signals_width] 262 +[sst_expanded] 1 +[sst_vpaned_height] 294 +@28 +functions.trx_read +functions.trx_write +functions.send_if5 +@29 +functions.trx_write_if +@28 +functions.recv_if5 +functions.trx_read_if +@24 +variables.trx_ts[63:0] +variables.trx_tst[63:0] +@28 +functions.eNB_thread_rxtx0 +@24 +variables.frame_number_RX0_eNB[63:0] +variables.subframe_number_RX0_eNB[63:0] +variables.frame_number_TX0_eNB[63:0] +variables.subframe_number_TX0_eNB[63:0] +@28 +functions.eNB_thread_rxtx1 +@24 +variables.frame_number_RX1_eNB[63:0] +variables.subframe_number_RX1_eNB[63:0] +variables.frame_number_TX1_eNB[63:0] +variables.subframe_number_TX1_eNB[63:0] +@28 +functions.phy_enb_sfgen +functions.phy_eNB_slot_fep +functions.phy_enb_prach_rx +@24 +variables.dci_info[63:0] +variables.ue0_BO[63:0] +@420 +variables.ue0_BSR[63:0] +variables.ue0_timing_advance[63:0] +@28 +functions.macxface_initiate_ra_proc +functions.macxface_terminate_ra_proc +functions.phy_enb_ulsch_msg3 +functions.macxface_SR_indication +@420 +variables.ue0_SR_ENERGY[63:0] +variables.ue0_SR_THRES[63:0] +@28 +functions.phy_enb_ulsch_decoding0 +@24 +variables.ue0_res0[63:0] +@420 +variables.ue0_rssi0[63:0] +variables.ue0_MCS0[63:0] +variables.ue0_RB0[63:0] +@24 +variables.ue0_ROUND0[63:0] +variables.ue0_SFN0[63:0] +@28 +functions.phy_enb_ulsch_decoding1 +@24 +variables.ue0_res1[63:0] +@420 +variables.ue0_rssi1[63:0] +variables.ue0_MCS1[63:0] +variables.ue0_RB1[63:0] +@24 +variables.ue0_ROUND1[63:0] +variables.ue0_SFN1[63:0] +@28 +functions.phy_enb_ulsch_decoding2 +@24 +variables.ue0_res2[63:0] +@420 +variables.ue0_rssi2[63:0] +variables.ue0_MCS2[63:0] +variables.ue0_RB2[63:0] +@24 +variables.ue0_ROUND2[63:0] +variables.ue0_SFN2[63:0] +@28 +functions.phy_enb_ulsch_decoding3 +@24 +variables.ue0_res3[63:0] +@420 +variables.ue0_rssi3[63:0] +variables.ue0_MCS3[63:0] +variables.ue0_RB3[63:0] +@24 +variables.ue0_ROUND3[63:0] +variables.ue0_SFN3[63:0] +@28 +functions.phy_enb_ulsch_decoding4 +@420 +variables.ue0_rssi4[63:0] +@24 +variables.ue0_res4[63:0] +@420 +variables.ue0_MCS4[63:0] +variables.ue0_RB4[63:0] +@24 +variables.ue0_ROUND4[63:0] +variables.ue0_SFN4[63:0] +@28 +functions.phy_enb_ulsch_decoding5 +@24 +variables.ue0_res5[63:0] +@420 +variables.ue0_rssi5[63:0] +variables.ue0_MCS5[63:0] +variables.ue0_RB5[63:0] +@24 +variables.ue0_ROUND5[63:0] +variables.ue0_SFN5[63:0] +@28 +functions.phy_enb_ulsch_decoding6 +@24 +variables.ue0_res6[63:0] +@420 +variables.ue0_rssi6[63:0] +variables.ue0_MCS6[63:0] +variables.ue0_RB6[63:0] +@24 +variables.ue0_ROUND6[63:0] +variables.ue0_SFN6[63:0] +@28 +functions.phy_enb_ulsch_decoding7 +@24 +variables.ue0_res7[63:0] +@420 +variables.ue0_rssi7[63:0] +variables.ue0_MCS7[63:0] +variables.ue0_RB7[63:0] +@24 +variables.ue0_ROUND7[63:0] +variables.ue0_SFN7[63:0] +@28 +functions.phy_enb_prach_rx +functions.phy_eNB_dlsch_encoding +functions.phy_eNB_dlsch_modulation +functions.phy_eNB_dlsch_scrambling +functions.phy_enb_pdcch_tx +functions.phy_enb_rs_tx +functions.rrc_mac_config_req +functions.rlc_data_req +functions.udp_enb_task +[pattern_trace] 1 +[pattern_trace] 0 From f000cec33f958a16b4fc6074e7251d0dc5a2a2c9 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 6 Aug 2016 20:47:50 +0200 Subject: [PATCH 151/206] configuration file changes. --- openair1/SCHED/phy_procedures_lte_eNb.c | 6 ++++-- .../GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf | 2 +- ...1.if4p5.usrpb210.conf => rcc.band7.tm1.if4p5.25PRB.conf} | 0 targets/RT/USER/lte-enb.c | 3 +-- 4 files changed, 6 insertions(+), 5 deletions(-) rename targets/PROJECTS/GENERIC-LTE-EPC/CONF/{rcc.band7.tm1.if4p5.usrpb210.conf => rcc.band7.tm1.if4p5.25PRB.conf} (100%) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 8d54e92834..52820350f4 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1101,6 +1101,8 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL; + int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; + #if defined(SMBV) // counts number of allocations in subframe // there is at least one allocation for PDCCH @@ -1110,7 +1112,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_DL)) return; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1); start_meas(&eNB->phy_proc_tx); T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe)); @@ -1396,7 +1398,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, phy_procedures_emos_eNB_TX(subframe, eNB); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0); stop_meas(&eNB->phy_proc_tx); } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index 0a9b61546b..d2e99a3481 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -31,7 +31,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 50; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.conf similarity index 100% rename from targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.usrpb210.conf rename to targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.conf diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 832e35465e..e5b7e25623 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1317,8 +1317,7 @@ static void* eNB_thread_single( void* param ) { proc_rxtx->subframe_rx = proc->subframe_rx; proc_rxtx->frame_rx = proc->frame_rx; proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10; - proc_rxtx->frame_tx = (proc->subframe_rx < 6) ? proc->frame_rx : (proc->frame_rx+1); - + proc_rxtx->frame_tx = (proc->subframe_rx < 6) ? proc->frame_rx : (proc->frame_rx+1)&1023; if (rxtx(eNB,proc_rxtx,"eNB_thread_single") < 0) break; } From f52cbeeb9597312e4ca1afc37290225ca6656e8f Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 7 Aug 2016 06:00:54 -0700 Subject: [PATCH 152/206] update of ulsim to use phy_procedures --- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 88 ++-- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 50 +- openair1/SCHED/phy_procedures_lte_ue.c | 2 +- openair1/SIMULATION/LTE_PHY/ulsim.c | 448 +++++++----------- 5 files changed, 253 insertions(+), 337 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index d673e12d38..dbe06ea6ba 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -44,7 +44,7 @@ #include "PHY/vars.h" #endif #include "assertions.h" - + //#define DEBUG_DCI uint32_t localRIV2alloc_LUT6[32]; @@ -1216,7 +1216,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - // msg("DCI: Setting subframe_tx for subframe %d\n",subframe); + // printf("DCI: Setting subframe_tx for subframe %d\n",subframe); dlsch[0]->subframe_tx[subframe] = 1; conv_rballoc(rah, @@ -4467,7 +4467,7 @@ int generate_ue_dlsch_params_from_dci(int frame, dlsch0_harq->Qm = (mcs-28)<<1; else LOG_E(PHY,"invalid mcs %d\n",mcs); - // msg("test: MCS %d, NPRB %d, TBS %d\n",mcs,NPRB,dlsch0_harq->TBS); + // printf("test: MCS %d, NPRB %d, TBS %d\n",mcs,NPRB,dlsch0_harq->TBS); dlsch[0]->current_harq_pid = harq_pid; dlsch[0]->active = 1; @@ -4735,7 +4735,7 @@ int generate_ue_dlsch_params_from_dci(int frame, dlsch[0]->g_pucch += delta_PUCCH_lut[TPC&3]; /* if (dlsch0_harq->mcs>20) { - msg("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs); + printf("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs); return(-1); } */ @@ -5411,7 +5411,7 @@ int generate_ue_dlsch_params_from_dci(int frame, /* if (dlsch0_harq->mcs>20) { - msg("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs); + printf("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs); return(-1); } */ @@ -5437,7 +5437,7 @@ int generate_ue_dlsch_params_from_dci(int frame, // Fix this tpmi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tpmi; - // msg("ue: tpmi %d\n",tpmi); + // printf("ue: tpmi %d\n",tpmi); switch (tpmi) { case 0 : @@ -5556,9 +5556,9 @@ uint8_t subframe2harq_pid(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t /* #ifdef DEBUG_DCI if (frame_parms->frame_type == TDD) - msg("dci_tools.c: subframe2_harq_pid, subframe %d for TDD configuration %d\n",subframe,frame_parms->tdd_config); + printf("dci_tools.c: subframe2_harq_pid, subframe %d for TDD configuration %d\n",subframe,frame_parms->tdd_config); else - msg("dci_tools.c: subframe2_harq_pid, subframe %d for FDD \n",subframe); + printf("dci_tools.c: subframe2_harq_pid, subframe %d for FDD \n",subframe); #endif */ if (frame_parms->frame_type == FDD) { @@ -5734,7 +5734,7 @@ uint16_t quantize_subband_pmi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,int nb_subba pmivect |= (pmiq<<(2*i)); } else { // This needs to be done properly!!! - msg("PMI feedback for rank>1 not supported!\n"); + printf("PMI feedback for rank>1 not supported!\n"); pmivect = 0; } } @@ -5928,7 +5928,7 @@ uint32_t fill_subband_cqi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t trans_mo void fill_CQI(LTE_UE_ULSCH_t *ulsch,PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t harq_pid,int N_RB_DL,uint16_t rnti, uint8_t trans_mode, double sinr_eff) { - // msg("[PHY][UE] Filling CQI for eNB %d, meas->wideband_cqi_tot[%d] %d\n", + // printf("[PHY][UE] Filling CQI for eNB %d, meas->wideband_cqi_tot[%d] %d\n", // eNB_id,eNB_id,meas->wideband_cqi_tot[eNB_id]); double sinr_tmp; uint8_t *o = ulsch->o; @@ -6288,7 +6288,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, RIV_max = RIV_max25; ulsch->harq_processes[harq_pid]->first_rb = RIV2first_rb_LUT25[rballoc]; ulsch->harq_processes[harq_pid]->nb_rb = RIV2nb_rb_LUT25[rballoc]; - // printf("***********rballoc %d, first_rb %d, nb_rb %d\n",rballoc,ulsch->harq_processes[harq_pid]->first_rb,ulsch->harq_processes[harq_pid]->nb_rb); + // printf("***********rballoc %d, first_rb %d, nb_rb %d (dci %p)\n",rballoc,ulsch->harq_processes[harq_pid]->first_rb,ulsch->harq_processes[harq_pid]->nb_rb,dci_pdu); break; case 50: @@ -6409,7 +6409,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, ulsch->rnti = rnti; } - // msg("[PHY][UE] DCI format 0: harq_pid %d nb_rb %d, rballoc %d\n",harq_pid,ulsch->harq_processes[harq_pid]->nb_rb, + // printf("[PHY][UE] DCI format 0: harq_pid %d nb_rb %d, rballoc %d\n",harq_pid,ulsch->harq_processes[harq_pid]->nb_rb, // ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->rballoc); //Mapping of cyclic shift field in DCI format0 to n_DMRS2 (3GPP 36.211, Table 5.5.2.1.1-1) if(cshift == 0) @@ -7007,21 +7007,21 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift; #ifdef DEBUG_DCI - msg("Format 0 DCI : ulsch (ue): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); - msg("Format 0 DCI :ulsch (ue): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb); - msg("Format 0 DCI :ulsch (ue): harq_pid %d\n",harq_pid); - msg("Format 0 DCI :ulsch (ue): round %d\n",ulsch->harq_processes[harq_pid]->round); - msg("Format 0 DCI :ulsch (ue): TBS %d\n",ulsch->harq_processes[harq_pid]->TBS); - msg("Format 0 DCI :ulsch (ue): mcs %d\n",ulsch->harq_processes[harq_pid]->mcs); - msg("Format 0 DCI :ulsch (ue): O %d\n",ulsch->O); + printf("Format 0 DCI : ulsch (ue): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); + printf("Format 0 DCI :ulsch (ue): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb); + printf("Format 0 DCI :ulsch (ue): harq_pid %d\n",harq_pid); + printf("Format 0 DCI :ulsch (ue): round %d\n",ulsch->harq_processes[harq_pid]->round); + printf("Format 0 DCI :ulsch (ue): TBS %d\n",ulsch->harq_processes[harq_pid]->TBS); + printf("Format 0 DCI :ulsch (ue): mcs %d\n",ulsch->harq_processes[harq_pid]->mcs); + printf("Format 0 DCI :ulsch (ue): O %d\n",ulsch->O); if (frame_parms->frame_type == TDD) - msg("Format 0 DCI :ulsch (ue): O_ACK/DAI %d/%d\n",ulsch->harq_processes[harq_pid]->O_ACK,dai); + printf("Format 0 DCI :ulsch (ue): O_ACK/DAI %d/%d\n",ulsch->harq_processes[harq_pid]->O_ACK,dai); else - msg("Format 0 DCI :ulsch (ue): O_ACK %d\n",ulsch->harq_processes[harq_pid]->O_ACK); + printf("Format 0 DCI :ulsch (ue): O_ACK %d\n",ulsch->harq_processes[harq_pid]->O_ACK); - msg("Format 0 DCI :ulsch (ue): Nsymb_pusch %d\n",ulsch->Nsymb_pusch); - msg("Format 0 DCI :ulsch (ue): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2); + printf("Format 0 DCI :ulsch (ue): Nsymb_pusch %d\n",ulsch->Nsymb_pusch); + printf("Format 0 DCI :ulsch (ue): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2); #else UNUSED_VARIABLE(dai); #endif @@ -7066,7 +7066,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, // uint32_t type; #ifdef DEBUG_DCI - LOG_D(PHY,"filling eNB ulsch params for rnti %x, dci format %d, dci %x, subframe %d\n", + printf("filling eNB ulsch params for rnti %x, dci format %d, dci %x, subframe %d\n", rnti,dci_format,*(uint32_t*)dci_pdu,subframe); #endif @@ -7200,7 +7200,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, } #ifdef DEBUG_DCI - LOG_D(PHY,"generate_eNB_ulsch_params_from_dci: subframe %d, rnti %x,harq_pid %d,cqi_req %d\n",subframe,rnti,harq_pid,cqi_req); + printf("generate_eNB_ulsch_params_from_dci: subframe %d, rnti %x,harq_pid %d,cqi_req %d\n",subframe,rnti,harq_pid,cqi_req); #endif ulsch->harq_processes[harq_pid]->dci_alloc = 1; @@ -7641,15 +7641,15 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, //ulsch->n_DMRS2 = cshift; #ifdef DEBUG_DCI - msg("ulsch (eNB): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); - msg("ulsch (eNB): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb); - msg("ulsch (eNB): harq_pid %d\n",harq_pid); - msg("ulsch (eNB): round %d\n",ulsch->harq_processes[harq_pid]->round); - msg("ulsch (eNB): TBS %d\n",ulsch->harq_processes[harq_pid]->TBS); - msg("ulsch (eNB): mcs %d\n",ulsch->harq_processes[harq_pid]->mcs); - msg("ulsch (eNB): Or1 %d\n",ulsch->harq_processes[harq_pid]->Or1); - msg("ulsch (eNB): Nsymb_pusch %d\n",ulsch->harq_processes[harq_pid]->Nsymb_pusch); - msg("ulsch (eNB): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2); + printf("ulsch (eNB): NBRB %d\n",ulsch->harq_processes[harq_pid]->nb_rb); + printf("ulsch (eNB): first_rb %d\n",ulsch->harq_processes[harq_pid]->first_rb); + printf("ulsch (eNB): harq_pid %d\n",harq_pid); + printf("ulsch (eNB): round %d\n",ulsch->harq_processes[harq_pid]->round); + printf("ulsch (eNB): TBS %d\n",ulsch->harq_processes[harq_pid]->TBS); + printf("ulsch (eNB): mcs %d\n",ulsch->harq_processes[harq_pid]->mcs); + printf("ulsch (eNB): Or1 %d\n",ulsch->harq_processes[harq_pid]->Or1); + printf("ulsch (eNB): Nsymb_pusch %d\n",ulsch->harq_processes[harq_pid]->Nsymb_pusch); + printf("ulsch (eNB): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2); #else UNUSED_VARIABLE(dai); #endif @@ -7782,7 +7782,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id) break; default: - msg("Problem in SINR Calculation for TM5 \n"); + printf("Problem in SINR Calculation for TM5 \n"); break; }//switch(qq) }//a_rx @@ -7848,7 +7848,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id) break; default: - msg("Problem in SINR Calculation for TM6 \n"); + printf("Problem in SINR Calculation for TM6 \n"); break; }//switch(qq) }//a_rx @@ -7860,7 +7860,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id) break; default: - msg("Problem in SINR Calculation for CQI \n"); + printf("Problem in SINR Calculation for CQI \n"); break; } @@ -7929,7 +7929,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id) 3) + p_qam64[5]*pow(I_qam64_avg,2) + p_qam64[6]*I_qam64_avg + p_qam64[7]); sinr_eff = cmax3(sinr_eff_qpsk,sinr_eff_qam16,sinr_eff_qam64); - //msg("SINR_Eff = %e\n",sinr_eff); + //printf("SINR_Eff = %e\n",sinr_eff); return(sinr_eff); } @@ -7948,20 +7948,20 @@ main() rah = 0; rballoc = 0x1fff; - msg("rballoc 0 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + printf("rballoc 0 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); rah = 1; rballoc = 0x1678; - msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); rballoc = 0xfffc; - msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); rballoc = 0xfffd; - msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); rballoc = 0xffff; - msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); rballoc = 0xfffe; - msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); + printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc)); } #endif diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 16cd847016..e673513f49 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -739,7 +739,7 @@ void ulsch_extract_rbs_single(int32_t **rxdataF, nb_rb1 = cmin(cmax((int)(frame_parms->N_RB_UL) - (int)(2*first_rb),(int)0),(int)(2*nb_rb)); // 2 times no. RBs before the DC nb_rb2 = 2*nb_rb - nb_rb1; // 2 times no. RBs after the DC - + #ifdef DEBUG_ULSCH printf("ulsch_extract_rbs_single: 2*nb_rb1 = %d, 2*nb_rb2 = %d\n",nb_rb1,nb_rb2); #endif diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 52820350f4..6053a151a4 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2346,10 +2346,11 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p int ret=0; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + if (eNB->ulsch[UE_id]==NULL) return; + num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups; - - if ((eNB->ulsch[UE_id]) && - (num_active_cba_groups > 0) && + + if ((num_active_cba_groups > 0) && (eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]>0) && (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1)) { rnti=0; @@ -2462,7 +2463,8 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p UE_id % eNB->ulsch[UE_id]->num_active_cba_groups, eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]); // detect if there is a CBA collision - if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) { + if ((eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) && + (eNB->mac_enabled==1)) { mac_xface->rx_sdu(eNB->Mod_id, eNB->CC_id, frame,subframe, @@ -2502,6 +2504,7 @@ void eNB_fep_full(PHY_VARS_eNB *eNB) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); + start_meas(&eNB->ofdm_demod_stats); remove_7_5_kHz(eNB,proc->subframe_rx<<1); remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1)); for (l=0; lsymbols_per_tti/2; l++) { @@ -2520,6 +2523,7 @@ void eNB_fep_full(PHY_VARS_eNB *eNB) { 0 ); } + stop_meas(&eNB->ofdm_demod_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0); @@ -2626,10 +2630,11 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const const int frame = proc->frame_rx; int offset = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1; + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 ); - start_meas(&eNB->phy_proc_rx); + #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe); #endif @@ -2920,14 +2925,15 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const eNB->UE_stats[i].ulsch_consecutive_errors++; // indicate error to MAC - mac_xface->rx_sdu(eNB->Mod_id, - eNB->CC_id, - frame,subframe, - eNB->ulsch[i]->rnti, - NULL, - 0, - harq_pid, - &eNB->ulsch[i]->Msg3_flag); + if (eNB->mac_enabled == 1) + mac_xface->rx_sdu(eNB->Mod_id, + eNB->CC_id, + frame,subframe, + eNB->ulsch[i]->rnti, + NULL, + 0, + harq_pid, + &eNB->ulsch[i]->Msg3_flag); } } } // ulsch in error @@ -2987,15 +2993,15 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n", eNB->Mod_id, frame,harq_pid,i); - - mac_xface->rx_sdu(eNB->Mod_id, - eNB->CC_id, - frame,subframe, - eNB->ulsch[i]->rnti, - eNB->ulsch[i]->harq_processes[harq_pid]->b, - eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3, - harq_pid, - &eNB->ulsch[i]->Msg3_flag); + if (eNB->mac_enabled) + mac_xface->rx_sdu(eNB->Mod_id, + eNB->CC_id, + frame,subframe, + eNB->ulsch[i]->rnti, + eNB->ulsch[i]->harq_processes[harq_pid]->b, + eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3, + harq_pid, + &eNB->ulsch[i]->Msg3_flag); // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI) if (eNB->ulsch[i]->Msg3_flag == 0 ) { diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 38609c6f43..2612302d54 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -828,7 +828,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB int i; int aa; int tx_amp; - uint8_t ulsch_input_buffer[2700] __attribute__ ((aligned(16))); + uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32))); uint8_t access_mode; // get harq_pid from subframe relationship diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 135ad59037..47565f4e0c 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -85,6 +85,93 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ + +void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mcs,int ndi,int cqi_flag) { + + switch (eNB->frame_parms.N_RB_UL) { + case 6: + break; + + case 25: + if (eNB->frame_parms.frame_type == TDD) { + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->type = 0; + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + //printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci); + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->mcs = mcs; + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->ndi = ndi; + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->TPC = 0; + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->cqi_req = cqi_flag&1; + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->cshift = 0; + ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->dai = 1; + } else { + ((DCI0_5MHz_FDD_t*)UL_dci)->type = 0; + ((DCI0_5MHz_FDD_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + // printf("nb_rb %d/%d, rballoc %d (dci %x) (dcip %p)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci,UL_dci); + ((DCI0_5MHz_FDD_t*)UL_dci)->mcs = mcs; + ((DCI0_5MHz_FDD_t*)UL_dci)->ndi = ndi; + ((DCI0_5MHz_FDD_t*)UL_dci)->TPC = 0; + ((DCI0_5MHz_FDD_t*)UL_dci)->cqi_req = cqi_flag&1; + ((DCI0_5MHz_FDD_t*)UL_dci)->cshift = 0; + } + + break; + + case 50: + if (eNB->frame_parms.frame_type == TDD) { + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->type = 0; + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci); + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->mcs = mcs; + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->ndi = ndi; + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->TPC = 0; + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->cqi_req = cqi_flag&1; + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->cshift = 0; + ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->dai = 1; + } else { + ((DCI0_10MHz_FDD_t*)UL_dci)->type = 0; + ((DCI0_10MHz_FDD_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + //printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci); + ((DCI0_10MHz_FDD_t*)UL_dci)->mcs = mcs; + ((DCI0_10MHz_FDD_t*)UL_dci)->ndi = ndi; + ((DCI0_10MHz_FDD_t*)UL_dci)->TPC = 0; + ((DCI0_10MHz_FDD_t*)UL_dci)->cqi_req = cqi_flag&1; + ((DCI0_10MHz_FDD_t*)UL_dci)->cshift = 0; + } + + break; + + case 100: + if (eNB->frame_parms.frame_type == TDD) { + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->type = 0; + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_TDD_1_6_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci); + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->mcs = mcs; + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->ndi = ndi; + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->TPC = 0; + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->cqi_req = cqi_flag&1; + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->cshift = 0; + ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->dai = 1; + } else { + ((DCI0_20MHz_FDD_t*)UL_dci)->type = 0; + ((DCI0_20MHz_FDD_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 + // printf("nb_rb %d/%d, rballoc %d (dci %x) (UL_dci %p)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_FDD_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci,(void*)UL_dci); + ((DCI0_20MHz_FDD_t*)UL_dci)->mcs = mcs; + ((DCI0_20MHz_FDD_t*)UL_dci)->ndi = ndi; + ((DCI0_20MHz_FDD_t*)UL_dci)->TPC = 0; + ((DCI0_20MHz_FDD_t*)UL_dci)->cqi_req = cqi_flag&1; + ((DCI0_20MHz_FDD_t*)UL_dci)->cshift = 0; + } + + break; + + default: + break; + } + +} + +extern void eNB_fep_full(PHY_VARS_eNB *eNB); + int main(int argc, char **argv) { @@ -190,6 +277,8 @@ int main(int argc, char **argv) int nb_rb_set = 0; int threequarter_fs=0; + int ndi; + opp_enabled=1; // to enable the time meas cpu_freq_GHz = (double)get_cpu_freq_GHz(); @@ -488,16 +577,6 @@ int main(int argc, char **argv) snr1 = snr0+snr_int; printf("SNR0 %f, SNR1 %f\n",snr0,snr1); - /* - txdataF = (int **)malloc16(2*sizeof(int*)); - txdataF[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - txdataF[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - - txdata = (int **)malloc16(2*sizeof(int*)); - txdata[0] = (int *)malloc16(FRAME_LENGTH_BYTES); - txdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES); - */ - frame_parms = &eNB->frame_parms; txdata = UE->common_vars.txdata; @@ -539,32 +618,6 @@ int main(int argc, char **argv) } } - /* - if(abstx) { - sprintf(fperen_name,"ULchan_estims_F_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz); - fperen = fopen(fperen_name,"a+"); - fprintf(fperen,"chest_f = ["); - fclose(fperen); - - sprintf(fmageren_name,"ChanMag_F_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz); - fmageren = fopen(fmageren_name,"a+"); - fprintf(fmageren,"mag_f = ["); - fclose(fmageren); - - sprintf(flogeren_name,"Log2Max_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz); - flogeren = fopen(flogeren_name,"a+"); - fprintf(flogeren,"mag_f = ["); - fclose(flogeren); - } - */ - - /* - sprintf(ftxlev_name,"txlevel_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz); - ftxlev = fopen(ftxlev_name,"a+"); - fprintf(ftxlev,"txlev = ["); - fclose(ftexlv); - */ - if(abstx) { // CSV file sprintf(csv_fname,"EULdataout_tx%d_mcs%d_nbrb%d_chan%d_nsimus%d_eren.m",transmission_mode,mcs,nb_rb,chMod,n_frames); @@ -581,10 +634,6 @@ int main(int argc, char **argv) s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - // r_re0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - // bzero(r_re0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - // r_im0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - // bzero(r_im0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); } @@ -660,85 +709,6 @@ int main(int argc, char **argv) } - switch (eNB->frame_parms.N_RB_UL) { - case 6: - break; - - case 25: - if (eNB->frame_parms.frame_type == TDD) { - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1; - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->cshift = 0; - ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai = 1; - } else { - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1; - ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->cshift = 0; - } - - break; - - case 50: - if (eNB->frame_parms.frame_type == TDD) { - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - // printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1; - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->cshift = 0; - ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai = 1; - } else { - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - //printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1; - ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->cshift = 0; - } - - break; - - case 100: - if (eNB->frame_parms.frame_type == TDD) { - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs = mcs; - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi = 1; - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC = 0; - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1; - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->cshift = 0; - ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai = 1; - } else { - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->type = 0; - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8 - printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu); - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->mcs = mcs; - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->ndi = 1; - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->TPC = 0; - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1; - ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->cshift = 0; - } - - break; - - default: - break; - } UE->measurements.rank[0] = 0; @@ -753,16 +723,21 @@ int main(int argc, char **argv) UE->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; eNB->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + + UE->mac_enabled=0; - eNB_rxtx_proc_t *proc_rxtx = &eNB->proc.proc_rxtx[subframe&1]; + eNB_rxtx_proc_t *proc_rxtx = &eNB->proc.proc_rxtx[subframe&1]; + UE_rxtx_proc_t *proc_rxtx_ue = &UE->proc.proc_rxtx[subframe&1]; proc_rxtx->frame_rx=1; proc_rxtx->subframe_rx=subframe; proc_rxtx->frame_tx=pdcch_alloc2ul_frame(&eNB->frame_parms,1,subframe); proc_rxtx->subframe_tx=pdcch_alloc2ul_subframe(&eNB->frame_parms,subframe); - UE->frame_tx = proc_rxtx->frame_rx; - UE->frame_rx = proc_rxtx->frame_tx; + proc_rxtx_ue->frame_tx = proc_rxtx->frame_rx; + proc_rxtx_ue->frame_rx = proc_rxtx->frame_tx; + proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx; + proc_rxtx_ue->subframe_rx = proc_rxtx->subframe_tx; printf("Init UL hopping UE\n"); init_ul_hopping(&UE->frame_parms); @@ -774,11 +749,13 @@ int main(int argc, char **argv) UE->ulsch_Msg3_active[eNB_id] = 0; UE->ul_power_control_dedicated[eNB_id].accumulationEnabled=1; + /* generate_ue_ulsch_params_from_dci((void *)&UL_alloc_pdu, 14, proc_rxtx->subframe_tx, format0, UE, + proc_rxtx_ue, SI_RNTI, 0, P_RNTI, @@ -798,6 +775,7 @@ int main(int argc, char **argv) P_RNTI, CBA_RNTI, srs_flag); + */ coded_bits_per_codeword = nb_rb * (12 * get_Qm_ul(mcs)) * nsymb; @@ -845,7 +823,7 @@ int main(int argc, char **argv) //randominit(0); - harq_pid = subframe2harq_pid(&UE->frame_parms,UE->frame_tx,subframe); + harq_pid = subframe2harq_pid(&UE->frame_parms,proc_rxtx_ue->frame_tx,subframe); input_buffer_length = UE->ulsch[0]->harq_processes[harq_pid]->TBS/8; input_buffer = (unsigned char *)memalign(32,input_buffer_length+64); // printf("UL frame %d/subframe %d, harq_pid %d\n",UE->frame,subframe,harq_pid); @@ -927,7 +905,7 @@ int main(int argc, char **argv) reset_meas(&eNB->ulsch_tc_intl1_stats); reset_meas(&eNB->ulsch_tc_intl2_stats); - // initialization + // initialization struct list time_vector_tx; initialize(&time_vector_tx); struct list time_vector_tx_ifft; @@ -946,32 +924,50 @@ int main(int argc, char **argv) struct list time_vector_rx_dec; initialize(&time_vector_rx_dec); + ndi=0; for (trials = 0; trialsframe++; // eNB->frame++; - + ndi = (1-ndi); fflush(stdout); round=0; while (round < 4) { eNB->ulsch[0]->harq_processes[harq_pid]->round=round; UE->ulsch[0]->harq_processes[harq_pid]->round=round; - // printf("Trial %d : Round %d ",trials,round); + // printf("Trial %d : Round %d (subframe %d, frame %d)\n",trials,round,proc_rxtx_ue->subframe_rx,proc_rxtx_ue->frame_rx); round_trials[round]++; - if (round == 0) { - //eNB->ulsch[0]->harq_processes[harq_pid]->Ndi = 1; - eNB->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; - //UE->ulsch[0]->harq_processes[harq_pid]->Ndi = 1; - UE->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; - } else { - //eNB->ulsch[0]->harq_processes[harq_pid]->Ndi = 0; - eNB->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; - //UE->ulsch[0]->harq_processes[harq_pid]->Ndi = 0; - UE->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1; - } + fill_ulsch_dci(eNB,(void*)&UL_alloc_pdu,first_rb,nb_rb,mcs,ndi,cqi_flag); + + UE->ulsch_Msg3_active[eNB_id] = 0; + UE->ul_power_control_dedicated[eNB_id].accumulationEnabled=1; + generate_ue_ulsch_params_from_dci((void *)&UL_alloc_pdu, + 14, + proc_rxtx->subframe_tx, + format0, + UE, + proc_rxtx_ue, + SI_RNTI, + 0, + P_RNTI, + CBA_RNTI, + 0, + srs_flag); + + generate_eNB_ulsch_params_from_dci(eNB,proc_rxtx, + (void *)&UL_alloc_pdu, + 14, + format0, + 0, + SI_RNTI, + 0, + P_RNTI, + CBA_RNTI, + srs_flag); + eNB->ulsch[0]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; ///////////////////// if (abstx) { @@ -991,26 +987,24 @@ int main(int argc, char **argv) if (input_fdUL == NULL) { - start_meas(&UE->phy_proc_tx); + eNB->proc.frame_rx = 1; + eNB->proc.subframe_rx = subframe; + proc_rxtx_ue->frame_tx = proc_rxtx->frame_rx; + proc_rxtx_ue->frame_rx = proc_rxtx->frame_tx; + proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx; + proc_rxtx_ue->subframe_rx = proc_rxtx->subframe_tx; -#ifdef OFDMA_ULSCH + phy_procedures_UE_TX(UE,proc_rxtx_ue,0,0,normal_txrx,no_relay); + /* if (srs_flag) generate_srs_tx(UE,0,AMP,subframe); - generate_drs_pusch(UE,0,AMP,subframe,first_rb,nb_rb,0); - -#else - - if (srs_flag) - generate_srs_tx(UE,0,AMP,subframe); - - generate_drs_pusch(UE,0, + generate_drs_pusch(UE,proc_rxtx_ue,0, AMP,subframe, UE->ulsch[0]->harq_processes[harq_pid]->first_rb, UE->ulsch[0]->harq_processes[harq_pid]->nb_rb, 0); -#endif if ((cqi_flag == 1) && (n_frames == 1) ) { printf("CQI information (O %d) %d %d\n",UE->ulsch[0]->O, @@ -1037,27 +1031,17 @@ int main(int argc, char **argv) stop_meas(&UE->ulsch_encoding_stats); start_meas(&UE->ulsch_modulation_stats); -#ifdef OFDMA_ULSCH ulsch_modulation(UE->common_vars.txdataF,AMP, - UE->frame_tx,subframe,&UE->frame_parms,UE->ulsch[0]); -#else - // printf("Generating PUSCH in subframe %d with amp %d, nb_rb %d\n",subframe,AMP,nb_rb); - ulsch_modulation(UE->common_vars.txdataF,AMP, - UE->frame_tx,subframe,&UE->frame_parms, + proc_rxtx_ue->frame_tx,subframe,&UE->frame_parms, UE->ulsch[0]); -#endif stop_meas(&UE->ulsch_modulation_stats); + */ - if (n_frames==1) { - write_output("txsigF0UL.m","txsF0", &UE->common_vars.txdataF[0][eNB->frame_parms.ofdm_symbol_size*nsymb*subframe],eNB->frame_parms.ofdm_symbol_size*nsymb,1, - 1); - //write_output("txsigF1.m","txsF1", UE->common_vars.txdataF[0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - } - tx_lev=0; - start_meas(&UE->ofdm_mod_stats); - for (aa=0; aa<1; aa++) { + + /* + for (aa=0; aa<1; aa++) { if (frame_parms->Ncp == EXTENDED) PHY_ofdm_mod(&UE->common_vars.txdataF[aa][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], // input &txdata[aa][eNB->frame_parms.samples_per_tti*subframe], // output @@ -1071,20 +1055,24 @@ int main(int argc, char **argv) nsymb, frame_parms); -#ifndef OFDMA_ULSCH + apply_7_5_kHz(UE,UE->common_vars.txdata[aa],subframe<<1); apply_7_5_kHz(UE,UE->common_vars.txdata[aa],1+(subframe<<1)); -#endif - stop_meas(&UE->ofdm_mod_stats); - stop_meas(&UE->phy_proc_tx); - tx_lev += signal_energy(&txdata[aa][eNB->frame_parms.samples_per_tti*subframe], - eNB->frame_parms.samples_per_tti); +*/ + tx_lev = signal_energy(&UE->common_vars.txdata[0][eNB->frame_parms.samples_per_tti*subframe], + eNB->frame_parms.samples_per_tti); + + + if (n_frames==1) { + write_output("txsigF0UL.m","txsF0", &UE->common_vars.txdataF[0][eNB->frame_parms.ofdm_symbol_size*nsymb*subframe],eNB->frame_parms.ofdm_symbol_size*nsymb,1, + 1); + //write_output("txsigF1.m","txsF1", UE->common_vars.txdataF[0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); } - } // input_fd == NULL - - + + } // input_fd == NULL + tx_lev_dB = (unsigned int) dB_fixed_times10(tx_lev); if (n_frames==1) { @@ -1100,7 +1088,8 @@ int main(int argc, char **argv) // compute tx_gain to achieve target SNR (per resource element!) tx_gain = sqrt(pow(10.0,.1*(N0+SNR))*(nb_rb*12/(double)UE->frame_parms.ofdm_symbol_size)/(double)tx_lev); - if (n_frames==1) + + if (n_frames==1) printf("tx_lev = %d (%d.%d dB,%f), gain %f\n",tx_lev,tx_lev_dB/10,tx_lev_dB,10*log10((double)tx_lev),10*log10(tx_gain)); @@ -1117,8 +1106,8 @@ int main(int argc, char **argv) for (i=0; iframe_parms.samples_per_tti; i++) { for (aa=0; aa<1; aa++) { - s_re[aa][i] = ((double)(((short *)&txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)]); - s_im[aa][i] = ((double)(((short *)&txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)+1]); + s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)]); + s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)+1]); } } @@ -1191,74 +1180,13 @@ int main(int argc, char **argv) //write_output("rxsig1UL.m","rxs1", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1); } -#ifndef OFDMA_ULSCH - remove_7_5_kHz(eNB,subframe<<1); - remove_7_5_kHz(eNB,1+(subframe<<1)); - // write_output("rxsig0_75.m","rxs0_75", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1); - // write_output("rxsig1_75.m","rxs1_75", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1); -#endif + eNB->fep = eNB_fep_full; + eNB->do_prach = NULL; - start_meas(&eNB->phy_proc_rx); - start_meas(&eNB->ofdm_demod_stats); - lte_eNB_I0_measurements(eNB, - subframe, - 0, - 1); + phy_procedures_eNB_common_RX(eNB); + phy_procedures_eNB_uespec_RX(eNB,proc_rxtx,no_relay); - for (l=subframe*UE->frame_parms.symbols_per_tti; l<((1+subframe)*UE->frame_parms.symbols_per_tti); l++) { - - slot_fep_ul(&eNB->frame_parms, - &eNB->common_vars, - l%(eNB->frame_parms.symbols_per_tti/2), - l/(eNB->frame_parms.symbols_per_tti/2), - 0, - 0); - } - - stop_meas(&eNB->ofdm_demod_stats); - - eNB->ulsch[0]->cyclicShift = cyclic_shift;// cyclic shift for DMRS - - /* - if(abstx) { - namepointer_log2 = &flogeren_name; - namepointer_chMag = &fmageren_name; - //namepointer_txlev = &ftxlev; - } - */ - - start_meas(&eNB->ulsch_demodulation_stats); - rx_ulsch(eNB,proc_rxtx, - 0, // this is the effective sector id - 0, // this is the UE_id - eNB->ulsch, - cooperation_flag); - stop_meas(&eNB->ulsch_demodulation_stats); - - /* - if(abstx) { - namepointer_chMag = NULL; - - if(trials==0 && round==0 && SNR==snr0) { - char* namepointer ; - namepointer = &fperen_name; - write_output(namepointer, "xxx" ,eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][0],300,1,10); - namepointer = NULL ; - // flagMag = 1; - } - } - */ - - start_meas(&eNB->ulsch_decoding_stats); - - ret= ulsch_decoding(eNB,proc_rxtx, - 0, // UE_id - control_only_flag, - 1, // Nbundled - llr8_flag); - stop_meas(&eNB->ulsch_decoding_stats); - stop_meas(&eNB->phy_proc_rx); if (cqi_flag > 0) { cqi_error = 0; @@ -1289,11 +1217,13 @@ int main(int argc, char **argv) // printf("ulsch_coding: O[%d] %d\n",i,o_flip[i]); + + // if (ret <= eNB->ulsch[0]->max_turbo_iterations) { + + if (eNB->ulsch[0]->harq_processes[harq_pid]->round == 0) { - if (ret <= eNB->ulsch[0]->max_turbo_iterations) { - - avg_iter += ret; - iter_trials++; + // avg_iter += ret; + iter_trials++; if (n_frames==1) { printf("No ULSCH errors found, o_ACK[0]= %d, cqi_crc_status=%d\n",eNB->ulsch[0]->harq_processes[harq_pid]->o_ACK[0],eNB->ulsch[0]->harq_processes[harq_pid]->cqi_crc_status); @@ -1308,7 +1238,7 @@ int main(int argc, char **argv) round=5; } else { - avg_iter += ret-1; + // avg_iter += ret-1; iter_trials++; errs[round]++; @@ -1342,6 +1272,8 @@ int main(int argc, char **argv) printf("ULSCH in error in round %d\n",round); } } // ulsch error + + } // round // printf("\n"); @@ -1757,7 +1689,7 @@ int main(int argc, char **argv) if (((double)errs[0]/(round_trials[0]))<1e-2) break; - } // SNR + } // SNR // @@ -1767,30 +1699,8 @@ int main(int argc, char **argv) }//ch realization - /* - if(abstx) { - fperen = fopen(fperen_name,"a+"); - fprintf(fperen,"];\n"); - fclose(fperen); - fmageren = fopen(fmageren_name,"a+"); - fprintf(fmageren,"];\n"); - fclose(fmageren); - - flogeren = fopen(flogeren_name,"a+"); - fprintf(flogeren,"];\n"); - fclose(flogeren); - } - */ - - // ftxlev = fopen(ftxlev_name,"a+"); - //fprintf(ftxlev,"];\n"); - //fclose(ftxlev); - - - // write_output("chestim_f_dene.m","chestf",ulchestim_f_all,300*12,2,1);*/ - - if(abstx) { // ABSTRACTION + if (abstx) { // ABSTRACTION fprintf(csv_fdUL,"];"); fclose(csv_fdUL); } From e64af6597ac52d5d97b1c3d2d472ba1fd3f9bd75 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 7 Aug 2016 09:47:42 -0700 Subject: [PATCH 153/206] testing of low-level parallelization of FEP in eNodeB RX. --- openair1/PHY/defs.h | 12 ++ openair1/SCHED/phy_procedures_lte_eNb.c | 152 ++++++++++++++++++++++++ openair1/SIMULATION/LTE_PHY/ulsim.c | 10 +- targets/RT/USER/lte-enb.c | 21 ++-- 4 files changed, 185 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 8a6c827ff8..5fdd88cd23 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -246,6 +246,8 @@ typedef struct eNB_proc_t_s { int frame_rx; /// frame to act upon for PRACH int frame_prach; + /// \internal This variable is protected by \ref mutex_fep. + int instance_cnt_fep; /// \brief Instance count for FH processing thread. /// \internal This variable is protected by \ref mutex_FH. int instance_cnt_FH; @@ -264,6 +266,8 @@ typedef struct eNB_proc_t_s { int first_rx; /// flag to indicate first TX transmission int first_tx; + /// pthread attributes for parallel fep thread + pthread_attr_t attr_fep; /// pthread attributes for FH processing thread pthread_attr_t attr_FH; /// pthread attributes for single eNB processing thread @@ -272,6 +276,8 @@ typedef struct eNB_proc_t_s { pthread_attr_t attr_prach; /// pthread attributes for asynchronous RX thread pthread_attr_t attr_asynch_rxtx; + /// scheduling parameters for parallel fep thread + struct sched_param sched_param_fep; /// scheduling parameters for FH thread struct sched_param sched_param_FH; /// scheduling parameters for single eNB thread @@ -280,14 +286,20 @@ typedef struct eNB_proc_t_s { struct sched_param sched_param_prach; /// scheduling parameters for asynch_rxtx thread struct sched_param sched_param_asynch_rxtx; + /// pthread structure for parallel fep thread + pthread_t pthread_fep; /// pthread structure for PRACH thread pthread_t pthread_prach; + /// condition variable for parallel fep thread + pthread_cond_t cond_fep; /// condition variable for FH thread pthread_cond_t cond_FH; /// condition variable for PRACH processing thread; pthread_cond_t cond_prach; /// condition variable for asynch RX/TX thread pthread_cond_t cond_asynch_rxtx; + /// mutex for parallel fep thread + pthread_mutex_t mutex_fep; /// mutex for FH pthread_mutex_t mutex_FH; /// mutex for PRACH thread diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6053a151a4..be7aedca65 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2497,6 +2497,158 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p } +typedef struct { + PHY_VARS_eNB *eNB; + int slot; +} fep_task; + +void fep0(PHY_VARS_eNB *eNB,int slot) { + + eNB_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + int l; + + remove_7_5_kHz(eNB,(slot&1)+(proc->subframe_rx<<1)); + for (l=0; lsymbols_per_tti/2; l++) { + slot_fep_ul(fp, + &eNB->common_vars, + l, + (slot&1)+(proc->subframe_rx<<1), + 0, + 0 + ); + } +} + +static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { + + if (pthread_mutex_lock(mutex) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + + *instance_cnt=*instance_cnt-1; + + if (pthread_mutex_unlock(mutex) != 0) { + LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + return(0); +} + +static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { + + if (pthread_mutex_lock(mutex) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + + while (*instance_cnt < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_rxtx is -1 + pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again + } + + if (pthread_mutex_unlock(mutex) != 0) { + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + return(0); +} + +extern int oai_exit; + + +static void *fep_thread(void *param) { + + PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; + eNB_proc_t *proc = &eNB->proc; + while (!oai_exit) { + printf("Waiting for parallel FEP signal\n"); + if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break; + printf("Running parallel FEP on first slot\n"); + fep0(eNB,0); + if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break; + } + return(NULL); +} + +void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) { + + eNB_proc_t *proc = &eNB->proc; + + proc->instance_cnt_fep = -1; + + pthread_mutex_init( &proc->mutex_fep, NULL); + pthread_cond_init( &proc->cond_fep, NULL); + + pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)eNB); + +} + +void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { + + eNB_proc_t *proc = &eNB->proc; + struct timespec wait; + int wait_cnt=0; + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); + start_meas(&eNB->ofdm_demod_stats); + + printf("Running 2 thread FEP\n"); + + if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { + printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep); + exit_fun( "error locking mutex_fep" ); + return; + } + + if (proc->instance_cnt_fep==0) { + printf("[eNB] FEP thread busy\n"); + exit_fun("FEP thread busy"); + pthread_mutex_unlock( &proc->mutex_fep ); + return; + } + + ++proc->instance_cnt_fep; + + printf("[eNB] waking up FEP thread\n"); + if (pthread_cond_signal(&proc->cond_fep) != 0) { + printf("[eNB] ERROR pthread_cond_signal for fep thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + + pthread_mutex_unlock( &proc->mutex_fep ); + + // call second slot in this symbol + printf("Calling FEP for 2nd slot\n"); + fep0(eNB,1); + + if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { + printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep); + exit_fun( "error locking mutex_fep" ); + return; + } + while (proc->instance_cnt_fep==0) { + wait_cnt++; + if (wait_cnt>10000) + break; + }; + + pthread_mutex_unlock( &proc->mutex_fep ); + if (wait_cnt>10000) { + printf("[eNB] parallel FEP didn't finish\n"); + exit_fun( "error" ); + } +} + void eNB_fep_full(PHY_VARS_eNB *eNB) { eNB_proc_t *proc = &eNB->proc; diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 47565f4e0c..70510cbc04 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -85,6 +85,8 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ +int oai_exit = 0; + void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mcs,int ndi,int cqi_flag) { @@ -171,6 +173,7 @@ void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mc } extern void eNB_fep_full(PHY_VARS_eNB *eNB); +extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB); int main(int argc, char **argv) { @@ -688,6 +691,8 @@ int main(int argc, char **argv) eNB->ulsch[0] = new_eNB_ulsch(max_turbo_iterations,N_RB_DL,0); UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); + init_fep_thread(eNB,&eNB->proc.attr_fep); + // Create transport channel structures for 2 transport blocks (MIMO) for (i=0; i<2; i++) { eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0); @@ -1181,7 +1186,7 @@ int main(int argc, char **argv) } - eNB->fep = eNB_fep_full; + eNB->fep = eNB_fep_full_2thread; eNB->do_prach = NULL; phy_procedures_eNB_common_RX(eNB); @@ -1700,6 +1705,9 @@ int main(int argc, char **argv) }//ch realization + oai_exit=1; + pthread_cond_signal(&eNB->proc.cond_fep); + if (abstx) { // ABSTRACTION fprintf(csv_fdUL,"];"); fclose(csv_fdUL); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index b614ca131d..d4f83d5a2c 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1329,6 +1329,7 @@ static void* eNB_thread_single( void* param ) { } +extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *); void init_eNB_proc(int inst) { @@ -1337,7 +1338,7 @@ void init_eNB_proc(int inst) { PHY_VARS_eNB *eNB; eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; - pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL; + pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL; for (CC_id=0; CC_idproc_rxtx; proc_rxtx[0].instance_cnt_rxtx = -1; proc_rxtx[1].instance_cnt_rxtx = -1; - proc->instance_cnt_prach = -1; - proc->instance_cnt_FH = -1; + proc->instance_cnt_prach = -1; + proc->instance_cnt_FH = -1; proc->instance_cnt_asynch_rxtx = -1; - proc->CC_id = CC_id; + proc->CC_id = CC_id; proc->first_rx=1; proc->first_tx=1; @@ -1373,6 +1374,7 @@ void init_eNB_proc(int inst) { attr_prach = &proc->attr_prach; attr_asynch = &proc->attr_asynch_rxtx; attr_single = &proc->attr_single; + attr_fep = &proc->attr_fep; #endif if (eNB->single_thread_flag==0) { @@ -1380,9 +1382,10 @@ void init_eNB_proc(int inst) { pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] ); pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc ); } - else + else { pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc); - + init_fep_thread(eNB,attr_fep); + } pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc ); if ((eNB->node_timing == synch_to_other) || (eNB->node_function == NGFI_RRU_IF5) || @@ -1631,7 +1634,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case NGFI_RRU_IF4p5: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; + eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread; eNB->proc_uespec_rx = NULL; eNB->proc_tx = NULL;//proc_tx_rru_if4p5; eNB->tx_fh = NULL; @@ -1658,7 +1661,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case eNodeB_3GPP: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; + eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = NULL; @@ -1676,7 +1679,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case eNodeB_3GPP_BBU: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; + eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = tx_fh_if5; From 5b9f4714a9e7670baf5982f9387c5760263933aa Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 7 Aug 2016 09:51:01 -0700 Subject: [PATCH 154/206] added unitary_defs.h --- openair1/SIMULATION/LTE_PHY/unitary_defs.h | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 openair1/SIMULATION/LTE_PHY/unitary_defs.h diff --git a/openair1/SIMULATION/LTE_PHY/unitary_defs.h b/openair1/SIMULATION/LTE_PHY/unitary_defs.h new file mode 100644 index 0000000000..1e1c66130a --- /dev/null +++ b/openair1/SIMULATION/LTE_PHY/unitary_defs.h @@ -0,0 +1,9 @@ +openair0_device openair0; + +void exit_fun(const char *s) { exit(-1); } + +extern unsigned int dlsch_tbs25[27][25],TBStable[27][110]; +extern unsigned char offset_mumimo_llr_drange_fix; + +extern unsigned short dftsizes[33]; +extern short *ul_ref_sigs[30][2][33]; From 12801c599153587ff19145fdf76f1685f92b3da7 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 7 Aug 2016 19:25:50 +0200 Subject: [PATCH 155/206] switch for parallel FEP on ulsim. Deactivated for real-time operation. --- openair1/SCHED/phy_procedures_lte_eNb.c | 11 ++++------- openair1/SIMULATION/LTE_PHY/dlsim.c | 2 +- openair1/SIMULATION/LTE_PHY/ulsim.c | 10 ++++------ openair1/SIMULATION/LTE_PHY/unitary_defs.h | 1 + targets/RT/USER/lte-enb.c | 6 +++--- 5 files changed, 13 insertions(+), 17 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index be7aedca65..980fa3335a 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2568,9 +2568,7 @@ static void *fep_thread(void *param) { PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; eNB_proc_t *proc = &eNB->proc; while (!oai_exit) { - printf("Waiting for parallel FEP signal\n"); if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break; - printf("Running parallel FEP on first slot\n"); fep0(eNB,0); if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break; } @@ -2601,8 +2599,6 @@ void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); start_meas(&eNB->ofdm_demod_stats); - printf("Running 2 thread FEP\n"); - if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep); exit_fun( "error locking mutex_fep" ); @@ -2618,7 +2614,7 @@ void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { ++proc->instance_cnt_fep; - printf("[eNB] waking up FEP thread\n"); + if (pthread_cond_signal(&proc->cond_fep) != 0) { printf("[eNB] ERROR pthread_cond_signal for fep thread\n"); exit_fun( "ERROR pthread_cond_signal" ); @@ -2628,7 +2624,6 @@ void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { pthread_mutex_unlock( &proc->mutex_fep ); // call second slot in this symbol - printf("Calling FEP for 2nd slot\n"); fep0(eNB,1); if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { @@ -2643,10 +2638,12 @@ void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { }; pthread_mutex_unlock( &proc->mutex_fep ); - if (wait_cnt>10000) { + if (wait_cnt>1000000) { printf("[eNB] parallel FEP didn't finish\n"); exit_fun( "error" ); } + + stop_meas(&eNB->ofdm_demod_stats); } void eNB_fep_full(PHY_VARS_eNB *eNB) { diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index f7824773e0..fb6a9d0288 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -13,7 +13,7 @@ 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 + You should haeve received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see . diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 70510cbc04..48b3f8cec1 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -85,8 +85,6 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ -int oai_exit = 0; - void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mcs,int ndi,int cqi_flag) { @@ -276,7 +274,7 @@ int main(int argc, char **argv) char channel_model_input[10]; uint8_t max_turbo_iterations=4; - uint8_t llr8_flag=0; + uint8_t parallel_flag=0; int nb_rb_set = 0; int threequarter_fs=0; @@ -534,7 +532,7 @@ int main(int argc, char **argv) break; case 'L': - llr8_flag=1; + parallel_flag=1; break; case 'I': @@ -691,7 +689,7 @@ int main(int argc, char **argv) eNB->ulsch[0] = new_eNB_ulsch(max_turbo_iterations,N_RB_DL,0); UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); - init_fep_thread(eNB,&eNB->proc.attr_fep); + if (parallel_flag == 1) init_fep_thread(eNB,&eNB->proc.attr_fep); // Create transport channel structures for 2 transport blocks (MIMO) for (i=0; i<2; i++) { @@ -1186,7 +1184,7 @@ int main(int argc, char **argv) } - eNB->fep = eNB_fep_full_2thread; + eNB->fep = (parallel_flag == 1) ? eNB_fep_full_2thread : eNB_fep_full; eNB->do_prach = NULL; phy_procedures_eNB_common_RX(eNB); diff --git a/openair1/SIMULATION/LTE_PHY/unitary_defs.h b/openair1/SIMULATION/LTE_PHY/unitary_defs.h index 1e1c66130a..6fefc47a72 100644 --- a/openair1/SIMULATION/LTE_PHY/unitary_defs.h +++ b/openair1/SIMULATION/LTE_PHY/unitary_defs.h @@ -1,4 +1,5 @@ openair0_device openair0; +int oai_exit=0; void exit_fun(const char *s) { exit(-1); } diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index d4f83d5a2c..8781869e17 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1634,7 +1634,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case NGFI_RRU_IF4p5: eNB->do_prach = do_prach; - eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread; + eNB->fep = eNB_fep_full; eNB->proc_uespec_rx = NULL; eNB->proc_tx = NULL;//proc_tx_rru_if4p5; eNB->tx_fh = NULL; @@ -1661,7 +1661,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case eNodeB_3GPP: eNB->do_prach = do_prach; - eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread; + eNB->fep = eNB_fep_full; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = NULL; @@ -1679,7 +1679,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case eNodeB_3GPP_BBU: eNB->do_prach = do_prach; - eNB->fep = (eNB->single_thread_flag == 0) ? NB_fep_full : eNB_fep_full_2thread; + eNB->fep = eNB_fep_full; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = tx_fh_if5; From 018fb07187299a67bd65423c5d6c1d9d5bcf8a73 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 7 Aug 2016 19:40:53 +0200 Subject: [PATCH 156/206] fixed affinity code (FH on CPU0, others on CPU 1-3) --- targets/RT/USER/lte-enb.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 8781869e17..e1129edb20 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -164,6 +164,7 @@ void stop_eNB(int nb_inst); static inline void thread_top_init(char *thread_name, + int affinity, uint64_t runtime, uint64_t deadline, uint64_t period) { @@ -207,7 +208,10 @@ static inline void thread_top_init(char *thread_name, #ifdef CPU_AFFINITY if (get_nprocs() > 2) { - for (j = 1; j < get_nprocs(); j++) + if (affinity == 0) + CPU_SET(0,&cpuset); + else + for (j = 1; j < get_nprocs(); j++) CPU_SET(j, &cpuset); s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); if (s != 0) @@ -625,7 +629,7 @@ static void* eNB_thread_rxtx( void* param ) { eNB_thread_rxtx_status = 0; sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1); - thread_top_init(thread_name,850000L,1000000L,2000000L); + thread_top_init(thread_name,1,850000L,1000000L,2000000L); while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); @@ -830,7 +834,7 @@ static void* eNB_thread_asynch_rxtx( void* param ) { int subframe=0, frame=0; - thread_top_init("thread_asynch",870000L,1000000L,1000000L); + thread_top_init("thread_asynch",1,870000L,1000000L,1000000L); // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe @@ -1153,7 +1157,7 @@ static void* eNB_thread_FH( void* param ) { // set default return value eNB_thread_FH_status = 0; - thread_top_init("eNB_thread_FH",870000,1000000,1000000); + thread_top_init("eNB_thread_FH",0,870000,1000000,1000000); wait_sync("eNB_thread_FH"); @@ -1233,7 +1237,7 @@ static void* eNB_thread_prach( void* param ) { // set default return value eNB_thread_prach_status = 0; - thread_top_init("eNB_thread_prach",500000L,1000000L,20000000L); + thread_top_init("eNB_thread_prach",1,500000L,1000000L,20000000L); while (!oai_exit) { @@ -1265,7 +1269,7 @@ static void* eNB_thread_single( void* param ) { // set default return value eNB_thread_single_status = 0; - thread_top_init("eNB_thread_single",870000,1000000,1000000); + thread_top_init("eNB_thread_single",0,870000,1000000,1000000); wait_sync("eNB_thread_single"); From 857af54015d4749385e912f8d067bb25cc4d7f96 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 8 Aug 2016 00:08:43 +0200 Subject: [PATCH 157/206] usrp 20 MHz on 30.72 master clock. fixed memory leak in prach.c for 20 MHz with 3/4 sampling. added default attributes to threads in lte-enb.c --- openair1/PHY/LTE_TRANSPORT/prach.c | 26 +++++++++++++++----- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 2 +- targets/RT/USER/lte-enb.c | 8 ++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index b24535c43a..cab6544b62 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -1161,6 +1161,9 @@ void rx_prach(PHY_VARS_eNB *eNB, break; } + if (eNB->frame_parms.threequarter_fs == 1) + Ncp=(Ncp*3)>>2; + switch (eNB->frame_parms.N_RB_UL) { case 6: Ncp>>=4; @@ -1258,13 +1261,24 @@ void rx_prach(PHY_VARS_eNB *eNB, break; case 100: - if (prach_fmt == 4) { - dft4096(prach2,rxsigF[aa],1); + if (eNB->frame_parms.threequarter_fs==0) { + if (prach_fmt == 4) { + dft4096(prach2,rxsigF[aa],1); + } else { + dft24576(prach2,rxsigF[aa]); + + if (prach_fmt>1) + dft24576(prach2+49152,rxsigF[aa]+49152); + } } else { - dft24576(prach2,rxsigF[aa]); - - if (prach_fmt>1) - dft24576(prach2+49152,rxsigF[aa]+49152); + if (prach_fmt == 4) { + dft3072(prach2,rxsigF[aa]); + } else { + dft18432(prach2,rxsigF[aa]); + + if (prach_fmt>1) + dft18432(prach2+36864,rxsigF[aa]+36864); + } } break; diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index fc4f8d5d39..b8e9b21866 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -610,7 +610,7 @@ extern "C" { switch ((int)openair0_cfg[0].sample_rate) { case 30720000: - s->usrp->set_master_clock_rate(61.44e6); + s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].tx_sample_advance = 115; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index e1129edb20..51ea3709e1 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1371,6 +1371,14 @@ void init_eNB_proc(int inst) { pthread_cond_init( &proc->cond_prach, NULL); pthread_cond_init( &proc->cond_FH, NULL); pthread_cond_init( &proc->cond_asynch_rxtx, NULL); + + pthread_attr_init( &proc->attr_FH); + pthread_attr_init( &proc->attr_prach); + pthread_attr_init( &proc->attr_asynch_rxtx); + pthread_attr_init( &proc->attr_single); + pthread_attr_init( &proc->attr_fep); + pthread_attr_init( &proc_rxtx[0].attr_rxtx); + pthread_attr_init( &proc_rxtx[1].attr_rxtx); #ifndef DEADLINE_SCHEDULER attr0 = &proc_rxtx[0].attr_rxtx; attr1 = &proc_rxtx[1].attr_rxtx; From 8d057b80e247d28aa80ea030f3468fd1f35bb363 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 12 Aug 2016 10:54:58 +0200 Subject: [PATCH 158/206] add helper for three quarter sampling for 20 MHz --- targets/RT/USER/lte-softmodem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 852147f462..f3e51890f1 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -401,6 +401,7 @@ void help (void) { printf(" -W Enable L2 wireshark messages on localhost \n"); printf(" -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n"); printf(" -x Set the transmission mode, valid options: 1 \n"); + printf(" -E Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n"); #if T_TRACER printf(" --T_port [port] use given port\n"); printf(" --T_nowait don't wait for tracer, start immediately\n"); From 8788b311e98b003b06bedfc0d5137b9c630a8043 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 12 Aug 2016 17:26:04 +0200 Subject: [PATCH 159/206] added some helper message to lte-softmodem --- targets/RT/USER/lte-softmodem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index f3e51890f1..b9d6907c8e 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -382,7 +382,8 @@ void help (void) { printf(" --ue-txgain set UE TX gain\n"); printf(" --ue-scan_carrier set UE to scan around carrier\n"); printf(" --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n"); - printf(" --mmapped-dma sets flag for improved EXMIMO UE performance\n"); + printf(" --mmapped-dma sets flag for improved EXMIMO UE performance\n"); + printf(" --single-thread runs lte-softmodem in only one thread\n"); printf(" -C Set the downlink frequency for all component carriers\n"); printf(" -d Enable soft scope and L1 and L2 stats (Xforms)\n"); printf(" -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"); From 48bab02f94a217336e38d9db727b5db07bc59781 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 20 Aug 2016 01:02:43 +0200 Subject: [PATCH 160/206] add compilation test cases for RRU/RCC NGFI --- cmake_targets/autotests/README.txt | 17 +++-- cmake_targets/autotests/test_case_list.xml | 79 ++++++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/cmake_targets/autotests/README.txt b/cmake_targets/autotests/README.txt index cf1e28dd05..245b235ebf 100644 --- a/cmake_targets/autotests/README.txt +++ b/cmake_targets/autotests/README.txt @@ -16,17 +16,22 @@ Obj.# Case# Test# Description 01 01 20 Build lte-softmodem.USRP.Rel10 01 01 21 Build lte-softmodem.EXMIMO.Rel10 01 01 22 Build lte-softmodem.BLADERF.Rel10 -01 01 23 Build lte-softmodem.ETHERNET.Rel10 +01 01 23 Build lte-softmodem.ETHERNET.Rel10 (RCC) 01 01 24 Build lte-softmodem.LMSSDR.Rel10 01 01 30 Build (dlsim.Rel10 + ulsim.Rel10 + pucchsim.Rel10 + prachsim.Rel10 + pdcchsim.Rel10 + pbchsim.Rel10 + mbmssim.Rel10 secu_knas_encrypt_eia1.Rel10 secu_kenb.Rel10 aes128_ctr_encrypt.Rel10 aes128_ctr_decrypt.Rel10 secu_knas_encrypt_eea2.Rel10 secu_knas.Rel10 secu_knas_encrypt_eea1.Rel10 kdf.Rel10 aes128_cmac_encrypt.Rel10 secu_knas_encrypt_eia2.Rel10) -01 01 40 Build RRH Gateway for USRP (Rel 10) -01 01 41 Build RRH Gateway for EXMIMO (Rel 10) -01 01 42 Build RRH Gateway for BLADERF (Rel 10) -01 01 43 Build RRH Gateway for LMSSDR (Rel 10) +01 01 40 Build RRH Gateway (time domain) for USRP (Rel 10) +01 01 41 Build RRH Gateway (time domain) for EXMIMO (Rel 10) +01 01 42 Build RRH Gateway (time domain) for BLADERF (Rel 10) +01 01 43 Build RRH Gateway (time domain) for LMSSDR (Rel 10) + +01 01 50 Build RRU (NGFI) for USRP (Rel 10) w/ ETHERNET transport +01 01 51 Build RRU (NGFI) for EXMIMO (Rel 10) w/ ETHERNET transport +01 01 52 Build RRU (NGFI) for BLADERF (Rel 10) w/ ETHERNET transport +01 01 53 Build RRU (NGFI) for LMSSDR (Rel 10) w/ ETHERNET transport 01 02 Run OAISIM-NOS1 Rel10 (TDD + 5MHz/10MHz/20MHz + TM 1,2), and check the operation @@ -249,4 +254,4 @@ Obj.# Case# Test# Description #TODO: Add test cases for 10,20 MHz #TODO: Add test cases for TDD/FDD #TODO: Test and compile seperately for Rel8/Rel10 -#TODO: Case03.py eMBMS test case \ No newline at end of file +#TODO: Case03.py eMBMS test case diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 28556445e9..f26c937135 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -381,6 +381,85 @@ 1 + + compilation + Build RRU (NGFI) for USRP (Rel 10) w/ ETHERNET transport + + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -t ETHERNET -c + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/liboai_usrpdevif.so + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_eth_transpro.so + $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash + + + + + + RRU.USRP.Rel10 + 1 + + + + compilation + Build RRU (NGFI) for EXMIMO (Rel 10) w/ ETHERNET transport + + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w EXMIMO -t ETHNERNET -c + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/CMakeFiles/openair_rf/openair_rf.ko + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/updatefw + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/oarf_config_exmimo.oct + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_exmimodevif.so + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_eth_transpro.so + $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash + + + + + + RRU.EXMIMO.Rel10 + 1 + + + + compilation + Build RRU (NGFI) for BLADERF (Rel 10) w/ ETHERNET transport + + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w BLADERF -t ETHERNET -c + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_bladerfdevif.so + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_eth_transpro.so + $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash + + + + + + RRU.BLADERF.Rel10 + 1 + + + + compilation + Build RRU (NGFI) for LMSSDR (Rel 10) w/ ETHERNET transport + + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w LMSSDR -t ETHERNET -c + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_lmssdrdevif.so + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_eth_transpro.so + $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash + + + + + + RRH.LMSSDR.Rel10 + 1 + + execution Run OAISIM Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2) and search for errors, segmentation fault or exit From 4f2e5d359aa2eacb50f75e24c13e20cb6c2d2e12 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 20 Aug 2016 01:33:48 +0200 Subject: [PATCH 161/206] minor fix for type for RRU/RCC compile tests --- cmake_targets/autotests/test_case_list.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index f26c937135..800b41a8b8 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -388,7 +388,7 @@ $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -t ETHERNET -c $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - $OPENAIR_DIR/cmake_targets/lte_build_oai/liboai_usrpdevif.so + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_usrpdevif.so $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_eth_transpro.so $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash @@ -405,7 +405,7 @@ Build RRU (NGFI) for EXMIMO (Rel 10) w/ ETHERNET transport $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w EXMIMO -t ETHNERNET -c + --eNB -w EXMIMO -t ETHERNET -c $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem $OPENAIR_DIR/cmake_targets/lte_build_oai/build/CMakeFiles/openair_rf/openair_rf.ko $OPENAIR_DIR/cmake_targets/lte_build_oai/build/updatefw @@ -456,7 +456,7 @@ - RRH.LMSSDR.Rel10 + RRU.LMSSDR.Rel10 1 From ea57f56466b92b87e94835ff6ec009aefbc8ea91 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 22 Aug 2016 19:18:58 +0200 Subject: [PATCH 162/206] merge selected commits from enhancement-10-harmony-rgu test branch --- cmake_targets/CMakeLists.txt | 1 + .../autotests/run_exec_lte-softmodem_tests.py | 7 ++ cmake_targets/autotests/test_case_list.xml | 30 ++++----- cmake_targets/autotests/tools/run_gdb | 4 ++ cmake_targets/build_oai | 32 +++++---- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 67 ++++++++++++++++--- 6 files changed, 104 insertions(+), 37 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 553309f237..2b164efe69 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -126,6 +126,7 @@ endmacro(add_list_string_option) if (CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE "RelWithDebInfo") endif() +message("CMAKE_BUILD_TYPE is ${CMAKE_BUILD_TYPE}") add_list_string_option(CMAKE_BUILD_TYPE "RelWithDebInfo" "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." Debug Release RelWithDebInfo MinSizeRel) Message("Architecture is ${CMAKE_SYSTEM_PROCESSOR}") diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 10f02ecfb8..791ceb97bb 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1020,6 +1020,13 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , run_result=0 run_result_string = ' RUN_'+str(run) + ' = FAIL(Thread_Busy)' + #If there is Segmentation fault, we mark the test case as failure as most likely eNB crashed + cmd = "grep -ilr \"segmentation fault\" " + logdir_local_testcase + " | cat " + cmd_out = subprocess.check_output ([cmd], shell=True) + if len(cmd_out) !=0: + run_result=0 + run_result_string = ' RUN_'+str(run) + ' = FAIL(SEGFAULT)' + run_result_string = run_result_string + tput_run_string test_result=test_result & run_result diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 800b41a8b8..a36390d8cf 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,6 +1,6 @@ -mozart hutch starsky stevens amerique calisson nano qseven +mozart hutch starsky stevens amerique calisson nano /mnt/sradio/TEST_RESULTS/ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git @@ -10,7 +10,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox exmimo_pci=`lspci -m | grep Xilinx`; if [ -n "$exmimo_pci" ] ; then $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; fi; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_huaweiE398_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue; uname -a; sudo -E dmesg 36000 - 010141 0102+ 010304 010305 0104+ 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 018502 018505 + 010141 0102+ 010304 010305 0104+ 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 3 mozart hutch starsky stevens amerique calisson nano @@ -3437,7 +3437,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -3509,7 +3509,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -3581,7 +3581,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -3653,7 +3653,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -3724,7 +3724,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -3796,7 +3796,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -3867,7 +3867,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -3939,7 +3939,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -4011,7 +4011,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -4083,7 +4083,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -4154,7 +4154,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -4226,7 +4226,7 @@ c --eNB -w USRP -x -c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf @@ -4299,7 +4299,7 @@ c --eNB -w USRP -x -c sleep 15; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail ; cp $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf $OPENAIR_TESTDIR/enb.conf - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf diff --git a/cmake_targets/autotests/tools/run_gdb b/cmake_targets/autotests/tools/run_gdb index aeb46bc398..a12d6ce21d 100755 --- a/cmake_targets/autotests/tools/run_gdb +++ b/cmake_targets/autotests/tools/run_gdb @@ -35,6 +35,10 @@ $SUDO echo "set pagination off" >> $gdb_file $SUDO echo "handle SIG33 pass nostop noprint" >> $gdb_file $SUDO echo "echo backtrace:\n" >> $gdb_file $SUDO echo "backtrace full" >> $gdb_file +$SUDO echo "echo \n\nVariables:\n" >> $gdb_file +$SUDO echo "info variables" >> $gdb_file +$SUDO echo "echo \n\nlocals:\n" >> $gdb_file +$SUDO echo "info locals" >> $gdb_file $SUDO echo "echo \n\nregisters:\n" >> $gdb_file $SUDO echo "info registers" >> $gdb_file $SUDO echo "echo \n\ncurrent instructions:\n" >> $gdb_file diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 7ff2673b6b..967c92f557 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -61,6 +61,7 @@ TEST_CASE_GROUP="" BUILD_DOXYGEN=0 T_TRACER="False" DISABLE_HARDWARE_DEPENDENCY="False" +CMAKE_BUILD_TYPE="" trap handle_ctrl_c INT function print_help() { @@ -82,7 +83,7 @@ Options --install-optional-packages Install useful but not mandatory packages such as valgrind -g | --run-with-gdb - Add debugging symbols to compilation directives + Add debugging symbols to compilation directives. It also disables any compiler optimization. -h | --help Print this help --eNB @@ -170,7 +171,8 @@ function main() { shift;; -g | --run-with-gdb) GDB=1 - echo_info "Will Compile with gdb symbols" + CMAKE_BUILD_TYPE="Debug" + echo_info "Will Compile with gdb symbols and disable compiler optimization" shift;; --eNB) eNB=1 @@ -443,6 +445,7 @@ function main() { if [ "$NOS1" = "1" ] ; then cat $DIR/$lte_build_dir/CMakeLists.template >> $cmake_file fi + echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file echo "set ( XFORMS $XFORMS )" >> $cmake_file echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file @@ -568,6 +571,8 @@ function main() { cp $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 $dbin fi + # oaisim compilation + ############### if [ "$oaisim" = "1" ] ; then dconf=$OPENAIR_DIR/targets/bin if [ "$NOS1" = "1" ] ; then @@ -581,6 +586,7 @@ function main() { echo_info "Compiling $oaisim_exec ($oaisim_build_dir)" cmake_file=$DIR/$oaisim_build_dir/CMakeLists.txt cp $DIR/$oaisim_build_dir/CMakeLists.template $cmake_file + echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file echo "set ( XFORMS $XFORMS )" >> $cmake_file echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file @@ -649,9 +655,10 @@ function main() { cmake_file=$DIR/oaisim_mme_build_oai/CMakeLists.txt cp $DIR/oaisim_mme_build_oai/CMakeLists.template $cmake_file - echo "set(XFORMS $XFORMS )" >> $cmake_file - echo "set(RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file - echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file + echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file + echo "set ( XFORMS $XFORMS )" >> $cmake_file + echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file + echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( T_TRACER $T_TRACER )" >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file #[ "$CLEAN" = "1" ] && rm -rf $DIR/oaisim_mme_build_oai/build @@ -676,13 +683,14 @@ function main() { mkdir -p $DIR/$rrh_build_dir/build cmake_file=$DIR/$rrh_build_dir/CMakeLists.txt echo "cmake_minimum_required(VERSION 2.8)" > $cmake_file - echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file - echo "set(ENABLE_ITTI False )" >> $cmake_file - echo "set(RF_BOARD \"${HW}\")" >> $cmake_file - echo "set(TRANSP_PRO \"${TP}\")" >> $cmake_file - echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file - echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file - echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file + echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file + echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file + echo "set ( ENABLE_ITTI False )" >> $cmake_file + echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file + echo "set ( TRANSP_PRO \"${TP}\")" >> $cmake_file + echo 'set ( PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file + echo "set ( DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file + echo "set ( CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file echo "set ( T_TRACER $T_TRACER )" >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$rrh_build_dir/build diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index b8e9b21866..f2cc289ed7 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -45,7 +45,7 @@ #include #include #include - +#include #include "common_lib.h" #ifdef __SSE4_1__ # include @@ -172,7 +172,13 @@ static void trx_usrp_end(openair0_device *device) */ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { - int ret; + static long long int loop=0; + static long time_min=0, time_max=0, time_avg=0; + struct timespec tp_start, tp_end; + long time_diff; + clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start); + + int ret=0, ret_i=0; usrp_state_t *s = (usrp_state_t*)device->priv; s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); @@ -196,7 +202,21 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, if (ret != nsamps) { printf("[xmit] tx samples %d != %d\n",ret,nsamps); } - + + clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end); + time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec); + if (time_min==0 ||loop==1 || time_min > time_diff) + time_min=time_diff; + if (time_max==0 ||loop==1 || time_max < time_diff) + time_max=time_diff; + if (time_avg ==0 ||loop==1) + time_avg= time_diff; + else + time_avg=(time_diff+time_avg) /2.0; + + if ( loop%10000 ==0) + printf("\n usrp_write: min(ns)=%d, max(ns)=%d, avg(ns)=%d", (int)time_min, (int)time_max,(int)time_avg); + loop++; return ret; } @@ -213,6 +233,11 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, */ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + static long long int loop=0; + static long time_min=0, time_max=0, time_avg=0; + struct timespec tp_start, tp_end; + long time_diff; + clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start); usrp_state_t *s = (usrp_state_t*)device->priv; int samples_received=0,i,j; int nsamps2; // aligned to upper 32 or 16 byte boundary @@ -293,7 +318,20 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); *ptimestamp = s->rx_timestamp; - return samples_received; + clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end); + time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec); + if (time_min==0 ||loop==1 || time_min > time_diff) + time_min=time_diff; + if (time_max==0 || loop==1|| time_max < time_diff) + time_max=time_diff; + if (time_avg ==0 ||loop==1) + time_avg= time_diff; + else + time_avg=(time_diff+time_avg) /2.0; + if ( loop % 10000==0) + printf("\n usrp_read: min(ns)=%d, max(ns)=%d, avg(ns)=%d", (int)time_min, (int)time_max,(int)time_avg); + loop++; + return samples_received; } /*! \brief Get current timestamp of USRP @@ -500,6 +538,7 @@ extern "C" { // Initialize USRP device + device->openair0_cfg = openair0_cfg; std::string args = "type=b200"; @@ -523,6 +562,8 @@ extern "C" { // workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); + args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096"; + uhd::device_addrs_t device_adds = uhd::device::find(args); if(device_adds.size() == 0) @@ -554,25 +595,25 @@ extern "C" { switch ((int)openair0_cfg[0].sample_rate) { case 30720000: // from usrp_time_offset - openair0_cfg[0].samples_per_packet = 2048; + //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; case 15360000: - openair0_cfg[0].samples_per_packet = 2048; + //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 45; openair0_cfg[0].tx_bw = 10e6; openair0_cfg[0].rx_bw = 10e6; break; case 7680000: - openair0_cfg[0].samples_per_packet = 1024; + //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].tx_bw = 5e6; openair0_cfg[0].rx_bw = 5e6; break; case 1920000: - openair0_cfg[0].samples_per_packet = 256; + //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].tx_bw = 1.25e6; openair0_cfg[0].rx_bw = 1.25e6; @@ -585,7 +626,7 @@ extern "C" { } else { printf("Found USRP B200"); - args += ",num_recv_frames=256" ; + args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096" ; s->usrp = uhd::usrp::multi_usrp::make(args); // s->usrp->set_rx_subdev_spec(rx_subdev); @@ -611,30 +652,35 @@ extern "C" { switch ((int)openair0_cfg[0].sample_rate) { case 30720000: s->usrp->set_master_clock_rate(30.72e6); + //openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 115; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; case 23040000: s->usrp->set_master_clock_rate(23.04e6); //to be checked + //openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 113; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; case 15360000: s->usrp->set_master_clock_rate(30.72e06); + //openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 103; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; case 7680000: s->usrp->set_master_clock_rate(30.72e6); + //openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 80; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; case 1920000: s->usrp->set_master_clock_rate(30.72e6); + //openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 40; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; @@ -758,7 +804,8 @@ extern "C" { device->trx_stop_func = trx_usrp_stop; device->trx_set_freq_func = trx_usrp_set_freq; device->trx_set_gains_func = trx_usrp_set_gains; - + device->openair0_cfg = openair0_cfg; + s->sample_rate = openair0_cfg[0].sample_rate; // TODO: // init tx_forward_nsamps based usrp_time_offset ex From c73535b439c372ce49b90b824a1d259328dd6042 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 22 Aug 2016 19:21:41 +0200 Subject: [PATCH 163/206] minor type for test_case_list.xml --- cmake_targets/autotests/test_case_list.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index a36390d8cf..b60e95c2a3 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -3393,7 +3393,6 @@ c sudo mkdir -p /usr/local/etc/oai/freeDiamter; sudo cp -vf $OPENAIRCN_DIR/ETC/hss.conf /usr/local/etc/oai ; sudo cp -vf $OPENAIRCN_DIR/ETC/hss_fd.conf /usr/local/etc/oai/freeDiameter ; $OPENAIRCN_DIR/SCRIPTS/check_hss_s6a_certificate /usr/local/etc/oai/freeDiameter/ hss.openair4G.eur; $OPENAIRCN_DIR/SCRIPTS/build_hss -c -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E ifconfig eth0 add 192.172.0.1 sleep 10;$OPENAIRCN_DIR/TEST/autotests/tools/run_epc From 6d3928739353cebe3924e7f36f0b5b1c8c2e5e6c Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 22 Aug 2016 20:16:55 +0200 Subject: [PATCH 164/206] minor type for syntax error --- targets/RT/USER/lte-enb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 51ea3709e1..f8249b755d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -188,7 +188,7 @@ static inline void thread_top_init(char *thread_name, if (sched_setattr(0, &attr, flags) < 0 ) { perror("[SCHED] eNB tx thread: sched_setattr failed\n"); - return &eNB_thread_rxtx_status; + exit_fun("Error setting deadline scheduler"); } LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); From 1309358bb5980a143e6ba5f79eb78f2177dc0259 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 24 Aug 2016 23:14:44 -0700 Subject: [PATCH 165/206] changes for oaisim to function with new threading architecture and trx_read/trx_write emulation. Tested for 5/10 MHz TM1. Multiple-antenna mode fails. --- cmake_targets/tools/build_helper | 2 +- openair1/PHY/INIT/lte_init.c | 3 +- openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c | 5 + openair1/PHY/TOOLS/defs.h | 4 +- openair1/PHY/TOOLS/signal_energy.c | 2 +- openair1/PHY/defs.h | 6 +- openair1/PHY/extern.h | 2 +- openair1/SCHED/phy_procedures_lte_ue.c | 53 +++--- openair1/SIMULATION/RF/adc.c | 4 +- openair1/SIMULATION/RF/dac.c | 8 +- openair1/SIMULATION/RF/defs.h | 16 +- openair1/SIMULATION/RF/rf.c | 4 +- openair1/SIMULATION/TOOLS/defs.h | 16 +- openair1/SIMULATION/TOOLS/multipath_channel.c | 16 +- ...enb.band7.generic.oaisim.local_no_mme.conf | 2 +- targets/RT/USER/lte-enb.c | 22 ++- targets/RT/USER/lte-ue.c | 38 +++- targets/SIMU/USER/channel_sim.c | 15 +- targets/SIMU/USER/oaisim.c | 87 ++++++--- targets/SIMU/USER/oaisim_config.c | 2 +- targets/SIMU/USER/oaisim_functions.c | 174 ++++++++++++++---- 21 files changed, 324 insertions(+), 157 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 4738acb7f3..514d7748ac 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -179,7 +179,7 @@ install_nettle_from_source() { cd /tmp echo "Downloading nettle archive" $SUDO rm -rf /tmp/nettle-2.5.tar.gz* /tmp/nettle-2.5 - wget https://ftp.gnu.org/gnu/nettle/nettle-2.5.tar.gz + wget http://ftp.nluug.nl/gnu/nettle/nettle-2.5.tar.gz if [ $? -ne 0 ]; then wget ftp://ftp.lysator.liu.se/pub/security/lsh/nettle-2.5.tar.gz fi diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 4386ca5d47..259a7ba77a 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -988,7 +988,8 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, ue->total_received_bits[eNB_id] = 0; } - ue->tx_power_dBm=-127; + for (i=0;i<10;i++) + ue->tx_power_dBm[i]=-127; if (abstraction_flag == 0) { diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c index b78a7e24fd..c2be7ad1bd 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c @@ -30,6 +30,8 @@ #include "PHY/defs.h" #include "PHY/extern.h" +#include "UTIL/LOG/vcd_signal_dumper.h" + #define DEBUG_PHY // Adjust location synchronization point to account for drift @@ -48,6 +50,8 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, int diff; short Re,Im,ncoef; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); + ncoef = 32767 - coef; #ifdef DEBUG_PHY @@ -98,6 +102,7 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms, ue->proc.proc_rxtx[0].frame_rx,ue->rx_offset,max_pos,max_pos_fil,temp); #endif //DEBUG_PHY + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); } diff --git a/openair1/PHY/TOOLS/defs.h b/openair1/PHY/TOOLS/defs.h index 8d30a7ea10..3a8a58b6f2 100644 --- a/openair1/PHY/TOOLS/defs.h +++ b/openair1/PHY/TOOLS/defs.h @@ -296,10 +296,10 @@ int32_t subcarrier_energy(int32_t *,uint32_t, int32_t* subcarrier_energy, uint16 */ int32_t signal_energy_nodc(int32_t *,uint32_t); -/*!\fn double signal_energy_fp(double **, double **,uint32_t, uint32_t,uint32_t); +/*!\fn double signal_energy_fp(double s_re[2][30720], double s_im[2][30720],uint32_t, uint32_t,uint32_t); \brief Computes the signal energy per subcarrier */ -double signal_energy_fp(double **s_re, double **s_im, uint32_t nb_antennas, uint32_t length,uint32_t offset); +double signal_energy_fp(double s_re[2][30720], double s_im[2][30720], uint32_t nb_antennas, uint32_t length,uint32_t offset); /*!\fn double signal_energy_fp2(struct complex *, uint32_t); \brief Computes the signal energy per subcarrier diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c index 373fdc0d90..afd1c727f3 100755 --- a/openair1/PHY/TOOLS/signal_energy.c +++ b/openair1/PHY/TOOLS/signal_energy.c @@ -255,7 +255,7 @@ int32_t signal_energy_nodc(int32_t *input,uint32_t length) } #endif -double signal_energy_fp(double **s_re,double **s_im,uint32_t nb_antennas,uint32_t length,uint32_t offset) +double signal_energy_fp(double s_re[2][30720],double s_im[2][30720],uint32_t nb_antennas,uint32_t length,uint32_t offset) { int32_t aa,i; diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 5fdd88cd23..c4c37d2b72 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -612,6 +612,8 @@ typedef struct { int is_synchronized; /// Data structure for UE process scheduling UE_proc_t proc; + /// Flag to indicate the UE shouldn't do timing correction at all + int no_timing_correction; /// \brief Total gain of the TX chain (16-bit baseband I/Q to antenna) uint32_t tx_total_gain_dB; /// \brief Total gain of the RX chain (antenna to baseband I/Q) This is a function of rx_gain_mode (and the corresponding gain) and the rx_gain of the card. @@ -623,9 +625,9 @@ typedef struct { /// \brief Total gains with bypassed RF gain stage (ExpressMIMO2/Lime) uint32_t rx_gain_byp[4]; /// \brief Current transmit power - int8_t tx_power_dBm; + int8_t tx_power_dBm[10]; /// \brief Total number of REs in current transmission - int tx_total_RE; + int tx_total_RE[10]; /// \brief Maximum transmit power int8_t tx_power_max_dBm; /// \brief Number of eNB seen by UE diff --git a/openair1/PHY/extern.h b/openair1/PHY/extern.h index 2144c4f01d..8a5bf5e8f5 100755 --- a/openair1/PHY/extern.h +++ b/openair1/PHY/extern.h @@ -111,7 +111,7 @@ extern double p_qam64[8]; extern double beta1_dlsch[6][MCS_COUNT]; extern double beta2_dlsch[6][MCS_COUNT]; -extern char eNB_functions[5][20]; +extern char eNB_functions[6][20]; extern char eNB_timing[2][20]; diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 2612302d54..58bbcc8ac0 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -718,7 +718,7 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin frame_tx, eNB_id, subframe_tx); - // LOG_I(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[Mod_id].radioResourceConfigCommon); + LOG_D(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[ue->Mod_id].radioResourceConfigCommon); } } @@ -744,17 +744,17 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->prach_resources[eNB_id]->ra_RNTI); if ((ue->mac_enabled==1) && (mode != calib_prach_tx)) { - ue->tx_power_dBm = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id); + ue->tx_power_dBm[subframe_tx] = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id); } else { - ue->tx_power_dBm = ue->tx_power_max_dBm; + ue->tx_power_dBm[subframe_tx] = ue->tx_power_max_dBm; ue->prach_resources[eNB_id]->ra_PreambleIndex = 19; } - ue->tx_total_RE = 96; + ue->tx_total_RE[subframe_tx] = 96; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm, + ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm[subframe_tx], ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL, 6); @@ -766,7 +766,7 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->Mod_id, proc->frame_rx, proc->subframe_tx, - ue->tx_power_dBm, + ue->tx_power_dBm[subframe_tx], ue->prach_vars[eNB_id]->amp); @@ -778,7 +778,7 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin LOG_D(PHY,"[UE %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n", ue->Mod_id, get_PL(ue->Mod_id,ue->CC_id,eNB_id), - ue->tx_power_dBm, + ue->tx_power_dBm[subframe_tx], dB_fixed(prach_power), ue->prach_vars[eNB_id]->amp); } else { @@ -1036,15 +1036,15 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB if (abstraction_flag == 0) { if (ue->mac_enabled==1) { pusch_power_cntl(ue,proc,eNB_id,1, abstraction_flag); - ue->tx_power_dBm = ue->ulsch[eNB_id]->Po_PUSCH; + ue->tx_power_dBm[subframe_tx] = ue->ulsch[eNB_id]->Po_PUSCH; } else { - ue->tx_power_dBm = ue->tx_power_max_dBm; + ue->tx_power_dBm[subframe_tx] = ue->tx_power_max_dBm; } - ue->tx_total_RE = nb_rb*12; + ue->tx_total_RE[subframe_tx] = nb_rb*12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - tx_amp = get_tx_amp(ue->tx_power_dBm, + tx_amp = get_tx_amp(ue->tx_power_dBm[, ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL, nb_rb); @@ -1052,7 +1052,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB tx_amp = AMP; #endif LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", - Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm,ue->tx_power_max_dBm, tx_amp); + Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm[subframe_tx],ue->tx_power_max_dBm, tx_amp); start_meas(&ue->ulsch_modulation_stats); ulsch_modulation(ue->common_vars.txdataF, tx_amp, @@ -1156,8 +1156,8 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin else { Po_PUCCH = ue->tx_power_max_dBm; } - ue->tx_power_dBm = Po_PUCCH; - ue->tx_total_RE = 12; + ue->tx_power_dBm[subframe_tx] = Po_PUCCH; + ue->tx_total_RE[subframe_tx] = 12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(Po_PUCCH, @@ -1220,8 +1220,8 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin else { Po_PUCCH = ue->tx_power_max_dBm; } - ue->tx_power_dBm = Po_PUCCH; - ue->tx_total_RE = 12; + ue->tx_power_dBm[subframe_tx] = Po_PUCCH; + ue->tx_total_RE[subframe_tx] = 12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(Po_PUCCH, @@ -1286,7 +1286,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui //phy_procedures_emos_UE_TX(next_slot); #endif - ue->tx_power_dBm=-127; + ue->tx_power_dBm[subframe_tx]=-127; if (abstraction_flag==0) { for (aa=0; aanb_antennas_tx; aa++) { @@ -1391,6 +1391,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) { // check if we have PRACH opportunity + if (is_prach_subframe(&ue->frame_parms,frame_tx,subframe_tx)) { ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode); @@ -1484,17 +1485,17 @@ void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); + eNB_id = 0; - if (abstraction_flag == 0) - lte_adjust_synch(&ue->frame_parms, - ue, - eNB_id, - 0, - 16384); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); + if (abstraction_flag == 0) { + if (ue->no_timing_correction==0) + lte_adjust_synch(&ue->frame_parms, + ue, + eNB_id, + 0, + 16384); + } } diff --git a/openair1/SIMULATION/RF/adc.c b/openair1/SIMULATION/RF/adc.c index 6dc1c7f8e6..3f89a3cfe5 100755 --- a/openair1/SIMULATION/RF/adc.c +++ b/openair1/SIMULATION/RF/adc.c @@ -26,8 +26,8 @@ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ -void adc(double **r_re, - double **r_im, +void adc(double r_re[2][30720], + double r_im[2][30720], unsigned int input_offset, unsigned int output_offset, unsigned int **output, diff --git a/openair1/SIMULATION/RF/dac.c b/openair1/SIMULATION/RF/dac.c index 22e286a496..ba67eb1f32 100755 --- a/openair1/SIMULATION/RF/dac.c +++ b/openair1/SIMULATION/RF/dac.c @@ -31,8 +31,8 @@ #include #include "PHY/TOOLS/defs.h" -void dac(double **s_re, - double **s_im, +void dac(double s_re[2][30720], + double s_im[2][30720], uint32_t **input, uint32_t input_offset, uint32_t nb_tx_antennas, @@ -81,8 +81,8 @@ void dac(double **s_re, } } -double dac_fixed_gain(double **s_re, - double **s_im, +double dac_fixed_gain(double s_re[2][30720], + double s_im[2][30720], uint32_t **input, uint32_t input_offset, uint32_t nb_tx_antennas, diff --git a/openair1/SIMULATION/RF/defs.h b/openair1/SIMULATION/RF/defs.h index 984dfa6ca8..4bd9528dae 100644 --- a/openair1/SIMULATION/RF/defs.h +++ b/openair1/SIMULATION/RF/defs.h @@ -64,16 +64,16 @@ void rf_rx(double **r_re, double IQ_imb_dB, double IQ_phase); -void rf_rx_simple(double **r_re, - double **r_im, +void rf_rx_simple(double r_re[2][30720], + double r_im[2][30720], unsigned int nb_rx_antennas, unsigned int length, double s_time, double rx_gain_dB); -void adc(double **r_re, - double **r_im, +void adc(double r_re[2][30720], + double r_im[2][30720], unsigned int input_offset, unsigned int output_offset, int **output, @@ -81,8 +81,8 @@ void adc(double **r_re, unsigned int length, unsigned char B); -void dac(double **s_re, - double **s_im, +void dac(double s_re[2][30720], + double s_im[2][30720], int **input, unsigned int input_offset, unsigned int nb_tx_antennas, @@ -92,8 +92,8 @@ void dac(double **s_re, unsigned int meas_length, unsigned int meas_offset); -double dac_fixed_gain(double **s_re, - double **s_im, +double dac_fixed_gain(double s_re[2][30720], + double s_im[2][30720], int **input, unsigned int input_offset, unsigned int nb_tx_antennas, diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c index 1f240595aa..2bcb64727d 100644 --- a/openair1/SIMULATION/RF/rf.c +++ b/openair1/SIMULATION/RF/rf.c @@ -206,8 +206,8 @@ void rf_rx(double **r_re, } } -void rf_rx_simple(double **r_re, - double **r_im, +void rf_rx_simple(double r_re[2][30720], + double r_im[2][30720], unsigned int nb_rx_antennas, unsigned int length, double s_time, diff --git a/openair1/SIMULATION/TOOLS/defs.h b/openair1/SIMULATION/TOOLS/defs.h index c72ea743b1..536655340b 100644 --- a/openair1/SIMULATION/TOOLS/defs.h +++ b/openair1/SIMULATION/TOOLS/defs.h @@ -219,10 +219,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); /**\fn void multipath_channel(channel_desc_t *desc, - double **tx_sig_re, - double **tx_sig_im, - double **rx_sig_re, - double **rx_sig_im, + double tx_sig_re[2][30720], + double tx_sig_im[2][30720], + double rx_sig_re[2][30720], + double rx_sig_im[2][30720], uint32_t length, uint8_t keep_channel) @@ -237,10 +237,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); */ void multipath_channel(channel_desc_t *desc, - double **tx_sig_re, - double **tx_sig_im, - double **rx_sig_re, - double **rx_sig_im, + double tx_sig_re[2][30720], + double tx_sig_im[2][30720], + double rx_sig_re[2][30720], + double rx_sig_im[2][30720], uint32_t length, uint8_t keep_channel); /* diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index 9a72ca6423..aae9e974a7 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -44,10 +44,10 @@ uint8_t multipath_channel_nosigconv(channel_desc_t *desc) //#define CHANNEL_SSE #ifdef CHANNEL_SSE void multipath_channel(channel_desc_t *desc, - double **tx_sig_re, - double **tx_sig_im, - double **rx_sig_re, - double **rx_sig_im, + double tx_sig_re[2][30720], + double tx_sig_im[2][30720], + double rx_sig_re[2][30720], + double rx_sig_im[2][30720], uint32_t length, uint8_t keep_channel) { @@ -150,10 +150,10 @@ void multipath_channel(channel_desc_t *desc, #else void multipath_channel(channel_desc_t *desc, - double **tx_sig_re, - double **tx_sig_im, - double **rx_sig_re, - double **rx_sig_im, + double tx_sig_re[2][30720], + double tx_sig_im[2][30720], + double rx_sig_re[2][30720], + double rx_sig_im[2][30720], uint32_t length, uint8_t keep_channel) { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf index ad3bcfcf92..3504adfff0 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf @@ -24,7 +24,7 @@ eNBs = component_carriers = ( { node_function = "eNodeB_3GPP"; - node_timing = "synch_to_other"; + node_timing = "synch_to_ext_device"; node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 51ea3709e1..cddef6ccc8 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -191,7 +191,7 @@ static inline void thread_top_init(char *thread_name, return &eNB_thread_rxtx_status; } - LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB %s deadline thread (TID %ld) started on CPU %d\n", gettid(), thread_name,sched_getcpu() ); #else //LOW_LATENCY int policy, s, j; @@ -654,7 +654,7 @@ static void* eNB_thread_rxtx( void* param ) { return &eNB_thread_rxtx_status; } -#if defined(ENABLE_ITTI) +#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME) /* Wait for eNB application initialization to be complete (eNB registration to MME) */ static void wait_system_ready (char *message, volatile int *start_flag) { @@ -1032,7 +1032,7 @@ void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) { void rx_fh_slave(PHY_VARS_eNB *eNB,int *frame,int *subframe) { // This case is for synchronization to another thread - // it just waits for an external event. The actual rx_rh is handle by the asynchronous RX thread + // it just waits for an external event. The actual rx_fh is handle by the asynchronous RX thread eNB_proc_t *proc=&eNB->proc; if (wait_on_condition(&proc->mutex_FH,&proc->cond_FH,&proc->instance_cnt_FH,"rx_fh_slave") < 0) @@ -1129,7 +1129,7 @@ void wakeup_slaves(eNB_proc_t *proc) { break; } } else { - LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); + LOG_W( PHY,"[eNB] Frame %d, slave CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave); exit_fun( "FH thread busy" ); break; } @@ -1161,7 +1161,7 @@ static void* eNB_thread_FH( void* param ) { wait_sync("eNB_thread_FH"); -#if defined(ENABLE_ITTI) +#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME) if (eNB->node_function < NGFI_RRU_IF5) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif @@ -1273,7 +1273,7 @@ static void* eNB_thread_single( void* param ) { wait_sync("eNB_thread_single"); -#if defined(ENABLE_ITTI) +#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME) if (eNB->node_function < NGFI_RRU_IF5) wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); #endif @@ -1307,6 +1307,7 @@ static void* eNB_thread_single( void* param ) { subframe++; } + LOG_D(PHY,"eNB Fronthaul thread, frame %d, subframe %d\n",frame,subframe); // synchronization on FH interface, acquire signals/data and block if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe); @@ -1314,6 +1315,7 @@ static void* eNB_thread_single( void* param ) { T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); + // At this point, all information for subframe has been received on FH interface // If this proc is to provide synchronization, do so wakeup_slaves(proc); @@ -1546,17 +1548,17 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c for (i=0; inb_antennas_rx; i++) { free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]); - rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + rxdata[i] = (int32_t*)(32 + malloc16(32+frame_parms->samples_per_tti*10*sizeof(int32_t))); // FIXME broken memory allocation phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD FIXME! N_TA_offset > 16 => access of unallocated memory - memset(rxdata[i], 0, openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t)); + memset(rxdata[i], 0, frame_parms->samples_per_tti*10*sizeof(int32_t)); printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset); } for (i=0; inb_antennas_tx; i++) { free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); - txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation + txdata[i] = (int32_t*)(32 + malloc16(32 + frame_parms->samples_per_tti*10*sizeof(int32_t))); // FIXME broken memory allocation phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i]; - memset(txdata[i],0, openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t)); + memset(txdata[i],0, frame_parms->samples_per_tti*10*sizeof(int32_t)); printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]); } } diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 88bce26d6c..c33005ebab 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -793,6 +793,16 @@ static void *UE_thread_rxn_txnp4(void *arg) UE->UE_mode[0] = PRACH; } } + + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || + (UE->frame_parms.frame_type == FDD) || + (subframe_select( &UE->frame_parms, proc->subframe_tx ) == SF_S)) { + + if (UE->mode != loop_through_memory) { + phy_procedures_UE_TX(UE,proc,0,0,normal_txrx,no_relay); + } + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 0 ); @@ -967,15 +977,18 @@ void *UE_thread(void *arg) { if (start_rx_stream==0) { start_rx_stream=1; if (UE->mode != loop_through_memory) { - LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); - rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void**)rxdata, - UE->rx_offset, - UE->frame_parms.nb_antennas_rx); - if (rxs != UE->rx_offset) { - exit_fun("problem in rx"); - return &UE_thread_retval; + + if (UE->no_timing_correction==0) { + LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); + rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void**)rxdata, + UE->rx_offset, + UE->frame_parms.nb_antennas_rx); + if (rxs != UE->rx_offset) { + exit_fun("problem in rx"); + return &UE_thread_retval; + } } UE->rx_offset=0; UE->proc.proc_rxtx[0].frame_rx++; @@ -1049,10 +1062,15 @@ void *UE_thread(void *arg) { int instance_cnt_rxtx = ++proc->instance_cnt_rxtx; proc->subframe_rx=sf; proc->subframe_tx=(sf+4)%10; - proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5)?1:0; + proc->frame_tx = proc->frame_rx + ((proc->subframe_rx>5)?1:0); proc->timestamp_tx = timestamp+(4*UE->frame_parms.samples_per_tti)-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; + if (sf != (timestamp/UE->frame_parms.samples_per_tti)%10) { + LOG_E(PHY,"steady-state UE_thread error : frame_rx %d, subframe_rx %d, frame_tx %d, subframe_tx %d, rx subframe %d\n",proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,(timestamp/UE->frame_parms.samples_per_tti)%10); + exit(-1); + } + if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" ); exit_fun("nothing to add"); diff --git a/targets/SIMU/USER/channel_sim.c b/targets/SIMU/USER/channel_sim.c index 8ff6c88962..9034fc0574 100644 --- a/targets/SIMU/USER/channel_sim.c +++ b/targets/SIMU/USER/channel_sim.c @@ -437,9 +437,14 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N txdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.txdata; sf_offset = subframe*frame_parms->samples_per_tti; - if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm + + if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe] + UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB) <= -125.0) { // don't simulate a UE that is too weak + LOG_D(OCM,"[SIM][UL] UE %d tx_pwr %d dBm (num_RE %d) for subframe %d (sf_offset %d)\n", + UE_id, + PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe], + PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe], + subframe,sf_offset); } else { tx_pwr = dac_fixed_gain((double**)s_re, @@ -451,13 +456,13 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N sf_offset, frame_parms->ofdm_symbol_size, 14, - (double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE), - PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE); // This make the previous argument the total power + (double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe]-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]), + PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]); // This make the previous argument the total power LOG_D(OCM,"[SIM][UL] UE %d tx_pwr %f dBm (target %d dBm, num_RE %d) for subframe %d (sf_offset %d)\n", UE_id, 10*log10(tx_pwr), - PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm, - PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE, + PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe], + PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe], subframe,sf_offset); diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c index fddbf517fd..258096fe73 100644 --- a/targets/SIMU/USER/oaisim.c +++ b/targets/SIMU/USER/oaisim.c @@ -139,8 +139,10 @@ node_desc_t *ue_data[NUMBER_OF_UE_MAX]; pthread_cond_t sync_cond; pthread_mutex_t sync_mutex; -int sync_var; +int sync_var=-1; +pthread_mutex_t subframe_mutex; +int subframe_eNB_mask=0,subframe_UE_mask=0; openair0_config_t openair0_cfg[MAX_CARDS]; uint32_t downlink_frequency[MAX_NUM_CCs][4]; @@ -451,6 +453,10 @@ typedef enum l2l1_task_state_e { l2l1_task_state_t l2l1_state = L2L1_WAITTING; +extern openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs]; +extern openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs]; + + /*------------------------------------------------------------------------------*/ void * l2l1_task (void *args_p) @@ -719,6 +725,40 @@ l2l1_task (void *args_p) clear_eNB_transport_info (oai_emulation.info.nb_enb_local); + CC_id=0; + int all_done=0; + while (all_done==0) { + pthread_mutex_lock(&subframe_mutex); + int subframe_eNB_mask_local = subframe_eNB_mask; + int subframe_UE_mask_local = subframe_UE_mask; + pthread_mutex_unlock(&subframe_mutex); + LOG_D(EMU,"Frame %d, Subframe %d: Checking masks %x,%x\n",frame,sf,subframe_eNB_mask,subframe_UE_mask); + if ((subframe_eNB_mask_local == ((1<frame_parms.samples_per_tti; + } + for (UE_inst = 0; UE_instframe_parms.samples_per_tti; + } + + for (eNB_inst = oai_emulation.info.first_enb_local; (eNB_inst < (oai_emulation.info.first_enb_local @@ -727,6 +767,7 @@ l2l1_task (void *args_p) if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) { T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(sf)); + /* LOG_D(EMU, "PHY procedures eNB %d for frame %d, subframe %d TDD %d/%d Nid_cell %d\n", eNB_inst, @@ -736,7 +777,7 @@ l2l1_task (void *args_p) PHY_vars_eNB_g[eNB_inst][0]->frame_parms.tdd_config, PHY_vars_eNB_g[eNB_inst][0]->frame_parms.Nid_cell); - + */ #ifdef OPENAIR2 //Application: traffic gen update_otg_eNB (eNB_inst, oai_emulation.info.time_ms); @@ -744,35 +785,8 @@ l2l1_task (void *args_p) //IP/OTG to PDCP and PDCP to IP operation // pdcp_run (frame, 1, 0, eNB_inst); //PHY_vars_eNB_g[eNB_id]->Mod_id #endif + - CC_id=0; - // trigger synch event to RAN FH thread for CC_id - eNB_proc_t *proc = &PHY_vars_eNB_g[eNB_inst][CC_id]->proc; - - - if (pthread_mutex_lock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "error locking mutex for FH\n"); - exit_fun( "error locking mutex" ); - break; - } - int cnt_FH = ++proc->instance_cnt_FH; - proc->frame_rx = frame; - proc->subframe_rx = sf; - proc->timestamp_rx += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti; - pthread_mutex_unlock( &proc->mutex_FH ); - - if (cnt_FH == 0) { - if (pthread_cond_signal(&proc->cond_FH) != 0) { - LOG_E(PHY,"ERROR pthread_cond_signal for eNB FH CCid %d\n",proc->CC_id); - exit_fun("ERROR pthread_cond_signal"); - break; - } - } - else { - LOG_W(PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %d)\n",proc->instance_cnt_FH); - exit_fun("FH thread busy"); - break; - } #ifdef PRINT_STATS if((sf==9) && frame%10==0) @@ -1099,6 +1113,10 @@ main (int argc, char **argv) sinr_dB = -20; } + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + pthread_mutex_init(&subframe_mutex, NULL); + #ifdef OPENAIR2 init_omv (); #endif @@ -1116,6 +1134,15 @@ main (int argc, char **argv) init_openair2 (); init_ocm (); + + // wait for all threads to startup + sleep(3); + printf("Sending sync to all threads\n"); + + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); #ifdef SMBV // Rohde&Schwarz SMBV100A vector signal generator diff --git a/targets/SIMU/USER/oaisim_config.c b/targets/SIMU/USER/oaisim_config.c index 51a5a03eac..a470558c27 100644 --- a/targets/SIMU/USER/oaisim_config.c +++ b/targets/SIMU/USER/oaisim_config.c @@ -456,7 +456,7 @@ int olg_config(void) set_comp_log(PHY, LOG_TRACE, 0x15, 1); set_comp_log(PDCP, LOG_DEBUG, 0x15,1); set_comp_log(RRC, LOG_DEBUG, 0x15,1); - set_comp_log(OCM, LOG_ERR, 0x15,20); + set_comp_log(OCM, LOG_DEBUG, 0x15,20); set_comp_log(OTG, LOG_DEBUG, 0x15,1); set_comp_log(OMG, LOG_NOTICE, 0x15,1); set_comp_log(OPT, LOG_ERR, 0x15,1); diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 7a5c36b45d..f6cb9fcb04 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -957,6 +957,11 @@ void init_seed(uint8_t set_seed) } } +openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs]; +openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs]; +openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs]; +openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs]; + int eNB_trx_start(openair0_device *device) { return(0); } @@ -990,42 +995,44 @@ int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { return(0); } +extern pthread_mutex_t subframe_mutex; +extern int subframe_eNB_mask,subframe_UE_mask; + int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { - return(0); -} - -int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { - return(0); -} - -int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { int eNB_id = device->Mod_id; int CC_id = device->CC_id; - int UE_id; - int subframe = (timestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10; - for (UE_id=0;UE_id<=NB_UE_INST;UE_id++) { - do_DL_sig(eNB2UE, - enb_data, - ue_data, - subframe, - 0, //abstraction_flag, - &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms, - UE_id, - CC_id); - } - return(0); -} + int subframe; + int ready_for_new_subframe=0; + int subframe_eNB_mask_local; + int sample_count=0; -int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + *ptimestamp = last_eNB_rx_timestamp[eNB_id][CC_id]; - int UE_id = device->Mod_id; - int CC_id = device->CC_id; - int eNB_id; - int subframe = (timestamp/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10; + LOG_D(PHY,"eNB_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps, + (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id], + (unsigned long long)last_eNB_rx_timestamp[eNB_id][CC_id], + (*ptimestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10); + // if we're at a subframe boundary generate UL signals for this eNB - for (eNB_id=0;eNB_id<=NB_eNB_INST;eNB_id++) { + while (sample_countframe_parms.samples_per_tti)%10; + LOG_D(PHY,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n", + subframe,(unsigned long long)*ptimestamp, + (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]); + do_UL_sig(UE2eNB, enb_data, ue_data, @@ -1035,8 +1042,87 @@ int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **bu 0, // frame is only used for abstraction eNB_id, CC_id); + + + last_eNB_rx_timestamp[eNB_id][CC_id] += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti; + sample_count += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti; } - return(0); + + return(nsamps); +} + +int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + + int UE_id = device->Mod_id; + int CC_id = device->CC_id; + int subframe; + int ready_for_new_subframe=0; + int subframe_UE_mask_local; + int sample_count=0; + int read_size; + + *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id]; + + LOG_D(PHY,"UE_trx_read nsamps %d TS(%llu,%llu)\n",nsamps, + (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id], + (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id]); + + if (nsamps < PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) + read_size = nsamps; + else + read_size = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti; + + while (sample_countframe_parms.samples_per_tti)%10; + if ((last_UE_rx_timestamp[UE_id][CC_id]%PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) > 0) + subframe++; + + last_UE_rx_timestamp[UE_id][CC_id] += read_size; + sample_count += read_size; + + if (subframe > 9) + return(nsamps); + + LOG_D(PHY,"UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu)\n", + subframe,(unsigned long long)*ptimestamp, + (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id]); + do_DL_sig(eNB2UE, + enb_data, + ue_data, + subframe, + 0, //abstraction_flag, + &PHY_vars_UE_g[UE_id][CC_id]->frame_parms, + UE_id, + CC_id); + } + + return(nsamps); +} + +int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + + return(nsamps); +} + +int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { + + return(nsamps); } void init_devices(void){ @@ -1055,8 +1141,10 @@ void init_devices(void){ PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_stop_func = eNB_trx_stop; PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_freq_func = eNB_trx_set_freq; PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_gains_func = eNB_trx_set_gains; + current_eNB_rx_timestamp[eNB_id][CC_id] = PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti; + last_eNB_rx_timestamp[eNB_id][CC_id] = 0; } - for (UE_id=0;UE_idrfdevice.Mod_id = UE_id; PHY_vars_UE_g[UE_id][CC_id]->rfdevice.CC_id = CC_id; PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_start_func = UE_trx_start; @@ -1066,6 +1154,9 @@ void init_devices(void){ PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_stop_func = UE_trx_stop; PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_freq_func = UE_trx_set_freq; PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_gains_func = UE_trx_set_gains; + current_UE_rx_timestamp[UE_id][CC_id] = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti; + last_UE_rx_timestamp[UE_id][CC_id] = 0; + } } } @@ -1123,7 +1214,11 @@ void init_openair1(void) //N_TA_offset for (CC_id=0; CC_iduse_ia_receiver = 0; + + PHY_vars_UE_g[UE_id][CC_id]->use_ia_receiver = 0; + PHY_vars_UE_g[UE_id][CC_id]->mode = normal_txrx; + PHY_vars_UE_g[UE_id][CC_id]->mac_enabled = 1; + PHY_vars_UE_g[UE_id][CC_id]->no_timing_correction = 1; if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.frame_type == TDD) { if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.N_RB_DL == 100) @@ -1396,7 +1491,7 @@ void update_ocm() enb_data[eNB_id]->tx_power_dBm = PHY_vars_eNB_g[eNB_id][0]->frame_parms.pdsch_config_common.referenceSignalPower; for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) - ue_data[UE_id]->tx_power_dBm = PHY_vars_UE_g[UE_id][0]->tx_power_dBm; + ue_data[UE_id]->tx_power_dBm = PHY_vars_UE_g[UE_id][0]->tx_power_dBm[0]; /* check if the openair channel model is activated used for PHY abstraction : path loss*/ @@ -1450,10 +1545,10 @@ void update_ocm() UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower; } - LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",eNB_id,UE_id,CC_id, + LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",eNB_id,UE_id,CC_id, eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB, PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB); - // printf("[SIM] Path loss from UE %d to eNB %d => %f dB\n",UE_id,eNB_id,UE2eNB[UE_id][eNB_id]->path_loss_dB); + } } } @@ -1721,3 +1816,14 @@ void init_time() td_avg = TARGET_SF_TIME_NS; } +int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) { + + return(0); + + +} + +int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) { + + return(0); +} From 9116065678834b0243418fcca308225ea93a985b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 25 Aug 2016 14:14:35 +0200 Subject: [PATCH 166/206] minor fix to usrp timing logging --- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 40 +++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index f2cc289ed7..f9c2309ab8 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "UTIL/LOG/log_extern.h" #include "common_lib.h" #ifdef __SSE4_1__ # include @@ -213,9 +214,11 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, time_avg= time_diff; else time_avg=(time_diff+time_avg) /2.0; - - if ( loop%10000 ==0) - printf("\n usrp_write: min(ns)=%d, max(ns)=%d, avg(ns)=%d", (int)time_min, (int)time_max,(int)time_avg); + + //prints statics of uhd every 10 seconds + if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0) + LOG_I(HW,"usrp_write: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg); + loop++; return ret; } @@ -318,20 +321,23 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); *ptimestamp = s->rx_timestamp; - clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end); - time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec); - if (time_min==0 ||loop==1 || time_min > time_diff) - time_min=time_diff; - if (time_max==0 || loop==1|| time_max < time_diff) - time_max=time_diff; - if (time_avg ==0 ||loop==1) - time_avg= time_diff; - else - time_avg=(time_diff+time_avg) /2.0; - if ( loop % 10000==0) - printf("\n usrp_read: min(ns)=%d, max(ns)=%d, avg(ns)=%d", (int)time_min, (int)time_max,(int)time_avg); - loop++; - return samples_received; + clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end); + time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec); + if (time_min==0 ||loop==1 || time_min > time_diff) + time_min=time_diff; + if (time_max==0 ||loop==1 || time_max < time_diff) + time_max=time_diff; + if (time_avg ==0 ||loop==1) + time_avg= time_diff; + else + time_avg=(time_diff+time_avg) /2.0; + + //prints statics of uhd every 10 seconds + if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0) + LOG_I(HW,"usrp_read: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg); + + loop++; + return samples_received; } /*! \brief Get current timestamp of USRP From 4f5d818065d5193ce4bf165555c852983755f648 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 25 Aug 2016 18:11:30 +0200 Subject: [PATCH 167/206] minor syntax fix of uespec_procedures --- openair1/SCHED/phy_procedures_lte_ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 58bbcc8ac0..5c884112fd 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -1044,7 +1044,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB ue->tx_total_RE[subframe_tx] = nb_rb*12; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - tx_amp = get_tx_amp(ue->tx_power_dBm[, + tx_amp = get_tx_amp(ue->tx_power_dBm, ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL, nb_rb); From 12e9b05abcc26cc7b2a7a1ed7a113c1f5c92454e Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 31 Aug 2016 11:08:37 -0700 Subject: [PATCH 168/206] change in a comment --- targets/RT/USER/lte-enb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index a7a0314bdc..9d4b0f1aeb 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1076,8 +1076,8 @@ int wakeup_rxtx(eNB_proc_t *proc,eNB_rxtx_proc_t *proc_rxtx,LTE_DL_FRAME_PARMS * // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti, - // and proc->subframe_tx = proc->subframe_rx+3 + // we want to generate subframe (n+4), so TS_tx = TX_rx+4*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+4 proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); proc_rxtx->frame_rx = proc->frame_rx; proc_rxtx->subframe_rx = proc->subframe_rx; From e10b7e8162ad2916756a330ba470916f876c0166 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 1 Sep 2016 03:47:51 -0700 Subject: [PATCH 169/206] RCC configuration files for IF4p5 --- .../CONF/rcc.band7.tm1.100PRB.if4p5.conf | 191 ++++++++++++++++++ .../CONF/rcc.band7.tm1.50PRB.if4p5.conf | 191 ++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.100PRB.if4p5.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.100PRB.if4p5.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.100PRB.if4p5.conf new file mode 100644 index 0000000000..d97dc0c002 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.100PRB.if4p5.conf @@ -0,0 +1,191 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "127.0.0.3"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "74:d4:35:cc:8d:15"; + local_address = "34:e6:d7:3c:ae:fc"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5.conf new file mode 100644 index 0000000000..b264993dd4 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.if4p5.conf @@ -0,0 +1,191 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "127.0.0.3"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24"; + ENB_INTERFACE_NAME_FOR_S1U = "lo"; + ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "74:d4:35:cc:8d:15"; + local_address = "34:e6:d7:3c:ae:fc"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw_if4p5"; + rf_preference = "usrp_b200"; + iq_txshift = 4; + tx_sample_advance = 80; + tx_scheduling_advance = 9; + } + ); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); + From a8fb38f40de59e85abd4c0520d465f5a619b663f Mon Sep 17 00:00:00 2001 From: "S. Sandeep Kumar" Date: Fri, 2 Sep 2016 13:18:47 +0530 Subject: [PATCH 170/206] fix prach packet in if4p5 UDP --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index 863b0d02d2..11aa8ed9ba 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -208,7 +208,9 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam if (flags == IF4p5_PDLFFT) { packet_size = UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks); } else if (flags == IF4p5_PULFFT) { - packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks); + packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks); + } else if (flags == IF4p5_PRACH) { + packet_size = UDP_IF4p5_PRACH_SIZE_BYTES; } else { printf("trx_eth_write_udp_IF4p5: unknown flags %d\n",flags); return(-1); From e8e940229423bbc9159099e6cc23b54f3da56698 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 3 Sep 2016 17:45:08 +0200 Subject: [PATCH 171/206] small changes for 20 MHz real-time operation --- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 3 +++ .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 2 +- targets/RT/USER/eNB_usrp.gtkw | 21 ++++++++++++------- targets/RT/USER/lte-enb.c | 4 ++-- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index dbe06ea6ba..2f578d9cc1 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -6221,6 +6221,9 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu, if (dci_format == format0) { + if (!ulsch) + return -1; + if (rnti == ra_rnti) harq_pid = 0; else diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index 8144147ea5..10da79724a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -31,7 +31,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2645000000L; + downlink_frequency = 2680000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 100; diff --git a/targets/RT/USER/eNB_usrp.gtkw b/targets/RT/USER/eNB_usrp.gtkw index 44401bd25e..47f505031e 100644 --- a/targets/RT/USER/eNB_usrp.gtkw +++ b/targets/RT/USER/eNB_usrp.gtkw @@ -1,19 +1,19 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sun Jul 24 14:21:37 2016 +[*] Wed Aug 31 12:37:04 2016 [*] [dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Sun Jul 24 14:18:00 2016" -[dumpfile_size] 7104337 +[dumpfile_mtime] "Wed Aug 31 11:48:14 2016" +[dumpfile_size] 411905827 [savefile] "/home/papillon/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw" [timestart] 10621768000 -[size] 1535 724 +[size] 1236 578 [pos] 309 0 *-19.793451 29026062100 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -[sst_width] 284 +[sst_width] 386 [signals_width] 262 [sst_expanded] 1 -[sst_vpaned_height] 294 +[sst_vpaned_height] 146 @28 functions.trx_read functions.trx_write @@ -28,14 +28,21 @@ variables.subframe_number_RX0_eNB[63:0] variables.frame_number_TX0_eNB[63:0] variables.subframe_number_TX0_eNB[63:0] @28 +functions.phy_procedures_eNb_rx_common0 +functions.phy_procedures_eNb_rx_uespec0 +functions.phy_procedures_eNb_tx0 functions.eNB_thread_rxtx1 @24 variables.frame_number_RX1_eNB[63:0] variables.subframe_number_RX1_eNB[63:0] variables.frame_number_TX1_eNB[63:0] -@25 variables.subframe_number_TX1_eNB[63:0] @28 +functions.phy_procedures_eNb_rx_common1 +functions.phy_procedures_eNb_rx_uespec1 +@29 +functions.phy_procedures_eNb_tx1 +@28 functions.phy_enb_sfgen functions.phy_eNB_slot_fep functions.phy_enb_prach_rx diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index a7a0314bdc..9f2a108f5b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -191,7 +191,7 @@ static inline void thread_top_init(char *thread_name, exit_fun("Error setting deadline scheduler"); } - LOG_I( HW, "[SCHED] eNB %s deadline thread (TID %ld) started on CPU %d\n", gettid(), thread_name,sched_getcpu() ); + LOG_I( HW, "[SCHED] eNB %s deadline thread started on CPU %d\n", thread_name,sched_getcpu() ); #else //LOW_LATENCY int policy, s, j; @@ -880,7 +880,7 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; unsigned int rxs,txs; int i; - int tx_sfoffset = (eNB->single_thread_flag == 1) ? 3 : 3; + int tx_sfoffset = 2;//(eNB->single_thread_flag == 1) ? 3 : 3; if (proc->first_rx==0) { // Transmit TX buffer based on timestamp from RX From a205844d77e774fe803614c4c06d99c438a7cffb Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 3 Sep 2016 08:49:14 -0700 Subject: [PATCH 172/206] addition of paging in UE, modifications for dlsim --- cmake_targets/CMakeLists.txt | 1 + openair1/PHY/INIT/lte_init.c | 662 +++++++++++------------ openair1/PHY/LTE_TRANSPORT/dci.c | 68 ++- openair1/PHY/LTE_TRANSPORT/defs.h | 1 + openair1/PHY/LTE_TRANSPORT/proto.h | 8 + openair1/PHY/defs.h | 37 +- openair1/SCHED/phy_procedures_lte_ue.c | 82 +++ openair1/SIMULATION/LTE_PHY/dlsim.c | 698 +------------------------ openair2/LAYER2/MAC/defs.h | 9 + openair2/LAYER2/MAC/main.c | 1 + openair2/LAYER2/MAC/proto.h | 2 + openair2/LAYER2/MAC/ue_procedures.c | 35 ++ openair2/PHY_INTERFACE/defs.h | 3 + openair2/RRC/LITE/L2_interface.c | 4 + openair2/RRC/LITE/proto.h | 6 + openair2/RRC/LITE/rrc_UE.c | 34 ++ openair2/UTIL/LOG/vcd_signal_dumper.c | 1 + openair2/UTIL/LOG/vcd_signal_dumper.h | 1 + 18 files changed, 583 insertions(+), 1070 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index a83bce5e8b..e1396b6398 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -960,6 +960,7 @@ set(PHY_SRC ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pucch.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch.c + ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pch.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/srs_modulation.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/drs_modulation.c diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 259a7ba77a..67d30bbb15 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -26,9 +26,6 @@ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ -#ifdef EXMIMO -#include "openair0_lib.h" -#endif #include "defs.h" #include "SCHED/defs.h" #include "PHY/extern.h" @@ -48,7 +45,7 @@ extern uint16_t prach_root_sequence_map4[138]; uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10}; // FIXME not used anywhere -void phy_config_mib(LTE_DL_FRAME_PARMS *frame_parms, +void phy_config_mib(LTE_DL_FRAME_PARMS *fp, uint8_t N_RB_DL, uint8_t Nid_cell, uint8_t Ncp, @@ -57,14 +54,14 @@ void phy_config_mib(LTE_DL_FRAME_PARMS *frame_parms, PHICH_CONFIG_COMMON *phich_config) { - frame_parms->N_RB_DL = N_RB_DL; - frame_parms->Nid_cell = Nid_cell; - frame_parms->nushift = Nid_cell%6; - frame_parms->Ncp = Ncp; - frame_parms->frame_type = frame_type; - frame_parms->nb_antennas_tx_eNB = p_eNB; - frame_parms->phich_config_common.phich_resource = phich_config->phich_resource; - frame_parms->phich_config_common.phich_duration = phich_config->phich_duration; + fp->N_RB_DL = N_RB_DL; + fp->Nid_cell = Nid_cell; + fp->nushift = Nid_cell%6; + fp->Ncp = Ncp; + fp->frame_type = frame_type; + fp->nb_antennas_tx_eNB = p_eNB; + fp->phich_config_common.phich_resource = phich_config->phich_resource; + fp->phich_config_common.phich_duration = phich_config->phich_duration; } void phy_config_sib1_eNB(uint8_t Mod_id, @@ -74,15 +71,15 @@ void phy_config_sib1_eNB(uint8_t Mod_id, uint16_t SIPeriod) { - LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; + LTE_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; if (tdd_Config) { - frame_parms->tdd_config = tdd_Config->subframeAssignment; - frame_parms->tdd_config_S = tdd_Config->specialSubframePatterns; + fp->tdd_config = tdd_Config->subframeAssignment; + fp->tdd_config_S = tdd_Config->specialSubframePatterns; } - frame_parms->SIwindowsize = SIwindowsize; - frame_parms->SIPeriod = SIPeriod; + fp->SIwindowsize = SIwindowsize; + fp->SIPeriod = SIPeriod; } void phy_config_sib1_ue(uint8_t Mod_id,int CC_id, @@ -92,15 +89,15 @@ void phy_config_sib1_ue(uint8_t Mod_id,int CC_id, uint16_t SIperiod) { - LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; + LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; if (tdd_Config) { - frame_parms->tdd_config = tdd_Config->subframeAssignment; - frame_parms->tdd_config_S = tdd_Config->specialSubframePatterns; + fp->tdd_config = tdd_Config->subframeAssignment; + fp->tdd_config_S = tdd_Config->specialSubframePatterns; } - frame_parms->SIwindowsize = SIwindowsize; - frame_parms->SIPeriod = SIperiod; + fp->SIwindowsize = SIwindowsize; + fp->SIPeriod = SIperiod; } void phy_config_sib2_eNB(uint8_t Mod_id, @@ -112,132 +109,132 @@ void phy_config_sib2_eNB(uint8_t Mod_id, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList) { - LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; + LTE_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; //LTE_eNB_UE_stats *eNB_UE_stats = PHY_vars_eNB_g[Mod_id][CC_id]->eNB_UE_stats; //int32_t rx_total_gain_eNB_dB = PHY_vars_eNB_g[Mod_id][CC_id]->rx_total_gain_eNB_dB; int i; LOG_D(PHY,"[eNB%d] CCid %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id); - frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - LOG_D(PHY,"prach_config_common.rootSequenceIndex = %d\n",frame_parms->prach_config_common.rootSequenceIndex ); + fp->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; + LOG_D(PHY,"prach_config_common.rootSequenceIndex = %d\n",fp->prach_config_common.rootSequenceIndex ); - frame_parms->prach_config_common.prach_Config_enabled=1; + fp->prach_config_common.prach_Config_enabled=1; - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_ConfigIndex = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex); + fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_ConfigIndex = %d\n",fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex); - frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.highSpeedFlag = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag); - frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig); - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; - LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_FreqOffset = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset); - compute_prach_seq(&frame_parms->prach_config_common,frame_parms->frame_type, + fp->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.highSpeedFlag = %d\n",fp->prach_config_common.prach_ConfigInfo.highSpeedFlag); + fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig = %d\n",fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig); + fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; + LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_FreqOffset = %d\n",fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset); + compute_prach_seq(&fp->prach_config_common,fp->frame_type, PHY_vars_eNB_g[Mod_id][CC_id]->X_u); - frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; - frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; - frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; - frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; + fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; + fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; + fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; + fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; - frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; - frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; + fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; + fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; - frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - LOG_D(PHY,"pusch_config_common.n_SB = %d\n",frame_parms->pusch_config_common.n_SB ); + fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; + LOG_D(PHY,"pusch_config_common.n_SB = %d\n",fp->pusch_config_common.n_SB ); - frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - LOG_D(PHY,"pusch_config_common.hoppingMode = %d\n",frame_parms->pusch_config_common.hoppingMode); + fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; + LOG_D(PHY,"pusch_config_common.hoppingMode = %d\n",fp->pusch_config_common.hoppingMode); - frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - LOG_D(PHY,"pusch_config_common.pusch_HoppingOffset = %d\n",frame_parms->pusch_config_common.pusch_HoppingOffset); + fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; + LOG_D(PHY,"pusch_config_common.pusch_HoppingOffset = %d\n",fp->pusch_config_common.pusch_HoppingOffset); - frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - LOG_D(PHY,"pusch_config_common.enable64QAM = %d\n",frame_parms->pusch_config_common.enable64QAM ); + fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; + LOG_D(PHY,"pusch_config_common.enable64QAM = %d\n",fp->pusch_config_common.enable64QAM ); - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled); + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled); - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH); + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH); - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled); + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled); - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; - LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift); + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; + LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift); - init_ul_hopping(frame_parms); + init_ul_hopping(fp); - frame_parms->soundingrs_ul_config_common.enabled_flag = 0; + fp->soundingrs_ul_config_common.enabled_flag = 0; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) { - frame_parms->soundingrs_ul_config_common.enabled_flag = 1; - frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; - frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; + fp->soundingrs_ul_config_common.enabled_flag = 1; + fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; + fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; + fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; + fp->soundingrs_ul_config_common.srs_MaxUpPts = 1; else - frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; + fp->soundingrs_ul_config_common.srs_MaxUpPts = 0; } - frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; - frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; - frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; - frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; + fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; + fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; + fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; + fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; + fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; + fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; - frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; + fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; // Now configure some of the Physical Channels // PUCCH - init_ncs_cell(frame_parms,PHY_vars_eNB_g[Mod_id][CC_id]->ncs_cell); + init_ncs_cell(fp,PHY_vars_eNB_g[Mod_id][CC_id]->ncs_cell); - init_ul_hopping(frame_parms); + init_ul_hopping(fp); // MBSFN if (mbsfn_SubframeConfigList != NULL) { - frame_parms->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; + fp->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; for (i=0; ilist.count; i++) { - frame_parms->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; - frame_parms->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; + fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; + fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { - frame_parms->MBSFN_config[i].fourFrames_flag = 0; - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration + fp->MBSFN_config[i].fourFrames_flag = 0; + fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + fp->MBSFN_config[i].mbsfn_SubframeConfig); } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration - frame_parms->MBSFN_config[i].fourFrames_flag = 1; - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = + fp->MBSFN_config[i].fourFrames_flag = 1; + fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16); LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + fp->MBSFN_config[i].mbsfn_SubframeConfig); } } } else - frame_parms->num_MBSFN_config = 0; + fp->num_MBSFN_config = 0; } @@ -250,106 +247,109 @@ void phy_config_sib2_ue(uint8_t Mod_id,int CC_id, struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList) { - LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; + PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; + LTE_DL_FRAME_PARMS *fp = &ue->frame_parms; int i; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_IN); LOG_I(PHY,"[UE%d] Applying radioResourceConfigCommon from eNB%d\n",Mod_id,CH_index); - frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; + fp->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - frame_parms->prach_config_common.prach_Config_enabled=1; - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; - frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; + fp->prach_config_common.prach_Config_enabled=1; + fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; + fp->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; + fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; + fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; - compute_prach_seq(&frame_parms->prach_config_common,frame_parms->frame_type,PHY_vars_UE_g[Mod_id][CC_id]->X_u); + compute_prach_seq(&fp->prach_config_common,fp->frame_type,ue->X_u); - frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; - frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; - frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; - frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; + fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; + fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; + fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; + fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; - frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; - frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; + fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; + fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; - frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; + fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; + fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; + fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; + fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; - init_ul_hopping(frame_parms); - frame_parms->soundingrs_ul_config_common.enabled_flag = 0; + init_ul_hopping(fp); + fp->soundingrs_ul_config_common.enabled_flag = 0; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) { - frame_parms->soundingrs_ul_config_common.enabled_flag = 1; - frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; - frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; + fp->soundingrs_ul_config_common.enabled_flag = 1; + fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; + fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; + fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; + fp->soundingrs_ul_config_common.srs_MaxUpPts = 1; else - frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; + fp->soundingrs_ul_config_common.srs_MaxUpPts = 0; } - frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; - frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; - frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; - frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; + fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; + fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; + fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; + fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; + fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; + fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; - frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; + fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; // Now configure some of the Physical Channels // PUCCH - init_ncs_cell(frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); + init_ncs_cell(fp,ue->ncs_cell); - init_ul_hopping(frame_parms); + init_ul_hopping(fp); + // PCH + init_ue_paging_info(ue,radioResourceConfigCommon->pcch_Config.defaultPagingCycle,radioResourceConfigCommon->pcch_Config.nB); // MBSFN if (mbsfn_SubframeConfigList != NULL) { - frame_parms->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; + fp->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; for (i=0; ilist.count; i++) { - frame_parms->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; - frame_parms->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; + fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; + fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { - frame_parms->MBSFN_config[i].fourFrames_flag = 0; - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration + fp->MBSFN_config[i].fourFrames_flag = 0; + fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + fp->MBSFN_config[i].mbsfn_SubframeConfig); } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration - frame_parms->MBSFN_config[i].fourFrames_flag = 1; - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig = + fp->MBSFN_config[i].fourFrames_flag = 1; + fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16); LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %ld\n", i, - frame_parms->MBSFN_config[i].mbsfn_SubframeConfig); + fp->MBSFN_config[i].mbsfn_SubframeConfig); } } } @@ -362,17 +362,17 @@ void phy_config_sib13_ue(uint8_t Mod_id,int CC_id,uint8_t CH_index,int mbsfn_Are long mbsfn_AreaId_r9) { - LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; + LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; LOG_I(PHY,"[UE%d] Applying MBSFN_Area_id %d for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx); if (mbsfn_Area_idx == 0) { - frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; + fp->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n"); } - lte_gold_mbsfn(frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_mbsfn_table,frame_parms->Nid_cell_mbsfn); + lte_gold_mbsfn(fp,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_mbsfn_table,fp->Nid_cell_mbsfn); } @@ -381,17 +381,17 @@ void phy_config_sib13_eNB(uint8_t Mod_id,int CC_id,int mbsfn_Area_idx, long mbsfn_AreaId_r9) { - LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; + LTE_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms; LOG_I(PHY,"[eNB%d] Applying MBSFN_Area_id %d for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx); if (mbsfn_Area_idx == 0) { - frame_parms->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; + fp->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n"); } - lte_gold_mbsfn(frame_parms,PHY_vars_eNB_g[Mod_id][CC_id]->lte_gold_mbsfn_table,frame_parms->Nid_cell_mbsfn); + lte_gold_mbsfn(fp,PHY_vars_eNB_g[Mod_id][CC_id]->lte_gold_mbsfn_table,fp->Nid_cell_mbsfn); } @@ -400,6 +400,7 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB) uint8_t UE_id; struct PhysicalConfigDedicated *physicalConfigDedicated; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; for (UE_id=0; UE_idphysicalConfigDedicated[UE_id]; @@ -421,7 +422,7 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB) eNB->pucch_config_dedicated[UE_id].ackNackRepetition=1; } - if (eNB->frame_parms.frame_type == FDD) { + if (fp->frame_type == FDD) { eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = multiplexing; } else { if (physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode) @@ -508,7 +509,7 @@ void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, Mobility PHY_vars_UE_g[Mod_id][CC_id]->ho_triggered = 1; //PHY_vars_UE_g[UE_id]->UE_mode[0] = PRACH; - LTE_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; + LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; // int N_ZC; // uint8_t prach_fmt; // int u; @@ -516,88 +517,88 @@ void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, Mobility LOG_I(PHY,"[UE%d] Handover triggered: Applying radioResourceConfigCommon from eNB %d\n", Mod_id,eNB_id); - frame_parms->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - frame_parms->prach_config_common.prach_Config_enabled=1; - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex; - frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->highSpeedFlag; - frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->zeroCorrelationZoneConfig; - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_FreqOffset; + fp->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex; + fp->prach_config_common.prach_Config_enabled=1; + fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex; + fp->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->highSpeedFlag; + fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->zeroCorrelationZoneConfig; + fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_FreqOffset; - // prach_fmt = get_prach_fmt(radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex,frame_parms->frame_type); + // prach_fmt = get_prach_fmt(radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex,fp->frame_type); // N_ZC = (prach_fmt <4)?839:139; - // u = (prach_fmt < 4) ? prach_root_sequence_map0_3[frame_parms->prach_config_common.rootSequenceIndex] : - // prach_root_sequence_map4[frame_parms->prach_config_common.rootSequenceIndex]; + // u = (prach_fmt < 4) ? prach_root_sequence_map0_3[fp->prach_config_common.rootSequenceIndex] : + // prach_root_sequence_map4[fp->prach_config_common.rootSequenceIndex]; //compute_prach_seq(u,N_ZC, PHY_vars_UE_g[Mod_id]->X_u); compute_prach_seq(&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common, - frame_parms->frame_type, + fp->frame_type, PHY_vars_UE_g[Mod_id][CC_id]->X_u); - frame_parms->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon->deltaPUCCH_Shift; - frame_parms->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon->nRB_CQI; - frame_parms->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon->nCS_AN; - frame_parms->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon->n1PUCCH_AN; - frame_parms->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon->referenceSignalPower; - frame_parms->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon->p_b; + fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon->deltaPUCCH_Shift; + fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon->nRB_CQI; + fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon->nCS_AN; + fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon->n1PUCCH_AN; + fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon->referenceSignalPower; + fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon->p_b; - frame_parms->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - frame_parms->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - frame_parms->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - frame_parms->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; + fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; + fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; + fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; + fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; - init_ul_hopping(frame_parms); - frame_parms->soundingrs_ul_config_common.enabled_flag = 0; + init_ul_hopping(fp); + fp->soundingrs_ul_config_common.enabled_flag = 0; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->present==SoundingRS_UL_ConfigCommon_PR_setup) { - frame_parms->soundingrs_ul_config_common.enabled_flag = 1; - frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_BandwidthConfig; - frame_parms->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig; - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.ackNackSRS_SimultaneousTransmission; + fp->soundingrs_ul_config_common.enabled_flag = 1; + fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_BandwidthConfig; + fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig; + fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.ackNackSRS_SimultaneousTransmission; if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_MaxUpPts) - frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 1; + fp->soundingrs_ul_config_common.srs_MaxUpPts = 1; else - frame_parms->soundingrs_ul_config_common.srs_MaxUpPts = 0; + fp->soundingrs_ul_config_common.srs_MaxUpPts = 0; } - frame_parms->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUSCH; - frame_parms->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon->alpha; - frame_parms->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUCCH; - frame_parms->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaPreambleMsg3; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1b; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2a; - frame_parms->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2b; + fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUSCH; + fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon->alpha; + fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUCCH; + fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaPreambleMsg3; + fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1; + fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1b; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2a; + fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2b; - frame_parms->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon->maxHARQ_Msg3Tx; + fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon->maxHARQ_Msg3Tx; // Now configure some of the Physical Channels if (radioResourceConfigCommon->antennaInfoCommon) - frame_parms->nb_antennas_tx = (1<antennaInfoCommon->antennaPortsCount); + fp->nb_antennas_tx = (1<antennaInfoCommon->antennaPortsCount); else - frame_parms->nb_antennas_tx = 1; + fp->nb_antennas_tx = 1; //PHICH if (radioResourceConfigCommon->antennaInfoCommon) { - frame_parms->phich_config_common.phich_resource = radioResourceConfigCommon->phich_Config->phich_Resource; - frame_parms->phich_config_common.phich_duration = radioResourceConfigCommon->phich_Config->phich_Duration; + fp->phich_config_common.phich_resource = radioResourceConfigCommon->phich_Config->phich_Resource; + fp->phich_config_common.phich_duration = radioResourceConfigCommon->phich_Config->phich_Duration; } //Target CellId - frame_parms->Nid_cell = mobilityControlInfo->targetPhysCellId; - frame_parms->nushift = frame_parms->Nid_cell%6; + fp->Nid_cell = mobilityControlInfo->targetPhysCellId; + fp->nushift = fp->Nid_cell%6; // PUCCH - init_ncs_cell(frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); + init_ncs_cell(fp,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); - init_ul_hopping(frame_parms); + init_ul_hopping(fp); // RNTI @@ -676,46 +677,13 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id, ARFCN_ValueEUTRA_t dl_CarrierFreq_r10 = sCellToAddMod_r10->cellIdentification_r10->dl_CarrierFreq_r10; uint32_t carrier_freq_local; -#ifdef EXMIMO -#ifdef DRIVER2013 - // exmimo_config_t *p_exmimo_config = openair0_exmimo_pci[rf_map[CC_id].card].exmimo_config_ptr; -#endif -#endif - if ((dl_CarrierFreq_r10>=36000) && (dl_CarrierFreq_r10<=36199)) { carrier_freq_local = 1900000000 + (dl_CarrierFreq_r10-36000)*100000; //band 33 from 3GPP 36.101 v 10.9 Table 5.7.3-1 LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); - /* -#ifdef EXMIMO -#ifdef DRIVER2013 - //carrier_freq[CC_id] = carrier_freq_local; - //openair_daq_vars.freq_offset = -6540; - p_exmimo_config->rf.rf_freq_rx[rf_map[CC_id].chain] = carrier_freq_local;//+openair_daq_vars.freq_offset2; - p_exmimo_config->rf.rf_freq_tx[rf_map[CC_id].chain] = carrier_freq_local;//+openair_daq_vars.freq_offset2; - p_exmimo_config->rf.tx_gain[rf_map[CC_id].chain][0] = 25; - p_exmimo_config->rf.rf_vcocal[rf_map[CC_id].chain] = 910; - p_exmimo_config->rf.rf_local[rf_map[CC_id].chain] = 8255063; //this should be taken form calibration file - p_exmimo_config->rf.rffe_band_mode[rf_map[CC_id].chain] = B19G_TDD; -#endif -#endif*/ } else if ((dl_CarrierFreq_r10>=6150) && (dl_CarrierFreq_r10<=6449)) { carrier_freq_local = 832000000 + (dl_CarrierFreq_r10-6150)*100000; //band 20 from 3GPP 36.101 v 10.9 Table 5.7.3-1 // this is actually for the UL only, but we use it for DL too, since there is no TDD mode for this band LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %d) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id); -/* -#ifdef EXMIMO -#ifdef DRIVER2013 - //carrier_freq[CC_id] = carrier_freq_local; - //openair_daq_vars.freq_offset = -2000; - p_exmimo_config->rf.rf_freq_rx[rf_map[CC_id].chain] = carrier_freq_local;//+openair_daq_vars.freq_offset2; - p_exmimo_config->rf.rf_freq_tx[rf_map[CC_id].chain] = carrier_freq_local;//+openair_daq_vars.freq_offset2; - p_exmimo_config->rf.tx_gain[rf_map[CC_id].chain][0] = 10; - p_exmimo_config->rf.rf_vcocal[rf_map[CC_id].chain] = 2015; - p_exmimo_config->rf.rf_local[rf_map[CC_id].chain] = 8254992; //this should be taken form calibration file - p_exmimo_config->rf.rffe_band_mode[rf_map[CC_id].chain] = DD_TDD; -#endif -#endif -*/ } else { LOG_E(PHY,"[eNB %d] Frame %d: ARFCN %d of SCell %d for UE %d not supported\n",Mod_id,/*eNB->frame*/0,dl_CarrierFreq_r10,CC_id,UE_id); } @@ -906,11 +874,11 @@ void phy_init_lte_top(LTE_DL_FRAME_PARMS *frame_parms) * \param[in] frame_parms LTE_DL_FRAME_PARMS structure. * \note This function is optimistic in that it expects malloc() to succeed. */ -void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS* const frame_parms ) +void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS* const fp ) { AssertFatal( pdsch, "pdsch==0" ); - pdsch->pmi_ext = (uint8_t*)malloc16_clear( frame_parms->N_RB_DL ); + pdsch->pmi_ext = (uint8_t*)malloc16_clear( fp->N_RB_DL ); pdsch->llr[0] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); pdsch->llr128 = (int16_t**)malloc16_clear( sizeof(int16_t*) ); pdsch->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) ); @@ -918,7 +886,7 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS pdsch->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->rxdataF_comp0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch->rho = (int32_t**)malloc16_clear( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pdsch->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) ); pdsch->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); @@ -926,14 +894,14 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS pdsch->dl_ch_magb0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); // the allocated memory size is fixed: - AssertFatal( frame_parms->nb_antennas_rx <= 2, "nb_antennas_rx > 2" ); + AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" ); - for (int i=0; inb_antennas_rx; i++) { - pdsch->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->N_RB_DL*12*7*2) ); + for (int i=0; inb_antennas_rx; i++) { + pdsch->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*7*2) ); - for (int j=0; j<4; j++) { //frame_parms->nb_antennas_tx; j++) + for (int j=0; j<4; j++) { //fp->nb_antennas_tx; j++) const int idx = (j<<1)+i; - const size_t num = 7*2*frame_parms->N_RB_DL*12; + const size_t num = 7*2*fp->N_RB_DL*12; pdsch->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdsch->rxdataF_comp0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); @@ -952,7 +920,7 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, { // create shortcuts - LTE_DL_FRAME_PARMS* const frame_parms = &ue->frame_parms; + LTE_DL_FRAME_PARMS* const fp = &ue->frame_parms; LTE_UE_COMMON* const common_vars = &ue->common_vars; LTE_UE_PDSCH** const pdsch_vars = ue->pdsch_vars; LTE_UE_PDSCH** const pdsch_vars_SI = ue->pdsch_vars_SI; @@ -965,11 +933,11 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, int i,j,k; int eNB_id; - printf("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,frame_parms->nb_antennas_tx,frame_parms->nb_antennas_rx); + printf("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,fp->nb_antennas_tx,fp->nb_antennas_rx); LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", ue->Mod_id+NB_eNB_INST); // many memory allocation sizes are hard coded - AssertFatal( frame_parms->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[eNB_id]" ); + AssertFatal( fp->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[eNB_id]" ); AssertFatal( ue->n_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" ); // init phy_vars_ue @@ -995,25 +963,25 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, // init TX buffers - common_vars->txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - common_vars->txdataF = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + common_vars->txdata = (int32_t**)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) ); + common_vars->txdataF = (int32_t **)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) ); - for (i=0; inb_antennas_tx; i++) { + for (i=0; inb_antennas_tx; i++) { - common_vars->txdata[i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); - common_vars->txdataF[i] = (int32_t *)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); + common_vars->txdata[i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) ); + common_vars->txdataF[i] = (int32_t *)malloc16_clear( fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) ); } // init RX buffers - common_vars->rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - common_vars->rxdataF = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - common_vars->rxdataF2 = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdata = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdataF = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdataF2 = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) { - common_vars->rxdata[i] = (int32_t*) malloc16_clear( (FRAME_LENGTH_COMPLEX_SAMPLES+2048)*sizeof(int32_t) ); - common_vars->rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->ofdm_symbol_size*14) ); - common_vars->rxdataF2[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*10) ); + for (i=0; inb_antennas_rx; i++) { + common_vars->rxdata[i] = (int32_t*) malloc16_clear( (fp->samples_per_tti*10+2048)*sizeof(int32_t) ); + common_vars->rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->ofdm_symbol_size*14) ); + common_vars->rxdataF2[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->ofdm_symbol_size*fp->symbols_per_tti*10) ); } } @@ -1022,11 +990,11 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, common_vars->dl_ch_estimates[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*)); common_vars->dl_ch_estimates_time[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*)); - for (i=0; inb_antennas_rx; i++) + for (i=0; inb_antennas_rx; i++) for (j=0; j<4; j++) { int idx = (j<<1) + i; - common_vars->dl_ch_estimates[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->symbols_per_tti*(frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) ); - common_vars->dl_ch_estimates_time[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size*2 ); + common_vars->dl_ch_estimates[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->symbols_per_tti*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) ); + common_vars->dl_ch_estimates_time[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); } } @@ -1041,9 +1009,9 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, pbch_vars[eNB_id] = (LTE_UE_PBCH *)malloc16_clear(sizeof(LTE_UE_PBCH)); if (abstraction_flag == 0) { - phy_init_lte_ue__PDSCH( pdsch_vars[eNB_id], frame_parms ); + phy_init_lte_ue__PDSCH( pdsch_vars[eNB_id], fp ); - pdsch_vars[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*frame_parms->N_RB_DL*12); + pdsch_vars[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*fp->N_RB_DL*12); pdsch_vars[eNB_id]->llr_shifts_p = pdsch_vars[eNB_id]->llr_shifts; pdsch_vars[eNB_id]->dl_ch_mag1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch_vars[eNB_id]->dl_ch_magb1 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); @@ -1052,19 +1020,19 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, for (k=0; k<8; k++) pdsch_vars[eNB_id]->rxdataF_comp1[k] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) + for (i=0; inb_antennas_rx; i++) for (j=0; j<4; j++) { int idx = (j<<1)+i; - pdsch_vars[eNB_id]->dl_ch_mag1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(frame_parms->N_RB_DL*12) ); - pdsch_vars[eNB_id]->dl_ch_magb1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(frame_parms->N_RB_DL*12) ); + pdsch_vars[eNB_id]->dl_ch_mag1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + pdsch_vars[eNB_id]->dl_ch_magb1[idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); for (k=0; k<8; k++) - pdsch_vars[eNB_id]->rxdataF_comp1[idx][k] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->N_RB_DL*12*14) ); + pdsch_vars[eNB_id]->rxdataF_comp1[idx][k] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*14) ); } - phy_init_lte_ue__PDSCH( pdsch_vars_SI[eNB_id], frame_parms ); - phy_init_lte_ue__PDSCH( pdsch_vars_ra[eNB_id], frame_parms ); - phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], frame_parms ); + phy_init_lte_ue__PDSCH( pdsch_vars_SI[eNB_id], fp ); + phy_init_lte_ue__PDSCH( pdsch_vars_ra[eNB_id], fp ); + phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], fp ); // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE pdcch_vars[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); pdcch_vars[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); @@ -1073,17 +1041,17 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, pdcch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdcch_vars[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdcch_vars[eNB_id]->rho = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pdcch_vars[eNB_id]->rho = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); pdcch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdcch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) { - //ue_pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(frame_parms->N_RB_DL*12*7*2) ); + for (i=0; inb_antennas_rx; i++) { + //ue_pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*7*2) ); pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) ); - for (j=0; j<4; j++) { //frame_parms->nb_antennas_tx; j++) + for (j=0; j<4; j++) { //fp->nb_antennas_tx; j++) int idx = (j<<1)+i; - // size_t num = 7*2*frame_parms->N_RB_DL*12; + // size_t num = 7*2*fp->N_RB_DL*12; size_t num = 4*100*12; // 4 symbols, 100 PRBs, 12 REs per PRB pdcch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdcch_vars[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); @@ -1093,17 +1061,17 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, } // PBCH - pbch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pbch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); pbch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pbch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pbch_vars[eNB_id]->llr = (int8_t*)malloc16_clear( 1920 ); - prach_vars[eNB_id]->prachF = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(frame_parms->ofdm_symbol_size*12)) ); - prach_vars[eNB_id]->prach = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(frame_parms->ofdm_symbol_size*12)) ); + prach_vars[eNB_id]->prachF = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); + prach_vars[eNB_id]->prach = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); - for (i=0; inb_antennas_rx; i++) { + for (i=0; inb_antennas_rx; i++) { pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); - for (j=0; j<4; j++) {//frame_parms->nb_antennas_tx;j++) { + for (j=0; j<4; j++) {//fp->nb_antennas_tx;j++) { int idx = (j<<1)+i; pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 ); @@ -1121,14 +1089,14 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) ); if (abstraction_flag == 0) { - phy_init_lte_ue__PDSCH( pdsch_vars[eNB_id], frame_parms ); + phy_init_lte_ue__PDSCH( pdsch_vars[eNB_id], fp ); pdsch_vars[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); } else { //abstraction == 1 - ue->sinr_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); + ue->sinr_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); } - ue->sinr_CQI_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); + ue->sinr_CQI_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); ue->init_averaging = 1; ue->pdsch_config_dedicated->p_a = dB0; // default value until overwritten by RRCConnectionReconfiguration @@ -1149,7 +1117,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, { // shortcuts - LTE_DL_FRAME_PARMS* const frame_parms = &eNB->frame_parms; + LTE_DL_FRAME_PARMS* const fp = &eNB->frame_parms; LTE_eNB_COMMON* const common_vars = &eNB->common_vars; LTE_eNB_PUSCH** const pusch_vars = eNB->pusch_vars; LTE_eNB_SRS* const srs_vars = eNB->srs_vars; @@ -1163,14 +1131,14 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, LOG_I(PHY,"[eNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d\n", eNB->Mod_id, - frame_parms->N_RB_DL,frame_parms->phich_config_common.phich_resource, - frame_parms->phich_config_common.phich_duration); + fp->N_RB_DL,fp->phich_config_common.phich_resource, + fp->phich_config_common.phich_duration); LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_eNB][MOD %02"PRIu8"][]\n", eNB->Mod_id); if (eNB->node_function != NGFI_RRU_IF4p5) { - lte_gold(frame_parms,eNB->lte_gold_table,frame_parms->Nid_cell); - generate_pcfich_reg_mapping(frame_parms); - generate_phich_reg_mapping(frame_parms); + lte_gold(fp,eNB->lte_gold_table,fp->Nid_cell); + generate_pcfich_reg_mapping(fp); + generate_phich_reg_mapping(fp); for (UE_id=0; UE_idfirst_run_timing_advance[UE_id] = @@ -1192,35 +1160,35 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, // TX vars if (eNB->node_function != NGFI_RCC_IF4p5) - common_vars->txdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); - common_vars->txdataF[eNB_id] = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) ); + common_vars->txdata[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) ); + common_vars->txdataF[eNB_id] = (int32_t **)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) ); - for (i=0; inb_antennas_tx; i++) { + for (i=0; inb_antennas_tx; i++) { if (eNB->node_function != NGFI_RCC_IF4p5) - common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); - common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) ); + common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) ); + common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) ); #ifdef DEBUG_PHY printf("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p\n",eNB_id,i,common_vars->txdata[eNB_id][i]); printf("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%d bytes)\n", eNB_id,i,common_vars->txdataF[eNB_id][i], - FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t)); #endif } // RX vars if (eNB->node_function != NGFI_RCC_IF4p5) { - common_vars->rxdata[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdata[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); } - common_vars->rxdataF[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + common_vars->rxdataF[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) { + for (i=0; inb_antennas_rx; i++) { if (eNB->node_function != NGFI_RCC_IF4p5) { - common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) ); - common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->samples_per_tti*sizeof(int32_t) ); + common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) ); + common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*sizeof(int32_t) ); } - common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti) ); + common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(fp->ofdm_symbol_size*fp->symbols_per_tti) ); #ifdef DEBUG_PHY printf("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata[eNB_id][i]); printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i]); @@ -1231,19 +1199,19 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, // Channel estimates for SRS for (UE_id=0; UE_idnb_antennas_rx*sizeof(int32_t*) ); - srs_vars[UE_id].srs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + srs_vars[UE_id].srs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + srs_vars[UE_id].srs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) { - srs_vars[UE_id].srs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size ); - srs_vars[UE_id].srs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->ofdm_symbol_size*2 ); + for (i=0; inb_antennas_rx; i++) { + srs_vars[UE_id].srs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size ); + srs_vars[UE_id].srs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); } } //UE_id - common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*frame_parms->samples_per_tti ); + common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_tti ); } } else { //UPLINK abstraction = 1 - eNB->sinr_dB = (double*) malloc16_clear( frame_parms->N_RB_DL*12*sizeof(double) ); + eNB->sinr_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); } } //eNB_id @@ -1255,7 +1223,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, // SRS for (UE_id=0; UE_idofdm_symbol_size*sizeof(int32_t)); + srs_vars[UE_id].srs = (int32_t*)malloc16_clear(2*fp->ofdm_symbol_size*sizeof(int32_t)); } } } @@ -1268,19 +1236,19 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) ); /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ - AssertFatal(frame_parms->nb_antennas_rx <= sizeof(prach_vars->rxsigF) / sizeof(prach_vars->rxsigF[0]), + AssertFatal(fp->nb_antennas_rx <= sizeof(prach_vars->rxsigF) / sizeof(prach_vars->rxsigF[0]), "nb_antennas_rx too large"); - for (i=0; inb_antennas_rx; i++) { - prach_vars->rxsigF[i] = (int16_t*)malloc16_clear( frame_parms->ofdm_symbol_size*12*2*sizeof(int16_t) ); + for (i=0; inb_antennas_rx; i++) { + prach_vars->rxsigF[i] = (int16_t*)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) ); #ifdef DEBUG_PHY printf("[openair][LTE_PHY][INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]); #endif } if (eNB->node_function != NGFI_RRU_IF4p5) { - AssertFatal(frame_parms->nb_antennas_rx <= sizeof(prach_vars->prach_ifft) / sizeof(prach_vars->prach_ifft[0]), + AssertFatal(fp->nb_antennas_rx <= sizeof(prach_vars->prach_ifft) / sizeof(prach_vars->prach_ifft[0]), "nb_antennas_rx too large"); - for (i=0; inb_antennas_rx; i++) { + for (i=0; inb_antennas_rx; i++) { prach_vars->prach_ifft[i] = (int16_t*)malloc16_clear(1024*2*sizeof(int16_t)); #ifdef DEBUG_PHY printf("[openair][LTE_PHY][INIT] prach_vars->prach_ifft[%d] = %p\n",i,prach_vars->prach_ifft[i]); @@ -1295,61 +1263,61 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, if (abstraction_flag==0) { for (eNB_id=0; eNB_id<3; eNB_id++) { - pusch_vars[UE_id]->rxdataF_ext[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_ext2[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_comp[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_mag[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_ext[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_ext2[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_comp[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_mag[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) { + for (i=0; inb_antennas_rx; i++) { // RK 2 times because of output format of FFT! // FIXME We should get rid of this - pusch_vars[UE_id]->rxdataF_ext[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - pusch_vars[UE_id]->rxdataF_ext2[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - pusch_vars[UE_id]->drs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*frame_parms->ofdm_symbol_size ); - pusch_vars[UE_id]->rxdataF_comp[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*frame_parms->N_RB_UL*12*frame_parms->symbols_per_tti ); - pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + pusch_vars[UE_id]->rxdataF_ext[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->rxdataF_ext2[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->drs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*fp->ofdm_symbol_size ); + pusch_vars[UE_id]->rxdataF_comp[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } // In case of Distributed Alamouti Collabrative scheme separate channel estimates are required for both the UEs if (cooperation_flag == 2) { - pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // UE 0 DRS estimates - pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // UE 1 DRS estimates + pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // UE 0 DRS estimates + pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // UE 1 DRS estimates - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } // Compensated data for the case of Distributed Alamouti Scheme - pusch_vars[UE_id]->rxdataF_comp_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y)*(h0*) - pusch_vars[UE_id]->rxdataF_comp_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y*)*(h1) + pusch_vars[UE_id]->rxdataF_comp_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y)*(h0*) + pusch_vars[UE_id]->rxdataF_comp_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y*)*(h1) - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->rxdataF_comp_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - pusch_vars[UE_id]->rxdataF_comp_1[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->rxdataF_comp_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->rxdataF_comp_1[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } // UE 0 - pusch_vars[UE_id]->ul_ch_mag_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb_0[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_mag_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->ul_ch_mag_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb_0[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->ul_ch_mag_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } // UE 1 - pusch_vars[UE_id]->ul_ch_mag_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb_1[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_mag_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->ul_ch_mag_1[eNB_id][i] = (int32_t*)malloc16( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb_1[eNB_id][i] = (int32_t*)malloc16( frame_parms->symbols_per_tti*sizeof(int32_t)*frame_parms->N_RB_UL*12 ); + for (i=0; inb_antennas_rx; i++) { + pusch_vars[UE_id]->ul_ch_mag_1[eNB_id][i] = (int32_t*)malloc16( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb_1[eNB_id][i] = (int32_t*)malloc16( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } }//cooperation_flag } //eNB_id @@ -1374,15 +1342,15 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, return(-1); } - for (j=0; jframe_parms.nb_antennas_tx; j++) { - eNB->dl_precoder_SeNB[eNB_id][j] = (int *)malloc16(2*sizeof(int)*(eNB->frame_parms.ofdm_symbol_size)); // repeated format (hence the '2*') + for (j=0; jnb_antennas_tx; j++) { + eNB->dl_precoder_SeNB[eNB_id][j] = (int *)malloc16(2*sizeof(int)*(fp->ofdm_symbol_size)); // repeated format (hence the '2*') if (eNB->dl_precoder_SeNB[eNB_id][j]) { #ifdef DEBUG_PHY printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j, eNB->dl_precoder_SeNB[eNB_id][j]); #endif - memset(eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(eNB->frame_parms.ofdm_symbol_size)); + memset(eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(fp->ofdm_symbol_size)); } else { printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j); return(-1); diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index 0117c8e7d2..5667740aec 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -2664,8 +2664,10 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, uint8_t mi, uint16_t si_rnti, uint16_t ra_rnti, + uint16_t p_rnti, uint8_t L, uint8_t format_si, + uint8_t format_p, uint8_t format_ra, uint8_t format_c, uint8_t sizeof_bits, @@ -2797,6 +2799,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, #endif if (((L>1) && ((crc == si_rnti)|| + (crc == p_rnti)|| (crc == ra_rnti)))|| (crc == pdcch_vars[eNB_id]->crnti)) { dci_alloc[*dci_cnt].dci_length = sizeof_bits; @@ -2831,6 +2834,9 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars, if (crc==si_rnti) { dci_alloc[*dci_cnt].format = format_si; *dci_cnt = *dci_cnt+1; + } else if (crc==p_rnti) { + dci_alloc[*dci_cnt].format = format_p; + *dci_cnt = *dci_cnt+1; } else if (crc==ra_rnti) { dci_alloc[*dci_cnt].format = format_ra; // store first nCCE of group for PUCCH transmission of ACK/NAK @@ -3118,7 +3124,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, if (ue->prach_resources[eNB_id]) ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; - // First check common search spaces at aggregation 4 (SI_RNTI and RA_RNTI format 0/1A), + // First check common search spaces at aggregation 4 (SI_RNTI, P_RNTI and RA_RNTI format 0/1A), // and UE_SPEC format0 (PUSCH) too while we're at it dci_decoding_procedure0(pdcch_vars,1,subframe, dci_alloc, @@ -3127,9 +3133,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 2, format1A, format1A, + format1A, format0, format1A_size_bits, format1A_size_bytes, @@ -3144,7 +3152,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); - // Now check common search spaces at aggregation 4 (SI_RNTI and RA_RNTI and C-RNTI format 1C), + // Now check common search spaces at aggregation 4 (SI_RNTI,P_RNTI and RA_RNTI and C-RNTI format 1C), // and UE_SPEC format0 (PUSCH) too while we're at it dci_decoding_procedure0(pdcch_vars,1,subframe, dci_alloc, @@ -3153,10 +3161,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 2, format1C, format1C, format1C, + format1C, format1C_size_bits, format1C_size_bytes, &dci_cnt, @@ -3170,7 +3180,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); - // Now check common search spaces at aggregation 8 (SI_RNTI and RA_RNTI format 1A), + // Now check common search spaces at aggregation 8 (SI_RNTI,P_RNTI and RA_RNTI format 1A), // and UE_SPEC format0 (PUSCH) too while we're at it // printf("[DCI search] doing common search/format0 aggregation 3\n"); #ifdef DEBUG_DCI_DECODING @@ -3182,10 +3192,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, frame_parms, mi, SI_RNTI, + P_RNTI, ra_rnti, 3, format1A, format1A, + format1A, format0, format1A_size_bits, format1A_size_bytes, @@ -3209,7 +3221,9 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, - 3, + P_RNTI, + 3, + format1C, format1C, format1C, format1C, @@ -3241,7 +3255,9 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, - 3, + P_RNTI, + 3, + format1A, format1A, format1A, format0, @@ -3268,7 +3284,9 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, - 2, + P_RNTI, + 2, + format1A, format1A, format1A, format0, @@ -3299,9 +3317,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 1, format1A, format1A, + format1A, format0, format0_size_bits, format0_size_bytes, @@ -3326,9 +3346,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 0, format1A, format1A, + format1A, format0, format0_size_bits, format0_size_bytes, @@ -3357,9 +3379,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 0, format1A, format1A, + format1A, format1, format1_size_bits, format1_size_bytes, @@ -3386,9 +3410,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 1, format1A, format1A, + format1A, format1, format1_size_bits, format1_size_bytes, @@ -3416,7 +3442,9 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, - 2, + P_RNTI, + 2, + format1A, format1A, format1A, format1, @@ -3446,9 +3474,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 3, format1A, format1A, + format1A, format1, format1_size_bits, format1_size_bytes, @@ -3479,9 +3509,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 0, format1A, format1A, + format1A, format2A, format2A_size_bits, format2A_size_bytes, @@ -3508,9 +3540,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 1, format1A, format1A, + format1A, format2A, format2A_size_bits, format2A_size_bytes, @@ -3537,9 +3571,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 2, format1A, format1A, + format1A, format2A, format2A_size_bits, format2A_size_bytes, @@ -3567,9 +3603,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 3, format1A, format1A, + format1A, format2A, format2A_size_bits, format2A_size_bytes, @@ -3591,9 +3629,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 0, format1A, format1A, + format1A, format2, format2_size_bits, format2_size_bytes, @@ -3620,9 +3660,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 1, format1A, format1A, + format1A, format2, format2_size_bits, format2_size_bytes, @@ -3649,9 +3691,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 2, format1A, format1A, + format1A, format2, format2_size_bits, format2_size_bytes, @@ -3679,9 +3723,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 3, format1A, format1A, + format1A, format2, format2_size_bits, format2_size_bytes, @@ -3706,9 +3752,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 0, format1A, format1A, + format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), @@ -3736,9 +3784,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 1, format1A, format1A, + format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), @@ -3765,9 +3815,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 2, format1A, format1A, + format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), @@ -3796,9 +3848,11 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, mi, SI_RNTI, ra_rnti, + P_RNTI, 3, format1A, format1A, + format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index 141e5a95dc..090ae4637f 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -729,6 +729,7 @@ typedef enum {format0, typedef enum { SI_PDSCH=0, RA_PDSCH, + P_PDSCH, PDSCH, PDSCH1, PMCH diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index c3922b13d5..d0d38b34a6 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1339,6 +1339,14 @@ int32_t generate_drs_pusch(PHY_VARS_UE *phy_vars_ue, @param frame_parms Pointer to a LTE_DL_FRAME_PARMS structure (eNB or UE)*/ void init_ul_hopping(LTE_DL_FRAME_PARMS *frame_parms); + +/*! + \brief This function implements the initialization of paging parameters for UE (See Section 7, 36.304).It must be called after setting IMSImod1024 during UE startup and after receiving SIB2 + @param ue Pointer to UE context + @param defaultPagingCycle T from 36.304 (0=32,1=64,2=128,3=256) + @param nB nB from 36.304 (0=4T,1=2T,2=T,3=T/2,4=T/4,5=T/8,6=T/16,7=T/32*/ +int init_ue_paging_info(PHY_VARS_UE *ue, long defaultPagingCycle, long nB); + int32_t compareints (const void * a, const void * b); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index c4c37d2b72..abf6038543 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -53,11 +53,6 @@ # define msg mexPrintf #else # ifdef OPENAIR2 -# if ENABLE_RAL -# include "collection/hashtable/hashtable.h" -# include "COMMON/ral_messages_types.h" -# include "UTIL/queue.h" -# endif # include "log.h" # define msg(aRGS...) LOG_D(PHY, ##aRGS) # else @@ -132,10 +127,6 @@ static inline void* malloc16_clear( size_t size ) #include "PHY/TOOLS/defs.h" #include "platform_types.h" -#ifdef OPENAIR_LTE - -//#include "PHY/LTE_ESTIMATION/defs.h" - #include "PHY/LTE_TRANSPORT/defs.h" #include @@ -178,16 +169,6 @@ typedef struct UE_SCAN_INFO_s { int32_t freq_offset_Hz[3][10]; } UE_SCAN_INFO_t; -#if ENABLE_RAL -typedef struct ral_threshold_phy_s { - SLIST_ENTRY(ral_threshold_phy_s) ral_thresholds; - ral_threshold_t threshold; - ral_th_action_t th_action; - ral_link_param_t link_param; - long timer_id; -} ral_threshold_phy_t; -#endif - /// Top-level PHY Data Structure for RN typedef struct { /// Module ID indicator for this instance @@ -647,17 +628,25 @@ typedef struct { LTE_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; + LTE_UE_PDSCH *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_PDCCH *pdcch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_DLSCH_t *dlsch[NUMBER_OF_CONNECTED_eNB_MAX][2]; LTE_UE_ULSCH_t *ulsch[NUMBER_OF_CONNECTED_eNB_MAX]; - LTE_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX],*dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX]; + LTE_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_eNB_MAX]; LTE_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; // This is for SIC in the UE, to store the reencoded data LTE_eNB_DLSCH_t *dlsch_eNB[NUMBER_OF_CONNECTED_eNB_MAX]; + //Paging parameters + uint32_t IMSImod1024; + uint32_t PF; + uint32_t PO; + // For abstraction-purposes only uint8_t sr[10]; uint8_t pucch_sel[10]; @@ -712,6 +701,8 @@ typedef struct { int dlsch_SI_errors[NUMBER_OF_CONNECTED_eNB_MAX]; int dlsch_ra_received[NUMBER_OF_CONNECTED_eNB_MAX]; int dlsch_ra_errors[NUMBER_OF_CONNECTED_eNB_MAX]; + int dlsch_p_received[NUMBER_OF_CONNECTED_eNB_MAX]; + int dlsch_p_errors[NUMBER_OF_CONNECTED_eNB_MAX]; int dlsch_mch_received_sf[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; int dlsch_mch_received[NUMBER_OF_CONNECTED_eNB_MAX]; int dlsch_mcch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; @@ -835,11 +826,6 @@ typedef struct { /// RF and Interface devices per CC openair0_device rfdevice; -#if ENABLE_RAL - hash_table_t *ral_thresholds_timed; - SLIST_HEAD(ral_thresholds_gen_poll_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX]; - SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; -#endif } PHY_VARS_UE; @@ -851,6 +837,5 @@ typedef struct { #include "PHY/LTE_ESTIMATION/defs.h" #include "SIMULATION/ETH_TRANSPORT/defs.h" -#endif //OPENAIR_LTE #endif // __PHY_DEFS__H__ diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 5c884112fd..8468d62cad 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -1627,8 +1627,10 @@ void restart_phy(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t ab ue->dlsch_fer[eNB_id] = 0; ue->dlsch_SI_received[eNB_id] = 0; ue->dlsch_ra_received[eNB_id] = 0; + ue->dlsch_p_received[eNB_id] = 0; ue->dlsch_SI_errors[eNB_id] = 0; ue->dlsch_ra_errors[eNB_id] = 0; + ue->dlsch_p_errors[eNB_id] = 0; ue->dlsch_mch_received[eNB_id] = 0; @@ -2027,6 +2029,35 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint } } + else if ((dci_alloc_rx[i].rnti == P_RNTI) && + ((dci_alloc_rx[i].format == format1A) || (dci_alloc_rx[i].format == format1C))) { + +#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d] subframe %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); +#endif + + + if (generate_ue_dlsch_params_from_dci(frame_rx, + subframe_rx, + (void *)&dci_alloc_rx[i].dci_pdu, + SI_RNTI, + dci_alloc_rx[i].format, + &ue->dlsch_SI[eNB_id], + &ue->frame_parms, + ue->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI)==0) { + + ue->dlsch_p_received[eNB_id]++; + + + LOG_D(PHY,"[UE %d] Frame %d, subframe %d : Generate UE DLSCH P_RNTI format 1%s\n",ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format==format1A?"A":"C"); + //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); + + } + } + else if ((ue->prach_resources[eNB_id]) && (dci_alloc_rx[i].rnti == ue->prach_resources[eNB_id]->ra_RNTI) && (dci_alloc_rx[i].format == format1A)) { @@ -2440,6 +2471,9 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, case RA_PDSCH: pdsch_vars = ue->pdsch_vars_ra[eNB_id]; break; + case P_PDSCH: + pdsch_vars = ue->pdsch_vars_p[eNB_id]; + break; case PDSCH: pdsch_vars = ue->pdsch_vars[eNB_id]; break; @@ -2557,6 +2591,14 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, ue->dlsch_SI[eNB_id]->harq_processes[0]->b, ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); break; + case P_PDSCH: + mac_xface->ue_decode_p(ue->Mod_id, + CC_id, + frame_rx, + eNB_id, + ue->dlsch_SI[eNB_id]->harq_processes[0]->b, + ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3); + break; case RA_PDSCH: process_rar(ue,proc,eNB_id,mode,abstraction_flag); break; @@ -2630,6 +2672,8 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin if (ue->dlsch_SI[eNB_id]) ue->dlsch_SI[eNB_id]->active = 0; + if (ue->dlsch_p[eNB_id]) + ue->dlsch_p[eNB_id]->active = 0; if (ue->dlsch_ra[eNB_id]) ue->dlsch_ra[eNB_id]->active = 0; @@ -2726,6 +2770,20 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->frame_parms.symbols_per_tti>>1, abstraction_flag); } + + // do procedures for SI-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + ue->pdcch_vars[eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + } + // do procedures for RA-RNTI if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { ue_pdsch_procedures(ue, @@ -2821,6 +2879,30 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin abstraction_flag); ue->dlsch_SI[eNB_id]->active = 0; } + + // do procedures for P-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + + ue_dlsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + &ue->dlsch_p_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_p[eNB_id]->active = 0; + } // do procedures for RA-RNTI if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { ue_pdsch_procedures(ue, diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index fb6a9d0288..cfd3da43ca 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -129,7 +129,8 @@ void do_OFDM_mod_l(int32_t **txdataF, int32_t **txdata, uint16_t next_slot, LTE_ } -void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,double SNR, int tx_lev,int hold_channel,int abstx, int num_rounds, int trials, int round, channel_desc_t *eNB2UE[4], double **s_re,double **s_im,double **r_re,double **r_im,FILE *csv_fd) { +void DL_channel(PHY_VARS_eNB *eNB,PHY_VARS_UE *UE,int subframe,int awgn_flag,double SNR, int tx_lev,int hold_channel,int abstx, int num_rounds, int trials, int round, channel_desc_t *eNB2UE[4], + double s_re[2][30720*2],double s_im[2][30720*2],double r_re[2][30720*2],double r_im[2][30720*2],FILE *csv_fd) { int i,u; int aa,aarx,aatx; @@ -1266,7 +1267,7 @@ int main(int argc, char **argv) double snr_step=1,input_snr_step=1, snr_int=30; LTE_DL_FRAME_PARMS *frame_parms; - double **s_re,**s_im,**r_re,**r_im; + double s_re[2][30720*2],s_im[2][30720*2],r_re[2][30720*2],r_im[2][30720*2]; double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel @@ -1798,13 +1799,6 @@ int main(int argc, char **argv) frame_parms = &eNB->frame_parms; - s_re = malloc(2*sizeof(double*)); - s_im = malloc(2*sizeof(double*)); - r_re = malloc(2*sizeof(double*)); - r_im = malloc(2*sizeof(double*)); - // r_re0 = malloc(2*sizeof(double*)); - // r_im0 = malloc(2*sizeof(double*)); - nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; printf("Channel Model= (%s,%d)\n",channel_model_input, channel_model); @@ -1948,14 +1942,6 @@ int main(int argc, char **argv) } */ - for (i=0; i<2; i++) { - s_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - } - - UE->pdcch_vars[0]->crnti = n_rnti; // Fill in UL_alloc @@ -2329,165 +2315,7 @@ int main(int argc, char **argv) } // common_flag == 0 - /* - num_pdcch_symbols_2 = generate_dci_top(num_ue_spec_dci, - num_common_dci, - dci_alloc, - 0, - AMP, - &eNB->frame_parms, - eNB->common_vars.txdataF[eNB_id], - subframe); - - if (n_frames==1) printf("Generated DCI, num_pdcch_symbols %d\n",num_pdcch_symbols_2); - if (num_pdcch_symbols_2 > num_pdcch_symbols) { - printf("Error: given num_pdcch_symbols not big enough (%d > %d)\n",num_pdcch_symbols_2,num_pdcch_symbols); - exit(-1); - } - - for (k=0; kframe_parms, - eNB->dlsch[k][cw]->harq_processes[0]->nb_rb, - eNB->dlsch[k][cw]->harq_processes[0]->rb_alloc, - get_Qm(eNB->dlsch[k][cw]->harq_processes[0]->mcs), - eNB->dlsch[k][cw]->harq_processes[0]->Nl, - num_pdcch_symbols, - 0,subframe); - - tbs = eNB->dlsch[k][cw]->harq_processes[0]->TBS; - rate = (double)tbs/(double)coded_bits_per_codeword; - - if ((SNR==snr0) && (trials==0) && (round==0)) - printf("User %d, cw %d: Rate = %f (%f bits/dim) (G %d, TBS %d, mod %d, pdcch_sym %d, ndi %d)\n", - k,cw,rate,rate*get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs), - coded_bits_per_codeword, - tbs, - get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs), - num_pdcch_symbols, - eNB->dlsch[0][0]->harq_processes[0]->round); - - // use the PMI from previous trial - if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { - eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL); - UE->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL); - - if (n_users>1) - eNB->dlsch[1][0]->harq_processes[0]->pmi_alloc = (eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc ^ 0x1555); - - - } - - - start_meas(&eNB->dlsch_encoding_stats); - - if (dlsch_encoding(((cw==0) ? input_buffer0[k] : input_buffer1[k]), - &eNB->frame_parms, - num_pdcch_symbols, - eNB->dlsch[k][cw], - 0,subframe, - &eNB->dlsch_rate_matching_stats, - &eNB->dlsch_turbo_encoding_stats, - &eNB->dlsch_interleaving_stats - )<0) - exit(-1); - - stop_meas(&eNB->dlsch_encoding_stats); - - eNB->dlsch[k][cw]->rnti = (common_flag==0) ? n_rnti+k : SI_RNTI; - start_meas(&eNB->dlsch_scrambling_stats); - dlsch_scrambling(&eNB->frame_parms, - 0, - eNB->dlsch[k][cw], - coded_bits_per_codeword, - 0, - subframe<<1); - stop_meas(&eNB->dlsch_scrambling_stats); - - if (n_frames==1) { - for (s=0; sdlsch[k][cw]->harq_processes[0]->C; s++) { - if (sdlsch[k][cw]->harq_processes[0]->Cminus) - Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kminus; - else - Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kplus; - - Kr_bytes = Kr>>3; - - for (i=0; idlsch[k][cw]->harq_processes[0]->c[s][i]); - } - } - } - - start_meas(&eNB->dlsch_modulation_stats); - - re_allocated = dlsch_modulation(eNB->common_vars.txdataF[eNB_id], - AMP, - subframe, - &eNB->frame_parms, - num_pdcch_symbols, - eNB->dlsch[k][0], - (transmission_mode==3)||(transmission_mode==4) ? eNB->dlsch[k][1] : NULL); - - (void)re_allocated; - - stop_meas(&eNB->dlsch_modulation_stats); - - } //n_users - - - generate_pilots(eNB, - eNB->common_vars.txdataF[eNB_id], - AMP, - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); - - start_meas(&eNB->ofdm_mod_stats); - - do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], - eNB->common_vars.txdata[eNB_id], - (subframe*2), - &eNB->frame_parms); - - do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], - eNB->common_vars.txdata[eNB_id], - (subframe*2)+1, - &eNB->frame_parms); - - stop_meas(&eNB->ofdm_mod_stats); - stop_meas(&eNB->phy_proc_tx); - - do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id], - eNB->common_vars.txdata[eNB_id], - (subframe*2)+2, - &eNB->frame_parms); - - if (n_frames==1) { - write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], - nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); - - if (eNB->frame_parms.nb_antennas_tx>1) - write_output("txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], - nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); - } - tx_lev = 0; - - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa] - [subframe*eNB->frame_parms.samples_per_tti], - eNB->frame_parms.samples_per_tti); - } - - tx_lev_dB = (unsigned int) dB_fixed(tx_lev); - - if (n_frames==1) { - printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB); - write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe* eNB->frame_parms.samples_per_tti], - - eNB->frame_parms.samples_per_tti,1,1); - } - } - */ /* else { // Read signal from file i=0; @@ -2533,7 +2361,6 @@ int main(int argc, char **argv) &eNB->frame_parms); stop_meas(&eNB->ofdm_mod_stats); - stop_meas(&eNB->phy_proc_tx); // generate next subframe for channel estimation @@ -2653,461 +2480,7 @@ int main(int argc, char **argv) } - /* - if (n_frames==1) { - printf("RX level in null symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); - printf("RX level in data symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2))); - printf("rx_level Null symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)))); - printf("rx_level data symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)))); - } - - if (eNB->frame_parms.Ncp == 0) { // normal prefix - pilot1 = 4; - pilot2 = 7; - pilot3 = 11; - } else { // extended prefix - pilot1 = 3; - pilot2 = 6; - pilot3 = 9; - } - - start_meas(&UE->phy_proc_rx); - // Inner receiver scheduling for 3 slots - for (Ns=(2*subframe); Ns<((2*subframe)+3); Ns++) { - for (l=0; lofdm_demod_stats); - slot_fep(UE, - l, - Ns%20, - 0, - 0, - 0); - stop_meas(&UE->ofdm_demod_stats); - - if (UE->perfect_ce==1) { - if (awgn_flag==0) { - for(k=0; knb_antennas_tx; aa++) { - for (aarx=0; aarxnb_antennas_rx; aarx++) { - for (i=0; iN_RB_DL*12; i++) { - ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( - eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP); - ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)( - eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP); - } - } - } - } - } else { - for(aa=0; aanb_antennas_tx; aa++) { - for (aarx=0; aarxnb_antennas_rx; aarx++) { - for (i=0; iN_RB_DL*12; i++) { - ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP); - ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2; - } - } - } - } - } - - - if ((Ns==((2*subframe))) && (l==0)) { - lte_ue_measurements(UE, - subframe*UE->frame_parms.samples_per_tti, - 1, - 0); - - if (transmission_mode==5 || transmission_mode==6) { - if (pmi_feedback == 1) { - pmi_feedback = 0; - hold_channel = 1; - goto PMI_FEEDBACK; - } - } - - } - - - if ((Ns==(2*subframe)) && (l==pilot1)) {// process symbols 0,1,2 - - if (dci_flag == 1) { - UE->UE_mode[0] = PUSCH; - start_meas(&UE->dlsch_rx_pdcch_stats); - rx_pdcch(&UE->common_vars, - UE->pdcch_vars, - &UE->frame_parms, - subframe, - 0, - (UE->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, - UE->high_speed_flag, - 0); - stop_meas(&UE->dlsch_rx_pdcch_stats); - // overwrite number of pdcch symbols - UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols; - - dci_cnt = dci_decoding_procedure(UE, - dci_alloc_rx,1, - eNB_id, - subframe); - //printf("dci_cnt %d\n",dci_cnt); - - if (dci_cnt==0) { - dlsch_active = 0; - - if (round==0) { - dci_errors++; - round=5; - errs[0]++; - //round_trials[0]++; - - if (n_frames==1) - printf("DCI error trial %d errs[0] %d\n",trials,errs[0]); - } - - // for (i=1;i<=round;i++) - // round_trials[i]--; - // round=5; - } - - for (i=0; idlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->first_tx=1; - - if ((dci_alloc_rx[i].rnti == n_rnti) && - (generate_ue_dlsch_params_from_dci(0, - subframe, - dci_alloc_rx[i].dci_pdu, - dci_alloc_rx[i].rnti, - dci_alloc_rx[i].format, - UE->dlsch[0], - &UE->frame_parms, - UE->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI)==0)) { - //dump_dci(&UE->frame_parms,&dci_alloc_rx[i]); - coded_bits_per_codeword = get_G(&eNB->frame_parms, - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->nb_rb, - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->rb_alloc_even, - get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs), - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->Nl, - UE->pdcch_vars[0]->num_pdcch_symbols, - 0,subframe); - printf("num_pdcch_symbols %d, G %d, TBS %d\n",UE->pdcch_vars[0]->num_pdcch_symbols,coded_bits_per_codeword, - UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->TBS); - - dlsch_active = 1; - } else { - dlsch_active = 0; - - if (round==0) { - dci_errors++; - errs[0]++; - //round_trials[0]++; - round=5; - - if (n_frames==1) - printf("DCI misdetection trial %d\n",trials); - - } - - // for (i=1;i<=round;i++) - // round_trials[i]--; - // round=5; - } - } - } // if dci_flag==1 - else { //dci_flag == 0 - - UE->pdcch_vars[0]->crnti = n_rnti; - UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols; - - if (round == 0) UE->dlsch[0][0]->harq_processes[0]->first_tx=1; - - switch (transmission_mode) { - case 1: - case 2: - generate_ue_dlsch_params_from_dci(0, - subframe, - &DLSCH_alloc_pdu_1[0], - (common_flag==0)? C_RNTI : SI_RNTI, - (common_flag==0)? format1 : format1A, - UE->dlsch[0], - &UE->frame_parms, - UE->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI); - break; - - case 3: - // printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx); - generate_ue_dlsch_params_from_dci(0, - subframe, - &DLSCH_alloc_pdu_1[0], - (common_flag==0)? C_RNTI : SI_RNTI, - (common_flag==0)? format2A : format1A, - UE->dlsch[0], - &UE->frame_parms, - UE->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI); - // printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx); - break; - - case 4: - generate_ue_dlsch_params_from_dci(0, - subframe, - &DLSCH_alloc_pdu_1[0], - (common_flag==0)? C_RNTI : SI_RNTI, - (common_flag==0)? format2 : format1A, - UE->dlsch[0], - &UE->frame_parms, - UE->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI); - break; - - case 5: - case 6: - generate_ue_dlsch_params_from_dci(0, - subframe, - &DLSCH_alloc_pdu2_1E[0], - C_RNTI, - format1E_2A_M10PRB, - UE->dlsch[0], - &UE->frame_parms, - UE->pdsch_config_dedicated, - SI_RNTI, - 0, - P_RNTI); - break; - - } - - dlsch_active = 1; - } // if dci_flag == 1 - } - - if (dlsch_active == 1) { - if ((Ns==(1+(2*subframe))) && (l==0)) {// process PDSCH symbols 1,2,3,4,5,(6 Normal Prefix) - - if ((transmission_mode == 5) && - (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->dl_power_off==0) && - (UE->use_ia_receiver ==1)) { - dual_stream_UE = 1; - } else { - dual_stream_UE = 0; - } - - - start_meas(&UE->dlsch_llr_stats); - - for (m=UE->pdcch_vars[0]->num_pdcch_symbols; - mpdcch_vars[0]->num_pdcch_symbols)?1:0, - dual_stream_UE, - i_mod, - UE->dlsch[0][0]->current_harq_pid)==-1) { - dlsch_active = 0; - break; - } - } - - stop_meas(&UE->dlsch_llr_stats); - } - - if ((Ns==(1+(2*subframe))) && (l==pilot1)) { - // process symbols (6 Extended Prefix),7,8,9 - start_meas(&UE->dlsch_llr_stats); - - for (m=pilot2; - mdlsch[0][0]->current_harq_pid)==-1) { - dlsch_active=0; - break; - } - } - - stop_meas(&UE->dlsch_llr_stats); - } - - if ((Ns==(2+(2*subframe))) && (l==0)) { // process symbols 10,11,(12,13 Normal Prefix) do deinterleaving for TTI - start_meas(&UE->dlsch_llr_stats); - - for (m=pilot3; - mframe_parms.symbols_per_tti; - m++) { - if (rx_pdsch(UE, - PDSCH, - eNB_id, - eNB_id_i, - subframe, - m, - 0, - dual_stream_UE, - i_mod, - UE->dlsch[0][0]->current_harq_pid)==-1) { - dlsch_active=0; - break; - } - } - - stop_meas(&UE->dlsch_llr_stats); - } - - if (test_perf ==0 ) { - if ((n_frames==1) && (Ns==(2+(2*subframe))) && (l==0)) { - write_output("ch0.m","ch0",eNB2UE[0]->ch[0],eNB2UE[0]->channel_length,1,8); - - if (eNB->frame_parms.nb_antennas_tx>1) - write_output("ch1.m","ch1",eNB2UE[0]->ch[eNB->frame_parms.nb_antennas_rx],eNB2UE[0]->channel_length,1,8); - - //common vars - write_output("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); - write_output("rxsigF0.m","rxsF0", &UE->common_vars.rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - - if (UE->frame_parms.nb_antennas_rx>1) { - write_output("rxsig1.m","rxs1", UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1); - write_output("rxsigF1.m","rxsF1", UE->common_vars.rxdataF[1],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - } - - write_output("dlsch00_r0.m","dl00_r0", - &(UE->common_vars.dl_ch_estimates[eNB_id][0][0]), - UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - - if (UE->frame_parms.nb_antennas_rx>1) - write_output("dlsch01_r0.m","dl01_r0", - &(UE->common_vars.dl_ch_estimates[eNB_id][1][0]), - UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - - if (eNB->frame_parms.nb_antennas_tx>1) - write_output("dlsch10_r0.m","dl10_r0", - &(UE->common_vars.dl_ch_estimates[eNB_id][2][0]), - UE->frame_parms.ofdm_symbol_size*nsymb,1,1); - - if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) - write_output("dlsch11_r0.m","dl11_r0", - &(UE->common_vars.dl_ch_estimates[eNB_id][3][0]), - UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); - - //pdsch_vars - dump_dlsch2(UE,eNB_id,coded_bits_per_codeword,round); - //dump_dlsch2(UE,eNB_id_i,coded_bits_per_codeword); - write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); - - //pdcch_vars - write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); - write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); - - write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1); - write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNB_id]->llr,2400,1,4); - - } - } - } - } - } - - //saving PMI in case of Transmission Mode > 5 - - if(abstx) { - if (trials==0 && round==0 && transmission_mode>=5) { - for (iii=0; iiilte_ue_pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[iii])); - fprintf(csv_fd,"%x,%x,",(UE->pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->pdsch_vars[eNB_id]->pmi_ext[iii])); - printf("%x ",(UE->pdsch_vars[eNB_id]->pmi_ext[iii])); - } - } - } - - for (int cw=Kmimo-1; cw>=0; cw--) { - UE->dlsch[0][cw]->rnti = (common_flag==0) ? n_rnti: SI_RNTI; - coded_bits_per_codeword = get_G(&eNB->frame_parms, - eNB->dlsch[0][cw]->harq_processes[0]->nb_rb, - eNB->dlsch[0][cw]->harq_processes[0]->rb_alloc, - get_Qm(eNB->dlsch[0][cw]->harq_processes[0]->mcs), - eNB->dlsch[0][cw]->harq_processes[0]->Nl, - num_pdcch_symbols, - 0,subframe); - - UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid]->G = coded_bits_per_codeword; - - - // calculate uncoded BLER - uncoded_ber=0; - for (i=0;idlsch[0][0]->harq_processes[0]->e[i] != (UE->pdsch_vars[0]->llr[0][i]<0)) { - uncoded_ber_bit[i] = 1; - uncoded_ber++; - } - else - uncoded_ber_bit[i] = 0; - - uncoded_ber/=coded_bits_per_codeword; - avg_ber += uncoded_ber; - - if (n_frames==1) - write_output("uncoded_ber_bit.m","uncoded_ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); - - - start_meas(&UE->dlsch_unscrambling_stats); - dlsch_unscrambling(&UE->frame_parms, - 0, - UE->dlsch[0][cw], - coded_bits_per_codeword, - UE->pdsch_vars[eNB_id]->llr[cw], - 0, - subframe<<1); - stop_meas(&UE->dlsch_unscrambling_stats); - - start_meas(&UE->dlsch_decoding_stats); - ret = dlsch_decoding(UE, - UE->pdsch_vars[eNB_id]->llr[cw], - &UE->frame_parms, - UE->dlsch[0][cw], - UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid], - subframe, - UE->dlsch[0][cw]->current_harq_pid, - 1,llr8_flag); - stop_meas(&UE->dlsch_decoding_stats); - - if (cw==1) { - if (ret <= UE->dlsch[0][cw]->max_turbo_iterations) { - } else { - errs2[round]++; - } - } - } - - - stop_meas(&UE->phy_proc_rx); - */ if (UE->dlsch_errors[0] == 0) { @@ -3120,45 +2493,7 @@ int main(int argc, char **argv) UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->TBS; TB0_active = 0; - if (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) { //try to decode second stream using SIC - - //for (round = 0 ; round < UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->round ; round++) { - // re-encoding of first stream - //dlsch0_ue_harq = UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]; - //dlsch0_eNB_harq = UE->dlsch[eNB_id]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]; - //dlsch0_eNB_harq->mimo_mode = LARGE_CDD; - //dlsch0_eNB_harq->rb_alloc[0] = dlsch0_ue_harq->rb_alloc_even[0]; - //dlsch0_eNB_harq->nb_rb = dlsch0_ue_harq->nb_rb; - //dlsch0_eNB_harq->mcs = dlsch0_ue_harq->mcs; - //dlsch0_eNB_harq->rvidx = dlsch0_ue_harq->rvidx; - //dlsch0_eNB_harq->Nl = dlsch0_ue_harq->Nl; - - //dlsch0_eNB_harq->TBS = dlsch0_ue_harq->TBS; - //dlsch0_eNB_harq->dl_power_off = dlsch0_ue_harq->dl_power_off; - //dlsch0_eNB_harq->status = dlsch0_ue_harq->status; - - //UE->dlsch[eNB_id]->active = UE->dlsch[eNB_id][0]->active; - //UE->dlsch[eNB_id]->rnti = UE->dlsch[eNB_id][0]->rnti; - - //dlsch_encoding(UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->b, - // &UE->frame_parms, - // num_pdcch_symbols, - // UE->dlsch[0], - // 0,subframe, - // &UE->dlsch_rate_matching_stats, - // &UE->dlsch_turbo_encoding_stats, - // &UE->dlsch_interleaving_stats - // ); - - //scrambling - - //modulation - - //stripping (from matched filter output?) - - //detection of second stream - } - + } // DLSCH received ok else { errs[round]++; @@ -3449,13 +2784,14 @@ int main(int argc, char **argv) printf("eNB TX function statistics (per 1ms subframe)\n\n"); std_phy_proc_tx = sqrt((double)eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000, 2)/eNB->phy_proc_tx.trials - pow((double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); - printf("Total PHY proc tx :%f us (%d trials)\n",(double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_tx.trials); - printf("|__ Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, - n_tx_dropped); std_phy_proc_tx_ifft = sqrt((double)eNB->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, 2)/eNB->ofdm_mod_stats.trials - pow((double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2)); printf("OFDM_mod time :%f us (%d trials)\n",(double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,eNB->ofdm_mod_stats.trials); printf("|__ Statistcs std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3); + printf("Total PHY proc tx :%f us (%d trials)\n",(double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_tx.trials); + printf("|__ Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, + n_tx_dropped); + std_phy_proc_tx_mod = sqrt((double)eNB->dlsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000, 2)/eNB->dlsch_modulation_stats.trials - pow((double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000,2)); printf("DLSCH modulation time :%f us (%d trials)\n",(double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0, @@ -3809,24 +3145,6 @@ int main(int argc, char **argv) } - printf("Freeing channel I/O\n"); - - for (i=0; i<2; i++) { - free(s_re[i]); - free(s_im[i]); - free(r_re[i]); - free(r_im[i]); - } - - free(s_re); - free(s_im); - free(r_re); - free(r_im); - - // lte_sync_time_free(); - - // printf("[MUMIMO] mcs %d, mcsi %d, offset %d, bler %f\n",mcs,mcs_i,offset_mumimo_llr_drange_fix,((double)errs[0])/((double)round_trials[0])); - return(0); } diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index bf166f6d64..5b558e2921 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -82,6 +82,7 @@ #define BCCH_PAYLOAD_SIZE_MAX 128 #define CCCH_PAYLOAD_SIZE_MAX 128 +#define PCCH_PAYLOAD_SIZE_MAX 128 #define SCH_PAYLOAD_SIZE_MAX 4096 /// Logical channel ids from 36-311 (Note BCCH is not specified in 36-311, uses the same as first DRB) @@ -263,6 +264,10 @@ typedef struct { typedef struct { uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ; } __attribute__((__packed__))BCCH_PDU; +/*! \brief BCCH payload */ +typedef struct { + uint8_t payload[PCCH_PAYLOAD_SIZE_MAX] ; +} __attribute__((__packed__))PCCH_PDU; #ifdef Rel10 /*! \brief MCCH payload */ @@ -291,6 +296,8 @@ typedef struct { #define CCCH_LCHANID 0 /*!\brief Values of BCCH logical channel */ #define BCCH 3 // SI +/*!\brief Values of PCCH logical channel */ +#define PCCH 4 // Paging /*!\brief Value of CCCH / SRB0 logical channel */ #define CCCH 0 // srb0 /*!\brief DCCH / SRB1 logical channel */ @@ -1104,6 +1111,8 @@ typedef struct { time_stats_t rx_mch_sdu; /// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind) time_stats_t rx_si; + /// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind) + time_stats_t rx_p; } UE_MAC_INST; /*! \brief ID of the neighboring cells used for HO*/ typedef struct { diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 7480babd24..fd29513470 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -480,6 +480,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui LOG_I(MAC,"[MAIN] init UE MAC functions \n"); mac_xface->ue_decode_si = ue_decode_si; + mac_xface->ue_decode_p = ue_decode_p; mac_xface->ue_send_sdu = ue_send_sdu; #ifdef Rel10 mac_xface->ue_send_mch_sdu = ue_send_mch_sdu; diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index b6b223bd6a..10d5093dd4 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -385,6 +385,8 @@ void mac_out_of_sync_ind(module_id_t module_idP, frame_t frameP, uint16_t CH_ind void ue_decode_si(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_index, void *pdu, uint16_t len); +void ue_decode_p(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_index, void *pdu, uint16_t len); + void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frame, uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index); diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index 1d7e49070b..a3c35d18b8 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -525,6 +525,41 @@ void ue_decode_si(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_i } } +void ue_decode_p(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len) +{ + + start_meas(&UE_mac_inst[module_idP].rx_p); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_IN); + + LOG_D(MAC,"[UE %d] Frame %d Sending Paging message to RRC (LCID Id %d,len %d)\n",module_idP,frameP,PCCH,len); + + mac_rrc_data_ind(module_idP, + CC_id, + frameP,0, // unknown subframe + P_RNTI, + PCCH, + (uint8_t *)pdu, + len, + ENB_FLAG_NO, + eNB_index, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_OUT); + stop_meas(&UE_mac_inst[module_idP].rx_p); + if (opt_enabled == 1) { + trace_pdu(0, + (uint8_t *)pdu, + len, + module_idP, + 4, + P_RNTI, + UE_mac_inst[module_idP].subframe, + 0, + 0); + LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n", + module_idP, frameP, CC_id, P_RNTI, len); + } +} + #ifdef Rel10 unsigned char *parse_mch_header(unsigned char *mac_header, unsigned char *num_sdu, diff --git a/openair2/PHY_INTERFACE/defs.h b/openair2/PHY_INTERFACE/defs.h index 5d933094f3..6b45bbdc7b 100755 --- a/openair2/PHY_INTERFACE/defs.h +++ b/openair2/PHY_INTERFACE/defs.h @@ -146,6 +146,9 @@ typedef struct { /// Send a received SI sdu void (*ue_decode_si)(module_id_t Mod_id,int CC_id,frame_t frameP, uint8_t CH_index, void *pdu, uint16_t len); + /// Send a received Paging sdu + void (*ue_decode_p)(module_id_t Mod_id,int CC_id,frame_t frameP, uint8_t CH_index, void *pdu, uint16_t len); + /// Send a received DLSCH sdu to MAC void (*ue_send_sdu)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index); diff --git a/openair2/RRC/LITE/L2_interface.c b/openair2/RRC/LITE/L2_interface.c index 0558376b1d..3bdd88b821 100644 --- a/openair2/RRC/LITE/L2_interface.c +++ b/openair2/RRC/LITE/L2_interface.c @@ -397,6 +397,10 @@ mac_rrc_data_ind( #endif } + if(srb_idP == PCCH) { + LOG_D(RRC,"[UE %d] Received SDU for PCCH on SRB %d from eNB %d\n",module_idP,srb_idP,eNB_indexP); + decode_PCCH_DLSCH_Message(&ctxt,eNB_indexP,(uint8_t*)sduP,sdu_lenP); + } if((srb_idP & RAB_OFFSET) == CCCH) { if (sdu_lenP>0) { LOG_T(RRC,"[UE %d] Received SDU for CCCH on SRB %d from eNB %d\n",module_idP,srb_idP & RAB_OFFSET,eNB_indexP); diff --git a/openair2/RRC/LITE/proto.h b/openair2/RRC/LITE/proto.h index 7b316ce953..f200b14d30 100644 --- a/openair2/RRC/LITE/proto.h +++ b/openair2/RRC/LITE/proto.h @@ -357,6 +357,12 @@ int decode_BCCH_DLSCH_Message( const uint8_t rsrq, const uint8_t rsrp ); +int decode_PCCH_DLSCH_Message( + const protocol_ctxt_t* const ctxt_pP, + const uint8_t eNB_index, + uint8_t* const Sdu, + const uint8_t Sdu_len); + void ue_meas_filtering( const protocol_ctxt_t* const ctxt_pP, diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c index c72c106e0f..8ea604f932 100644 --- a/openair2/RRC/LITE/rrc_UE.c +++ b/openair2/RRC/LITE/rrc_UE.c @@ -58,6 +58,7 @@ #include "UL-DCCH-Message.h" #include "DL-DCCH-Message.h" #include "BCCH-DL-SCH-Message.h" +#include "PCCH-Message.h" #ifdef Rel10 #include "MCCH-Message.h" #endif @@ -2463,6 +2464,39 @@ int decode_BCCH_DLSCH_Message( return 0; } +//----------------------------------------------------------------------------- +int decode_PCCH_DLSCH_Message( + const protocol_ctxt_t* const ctxt_pP, + const uint8_t eNB_index, + uint8_t* const Sdu, + const uint8_t Sdu_len) +{ + PCCH_Message_t *pcch_message = NULL; + int i; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_IN ); + + asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + &asn_DEF_PCCH_Message, + (void **)&pcch_message, + (const void *)Sdu, + Sdu_len ); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E( RRC, "[UE %"PRIu8"] Failed to decode PCCH_MESSAGE (%zu bits)\n", + ctxt_pP->module_id, + dec_rval.consumed ); + for (i=0;i Date: Sat, 3 Sep 2016 08:57:59 -0700 Subject: [PATCH 173/206] added pch.c --- openair1/PHY/LTE_TRANSPORT/pch.c | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 openair1/PHY/LTE_TRANSPORT/pch.c diff --git a/openair1/PHY/LTE_TRANSPORT/pch.c b/openair1/PHY/LTE_TRANSPORT/pch.c new file mode 100644 index 0000000000..167d9c19ae --- /dev/null +++ b/openair1/PHY/LTE_TRANSPORT/pch.c @@ -0,0 +1,61 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ +#include "PHY/defs.h" +#include "PHY/extern.h" +#include "assertions.h" + +const unsigned int Ttab[4] = {32,64,128,256}; + +// This function implements the initialization of paging parameters for UE (See Section 7, 36.304) +// It must be called after setting IMSImod1024 during UE startup and after receiving SIB2 +int init_ue_paging_info(PHY_VARS_UE *ue, long defaultPagingCycle, long nB) { + + LTE_DL_FRAME_PARMS *fp = &ue->frame_parms; + + unsigned int T = Ttab[defaultPagingCycle]; + unsigned int N = (nB<=2) ? T : (T>>(nB-2)); + unsigned int Ns = (nB<2) ? (1<<(2-nB)) : 1; + unsigned int UE_ID = ue->IMSImod1024; + unsigned int i_s = (UE_ID/N)%Ns; + + + ue->PF = (T/N) * (UE_ID % N); + + // This implements Section 7.2 from 36.304 + if (Ns==1) + ue->PO = (fp->frame_type==FDD) ? 9 : 0; + else if (Ns==2) + ue->PO = (fp->frame_type==FDD) ? (4+(5*i_s)) : (5*i_s); + else if (Ns==4) + ue->PO = (fp->frame_type==FDD) ? (4*(i_s&1)+(5*(i_s>>1))) : ((i_s&1)+(5*(i_s>>1))); + else + AssertFatal(1==0,"init_ue_paging_info: Ns is %d\n",Ns); + + return(0); +} From b8b2edb3a9e23c4f824ad4da3dc13fa98e07e944 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 3 Sep 2016 12:52:28 -0700 Subject: [PATCH 174/206] updates in ulsim for new multipath_channel declaration. Small optimization in dlsch_modulation.c --- openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 29 ++++++++++++++++- openair1/SIMULATION/LTE_PHY/ulsim.c | 31 +------------------ 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 034dc0ada8..48b3f53be4 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -328,7 +328,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; re<12; - re++,x0p+=6,tti_offset++) { + re+=4,x0p+=24,tti_offset+=4) { qam64_table_offset_re=FOUR[x0p[0]]; qam64_table_offset_im=FOUR[x0p[1]]; @@ -338,6 +338,33 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, qam64_table_offset_im+=x0p[5]; ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam64_table_offset_re]; ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam64_table_offset_im]; + + qam64_table_offset_re=FOUR[x0p[6]]; + qam64_table_offset_im=FOUR[x0p[7]]; + qam64_table_offset_re+=TWO[x0p[8]]; + qam64_table_offset_im+=TWO[x0p[9]]; + qam64_table_offset_re+=x0p[10]; + qam64_table_offset_im+=x0p[11]; + ((int16_t *)&txdataF[0][tti_offset])[2]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[3]=qam_table_s0[qam64_table_offset_im]; + + qam64_table_offset_re=FOUR[x0p[12]]; + qam64_table_offset_im=FOUR[x0p[13]]; + qam64_table_offset_re+=TWO[x0p[14]]; + qam64_table_offset_im+=TWO[x0p[15]]; + qam64_table_offset_re+=x0p[16]; + qam64_table_offset_im+=x0p[17]; + ((int16_t *)&txdataF[0][tti_offset])[4]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[5]=qam_table_s0[qam64_table_offset_im]; + + qam64_table_offset_re=FOUR[x0p[18]]; + qam64_table_offset_im=FOUR[x0p[19]]; + qam64_table_offset_re+=TWO[x0p[20]]; + qam64_table_offset_im+=TWO[x0p[21]]; + qam64_table_offset_re+=x0p[22]; + qam64_table_offset_im+=x0p[23]; + ((int16_t *)&txdataF[0][tti_offset])[6]=qam_table_s0[qam64_table_offset_re]; + ((int16_t *)&txdataF[0][tti_offset])[7]=qam_table_s0[qam64_table_offset_im]; } } else { diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 48b3f8cec1..2c2b03ce78 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -188,7 +188,7 @@ int main(int argc, char **argv) int **txdata; LTE_DL_FRAME_PARMS *frame_parms; - double **s_re,**s_im,**r_re,**r_im; + double s_re[2][30720],s_im[2][30720],r_re[2][30720],r_im[2][30720]; double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel double iqim=0.0; uint8_t extended_prefix_flag=0; @@ -583,12 +583,6 @@ int main(int argc, char **argv) txdata = UE->common_vars.txdata; - s_re = malloc(2*sizeof(double*)); - s_im = malloc(2*sizeof(double*)); - r_re = malloc(2*sizeof(double*)); - r_im = malloc(2*sizeof(double*)); - // r_re0 = malloc(2*sizeof(double*)); - // r_im0 = malloc(2*sizeof(double*)); nsymb = (eNB->frame_parms.Ncp == NORMAL) ? 14 : 12; @@ -630,13 +624,6 @@ int main(int argc, char **argv) fprintf(csv_fdUL,"data_all%d=[",mcs); } - for (i=0; i<2; i++) { - s_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - } - if (xforms==1) { fl_initialize (&argc, argv, NULL, 0, 0); @@ -1716,22 +1703,6 @@ int main(int argc, char **argv) if (test_perf !=0) fclose (time_meas_fd); - printf("Freeing channel I/O\n"); - - for (i=0; i<2; i++) { - free(s_re[i]); - free(s_im[i]); - free(r_re[i]); - free(r_im[i]); - } - - free(s_re); - free(s_im); - free(r_re); - free(r_im); - - // lte_sync_time_free(); - return(0); } From 8fffd732cc16fd5145e8deead3fe8b8c76a8453f Mon Sep 17 00:00:00 2001 From: luhan wang Date: Thu, 8 Sep 2016 16:28:44 +0200 Subject: [PATCH 175/206] added const declarations to coefficients for FFT --- openair1/PHY/TOOLS/lte_dfts.c | 112 +++++++++++++++++----------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/lte_dfts.c index 00e1b0b5ce..b50e6c5e34 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/lte_dfts.c @@ -58,10 +58,10 @@ #define print_ints(s,x) printf("%s %d %d %d %d\n",s,(x)[0],(x)[1],(x)[2],(x)[3]) -static int16_t conjugatedft[32] __attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1}; +const static int16_t conjugatedft[32] __attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1}; -static int16_t reflip[32] __attribute__((aligned(32))) = {1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1}; +const static int16_t reflip[32] __attribute__((aligned(32))) = {1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1}; #if defined(__x86_64__) || defined(__i386__) static inline void cmac(__m128i a,__m128i b, __m128i *re32, __m128i *im32) __attribute__((always_inline)); @@ -474,33 +474,33 @@ static inline int16x8_t packed_cmult2(int16x8_t a,int16x8_t b, int16x8_t b2) #endif -static int16_t W0s[16]__attribute__((aligned(32))) = {32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,32767,0}; +const static int16_t W0s[16]__attribute__((aligned(32))) = {32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,32767,0}; -static int16_t W13s[16]__attribute__((aligned(32))) = {-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378}; -static int16_t W23s[16]__attribute__((aligned(32))) = {-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378}; +const static int16_t W13s[16]__attribute__((aligned(32))) = {-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378,-16384,-28378}; +const static int16_t W23s[16]__attribute__((aligned(32))) = {-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378,-16384,28378}; -static int16_t W15s[16]__attribute__((aligned(32))) = {10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163}; -static int16_t W25s[16]__attribute__((aligned(32))) = {-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260}; -static int16_t W35s[16]__attribute__((aligned(32))) = {-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260}; -static int16_t W45s[16]__attribute__((aligned(32))) = {10126,31163,10126,31163,10126,31163,10126,31163,10126,31163,10126,31163,10126,31163,10126,31163}; +const static int16_t W15s[16]__attribute__((aligned(32))) = {10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163,10126,-31163}; +const static int16_t W25s[16]__attribute__((aligned(32))) = {-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260,-26509,-19260}; +const static int16_t W35s[16]__attribute__((aligned(32))) = {-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260,-26510,19260}; +const static int16_t W45s[16]__attribute__((aligned(32))) = {10126,31163,10126,31163,10126,31163,10126,31163,10126,31163,10126,31163,10126,31163,10126,31163}; #if defined(__x86_64__) || defined(__i386__) -__m128i *W0 = (__m128i *)W0s; -__m128i *W13 = (__m128i *)W13s; -__m128i *W23 = (__m128i *)W23s; -__m128i *W15 = (__m128i *)W15s; -__m128i *W25 = (__m128i *)W25s; -__m128i *W35 = (__m128i *)W35s; -__m128i *W45 = (__m128i *)W45s; +const __m128i *W0 = (__m128i *)W0s; +const __m128i *W13 = (__m128i *)W13s; +const __m128i *W23 = (__m128i *)W23s; +const __m128i *W15 = (__m128i *)W15s; +const __m128i *W25 = (__m128i *)W25s; +const __m128i *W35 = (__m128i *)W35s; +const __m128i *W45 = (__m128i *)W45s; #ifdef __AVX2__ -__m256i *W0_256 = (__m256i *)W0s; -__m256i *W13_256 = (__m256i *)W13s; -__m256i *W23_256 = (__m256i *)W23s; -__m256i *W15_256 = (__m256i *)W15s; -__m256i *W25_256 = (__m256i *)W25s; -__m256i *W35_256 = (__m256i *)W35s; -__m256i *W45_256 = (__m256i *)W45s; +const __m256i *W0_256 = (__m256i *)W0s; +const __m256i *W13_256 = (__m256i *)W13s; +const __m256i *W23_256 = (__m256i *)W23s; +const __m256i *W15_256 = (__m256i *)W15s; +const __m256i *W25_256 = (__m256i *)W25s; +const __m256i *W35_256 = (__m256i *)W35s; +const __m256i *W45_256 = (__m256i *)W45s; #endif #elif defined(__arm__) @@ -512,23 +512,23 @@ int16x8_t *W25 = (int16x8_t *)W25s; int16x8_t *W35 = (int16x8_t *)W35s; int16x8_t *W45 = (int16x8_t *)W45s; #endif -static int16_t dft_norm_table[16] = {9459, //12 - 6689,//24 - 5461,//36 - 4729,//482 - 4230,//60 - 23170,//72 - 3344,//96 - 3153,//108 - 2991,//120 - 18918,//sqrt(3),//144 - 18918,//sqrt(3),//180 - 16384,//2, //192 - 18918,//sqrt(3), // 216 - 16384,//2, //240 - 18918,//sqrt(3), // 288 - 14654 - }; //sqrt(5) //300 +const static int16_t dft_norm_table[16] = {9459, //12 + 6689,//24 + 5461,//36 + 4729,//482 + 4230,//60 + 23170,//72 + 3344,//96 + 3153,//108 + 2991,//120 + 18918,//sqrt(3),//144 + 18918,//sqrt(3),//180 + 16384,//2, //192 + 18918,//sqrt(3), // 216 + 16384,//2, //240 + 18918,//sqrt(3), // 288 + 14654 +}; //sqrt(5) //300 #if defined(__x86_64__) || defined(__i386__) @@ -2036,42 +2036,42 @@ static inline void transpose4_ooff(int16x4_t *x,int16x4_t *y,int off) // 16-point optimized DFT kernel -int16_t tw16[24] __attribute__((aligned(32))) = { 32767,0,30272,-12540,23169 ,-23170,12539 ,-30273, +const static int16_t tw16[24] __attribute__((aligned(32))) = { 32767,0,30272,-12540,23169 ,-23170,12539 ,-30273, 32767,0,23169,-23170,0 ,-32767,-23170,-23170, 32767,0,12539,-30273,-23170,-23170,-30273,12539 }; -int16_t tw16a[24] __attribute__((aligned(32))) = {32767,0,30272,12540,23169 ,23170,12539 ,30273, +const static int16_t tw16a[24] __attribute__((aligned(32))) = {32767,0,30272,12540,23169 ,23170,12539 ,30273, 32767,0,23169,23170,0 ,32767,-23170,23170, 32767,0,12539,30273,-23170,23170,-30273,-12539 }; -int16_t tw16b[24] __attribute__((aligned(32))) = { 0,32767,-12540,30272,-23170,23169 ,-30273,12539, +const static int16_t tw16b[24] __attribute__((aligned(32))) = { 0,32767,-12540,30272,-23170,23169 ,-30273,12539, 0,32767,-23170,23169,-32767,0 ,-23170,-23170, 0,32767,-30273,12539,-23170,-23170,12539 ,-30273 }; -int16_t tw16c[24] __attribute__((aligned(32))) = { 0,32767,12540,30272,23170,23169 ,30273 ,12539, +const static int16_t tw16c[24] __attribute__((aligned(32))) = { 0,32767,12540,30272,23170,23169 ,30273 ,12539, 0,32767,23170,23169,32767,0 ,23170 ,-23170, 0,32767,30273,12539,23170,-23170,-12539,-30273 }; -int16_t tw16rep[48] __attribute__((aligned(32))) = { 32767,0,30272,-12540,23169 ,-23170,12539 ,-30273,32767,0,30272,-12540,23169 ,-23170,12539 ,-30273, +const static int16_t tw16rep[48] __attribute__((aligned(32))) = { 32767,0,30272,-12540,23169 ,-23170,12539 ,-30273,32767,0,30272,-12540,23169 ,-23170,12539 ,-30273, 32767,0,23169,-23170,0 ,-32767,-23170,-23170,32767,0,23169,-23170,0 ,-32767,-23170,-23170, 32767,0,12539,-30273,-23170,-23170,-30273,12539,32767,0,12539,-30273,-23170,-23170,-30273,12539 }; -int16_t tw16arep[48] __attribute__((aligned(32))) = {32767,0,30272,12540,23169 ,23170,12539 ,30273,32767,0,30272,12540,23169 ,23170,12539 ,30273, +const static int16_t tw16arep[48] __attribute__((aligned(32))) = {32767,0,30272,12540,23169 ,23170,12539 ,30273,32767,0,30272,12540,23169 ,23170,12539 ,30273, 32767,0,23169,23170,0 ,32767,-23170,23170,32767,0,23169,23170,0 ,32767,-23170,23170, 32767,0,12539,30273,-23170,23170,-30273,-12539,32767,0,12539,30273,-23170,23170,-30273,-12539 }; -int16_t tw16brep[48] __attribute__((aligned(32))) = { 0,32767,-12540,30272,-23170,23169 ,-30273,12539,0,32767,-12540,30272,-23170,23169 ,-30273,12539, +const static int16_t tw16brep[48] __attribute__((aligned(32))) = { 0,32767,-12540,30272,-23170,23169 ,-30273,12539,0,32767,-12540,30272,-23170,23169 ,-30273,12539, 0,32767,-23170,23169,-32767,0 ,-23170,-23170,0,32767,-23170,23169,-32767,0 ,-23170,-23170, 0,32767,-30273,12539,-23170,-23170,12539 ,-30273,0,32767,-30273,12539,-23170,-23170,12539 ,-30273 }; -int16_t tw16crep[48] __attribute__((aligned(32))) = { 0,32767,12540,30272,23170,23169 ,30273 ,12539,0,32767,12540,30272,23170,23169 ,30273 ,12539, +const static int16_t tw16crep[48] __attribute__((aligned(32))) = { 0,32767,12540,30272,23170,23169 ,30273 ,12539,0,32767,12540,30272,23170,23169 ,30273 ,12539, 0,32767,23170,23169,32767,0 ,23170 ,-23170,0,32767,23170,23169,32767,0 ,23170 ,-23170, 0,32767,30273,12539,23170,-23170,-12539,-30273,0,32767,30273,12539,23170,-23170,-12539,-30273 }; @@ -2502,7 +2502,7 @@ static inline void idft16_simd256(int16_t *x,int16_t *y) // 64-point optimized DFT -int16_t tw64[96] __attribute__((aligned(32))) = { +const static int16_t tw64[96] __attribute__((aligned(32))) = { 32767,0,32609,-3212,32137,-6393,31356,-9512, 30272,-12540,28897,-15447,27244,-18205,25329,-20788, 23169,-23170,20787,-25330,18204,-27245,15446,-28898, @@ -2517,7 +2517,7 @@ int16_t tw64[96] __attribute__((aligned(32))) = { -30273,12539,-25330,20787,-18205,27244,-9512,31356 }; -int16_t tw64rep[192] __attribute__((aligned(32))) = { +const static int16_t tw64rep[192] __attribute__((aligned(32))) = { 32767,0,32609,-3212,32137,-6393,31356,-9512,32767,0,32609,-3212,32137,-6393,31356,-9512, 30272,-12540,28897,-15447,27244,-18205,25329,-20788,30272,-12540,28897,-15447,27244,-18205,25329,-20788, 23169,-23170,20787,-25330,18204,-27245,15446,-28898,23169,-23170,20787,-25330,18204,-27245,15446,-28898, @@ -2532,7 +2532,7 @@ int16_t tw64rep[192] __attribute__((aligned(32))) = { -30273,12539,-25330,20787,-18205,27244,-9512,31356,-30273,12539,-25330,20787,-18205,27244,-9512,31356 }; -int16_t tw64a[96] __attribute__((aligned(32))) = { +const static int16_t tw64a[96] __attribute__((aligned(32))) = { 32767,0,32609,3212,32137,6393,31356,9512, 30272,12540,28897,15447,27244,18205,25329,20788, 23169,23170,20787,25330,18204,27245,15446,28898, @@ -2546,7 +2546,7 @@ int16_t tw64a[96] __attribute__((aligned(32))) = { -23170,23170,-28898,15447,-32138,6393,-32610,-3211, -30273,-12539,-25330,-20787,-18205,-27244,-9512,-31356 }; -int16_t tw64arep[192] __attribute__((aligned(32))) = { +const static int16_t tw64arep[192] __attribute__((aligned(32))) = { 32767,0,32609,3212,32137,6393,31356,9512,32767,0,32609,3212,32137,6393,31356,9512, 30272,12540,28897,15447,27244,18205,25329,20788,30272,12540,28897,15447,27244,18205,25329,20788, 23169,23170,20787,25330,18204,27245,15446,28898,23169,23170,20787,25330,18204,27245,15446,28898, @@ -2561,7 +2561,7 @@ int16_t tw64arep[192] __attribute__((aligned(32))) = { -30273,-12539,-25330,-20787,-18205,-27244,-9512,-31356,-30273,-12539,-25330,-20787,-18205,-27244,-9512,-31356 }; -int16_t tw64b[96] __attribute__((aligned(32))) = { +const static int16_t tw64b[96] __attribute__((aligned(32))) = { 0,32767,-3212,32609,-6393,32137,-9512,31356, -12540,30272,-15447,28897,-18205,27244,-20788,25329, -23170,23169,-25330,20787,-27245,18204,-28898,15446, @@ -2576,7 +2576,7 @@ int16_t tw64b[96] __attribute__((aligned(32))) = { 12539,-30273,20787,-25330,27244,-18205,31356,-9512 }; -int16_t tw64brep[192] __attribute__((aligned(32))) = { +const static int16_t tw64brep[192] __attribute__((aligned(32))) = { 0,32767,-3212,32609,-6393,32137,-9512,31356,0,32767,-3212,32609,-6393,32137,-9512,31356, -12540,30272,-15447,28897,-18205,27244,-20788,25329,-12540,30272,-15447,28897,-18205,27244,-20788,25329, -23170,23169,-25330,20787,-27245,18204,-28898,15446,-23170,23169,-25330,20787,-27245,18204,-28898,15446, @@ -2591,7 +2591,7 @@ int16_t tw64brep[192] __attribute__((aligned(32))) = { 12539,-30273,20787,-25330,27244,-18205,31356,-9512,12539,-30273,20787,-25330,27244,-18205,31356,-9512 }; -int16_t tw64c[96] __attribute__((aligned(32))) = { +const static int16_t tw64c[96] __attribute__((aligned(32))) = { 0,32767,3212,32609,6393,32137,9512,31356, 12540,30272,15447,28897,18205,27244,20788,25329, 23170,23169,25330,20787,27245,18204,28898,15446, @@ -2606,7 +2606,7 @@ int16_t tw64c[96] __attribute__((aligned(32))) = { -12539,-30273,-20787,-25330,-27244,-18205,-31356,-9512 }; -int16_t tw64crep[192] __attribute__((aligned(32))) = { +const static int16_t tw64crep[192] __attribute__((aligned(32))) = { 0,32767,3212,32609,6393,32137,9512,31356,0,32767,3212,32609,6393,32137,9512,31356, 12540,30272,15447,28897,18205,27244,20788,25329,12540,30272,15447,28897,18205,27244,20788,25329, 23170,23169,25330,20787,27245,18204,28898,15446,23170,23169,25330,20787,27245,18204,28898,15446, From f329139f189e3bd2452691837094f06622c8c017 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 10 Sep 2016 01:44:19 -0700 Subject: [PATCH 176/206] minor cleanup in ulsch_decoding.c. Some modifications to comments in impl_defs_lte.h. --- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 142 +++++++++----------- openair1/PHY/impl_defs_lte.h | 32 ++--- 2 files changed, 83 insertions(+), 91 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 6ed0f91101..b0c1aa1886 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -127,7 +127,7 @@ LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uin ulsch->Mlimit = 4; for (i=0; i<8; i++) { - // msg("new_ue_ulsch: Harq process %d\n",i); + // printf("new_ue_ulsch: Harq process %d\n",i); ulsch->harq_processes[i] = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t)); if (ulsch->harq_processes[i]) { @@ -202,11 +202,11 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) uint8_t crc; crc = cqi[CQI_LENGTH>>3]; - // msg("crc1: %x, shift %d\n",crc,CQI_LENGTH&0x7); + // printf("crc1: %x, shift %d\n",crc,CQI_LENGTH&0x7); crc = (crc<<(CQI_LENGTH&0x7)); // clear crc bits // ((char *)cqi)[CQI_LENGTH>>3] &= 0xff>>(8-(CQI_LENGTH&0x7)); - // msg("crc2: %x, cqi0 %x\n",crc,cqi[1+(CQI_LENGTH>>3)]); + // printf("crc2: %x, cqi0 %x\n",crc,cqi[1+(CQI_LENGTH>>3)]); crc |= (cqi[1+(CQI_LENGTH>>3)])>>(8-(CQI_LENGTH&0x7)); // clear crc bits //(((char *)cqi)[1+(CQI_LENGTH>>3)]) = 0; @@ -258,7 +258,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, // uint8_t ytag2[6*14*1200],*ytag2_ptr; int16_t cseq[6*14*1200]; int off; - int status[20]; + int subframe = proc->subframe_rx; LTE_UL_eNB_HARQ_t *ulsch_harq; @@ -312,7 +312,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n", + printf("ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n", frame_parms->Nid_cell,ulsch->rnti,x2, ulsch_harq->round, ulsch_harq->rvidx, @@ -401,7 +401,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, // Q_ACK = Qprime * Q_m; Qprime_ACK = Qprime; #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding.c: Qprime_ACK %d, Msc_initial %d, Nsymb_initial %d, sumKr %d\n", + printf("ulsch_decoding.c: Qprime_ACK %d, Msc_initial %d, Nsymb_initial %d, sumKr %d\n", Qprime_ACK,ulsch_harq->Msc_initial,ulsch_harq->Nsymb_initial,sumKr); #endif @@ -430,7 +430,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, Q_CQI = Q_m * Qprime; #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding: G %d, Q_RI %d, Q_CQI %d (L %d, Or1 %d) O_ACK %d\n",G,Q_RI,Q_CQI,L,ulsch_harq->Or1,ulsch_harq->O_ACK); + printf("ulsch_decoding: G %d, Q_RI %d, Q_CQI %d (L %d, Or1 %d) O_ACK %d\n",G,Q_RI,Q_CQI,L,ulsch_harq->Or1,ulsch_harq->O_ACK); #endif G = G - Q_RI - Q_CQI; @@ -531,7 +531,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, } #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding.c: ACK i %d, r %d, j %d, ColumnSet[j] %d\n",i,r,j,columnset[j]); + printf("ulsch_decoding.c: ACK i %d, r %d, j %d, ColumnSet[j] %d\n",i,r,j,columnset[j]); #endif j=(j+3)&3; } @@ -964,15 +964,15 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, } #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding: Or1=%d\n",ulsch_harq->Or1); + printf("ulsch_decoding: Or1=%d\n",ulsch_harq->Or1); for (i=0; i<1+((8+ulsch_harq->Or1)/8); i++) - msg("ulsch_decoding: O[%d] %d\n",i,ulsch_harq->o[i]); + printf("ulsch_decoding: O[%d] %d\n",i,ulsch_harq->o[i]); if (ulsch_harq->cqi_crc_status == 1) - msg("RX CQI CRC OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); + printf("RX CQI CRC OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); else - msg("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); + printf("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); #endif } @@ -985,6 +985,10 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, r_offset = 0; + offset = 0; + + ret = 1; + for (r=0; rC; r++) { // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); @@ -1010,7 +1014,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, } #ifdef DEBUG_ULSCH_DECODING - msg("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0); + printf("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0); #endif memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); @@ -1019,7 +1023,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING - msg("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n", + printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n", r, G, Kr*3, Q_m, @@ -1056,75 +1060,63 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, &ulsch_harq->d[r][96], ulsch_harq->w[r]); stop_meas(&eNB->ulsch_deinterleaving_stats); - } + - for (r=0; rC; r++) { + if (ulsch_harq->C == 1) + crc_type = CRC24_A; + else + crc_type = CRC24_B; + + start_meas(&eNB->ulsch_turbo_decoding_stats); + + ret = tc(&ulsch_harq->d[r][96], + ulsch_harq->c[r], + Kr, + f1f2mat_old[iind*2], + f1f2mat_old[(iind*2)+1], + ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, + crc_type, + (r==0) ? ulsch_harq->F : 0, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + + stop_meas(&eNB->ulsch_turbo_decoding_stats); + - /* printf("c[%d] : %p\n",r, - ulsch_harq->c[r]); - */ - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - - ret = tc(&ulsch_harq->d[r][96], - ulsch_harq->c[r], - Kr, - f1f2mat_old[iind*2], - f1f2mat_old[(iind*2)+1], - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - stop_meas(&eNB->ulsch_turbo_decoding_stats); - - status[r] = ret; - - } + + // Reassembly of Transport block here - offset = 0; - ret = 1; - - for (r=0; rC; r++) { - if (status[r] != (1+ulsch->max_turbo_iterations)) { + if (ret != (1+ulsch->max_turbo_iterations)) { if (rCminus) - Kr = ulsch_harq->Kminus; + Kr = ulsch_harq->Kminus; else - Kr = ulsch_harq->Kplus; - + Kr = ulsch_harq->Kplus; + Kr_bytes = Kr>>3; - + if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); + memcpy(ulsch_harq->b, + &ulsch_harq->c[0][(ulsch_harq->F>>3)], + Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); + offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); + memcpy(ulsch_harq->b+offset, + ulsch_harq->c[r], + Kr_bytes - ((ulsch_harq->C>1)?3:0)); + offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); } - - if (ret != (1+ulsch->max_turbo_iterations)) - ret = status[r]; + } else { - ret = 1+ulsch->max_turbo_iterations; + break; } - + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); @@ -1208,7 +1200,7 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb sinr_db1 = sinr_dB[offset*2]; sinr_db2 = sinr_dB[offset*2+1]; - msg("sinr_db1=%f\n,sinr_db2=%f\n",sinr_db1,sinr_db2); + printf("sinr_db1=%f\n,sinr_db2=%f\n",sinr_db1,sinr_db2); //rounding up for the table lookup sinr_db1 *= 10; @@ -1462,7 +1454,7 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs]; } - msg("SINR_Eff = %e\n",sinr_eff); + printf("SINR_Eff = %e\n",sinr_eff); sinr_eff *= 10; sinr_eff = floor(sinr_eff); @@ -1470,7 +1462,7 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb // sinr_eff += 1; // } sinr_eff /= 10; - msg("sinr_eff after rounding = %f\n",sinr_eff); + printf("sinr_eff after rounding = %f\n",sinr_eff); for (index = 0; index < 16; index++) { if(index == 0) { @@ -1488,10 +1480,10 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb #ifdef USER_MODE // need to be adapted for the emulation in the kernel space if (uniformrandom() < bler) { - msg("abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); + printf("abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(0); } else { - msg("abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); + printf("abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(1); } diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h index 7c38048a55..bed2057800 100644 --- a/openair1/PHY/impl_defs_lte.h +++ b/openair1/PHY/impl_defs_lte.h @@ -607,34 +607,34 @@ typedef struct { int32_t **txdataF[3]; /// \brief Holds the received data in time domain. /// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna [0..nb_antennas_rx[ /// - third index: sample [0..] int32_t **rxdata[3]; /// \brief Holds the last subframe of received data in time domain after removal of 7.5kHz frequency offset. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: secotr id [0..2] (hard coded) /// - second index: rx antenna [0..nb_antennas_rx[ /// - third index: sample [0..samples_per_tti[ int32_t **rxdata_7_5kHz[3]; /// \brief Holds the received data in the frequency domain. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna [0..nb_antennas_rx[ /// - third index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[ int32_t **rxdataF[3]; /// \brief Holds output of the sync correlator. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: sample [0..samples_per_tti*10[ uint32_t *sync_corr[3]; } LTE_eNB_COMMON; typedef struct { /// \brief Hold the channel estimates in frequency domain based on SRS. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..ofdm_symbol_size[ int32_t **srs_ch_estimates[3]; /// \brief Hold the channel estimates in time domain based on SRS. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..2*ofdm_symbol_size[ int32_t **srs_ch_estimates_time[3]; @@ -645,54 +645,54 @@ typedef struct { typedef struct { /// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..2*ofdm_symbol_size[ /// - third index (definition from phy_init_lte_eNB()): ? [0..24*N_RB_UL*frame_parms->symbols_per_tti[ /// \warning inconsistent third index definition int32_t **rxdataF_ext[3]; /// \brief Holds the received data in the frequency domain for the allocated RBs in normal format. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **rxdataF_ext2[3]; /// \brief Hold the channel estimates in time domain based on DRS. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..4*ofdm_symbol_size[ int32_t **drs_ch_estimates_time[3]; /// \brief Hold the channel estimates in frequency domain based on DRS. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **drs_ch_estimates[3]; /// \brief Hold the channel estimates for UE0 in case of Distributed Alamouti Scheme. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **drs_ch_estimates_0[3]; /// \brief Hold the channel estimates for UE1 in case of Distributed Almouti Scheme. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **drs_ch_estimates_1[3]; /// \brief Holds the compensated signal. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **rxdataF_comp[3]; /// \brief Hold the compensated data (y)*(h0*) in case of Distributed Alamouti Scheme. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **rxdataF_comp_0[3]; /// \brief Hold the compensated data (y*)*(h1) in case of Distributed Alamouti Scheme. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **rxdataF_comp_1[3]; /// \brief ?. - /// - first index: eNB id [0..2] (hard coded) + /// - first index: sector id [0..2] (hard coded) /// - second index: rx antenna id [0..nb_antennas_rx[ /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **ul_ch_mag[3]; From 862e480e7565a6ab08522b6712db61070f13c005 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 10 Sep 2016 11:19:56 +0200 Subject: [PATCH 177/206] nothing important --- cmake_targets/CMakeLists.txt | 2 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 152 ++++++++++++------- openair1/SCHED/phy_procedures_lte_eNb.c | 80 ++++++++-- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 2 +- 4 files changed, 167 insertions(+), 69 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index e1396b6398..9f3c0ece0d 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -178,7 +178,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU # these changes are related to hardcoded path to include .h files add_definitions(-DCMAKER) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O3") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2") set(GIT_BRANCH "UNKNOWN") diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 6ed0f91101..1d0c8c25e3 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -127,7 +127,7 @@ LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uin ulsch->Mlimit = 4; for (i=0; i<8; i++) { - // msg("new_ue_ulsch: Harq process %d\n",i); + // printf("new_ue_ulsch: Harq process %d\n",i); ulsch->harq_processes[i] = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t)); if (ulsch->harq_processes[i]) { @@ -202,11 +202,11 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) uint8_t crc; crc = cqi[CQI_LENGTH>>3]; - // msg("crc1: %x, shift %d\n",crc,CQI_LENGTH&0x7); + // printf("crc1: %x, shift %d\n",crc,CQI_LENGTH&0x7); crc = (crc<<(CQI_LENGTH&0x7)); // clear crc bits // ((char *)cqi)[CQI_LENGTH>>3] &= 0xff>>(8-(CQI_LENGTH&0x7)); - // msg("crc2: %x, cqi0 %x\n",crc,cqi[1+(CQI_LENGTH>>3)]); + // printf("crc2: %x, cqi0 %x\n",crc,cqi[1+(CQI_LENGTH>>3)]); crc |= (cqi[1+(CQI_LENGTH>>3)])>>(8-(CQI_LENGTH&0x7)); // clear crc bits //(((char *)cqi)[1+(CQI_LENGTH>>3)]) = 0; @@ -217,7 +217,54 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) } +typedef struct { + PHY_VARS_eNB *eNB; + +} tc_param; +static void *td_thread(void *param) { + + PHY_VARS_eNB *eNB = (tc_param*)param->eNB; + eNB_proc_t *proc = &eNB->proc; + + while (!oai_exit) { + + if (wait_on_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread")<0) break; + // TD here + ret = tc(&ulsch_harq->d[r][96], + ulsch_harq->c[r], + Kr, + f1f2mat_old[iind*2], + f1f2mat_old[(iind*2)+1], + ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, + crc_type, + (r==0) ? ulsch_harq->F : 0, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + + stop_meas(&eNB->ulsch_turbo_decoding_stats); + + status[r] = ret; + + if (release_thread(&proc->mutex_td,&proc->instance_cnt_td,"td thread")<0) break; + + if (pthread_cond_signal(&proc->cond_td) != 0) { + printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + } + + + + return(NULL); +} + unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, uint8_t UE_id, uint8_t control_only_flag, @@ -312,7 +359,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n", + printf("ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n", frame_parms->Nid_cell,ulsch->rnti,x2, ulsch_harq->round, ulsch_harq->rvidx, @@ -401,7 +448,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, // Q_ACK = Qprime * Q_m; Qprime_ACK = Qprime; #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding.c: Qprime_ACK %d, Msc_initial %d, Nsymb_initial %d, sumKr %d\n", + printf("ulsch_decoding.c: Qprime_ACK %d, Msc_initial %d, Nsymb_initial %d, sumKr %d\n", Qprime_ACK,ulsch_harq->Msc_initial,ulsch_harq->Nsymb_initial,sumKr); #endif @@ -430,7 +477,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, Q_CQI = Q_m * Qprime; #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding: G %d, Q_RI %d, Q_CQI %d (L %d, Or1 %d) O_ACK %d\n",G,Q_RI,Q_CQI,L,ulsch_harq->Or1,ulsch_harq->O_ACK); + printf("ulsch_decoding: G %d, Q_RI %d, Q_CQI %d (L %d, Or1 %d) O_ACK %d\n",G,Q_RI,Q_CQI,L,ulsch_harq->Or1,ulsch_harq->O_ACK); #endif G = G - Q_RI - Q_CQI; @@ -531,7 +578,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, } #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding.c: ACK i %d, r %d, j %d, ColumnSet[j] %d\n",i,r,j,columnset[j]); + printf("ulsch_decoding.c: ACK i %d, r %d, j %d, ColumnSet[j] %d\n",i,r,j,columnset[j]); #endif j=(j+3)&3; } @@ -964,15 +1011,15 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, } #ifdef DEBUG_ULSCH_DECODING - msg("ulsch_decoding: Or1=%d\n",ulsch_harq->Or1); + printf("ulsch_decoding: Or1=%d\n",ulsch_harq->Or1); for (i=0; i<1+((8+ulsch_harq->Or1)/8); i++) - msg("ulsch_decoding: O[%d] %d\n",i,ulsch_harq->o[i]); + printf("ulsch_decoding: O[%d] %d\n",i,ulsch_harq->o[i]); if (ulsch_harq->cqi_crc_status == 1) - msg("RX CQI CRC OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); + printf("RX CQI CRC OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); else - msg("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); + printf("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc(o_flip,ulsch_harq->Or1)); #endif } @@ -1010,7 +1057,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, } #ifdef DEBUG_ULSCH_DECODING - msg("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0); + printf("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0); #endif memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); @@ -1019,7 +1066,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING - msg("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n", + printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n", r, G, Kr*3, Q_m, @@ -1058,40 +1105,41 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, stop_meas(&eNB->ulsch_deinterleaving_stats); } - for (r=0; rC; r++) { - - /* printf("c[%d] : %p\n",r, - ulsch_harq->c[r]); - */ - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - - ret = tc(&ulsch_harq->d[r][96], - ulsch_harq->c[r], - Kr, - f1f2mat_old[iind*2], - f1f2mat_old[(iind*2)+1], - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - stop_meas(&eNB->ulsch_turbo_decoding_stats); - - status[r] = ret; - - } + for (r=0; rC; r+=2) { + + /* printf("c[%d] : %p\n",r, + ulsch_harq->c[r]); + */ + + if (ulsch_harq->C == 1) + crc_type = CRC24_A; + else + crc_type = CRC24_B; + + start_meas(&eNB->ulsch_turbo_decoding_stats); + + ret = tc(&ulsch_harq->d[r][96], + ulsch_harq->c[r], + Kr, + f1f2mat_old[iind*2], + f1f2mat_old[(iind*2)+1], + ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, + crc_type, + (r==0) ? ulsch_harq->F : 0, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + + stop_meas(&eNB->ulsch_turbo_decoding_stats); + + status[r] = ret; + if (ret==(1+ulsch->max_turbo_iterations)) + break; + } // Reassembly of Transport block here offset = 0; @@ -1208,7 +1256,7 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb sinr_db1 = sinr_dB[offset*2]; sinr_db2 = sinr_dB[offset*2+1]; - msg("sinr_db1=%f\n,sinr_db2=%f\n",sinr_db1,sinr_db2); + printf("sinr_db1=%f\n,sinr_db2=%f\n",sinr_db1,sinr_db2); //rounding up for the table lookup sinr_db1 *= 10; @@ -1462,7 +1510,7 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs]; } - msg("SINR_Eff = %e\n",sinr_eff); + printf("SINR_Eff = %e\n",sinr_eff); sinr_eff *= 10; sinr_eff = floor(sinr_eff); @@ -1470,7 +1518,7 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb // sinr_eff += 1; // } sinr_eff /= 10; - msg("sinr_eff after rounding = %f\n",sinr_eff); + printf("sinr_eff after rounding = %f\n",sinr_eff); for (index = 0; index < 16; index++) { if(index == 0) { @@ -1488,10 +1536,10 @@ int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb #ifdef USER_MODE // need to be adapted for the emulation in the kernel space if (uniformrandom() < bler) { - msg("abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); + printf("abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(0); } else { - msg("abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); + printf("abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(1); } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 980fa3335a..cbea52db81 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2508,6 +2508,8 @@ void fep0(PHY_VARS_eNB *eNB,int slot) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; int l; + // printf("fep0: slot %d\n",slot); + remove_7_5_kHz(eNB,(slot&1)+(proc->subframe_rx<<1)); for (l=0; lsymbols_per_tti/2; l++) { slot_fep_ul(fp, @@ -2560,21 +2562,68 @@ static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond, return(0); } +static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { + + if (pthread_mutex_lock(mutex) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + + while (*instance_cnt == 0) { + // most of the time the thread will skip this + // waits only if proc->instance_cnt_rxtx is 0 + pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again + } + + if (pthread_mutex_unlock(mutex) != 0) { + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + return(0); +} + extern int oai_exit; +#define THREAD_FULL 1 +#ifdef THREAD_FULL static void *fep_thread(void *param) { PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; eNB_proc_t *proc = &eNB->proc; while (!oai_exit) { + if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break; fep0(eNB,0); if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break; + + if (pthread_cond_signal(&proc->cond_fep) != 0) { + printf("[eNB] ERROR pthread_cond_signal for fep thread exit\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } } + + + return(NULL); } +#else + +static void *fep_thread(void *param) { + + PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; + eNB_proc_t *proc = &eNB->proc; + + fep0(eNB,0); + + return(NULL); +} + +#endif void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) { eNB_proc_t *proc = &eNB->proc; @@ -2584,13 +2633,17 @@ void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) { pthread_mutex_init( &proc->mutex_fep, NULL); pthread_cond_init( &proc->cond_fep, NULL); +#ifdef THREAD_FULL pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)eNB); +#endif } + void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { eNB_proc_t *proc = &eNB->proc; + struct timespec wait; int wait_cnt=0; wait.tv_sec=0; @@ -2599,6 +2652,8 @@ void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1); start_meas(&eNB->ofdm_demod_stats); +#ifdef THREAD_FULL + if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep); exit_fun( "error locking mutex_fep" ); @@ -2626,26 +2681,21 @@ void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { // call second slot in this symbol fep0(eNB,1); - if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep); - exit_fun( "error locking mutex_fep" ); - return; - } - while (proc->instance_cnt_fep==0) { - wait_cnt++; - if (wait_cnt>10000) - break; - }; + wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread"); - pthread_mutex_unlock( &proc->mutex_fep ); - if (wait_cnt>1000000) { - printf("[eNB] parallel FEP didn't finish\n"); - exit_fun( "error" ); - } +#else + pthread_create(&proc->pthread_fep, NULL, fep_thread, (void*)eNB); + // call second slot in this symbol + fep0(eNB,1); + pthread_join(proc->pthread_fep,(void**)NULL); + +#endif stop_meas(&eNB->ofdm_demod_stats); } + + void eNB_fep_full(PHY_VARS_eNB *eNB) { eNB_proc_t *proc = &eNB->proc; diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index f9c2309ab8..56a0f50ff4 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -568,7 +568,7 @@ extern "C" { // workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); - args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096"; +// args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096"; uhd::device_addrs_t device_adds = uhd::device::find(args); From 1e9687fa0bbd5441cb9e8ddd487eae5f19c14c26 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 14 Sep 2016 03:47:51 -0700 Subject: [PATCH 178/206] some cleanup in dlsch_modulation prior to parallelization --- openair1/PHY/INIT/init_top.c | 2 +- openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 265 ++++++++++-------- 2 files changed, 145 insertions(+), 122 deletions(-) diff --git a/openair1/PHY/INIT/init_top.c b/openair1/PHY/INIT/init_top.c index e0de14bbb8..350f0f0c94 100755 --- a/openair1/PHY/INIT/init_top.c +++ b/openair1/PHY/INIT/init_top.c @@ -45,7 +45,7 @@ */ //#define DEBUG_PHY - +t /* diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index e80a86b7cd..8438e86496 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -1542,6 +1542,142 @@ uint8_t get_pmi(uint8_t N_RB_DL,LTE_DL_eNB_HARQ_t *dlsch_harq,uint16_t rb) } +inline int check_skip(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms,int l,int nsymb) __attribute__((always_inline)); +inline int check_skip(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms,int l,int nsymb) { + + + if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL + // PBCH + if ((subframe_offset==0) && + (rb>((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) { + return(1); + } + if (frame_parms->frame_type == TDD) { // TDD + //SSS TDD + if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1)) ) { + return(1); + } + //PSS TDD + if (((subframe_offset==1) || (subframe_offset==6)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==2) ) { + return(1); + } + } else { + //PSS FDD + if (((subframe_offset==0)||(subframe_offset==5)) && + (rb>((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l==((nsymb>>1)-1)) ) { + return(1); + } + //SSS FDD + if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) { + return(1); + } + } + } + else { // even N_RB_DL + //PBCH + if ((subframe_offset==0) && + (rb>=((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) + return(1); + + if (frame_parms->frame_type == TDD) { // TDD + //SSS + if (((subframe_offset==0)|| + (subframe_offset==5)) && + (rb>=((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l==nsymb-1) ) { + return(1); + } + + //PSS + if (((subframe_offset==1)|| + (subframe_offset==6)) && + (rb>=((frame_parms->N_RB_DL>>1)-3)) && + (rb<((frame_parms->N_RB_DL>>1)+3)) && + (l==2) ) { + return(1); + } + } else { // FDD + //SSS + if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) { + return(1); + } + + //PSS + if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-1)) ) { + return(1); + } + } + } + + return(0); +} + +inline int check_skiphalf(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms,int l,int nsymb) __attribute__((always_inline)); +inline int check_skiphalf(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms,int l,int nsymb) { + + printf("check_skiphalf : rb %d, subframe_offset %d,l %d, nsymb %d\n",rb,subframe_offset,l,nsymb); + + if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL + + // PBCH + if ((subframe_offset==0) && + (rb==((frame_parms->N_RB_DL>>1)-3)) && + (l>=(nsymb>>1)) && + (l<((nsymb>>1) + 4))) + return(1); + else if ((subframe_offset==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) + return(2); + + if (frame_parms->frame_type == TDD) { // TDD + //SSS TDD + if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==(nsymb-1))) + return(1); + else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1))) + return(2); + //PSS TDD + if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==2)) + return(1); + else if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==2)) + return(2); + } + else { // FDD + //PSS FDD + if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==((nsymb>>1)-1))) + return(1); + else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(((nsymb>>1)-1)))) + return(2); + //SSS FDD + if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && ((l==((nsymb>>1)-2)))) + return(1); + else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && ((l==(nsymb>>1)-2))) + return(2); + } + } + else { // EVEN N_RB_DL + return(0); + } + + return(0); +} + +inline int check_skip_dc(int rb,LTE_DL_FRAME_PARMS *frame_parms) __attribute__((always_inline)); +inline int check_skip_dc(int rb,LTE_DL_FRAME_PARMS *frame_parms) { + + if (((frame_parms->N_RB_DL&1) == 1) && // odd N_RB_DL, rb==N_RB_DL/2 PRB contains DC element + (rb==(frame_parms->N_RB_DL>>1))) + return(1); + else + return(0); +} + int dlsch_modulation(int32_t **txdataF, int16_t amp, uint32_t subframe_offset, @@ -1560,7 +1696,7 @@ int dlsch_modulation(int32_t **txdataF, uint32_t rb_alloc_ind; uint32_t *rb_alloc = dlsch0_harq->rb_alloc; uint8_t pilots=0; - uint8_t skip_dc,skip_half; + uint8_t skip_dc=0,skip_half=0; uint8_t mod_order0 = get_Qm(dlsch0_harq->mcs); uint8_t mod_order1 = 0; int16_t amp_rho_a, amp_rho_b; @@ -1636,6 +1772,7 @@ int dlsch_modulation(int32_t **txdataF, jj2=0; re_allocated=0; + // printf("num_pdcch_symbols %d, nsymb %d\n",num_pdcch_symbols,nsymb); for (l=num_pdcch_symbols; lN_RB_DL&1) == 1) { // ODD N_RB_DL - - if (rb==(frame_parms->N_RB_DL>>1)) - skip_dc = 1; - else - skip_dc = 0; - - // PBCH - if ((subframe_offset==0) && - (rb>((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) { - rb_alloc_ind = 0; - } - - //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 - if ((subframe_offset==0) && - (rb==((frame_parms->N_RB_DL>>1)-3)) && - (l>=(nsymb>>1)) && - (l<((nsymb>>1) + 4))) - skip_half=1; - else if ((subframe_offset==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) - skip_half=2; - - if (frame_parms->frame_type == TDD) { // TDD - //SSS TDD - if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1)) ) { - rb_alloc_ind = 0; - } - - //SSS TDD - if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==(nsymb-1))) - skip_half=1; - else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1))) - skip_half=2; - - //PSS TDD - if (((subframe_offset==1) || (subframe_offset==6)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==2) ) { - rb_alloc_ind = 0; - } - - //PSS TDD - if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==2)) - skip_half=1; - else if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==2)) - skip_half=2; - } else { - //PSS FDD - if (((subframe_offset==0)||(subframe_offset==5)) && - (rb>((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l==((nsymb>>1)-1)) ) { - rb_alloc_ind = 0; - } - - //PSS FDD - if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==((nsymb>>1)-1))) - skip_half=1; - else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(((nsymb>>1)-1)))) - skip_half=2; - - //SSS FDD - if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) { - rb_alloc_ind = 0; - } - - //SSS FDD - if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && ((l==((nsymb>>1)-2)))) - skip_half=1; - else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && ((l==(nsymb>>1)-2))) - skip_half=2; - - } - - } else { // EVEN N_RB_DL - //PBCH - if ((subframe_offset==0) && - (rb>=((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) - rb_alloc_ind = 0; - - skip_dc=0; - skip_half=0; - - if (frame_parms->frame_type == TDD) { // TDD - //SSS - if (((subframe_offset==0)|| - (subframe_offset==5)) && - (rb>=((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l==nsymb-1) ) { - rb_alloc_ind = 0; - } - - //PSS - if (((subframe_offset==1)|| - (subframe_offset==6)) && - (rb>=((frame_parms->N_RB_DL>>1)-3)) && - (rb<((frame_parms->N_RB_DL>>1)+3)) && - (l==2) ) { - rb_alloc_ind = 0; - } - } else { // FDD - //SSS - if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) { - rb_alloc_ind = 0; - } - - //PSS - if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-1)) ) { - rb_alloc_ind = 0; - } - } + if (check_skip(rb,subframe_offset,frame_parms,l,nsymb)==1) + rb_alloc_ind = 0; + else { + skip_half = check_skiphalf(rb,subframe_offset,frame_parms,l,nsymb); + skip_dc = check_skip_dc(rb,frame_parms); } - if (dlsch0_harq->Nlayers>1) { printf("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); return(-1); @@ -1909,7 +1932,7 @@ int dlsch_modulation(int32_t **txdataF, if (rb_alloc_ind > 0) { - // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); + printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); allocate_REs(frame_parms, txdataF, &jj, From 2d73663bc6c1028169ad5c8b951274780ec156e9 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 15 Sep 2016 10:03:50 -0700 Subject: [PATCH 179/206] modifications for odd N_RB_DL in dlsch_modulation.c --- openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 30 +++++++++++-------- openair1/SIMULATION/LTE_PHY/dlsim.c | 2 ++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 8438e86496..5f51e20ecc 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -182,10 +182,11 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, } } else { + // 1st half of PRB for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0; re<6; re++,x0p+=4,tti_offset++) { - + qam16_table_offset_re=TWO[x0p[0]]; qam16_table_offset_im=TWO[x0p[1]]; qam16_table_offset_re+=x0p[2]; @@ -193,7 +194,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms, ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qam16_table_offset_re]; ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qam16_table_offset_im]; } - + // 2nd half of PRB for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7; re<12; re++,x0p+=4,tti_offset++) { @@ -626,7 +627,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, switch (mod_order0) { case 2: //QPSK -// printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + // printf("re %d %d(%d) : %d,%d => ",re,tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); for (aa=0; aanb_antennas_tx; aa++) { ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i } @@ -639,7 +640,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, *jj = *jj + 1; - // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); break; case 4: //16QAM @@ -1623,7 +1624,7 @@ inline int check_skip(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms inline int check_skiphalf(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms,int l,int nsymb) __attribute__((always_inline)); inline int check_skiphalf(int rb,int subframe_offset,LTE_DL_FRAME_PARMS *frame_parms,int l,int nsymb) { - printf("check_skiphalf : rb %d, subframe_offset %d,l %d, nsymb %d\n",rb,subframe_offset,l,nsymb); + // printf("check_skiphalf : rb %d, subframe_offset %d,l %d, nsymb %d\n",rb,subframe_offset,l,nsymb); if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL @@ -1913,10 +1914,11 @@ int dlsch_modulation(int32_t **txdataF, if (check_skip(rb,subframe_offset,frame_parms,l,nsymb)==1) rb_alloc_ind = 0; - else { - skip_half = check_skiphalf(rb,subframe_offset,frame_parms,l,nsymb); - skip_dc = check_skip_dc(rb,frame_parms); - } + + skip_half = check_skiphalf(rb,subframe_offset,frame_parms,l,nsymb); + skip_dc = check_skip_dc(rb,frame_parms); + + if (dlsch0_harq->Nlayers>1) { printf("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset); return(-1); @@ -1932,7 +1934,7 @@ int dlsch_modulation(int32_t **txdataF, if (rb_alloc_ind > 0) { - printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); + // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj); allocate_REs(frame_parms, txdataF, &jj, @@ -1952,11 +1954,13 @@ int dlsch_modulation(int32_t **txdataF, P1_SHIFT, P2_SHIFT); } - + else { + // printf("Unallocated rb %d/symbol %d, re_offset %d, jj %d\n",rb,l,re_offset,jj); + } re_offset+=12; // go to next RB - - // check if we crossed the symbol boundary and skip DC + + // check if we crossed the symbol boundary and skip DCs if (re_offset >= frame_parms->ofdm_symbol_size) { if (skip_dc == 0) //even number of RBs (doesn't straddle DC) re_offset=1; diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 2adbb777d0..4fd04dcbd4 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -2404,6 +2404,8 @@ int main(int argc, char **argv) write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe* eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti,1,1); + write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], + nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); } } From b8a37a34cf348d26dee7439cf431c9fad5eff7c5 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 17 Sep 2016 14:55:26 -0700 Subject: [PATCH 180/206] pucch format 2/2a/2b UE TX --- openair1/PHY/CODING/lte_rate_matching.c | 3 +- openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 1 + openair1/PHY/LTE_TRANSPORT/pmch.c | 4 +- openair1/PHY/LTE_TRANSPORT/proto.h | 21 +- openair1/PHY/LTE_TRANSPORT/pucch.c | 318 ++++++++++++++---- openair1/SCHED/phy_procedures_lte_ue.c | 42 ++- openair1/SIMULATION/LTE_PHY/pucchsim.c | 57 +--- 7 files changed, 302 insertions(+), 144 deletions(-) diff --git a/openair1/PHY/CODING/lte_rate_matching.c b/openair1/PHY/CODING/lte_rate_matching.c index 76586eecf4..0b49fe6f5a 100644 --- a/openair1/PHY/CODING/lte_rate_matching.c +++ b/openair1/PHY/CODING/lte_rate_matching.c @@ -518,7 +518,8 @@ uint32_t lte_rate_matching_turbo(uint32_t RTC, // if (rvidx==3) // for (cnt=0;cnt=(3*RTC<<5),"Exiting, RM condition (Ncb %d, Nir/C %d, Nsoft %d, Kw %d\n",Ncb,Nir/C,Nsoft,3*(RTC<<5)); + if (Ncb>(3*(RTC<<5))) + AssertFatal(1==0,"Exiting, RM condition (Ncb %d, RTC %d, Nir/C %d, Nsoft %d, Kw %d)\n",Ncb,RTC,Nir/C,Nsoft,3*(RTC<<5)); Gp = G/Nl/Qm; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 5f51e20ecc..3cc512a8d8 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -1679,6 +1679,7 @@ inline int check_skip_dc(int rb,LTE_DL_FRAME_PARMS *frame_parms) { return(0); } + int dlsch_modulation(int32_t **txdataF, int16_t amp, uint32_t subframe_offset, diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 93922207bb..8003fb177b 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -319,8 +319,8 @@ void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a) AMP); - if (dlsch_encoding(a, - &eNB->frame_parms, + if (dlsch_encoding(eNB, + a, 1, eNB->dlsch_MCH, proc->frame_tx, diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index f37e4be480..055c1d7fb9 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1709,17 +1709,16 @@ void dlsch_unscrambling(LTE_DL_FRAME_PARMS *frame_parms, void init_ncs_cell(LTE_DL_FRAME_PARMS *frame_parms,uint8_t ncs_cell[20][7]); -void generate_pucch(int32_t **txdataF, - LTE_DL_FRAME_PARMS *frame_parms, - uint8_t ncs_cell[20][7], - PUCCH_FMT_t fmt, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint16_t n1_pucch, - uint16_t n2_pucch, - uint8_t shortened_format, - uint8_t *payload, - int16_t amp, - uint8_t subframe); +void generate_pucch1x(int32_t **txdataF, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t ncs_cell[20][7], + PUCCH_FMT_t fmt, + PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, + uint16_t n1_pucch, + uint8_t shortened_format, + uint8_t *payload, + int16_t amp, + uint8_t subframe); void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, UE_rxtx_proc_t *proc, diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 9b9693c82f..2569b5d8c7 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -38,7 +38,7 @@ * \warning */ #include "PHY/defs.h" -#include "PHY/extern.h" +#include "PHY/extern.h" #include "LAYER2/MAC/extern.h" #include "UTIL/LOG/log.h" @@ -97,7 +97,7 @@ void init_ncs_cell(LTE_DL_FRAME_PARMS *frame_parms,uint8_t ncs_cell[20][7]) } #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH ncs_cell init (j %d): Ns %d, l %d => ncs_cell %d\n",j,ns,l,ncs_cell[ns][l]); + printf("[PHY] PUCCH ncs_cell init (j %d): Ns %d, l %d => ncs_cell %d\n",j,ns,l,ncs_cell[ns][l]); #endif } @@ -123,17 +123,16 @@ int16_t W3_im[3][6] = {{0 ,0 ,0 }, char pucch_format_string[6][20] = {"format 1\0","format 1a\0","format 1b\0","format 2\0","format 2a\0","format 2b\0"}; -void generate_pucch(int32_t **txdataF, - LTE_DL_FRAME_PARMS *frame_parms, - uint8_t ncs_cell[20][7], - PUCCH_FMT_t fmt, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint16_t n1_pucch, - uint16_t n2_pucch, - uint8_t shortened_format, - uint8_t *payload, - int16_t amp, - uint8_t subframe) +void generate_pucch1x(int32_t **txdataF, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t ncs_cell[20][7], + PUCCH_FMT_t fmt, + PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, + uint16_t n1_pucch, + uint8_t shortened_format, + uint8_t *payload, + int16_t amp, + uint8_t subframe) { uint32_t u,v,n; @@ -152,7 +151,8 @@ void generate_pucch(int32_t **txdataF, uint8_t deltaPUCCH_Shift = frame_parms->pucch_config_common.deltaPUCCH_Shift; uint8_t NRB2 = frame_parms->pucch_config_common.nRB_CQI; - uint8_t Ncs1_div_deltaPUCCH_Shift = frame_parms->pucch_config_common.nCS_AN; + uint8_t Ncs1 = frame_parms->pucch_config_common.nCS_AN; + uint8_t Ncs1_div_deltaPUCCH_Shift = Ncs1/deltaPUCCH_Shift; uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30; uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30; @@ -160,12 +160,12 @@ void generate_pucch(int32_t **txdataF, uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) { - msg("[PHY] generate_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift); + printf("[PHY] generate_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift); return; } if (Ncs1_div_deltaPUCCH_Shift > 7) { - msg("[PHY] generate_pucch: Illegal Ncs1_div_deltaPUCCH_Shift %d (should be 0...7)\n",Ncs1_div_deltaPUCCH_Shift); + printf("[PHY] generate_pucch: Illegal Ncs1_div_deltaPUCCH_Shift %d (should be 0...7)\n",Ncs1_div_deltaPUCCH_Shift); return; } @@ -175,7 +175,7 @@ void generate_pucch(int32_t **txdataF, Nprime = Nprime_div_deltaPUCCH_Shift * deltaPUCCH_Shift; #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch); + printf("[PHY] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch); #endif N_UL_symb = (frame_parms->Ncp==0) ? 7 : 6; @@ -194,7 +194,7 @@ void generate_pucch(int32_t **txdataF, } #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH: nprime0 %d nprime1 %d, %s, payload (%d,%d)\n",nprime0,nprime1,pucch_format_string[fmt],payload[0],payload[1]); + printf("[PHY] PUCCH: nprime0 %d nprime1 %d, %s, payload (%d,%d)\n",nprime0,nprime1,pucch_format_string[fmt],payload[0],payload[1]); #endif n_oc0 = nprime0/Nprime_div_deltaPUCCH_Shift; @@ -208,7 +208,7 @@ void generate_pucch(int32_t **txdataF, n_oc1<<=1; #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH: noc0 %d noc11 %d\n",n_oc0,n_oc1); + printf("[PHY] PUCCH: noc0 %d noc11 %d\n",n_oc0,n_oc1); #endif nprime=nprime0; @@ -280,7 +280,7 @@ void generate_pucch(int32_t **txdataF, } #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs); + printf("[PHY] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs); #endif alpha_ind=0; // compute output sequence @@ -329,15 +329,9 @@ void generate_pucch(int32_t **txdataF, break; case pucch_format2: - msg("[PHY] PUCCH format 2 not implemented\n"); - break; - case pucch_format2a: - msg("[PHY] PUCCH format 2a not implemented\n"); - break; - case pucch_format2b: - msg("[PHY] PUCCH format 2b not implemented\n"); + AssertFatal(1==0,"should not go here\n"); break; } // switch fmt } else { // These are PUCCH reference symbols @@ -348,7 +342,7 @@ void generate_pucch(int32_t **txdataF, } #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,((int16_t *)&zptr[n])[0],((int16_t *)&zptr[n])[1], + printf("[PHY] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,((int16_t *)&zptr[n])[0],((int16_t *)&zptr[n])[1], alpha_ind,alpha_re[alpha_ind],alpha_im[alpha_ind]); #endif alpha_ind = (alpha_ind + n_cs)%12; @@ -366,13 +360,12 @@ void generate_pucch(int32_t **txdataF, m = (n1_pucch < thres) ? NRB2 : (((n1_pucch-thres)/(12*c/deltaPUCCH_Shift))+NRB2+((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)+rem); #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH: m %d\n",m); + printf("[PHY] PUCCH: m %d\n",m); #endif nsymb = N_UL_symb<<1; //for (j=0,l=0;l<(nsymb-1);l++) { for (j=0,l=0; l<(nsymb); l++) { - if ((l<(nsymb>>1)) && ((m&1) == 0)) re_offset = (m*6) + frame_parms->first_carrier_offset; else if ((l<(nsymb>>1)) && ((m&1) == 1)) @@ -395,7 +388,7 @@ void generate_pucch(int32_t **txdataF, re_offset = 0; #ifdef DEBUG_PUCCH_TX - msg("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]); + printf("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]); #endif } } @@ -431,13 +424,210 @@ void generate_pucch_emul(PHY_VARS_UE *ue, ue->pucch_payload[0] = pucch_payload[0] + (pucch_payload[1]<<1); UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0] + (pucch_payload[1]<<1); } else if (format == pucch_format1) { - LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",ue->Mod_id,proc->frame_tx,subframe,sr); + // LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",ue->Mod_id,proc->frame_tx,subframe,sr); } ue->sr[subframe] = sr; } + +inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) __attribute__((always_inline)); +inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) { + + uint32_t x1, x2, s=0; + int i; + uint8_t c; + + x2 = (rnti<<14) + ((1+subframe)<<16)*(1+(fp->Nid_cell<<1)); //this is c_init in 36.211 Sec 6.3.1 + s = lte_gold_generic(&x1, &x2, 1); + for (i=0;i<19;i++) { + c = (uint8_t)((s>>i)&1); + btilde[i] = (((B>>i)&1) ^ c); + } +} + +inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) __attribute__((always_inline)); +inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) { + + int i; + + for (i=0;i<20;i++) + d[i] = btilde[i] == 1 ? amp : -amp; + +} + +uint32_t pucch_code[13] = {0xFFFFF,0x5A933,0x10E5A,0x6339C,0x73CE0, + 0xFFC00,0xD8E64,0x4F6B0,0x218EC,0x1B746, + 0x0FFFF,0x33FFF,0x3FFFC}; + +void generate_pucch2x(int32_t **txdataF, + LTE_DL_FRAME_PARMS *fp, + uint8_t ncs_cell[20][7], + PUCCH_FMT_t fmt, + PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, + uint16_t n2_pucch, + uint8_t shortened_format, + uint32_t *payload, + int A, + int B2, + int16_t amp, + uint8_t subframe, + uint16_t rnti) { + + int i,j; + uint32_t B=0; + uint8_t btilde[20]; + int16_t d[22]; + uint8_t deltaPUCCH_Shift = fp->pucch_config_common.deltaPUCCH_Shift; + uint8_t NRB2 = fp->pucch_config_common.nRB_CQI; + uint8_t Ncs1 = fp->pucch_config_common.nCS_AN; + + uint32_t u0 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30; + uint32_t u1 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30; + uint32_t v0=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; + uint32_t v1=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; + uint32_t z[12*14],*zptr; + uint32_t u,v,n; + uint8_t ns,N_UL_symb,nsymb; + uint32_t nprime,l,n_cs; + int alpha_ind,data_ind; + int16_t ref_re,ref_im; + int m,re_offset,symbol_offset; + int32_t *txptr; + + if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) { + printf("[PHY] generate_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift); + return; + } + + if (Ncs1 > 7) { + printf("[PHY] generate_pucch: Illegal Ncs1 %d (should be 0...7)\n",Ncs1); + return; + } + + + // pucch2x_encoding + for (i=0;i 0) + B=B^pucch_code[i]; + + // scrambling + pucch2x_scrambling(fp,subframe,rnti,B,btilde); + // modulation + pucch2x_modulation(btilde,d,amp); + + // add extra symbol for 2a/2b + d[20]=0; + d[21]=0; + if (fmt==pucch_format2a) + d[20] = (B2 == 0) ? amp : -amp; + else if (fmt==pucch_format2b) { + switch (B2) { + case 0: + d[20] = amp; + break; + case 1: + d[21] = -amp; + break; + case 2: + d[21] = amp; + break; + case 3: + d[20] = -amp; + break; + default: + AssertFatal(1==0,"Illegal modulation symbol %d for PUCCH %s\n",B2,pucch_format_string[fmt]); + break; + } + } + + zptr = z; + +#ifdef DEBUG_PUCCH_TX + printf("[PHY] PUCCH2x: n2_pucch %d\n",n2_pucch); +#endif + + N_UL_symb = (fp->Ncp==0) ? 7 : 6; + + for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) { + + if ((ns&1) == 0) + nprime = (n2_pucch < 12*NRB2) ? + n2_pucch % 12 : + (n2_pucch+Ncs1 + 1)%12; + else + nprime = (n2_pucch < 12*NRB2) ? + ((12*(nprime+1)) % 13)-1 : + (10-n2_pucch)%12; + + //loop over symbols in slot + for (l=0; l>15); + ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15); + + if ((l<2)||(l>=(N_UL_symb-2))) { //these are PUCCH data symbols + ((int16_t *)&zptr[n])[0] = ((int32_t)d[data_ind]*ref_re - (int32_t)d[data_ind+1]*ref_im)>>15; + ((int16_t *)&zptr[n])[1] = ((int32_t)d[data_ind]*ref_im + (int32_t)d[data_ind+1]*ref_re)>>15; + } + else { + ((int16_t *)&zptr[n])[0] = ref_re; + ((int16_t *)&zptr[n])[1] = ref_im; + } + + } // n + if ((l<2)||(l>=(N_UL_symb-2))) //these are PUCCH data symbols so increment data index + data_ind+=2; + } // l + } //ns + + m = n2_pucch/12; + +#ifdef DEBUG_PUCCH_TX + printf("[PHY] PUCCH: m %d\n",m); +#endif + nsymb = N_UL_symb<<1; + + //for (j=0,l=0;l<(nsymb-1);l++) { + for (j=0,l=0; l<(nsymb); l++) { + if ((l<(nsymb>>1)) && ((m&1) == 0)) + re_offset = (m*6) + fp->first_carrier_offset; + else if ((l<(nsymb>>1)) && ((m&1) == 1)) + re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12; + else if ((m&1) == 0) + re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12; + else + re_offset = ((m-1)*6) + fp->first_carrier_offset; + + if (re_offset > fp->ofdm_symbol_size) + re_offset -= (fp->ofdm_symbol_size); + + symbol_offset = (unsigned int)fp->ofdm_symbol_size*(l+(subframe*nsymb)); + txptr = &txdataF[0][symbol_offset]; + + for (i=0; i<12; i++,j++) { + txptr[re_offset++] = z[j]; + + if (re_offset==fp->ofdm_symbol_size) + re_offset = 0; + +#ifdef DEBUG_PUCCH_TX + printf("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]); +#endif + } + } +} + + uint32_t rx_pucch(PHY_VARS_eNB *eNB, PUCCH_FMT_t fmt, uint8_t UE_id, @@ -535,7 +725,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, Nprime = Nprime_div_deltaPUCCH_Shift * deltaPUCCH_Shift; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch); + printf("[eNB] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch); #endif N_UL_symb = (frame_parms->Ncp==NORMAL) ? 7 : 6; @@ -554,7 +744,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"PUCCH: nprime0 %d nprime1 %d\n",nprime0,nprime1); + printf("PUCCH: nprime0 %d nprime1 %d\n",nprime0,nprime1); #endif n_oc0 = nprime0/Nprime_div_deltaPUCCH_Shift; @@ -568,7 +758,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, n_oc1<<=1; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH: noc0 %d noc11 %d\n",n_oc0,n_oc1); + printf("[eNB] PUCCH: noc0 %d noc11 %d\n",n_oc0,n_oc1); #endif nprime=nprime0; @@ -647,7 +837,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs); + printf("[eNB] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs); #endif alpha_ind=0; // compute output sequence @@ -663,7 +853,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, zptr[1+(n<<1)] = -(tmp_re*W_im + tmp_im*W_re)>>15; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,zptr[n<<1],zptr[(n<<1)+1], + printf("[eNB] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,zptr[n<<1],zptr[(n<<1)+1], alpha_ind,alpha_re[alpha_ind],alpha_im[alpha_ind]); #endif @@ -682,7 +872,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, m = (n1_pucch < thres) ? NRB2 : (((n1_pucch-thres)/(12*c/deltaPUCCH_Shift))+NRB2+((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)+rem); #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH: m %d\n",m); + printf("[eNB] PUCCH: m %d\n",m); #endif nsymb = N_UL_symb<<1; @@ -716,7 +906,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, re_offset = 0; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,i,re_offset,m,j, + printf("[eNB] PUCCH subframe %d (%d,%d,%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,i,re_offset,m,j, rxptr[re_offset<<1],rxptr[1+(re_offset<<1)], zptr[j],zptr[1+j], rxcomp[aa][j],rxcomp[aa][1+j]); @@ -731,7 +921,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, if (fmt == pucch_format1) { #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"Doing PUCCH detection for format 1\n"); + printf("Doing PUCCH detection for format 1\n"); #endif stat_max = 0; @@ -754,7 +944,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) , stat %d\n",subframe,phase,l,re, + printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) , stat %d\n",subframe,phase,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], stat_re,stat_im,stat); @@ -767,7 +957,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, off+=2; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d), stat %d\n",subframe,phase,l2,re, + printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d), stat %d\n",subframe,phase,l2,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l2<<1],cfo[1+(l2<<1)], stat_re,stat_im,stat); @@ -791,7 +981,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, stat_max *= nsymb; // normalize to energy per symbol stat_max /= (frame_parms->N_RB_UL*12); // #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max); + printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max); #endif #ifdef DEBUG_PUCCH_RX @@ -825,7 +1015,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, *payload = 0; *Po_PUCCH1_below = ((*Po_PUCCH1_below<<9) + (stat_max<<9)+1024)>>10; } - LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); + printf("[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); *Po_PUCCH_update = 1; if (UE_id==0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_ENERGY,dB_fixed(stat_max)); @@ -861,7 +1051,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, off+=2; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, + printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], stat_re,stat_im); @@ -882,7 +1072,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, off+=2; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l2,re, + printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l2,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l2<<1],cfo[1+(l2<<1)], stat_re,stat_im); @@ -891,7 +1081,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"aa%d re %d : phase %d : stat %d\n",aa,re,phase,stat); + printf("aa%d re %d : phase %d : stat %d\n",aa,re,phase,stat); #endif stat += ((((stat_re*stat_re)) + ((stat_im*stat_im)) + @@ -911,23 +1101,23 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } //phase stat_max/=(12); //normalize to energy per symbol and RE - //#ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH fmt1a/b: stat_max : %d, phase_max : %d\n",stat_max,phase_max); - //#endif +#ifdef DEBUG_PUCCH_RX + printf("[eNB] PUCCH fmt1a/b: stat_max : %d, phase_max : %d\n",stat_max,phase_max); +#endif stat_re=0; stat_im=0; - LOG_D(PHY,"PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH); + printf("PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH); *Po_PUCCH = ((*Po_PUCCH>>1) + ((stat_max)>>1)); *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - eNB->rx_total_gain_dB; *Po_PUCCH_update = 1; - LOG_D(PHY,"PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n", - dB_fixed(stat_max), - pucch1_thres+sigma2_dB, - pucch1_thres, - sigma2_dB, - dB_fixed(*Po_PUCCH)); + printf("PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n", + dB_fixed(stat_max), + pucch1_thres+sigma2_dB, + pucch1_thres, + sigma2_dB, + dB_fixed(*Po_PUCCH)); // Do detection now if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) {// @@ -951,7 +1141,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d l %d re %d chest1 => (%d,%d)\n",subframe,l,re, + printf("[eNB] PUCCH subframe %d l %d re %d chest1 => (%d,%d)\n",subframe,l,re, chest_re,chest_im); #endif @@ -963,7 +1153,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, + printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], stat_re,stat_im); @@ -978,7 +1168,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15)/4); off+=2; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, + printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], stat_re,stat_im); @@ -996,7 +1186,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d l %d re %d chest2 => (%d,%d)\n",subframe,l,re, + printf("[eNB] PUCCH subframe %d l %d re %d chest2 => (%d,%d)\n",subframe,l,re, chest_re,chest_im); #endif @@ -1008,7 +1198,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, + printf("[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], stat_re,stat_im); @@ -1023,7 +1213,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, + printf("[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], stat_re,stat_im); @@ -1031,7 +1221,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"aa%d re %d : stat %d,%d\n",aa,re,stat_re,stat_im); + printf("aa%d re %d : stat %d,%d\n",aa,re,stat_re,stat_im); #endif } //re diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 8468d62cad..a1daeea089 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -1189,17 +1189,16 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin if (abstraction_flag == 0) { - generate_pucch(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - format, - &ue->pucch_config_dedicated[eNB_id], - n1_pucch, - 0, // n2_pucch - 1, // shortened format - pucch_ack_payload, - tx_amp, - subframe_tx); + generate_pucch1x(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, + format, + &ue->pucch_config_dedicated[eNB_id], + n1_pucch, + 1, // shortened format + pucch_ack_payload, + tx_amp, + subframe_tx); } else { #ifdef PHY_ABSTRACTION @@ -1240,17 +1239,16 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin if (abstraction_flag == 0) { - generate_pucch(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - pucch_format1, - &ue->pucch_config_dedicated[eNB_id], - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - 0, // n2_pucch - 1, // shortened format - pucch_ack_payload, // this is ignored anyway, we just need a pointer - tx_amp, - subframe_tx); + generate_pucch1x(ue->common_vars.txdataF, + &ue->frame_parms, + ue->ncs_cell, + pucch_format1, + &ue->pucch_config_dedicated[eNB_id], + ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, + 1, // shortened format + pucch_ack_payload, // this is ignored anyway, we just need a pointer + tx_amp, + subframe_tx); } else { LOG_D(PHY,"Calling generate_pucch_emul ...\n"); generate_pucch_emul(ue, diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c index 09777d54ce..4f9b8f9a88 100644 --- a/openair1/SIMULATION/LTE_PHY/pucchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c @@ -66,7 +66,7 @@ int main(int argc, char **argv) uint8_t snr1set=0; //mod_sym_t **txdataF; int **txdata; - double **s_re,**s_im,**r_re,**r_im; + double s_re[2][30720],s_im[2][30720],r_re[2][30720],r_im[2][30720]; double ricean_factor=0.0000005,iqim=0.0; int trial, n_trials, ntrials=1, n_errors; @@ -325,10 +325,6 @@ int main(int argc, char **argv) txdata = eNB->common_vars.txdata[eNB_id]; - s_re = malloc(2*sizeof(double*)); - s_im = malloc(2*sizeof(double*)); - r_re = malloc(2*sizeof(double*)); - r_im = malloc(2*sizeof(double*)); nsymb = (frame_parms->Ncp == 0) ? 14 : 12; printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Symbols per subframe %d\n",NUMBER_OF_OFDM_CARRIERS, @@ -352,19 +348,6 @@ int main(int argc, char **argv) exit(-1); } - for (i=0; i<2; i++) { - - s_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - bzero(s_re[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - bzero(s_im[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - - r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - bzero(r_re[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - bzero(r_im[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); - } - init_ncs_cell(&eNB->frame_parms,eNB->ncs_cell); init_ncs_cell(&UE->frame_parms,UE->ncs_cell); @@ -378,17 +361,16 @@ int main(int argc, char **argv) pucch_payload = 0; - generate_pucch(UE->common_vars.txdataF, - frame_parms, - UE->ncs_cell, - pucch_format, - &pucch_config_dedicated, - n1_pucch, - n2_pucch, - 0, //shortened_format, - &pucch_payload, - AMP, //amp, - subframe); //subframe + generate_pucch1x(UE->common_vars.txdataF, + frame_parms, + UE->ncs_cell, + pucch_format, + &pucch_config_dedicated, + n1_pucch, + 0, //shortened_format, + &pucch_payload, + AMP, //amp, + subframe); //subframe write_output("txsigF0.m","txsF0", &UE->common_vars.txdataF[0][2*subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX*nsymb,1,1); tx_lev = 0; @@ -453,7 +435,7 @@ int main(int argc, char **argv) multipath_channel(UE2eNB,s_re,s_im,r_re,r_im, - 2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,0); + eNB->frame_parms.samples_per_tti,0); sigma2_dB = N0;//10*log10((double)tx_lev) - SNR; tx_gain = sqrt(pow(10.0,.1*(N0+SNR))/(double)tx_lev); @@ -509,8 +491,7 @@ int main(int argc, char **argv) if (sig==1) { ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) (((tx_gain*r_re[aa][i]) +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) (((tx_gain*r_im[aa][i]) + (iqim*r_re[aa][i]*tx_gain) + sqrt(sigma2/2)*gaussdouble( - 0.0,1.0))); + ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) (((tx_gain*r_im[aa][i]) + (iqim*r_re[aa][i]*tx_gain) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } else { ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); ((short*) &eNB->common_vars.rxdata[0][aa][subframe*frame_parms->samples_per_tti])[2*i+1] = (short) ((sqrt(sigma2/2)*gaussdouble(0.0,1.0))); @@ -603,18 +584,6 @@ int main(int argc, char **argv) } - for (i=0; i<2; i++) { - free(s_re[i]); - free(s_im[i]); - free(r_re[i]); - free(r_im[i]); - } - - free(s_re); - free(s_im); - free(r_re); - free(r_im); - lte_sync_time_free(); return(n_errors); From 43f96a0eacb5bb6b0187c7b6be850453a007e19f Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 19 Sep 2016 14:13:11 -0700 Subject: [PATCH 181/206] finishing merge with develop --- openair1/PHY/INIT/defs.h | 2 -- openair1/PHY/INIT/lte_init.c | 40 --------------------- openair1/PHY/INIT/lte_param_init.c | 2 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 5 --- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 10 +++--- openair1/SCHED/phy_mac_stub.c | 1 - openair1/SCHED/phy_procedures_lte_eNb.c | 4 +-- openair1/SCHED/phy_procedures_lte_ue.c | 5 +++ openair2/RRC/LITE/rrc_eNB.c | 5 +-- targets/RT/USER/lte-enb.c | 12 ++++--- targets/RT/USER/lte-softmodem.c | 7 ++-- targets/SIMU/USER/init_lte.c | 8 ++--- targets/SIMU/USER/init_lte.h | 1 - 13 files changed, 31 insertions(+), 71 deletions(-) diff --git a/openair1/PHY/INIT/defs.h b/openair1/PHY/INIT/defs.h index 89cfebff51..fd14c0c9a5 100644 --- a/openair1/PHY/INIT/defs.h +++ b/openair1/PHY/INIT/defs.h @@ -73,7 +73,6 @@ int phy_init_lte_ue(PHY_VARS_UE *phy_vars_ue, \details Only a subset of phy_vars_eNb is initialized. @param[out] phy_vars_eNb Pointer to eNB Variables @param is_secondary_eNb Flag to indicate this eNB gets synch from another -@param cooperation_flag 0 for no cooperation, 1 for Delay Diversity and 2 for Distributed Alamouti @param abstraction_flag 1 indicates memory should be allocated for abstracted MODEM @returns 0 on success @returns -1 if any memory allocation failed @@ -81,7 +80,6 @@ int phy_init_lte_ue(PHY_VARS_UE *phy_vars_ue, */ int phy_init_lte_eNB(PHY_VARS_eNB *phy_vars_eNb, unsigned char is_secondary_eNb, - unsigned char cooperation_flag, unsigned char abstraction_flag); /** \brief Configure LTE_DL_FRAME_PARMS with components derived after initial synchronization (MIB decoding + primary/secondary synch). diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index c9aeb6e1d9..a2e4fa8747 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -1175,7 +1175,6 @@ int phy_init_lte_ue(PHY_VARS_UE *ue, int phy_init_lte_eNB(PHY_VARS_eNB *eNB, unsigned char is_secondary_eNB, - uint8_t cooperation_flag, unsigned char abstraction_flag) { @@ -1191,7 +1190,6 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, eNB->total_transmitted_bits = 0; eNB->total_system_throughput = 0; eNB->check_for_MUMIMO_transmissions=0; - LOG_I(PHY,"[eNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d\n", eNB->Mod_id, fp->N_RB_DL,fp->phich_config_common.phich_resource, @@ -1345,44 +1343,6 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } - - // In case of Distributed Alamouti Collabrative scheme separate channel estimates are required for both the UEs - if (cooperation_flag == 2) { - pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // UE 0 DRS estimates - pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // UE 1 DRS estimates - - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->drs_ch_estimates_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - pusch_vars[UE_id]->drs_ch_estimates_1[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - } - - // Compensated data for the case of Distributed Alamouti Scheme - pusch_vars[UE_id]->rxdataF_comp_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y)*(h0*) - pusch_vars[UE_id]->rxdataF_comp_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); // it will contain(y*)*(h1) - - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->rxdataF_comp_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - pusch_vars[UE_id]->rxdataF_comp_1[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - } - - // UE 0 - pusch_vars[UE_id]->ul_ch_mag_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb_0[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->ul_ch_mag_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb_0[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - } - - // UE 1 - pusch_vars[UE_id]->ul_ch_mag_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb_1[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); - - for (i=0; inb_antennas_rx; i++) { - pusch_vars[UE_id]->ul_ch_mag_1[eNB_id][i] = (int32_t*)malloc16( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb_1[eNB_id][i] = (int32_t*)malloc16( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - } - }//cooperation_flag } //eNB_id pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c index 8d9acdbe92..114e1f285a 100644 --- a/openair1/PHY/INIT/lte_param_init.c +++ b/openair1/PHY/INIT/lte_param_init.c @@ -83,7 +83,7 @@ void lte_param_init(unsigned char N_tx, lte_gold(frame_parms,UE->lte_gold_table[i],Nid_cell+i); phy_init_lte_ue(UE,1,0); - phy_init_lte_eNB(eNB,0,0,0); + phy_init_lte_eNB(eNB,0,0); generate_pcfich_reg_mapping(&UE->frame_parms); generate_phich_reg_mapping(&UE->frame_parms); diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 3e0af70deb..05ba6fc474 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -384,11 +384,6 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, unsigned int Kr=0,Kr_bytes,r,r_offset=0; unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - struct timespec wait; - - wait.tv_sec=0; - wait.tv_nsec=5000000L; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); A = dlsch->harq_processes[harq_pid]->TBS; //6228 diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index d194439f3b..7141a4983d 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -6,7 +6,7 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + OpenAirInterface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -490,19 +490,19 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr tc = phy_threegpplte_turbo_decoder8; if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for TD thread %d (IC %d)\n", proc->instance_cnt_td); + printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); exit_fun( "error locking mutex_fep" ); - return; + return -1; } if (proc->instance_cnt_td==0) { printf("[eNB] TD thread busy\n"); exit_fun("TD thread busy"); pthread_mutex_unlock( &proc->mutex_td ); - return; + return -1; } - ++proc->instance_cnt_te; + ++proc->instance_cnt_td; proc->tdp.eNB = eNB; proc->tdp.UE_id = UE_id; diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c index 21bed06a57..3b343d4994 100644 --- a/openair1/SCHED/phy_mac_stub.c +++ b/openair1/SCHED/phy_mac_stub.c @@ -60,7 +60,6 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) int subframe = proc->subframe_tx; - LTE_eNB_DLSCH_t *DLSCH_ptr = eNB->dlsch[0][0]; /* uint32_t rand = taus(); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 70b0ce1924..e29e2215b5 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2541,7 +2541,7 @@ static void *fep_thread(void *param) { if (pthread_cond_signal(&proc->cond_fep) != 0) { printf("[eNB] ERROR pthread_cond_signal for fep thread exit\n"); exit_fun( "ERROR pthread_cond_signal" ); - return; + return NULL; } } @@ -2611,7 +2611,7 @@ void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) { start_meas(&eNB->ofdm_demod_stats); if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep); + printf("[eNB] ERROR pthread_mutex_lock for fep thread (IC %d)\n", proc->instance_cnt_fep); exit_fun( "error locking mutex_fep" ); return; } diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index a1daeea089..538f9e1126 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -2481,6 +2481,11 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, pdsch_vars = NULL; return; break; + default: + pdsch_vars = NULL; + return; + break; + } harq_pid = dlsch0->current_harq_pid; diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index 9e5c54cb07..891db7bee5 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -3736,6 +3736,7 @@ rrc_eNB_generate_RRCConnectionSetup( SRB_ToAddModList_t **SRB_configList; SRB_ToAddMod_t *SRB1_config; int cnt; + LTE_DL_FRAME_PARMS *fp = mac_xface->get_lte_frame_parms(ctxt_pP->module_id,CC_id); T(T_ENB_RRC_CONNECTION_SETUP, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); @@ -3745,9 +3746,9 @@ rrc_eNB_generate_RRCConnectionSetup( do_RRCConnectionSetup(ctxt_pP, ue_context_pP, (uint8_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload, - (mac_xface->lte_frame_parms->nb_antennas_tx_eNB==2)?2:1, //at this point we do not have the UE capability information, so it can only be TM1 or TM2 + (fp->nb_antennas_tx_eNB==2)?2:1, //at this point we do not have the UE capability information, so it can only be TM1 or TM2 rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), - mac_xface->frame_parms, + fp, SRB_configList, &ue_context_pP->ue_context.physicalConfigDedicated); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index c095d46729..a05b1c8a9d 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1291,6 +1291,8 @@ static void* eNB_thread_single( void* param ) { } extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *); +extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *); +extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *); void init_eNB_proc(int inst) { @@ -1299,7 +1301,7 @@ void init_eNB_proc(int inst) { PHY_VARS_eNB *eNB; eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; - pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL; + pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te; for (CC_id=0; CC_iddo_prach = do_prach; eNB->fep = eNB_fep_full; eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2thread; + eNB->te = dlsch_encoding_2threads; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = NULL; @@ -1662,7 +1664,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = do_prach; eNB->fep = eNB_fep_full; eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2thread; + eNB->te = dlsch_encoding_2threads; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = tx_fh_if5; @@ -1686,7 +1688,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = do_prach; eNB->fep = NULL; eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2thread; + eNB->te = dlsch_encoding_2threads; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_high; eNB->tx_fh = tx_fh_if4p5; @@ -1709,7 +1711,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->do_prach = do_prach; eNB->fep = NULL; eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2thread; + eNB->te = dlsch_encoding_2threads; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_high; eNB->tx_fh = tx_fh_if4p5; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index ca0c23f335..4eb34321d7 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1121,7 +1121,7 @@ static void get_options (int argc, char **argv) frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = enb_properties->properties[i]->prach_config_index[CC_id]; frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset = enb_properties->properties[i]->prach_freq_offset[CC_id]; - frame_parms[CC_id]->mode1_flag = (transmission_mode == 1) ? 1 : 0; + frame_parms[CC_id]->mode1_flag = (frame_parms[CC_id]->nb_antennas_tx_eNB == 1) ? 1 : 0; frame_parms[CC_id]->threequarter_fs = threequarter_fs; //} // j @@ -1202,7 +1202,8 @@ int T_port = 2021; /* default port to listen to to wait for the tracer */ int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */ #endif -void set_default_frame_parms() { +void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); +void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { int CC_id; @@ -1248,6 +1249,8 @@ void set_default_frame_parms() { } +void init_openair0(void); + void init_openair0() { int card; diff --git a/targets/SIMU/USER/init_lte.c b/targets/SIMU/USER/init_lte.c index 54c5e2ad46..5a244207da 100644 --- a/targets/SIMU/USER/init_lte.c +++ b/targets/SIMU/USER/init_lte.c @@ -49,7 +49,6 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, uint8_t eNB_id, uint8_t Nid_cell, - uint8_t cooperation_flag, uint8_t abstraction_flag) { @@ -57,18 +56,17 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, PHY_VARS_eNB* PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); memset(PHY_vars_eNB,0,sizeof(PHY_VARS_eNB)); PHY_vars_eNB->Mod_id=eNB_id; - PHY_vars_eNB->cooperation_flag=cooperation_flag; + PHY_vars_eNB->cooperation_flag=0;//cooperation_flag; memcpy(&(PHY_vars_eNB->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS)); PHY_vars_eNB->frame_parms.Nid_cell = ((Nid_cell/3)*3)+((eNB_id+Nid_cell)%3); PHY_vars_eNB->frame_parms.nushift = PHY_vars_eNB->frame_parms.Nid_cell%6; - phy_init_lte_eNB(PHY_vars_eNB,0,cooperation_flag,abstraction_flag); + phy_init_lte_eNB(PHY_vars_eNB,0,abstraction_flag); LOG_I(PHY,"init eNB: Nid_cell %d\n", frame_parms->Nid_cell); LOG_I(PHY,"init eNB: frame_type %d,tdd_config %d\n", frame_parms->frame_type,frame_parms->tdd_config); LOG_I(PHY,"init eNB: number of ue max %d number of enb max %d number of harq pid max %d\n", NUMBER_OF_UE_MAX, NUMBER_OF_eNB_MAX, NUMBER_OF_HARQ_PID_MAX); LOG_I(PHY,"init eNB: N_RB_DL %d\n", frame_parms->N_RB_DL); - LOG_I(PHY,"init eNB: Transmission mode %d\n", transmission_mode); LOG_I(PHY,"init eNB: prach_config_index %d\n", frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex); @@ -281,7 +279,7 @@ void init_lte_vars(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs], PHY_vars_eNB_g[eNB_id] = (PHY_VARS_eNB**) malloc(MAX_NUM_CCs*sizeof(PHY_VARS_eNB*)); for (CC_id=0; CC_idMod_id=eNB_id; PHY_vars_eNB_g[eNB_id][CC_id]->CC_id=CC_id; } diff --git a/targets/SIMU/USER/init_lte.h b/targets/SIMU/USER/init_lte.h index 72ffd60765..d9f0725a7c 100644 --- a/targets/SIMU/USER/init_lte.h +++ b/targets/SIMU/USER/init_lte.h @@ -33,7 +33,6 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, uint8_t eNB_id, uint8_t Nid_cell, - uint8_t cooperation_flag, uint8_t abstraction_flag); PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms, From 8d15dfe89441abd606fba2984b7edeadd4495820 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 20 Sep 2016 07:57:27 -0700 Subject: [PATCH 182/206] small bugs for lte-softmodem with parallel threads in L1 --- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 05ba6fc474..8afb1e6f1c 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -344,10 +344,12 @@ void *te_thread(void *param) { eNB_proc_t *proc = &((te_params *)param)->eNB->proc; while (!oai_exit) { + if (wait_on_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread")<0) break; dlsch_encoding_2threads0((te_params*)param); + if (release_thread(&proc->mutex_te,&proc->instance_cnt_te,"te thread")<0) break; if (pthread_cond_signal(&proc->cond_te) != 0) { From f05013a2876fa739b1f5540c773f6a5aa2ca25e4 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 20 Sep 2016 16:55:16 +0200 Subject: [PATCH 183/206] real changes for L1 threading. previous was bogus --- .../GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index d2e99a3481..03dcabefe2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -36,6 +36,7 @@ eNBs = Nid_cell = 0; N_RB_DL = 50; Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; @@ -100,6 +101,8 @@ eNBs = ue_TimersAndConstants_t311 = 10000; ue_TimersAndConstants_n310 = 20; ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; } ); From 7af3d98fd9bcc3cc2db773c6f682118e40a9e919 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 21 Sep 2016 17:23:50 +0200 Subject: [PATCH 184/206] bugfix in ulsch_decoding. removal of logging in pucch.c and usrp_lib.cpp. --- openair1/PHY/LTE_TRANSPORT/pucch.c | 8 +-- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 61 +++++++++++-------- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 8 +-- .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 5 +- targets/RT/USER/lte-enb.c | 2 +- 5 files changed, 47 insertions(+), 37 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 507ff91199..7787ddfcf3 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -1015,7 +1015,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, *payload = 0; *Po_PUCCH1_below = ((*Po_PUCCH1_below<<9) + (stat_max<<9)+1024)>>10; } - printf("[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); + //printf("[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); *Po_PUCCH_update = 1; if (UE_id==0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_ENERGY,dB_fixed(stat_max)); @@ -1107,18 +1107,18 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, stat_re=0; stat_im=0; - printf("PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH); + // printf("PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH); *Po_PUCCH = ((*Po_PUCCH>>1) + ((stat_max)>>1)); *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - eNB->rx_total_gain_dB; *Po_PUCCH_update = 1; - + /* printf("PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n", dB_fixed(stat_max), pucch1_thres+sigma2_dB, pucch1_thres, sigma2_dB, dB_fixed(*Po_PUCCH)); - + */ // Do detection now if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) {// diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 7141a4983d..de81897d5a 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -302,7 +302,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { } // go through second half of segments - for (; r<(ulsch_harq->C/2); r++) { + for (; r<(ulsch_harq->C); r++) { // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); @@ -461,6 +461,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr int Q_m = get_Qm_ul(ulsch_harq->mcs); int G = ulsch_harq->nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch; unsigned int E; + int Cby2; uint8_t (*tc)(int16_t *y, uint8_t *, @@ -489,38 +490,44 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr else tc = phy_threegpplte_turbo_decoder8; - if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); - exit_fun( "error locking mutex_fep" ); - return -1; - } + if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment + if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { + printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); + exit_fun( "error locking mutex_fep" ); + return -1; + } + + if (proc->instance_cnt_td==0) { + printf("[eNB] TD thread busy\n"); + exit_fun("TD thread busy"); + pthread_mutex_unlock( &proc->mutex_td ); + return -1; + } + + ++proc->instance_cnt_td; + + proc->tdp.eNB = eNB; + proc->tdp.UE_id = UE_id; + proc->tdp.harq_pid = harq_pid; + proc->tdp.llr8_flag = llr8_flag; + + + // wakeup worker to do second half segments + if (pthread_cond_signal(&proc->cond_td) != 0) { + printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return (1+ulsch->max_turbo_iterations); + } - if (proc->instance_cnt_td==0) { - printf("[eNB] TD thread busy\n"); - exit_fun("TD thread busy"); pthread_mutex_unlock( &proc->mutex_td ); - return -1; + Cby2 = ulsch_harq->C/2; } - - ++proc->instance_cnt_td; - - proc->tdp.eNB = eNB; - proc->tdp.UE_id = UE_id; - proc->tdp.harq_pid = harq_pid; - proc->tdp.llr8_flag = llr8_flag; - - // wakeup worker to do second half segments - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (1+ulsch->max_turbo_iterations); + else { + Cby2 = 1; } - pthread_mutex_unlock( &proc->mutex_td ); - - // go through first half of segments in main thread - for (r=0; r<(ulsch_harq->C/2); r++) { + for (r=0; rc[r]); // Get Turbo interleaver parameters diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 56a0f50ff4..1a23015cbb 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -215,10 +215,10 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, else time_avg=(time_diff+time_avg) /2.0; - //prints statics of uhd every 10 seconds + /* //prints statics of uhd every 10 seconds if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0) LOG_I(HW,"usrp_write: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg); - + */ loop++; return ret; } @@ -331,12 +331,12 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp time_avg= time_diff; else time_avg=(time_diff+time_avg) /2.0; - + /* //prints statics of uhd every 10 seconds if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0) LOG_I(HW,"usrp_read: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg); - loop++; + loop++;*/ return samples_received; } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index 10da79724a..fea29a7d59 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -31,11 +31,12 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 100; Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; @@ -100,6 +101,8 @@ eNBs = ue_TimersAndConstants_t311 = 10000; ue_TimersAndConstants_n310 = 20; ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; } ); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index a05b1c8a9d..b8ce8dba57 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -835,7 +835,7 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) { void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; unsigned int rxs,txs; int i; - int tx_sfoffset = 2;//(eNB->single_thread_flag == 1) ? 3 : 3; + int tx_sfoffset = 3;//(eNB->single_thread_flag == 1) ? 3 : 3; if (proc->first_rx==0) { // Transmit TX buffer based on timestamp from RX From 898774d68a8fa1c5062961c3a5d76f9bfda99ea4 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 21 Sep 2016 19:08:25 +0200 Subject: [PATCH 185/206] minor compilation fix --- openair2/ENB_APP/enb_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index cdcf5544c6..def056ee3f 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -536,6 +536,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) config_setting_t *setting_enb = NULL; config_setting_t *setting_otg = NULL; config_setting_t *subsetting_otg = NULL; + int parse_errors = 0; int num_enb_properties = 0; int enb_properties_index = 0; int num_enbs = 0; From fea3c34b5816be0e638ce1962c19d616b289de72 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 22 Sep 2016 16:03:11 +0200 Subject: [PATCH 186/206] minor fix to UE logging for test setup --- .../autotests/tools/configure_cots_sony_experia_m4_ue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py b/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py index c136067a61..46ee33e97a 100755 --- a/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py +++ b/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py @@ -73,7 +73,7 @@ def start_ue () : time.sleep ( 2) #Now we check if ppp0 interface is up and running try: - cmd = 'sudo adb -s ' + device_id + ' shell netcfg |grep 192.' + cmd = 'sudo adb -s ' + device_id + ' shell netcfg |grep UP' status, out = commands.getstatusoutput(cmd) if (out == '') : print "Waiting for UE to connect and get IP Address..." From e5b643d03c0fa565965f6ed4fb09c9a7dbbeb3b1 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 22 Sep 2016 16:22:55 +0200 Subject: [PATCH 187/206] updates for UE with USRP --- targets/RT/USER/lte-softmodem.c | 28 ++++++++++++++++++---------- targets/RT/USER/lte-ue.c | 29 ++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4eb34321d7..c9aa16441f 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -424,10 +424,16 @@ void exit_fun(const char* s) oai_exit = 1; for(CC_id=0; CC_idrfdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); - if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) - PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + if (UE_flag == 0) { + if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); + if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) + PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); + } + else { + if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) + PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } } #if defined(ENABLE_ITTI) @@ -1789,14 +1795,16 @@ int main( int argc, char **argv ) // start the main thread if (UE_flag == 1) init_UE(1); - else init_eNB(node_function,node_timing,1,eth_params,single_thread_flag); + else { + init_eNB(node_function,node_timing,1,eth_params,single_thread_flag); // Sleep to allow all threads to setup - number_of_cards = 1; - - for(CC_id=0; CC_idrf_map.card=0; - PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; + number_of_cards = 1; + + for(CC_id=0; CC_idrf_map.card=0; + PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; + } } // connect the TX/RX buffers diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index c33005ebab..190951bf00 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -188,7 +188,7 @@ void init_UE(int nb_inst) { ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]); UE->rfdevice.host_type = BBU_HOST; - UE->rfdevice.type = NONE_DEV; + // UE->rfdevice.type = NONE_DEV; error_code = pthread_create(&UE->proc.pthread_ue, &UE->proc.attr_ue, UE_thread, NULL); if (error_code!= 0) { @@ -369,10 +369,7 @@ static void *UE_thread_synch(void *arg) } - if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { - LOG_E(HW,"Could not start the device\n"); - oai_exit=1; - } + pthread_mutex_lock(&sync_mutex); printf("Locked sync_mutex, waiting (UE_sync_thread)\n"); @@ -382,6 +379,11 @@ static void *UE_thread_synch(void *arg) pthread_mutex_unlock(&sync_mutex); printf("Started device, unlocked sync_mutex (UE_sync_thread)\n"); + if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { + LOG_E(HW,"Could not start the device\n"); + oai_exit=1; + } + while (oai_exit==0) { if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) { @@ -941,7 +943,14 @@ void *UE_thread(void *arg) { rxp, UE->frame_parms.samples_per_tti*10, UE->frame_parms.nb_antennas_rx); + + + if (rxs!=UE->frame_parms.samples_per_tti*10) { + exit_fun("problem in rx"); + return &UE_thread_retval; + } } + instance_cnt_synch = ++UE->proc.instance_cnt_synch; if (instance_cnt_synch == 0) { if (pthread_cond_signal(&UE->proc.cond_synch) != 0) { @@ -968,6 +977,12 @@ void *UE_thread(void *arg) { rxp, UE->frame_parms.samples_per_tti, UE->frame_parms.nb_antennas_rx); + + if (rxs!=UE->frame_parms.samples_per_tti){ + exit_fun("problem in rx"); + return &UE_thread_retval; + } + } } } @@ -1065,12 +1080,12 @@ void *UE_thread(void *arg) { proc->frame_tx = proc->frame_rx + ((proc->subframe_rx>5)?1:0); proc->timestamp_tx = timestamp+(4*UE->frame_parms.samples_per_tti)-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; - + /* if (sf != (timestamp/UE->frame_parms.samples_per_tti)%10) { LOG_E(PHY,"steady-state UE_thread error : frame_rx %d, subframe_rx %d, frame_tx %d, subframe_tx %d, rx subframe %d\n",proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,(timestamp/UE->frame_parms.samples_per_tti)%10); exit(-1); } - + */ if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" ); exit_fun("nothing to add"); From 29fac70eb6f61a7ed9038d02139621edc00996d1 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 22 Sep 2016 18:36:35 +0200 Subject: [PATCH 188/206] minor fix pthread_create call --- targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index 17a1d18ce6..ada82b8510 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -487,7 +487,7 @@ void create_watchdog(openair0_device *dev) { pthread_attr_setschedpolicy(&priv->watchdog_attr,SCHED_FIFO); pthread_create(&priv->watchdog,&priv->watchdog_attr,watchdog_thread,dev); #else - pthread_create(&priv->watchdog,NULL,watchdog_thread,devv); + pthread_create(&priv->watchdog,NULL,watchdog_thread,dev); #endif pthread_mutex_init(&priv->watchdog_mutex,NULL); From 23822ea203e00f2100fa41c7ee3084ec55b884fe Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 22 Sep 2016 18:55:14 +0200 Subject: [PATCH 189/206] send SIGINT before processes are killed in test setup --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index eed2fffb77..50ff6451f8 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -313,7 +313,7 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote, logd # \param CleanUpAluLteBox program to terminate AlU Bell Labs LTE Box # \param ExmimoRfStop String to stop EXMIMO card (specified in test_case_list.xml) def cleanOldPrograms(oai, programList, CleanUpAluLteBox, ExmimoRfStop, logdir, logdirOAI5GRepo): - cmd = 'sudo -E killall -9 -q -r ' + programList + cmd = 'sudo -E killall -s INT -q -r ' + programList + ' ; sleep 5 ; sudo -E killall -9 -q -r ' + programList result = oai.send(cmd, True) print "Killing old programs..." + result programArray = programList.split() From 5e7f0070090c80969f81511ef5ac662b2f4925c2 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 23 Sep 2016 02:08:52 +0200 Subject: [PATCH 190/206] fixed --single-thread flag (when not set) --- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 13 +++--- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 27 ++++++------ openair1/SCHED/phy_procedures_lte_ue.c | 2 + .../LAYER2/MAC/eNB_scheduler_primitives.c | 44 ++++++++++++++++++- openair2/RRC/LITE/L2_interface.c | 4 +- openair2/UTIL/LOG/vcd_signal_dumper.c | 1 + openair2/UTIL/LOG/vcd_signal_dumper.h | 1 + .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 4 +- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 2 +- targets/RT/USER/lte-enb.c | 26 ++++++----- 10 files changed, 85 insertions(+), 39 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 8afb1e6f1c..b3601d1456 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -266,10 +266,7 @@ int dlsch_encoding_2threads0(te_params *tep) { unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - - - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_IN); if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet @@ -333,7 +330,7 @@ int dlsch_encoding_2threads0(te_params *tep) { m); // r } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_OUT); return(0); } @@ -424,7 +421,8 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, pthread_mutex_unlock( &proc->mutex_te ); return(-1); } - + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); ++proc->instance_cnt_te; proc->tep.eNB = eNB; @@ -440,6 +438,7 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, pthread_mutex_unlock( &proc->mutex_te ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); for (r=dlsch->harq_processes[harq_pid]->C>>1; rharq_processes[harq_pid]->C; r++) { if (rharq_processes[harq_pid]->Cminus) @@ -500,7 +499,7 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the // outputs for each code segment, see Section 5.1.5 p.20 - for (r=0; rharq_processes[harq_pid]->C; r++) { + for (r=0,r_offset=0; rharq_processes[harq_pid]->C; r++) { // get information for E for the segments that are handled by the worker thread if (r<(dlsch->harq_processes[harq_pid]->C>>1)) { diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index de81897d5a..8bdccd9adf 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -299,6 +299,12 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { E = Nl*Q_m * ((GpmodC==0?0:1) + (Gp/C)); r_offset += E; + + if (r==0) { + offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); + } else { + offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); + } } // go through second half of segments @@ -393,8 +399,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { &eNB->ulsch_tc_intl1_stats, &eNB->ulsch_tc_intl2_stats); - - // Reassembly of Transport block here + // Reassembly of Transport block here if (ret != (1+ulsch->max_turbo_iterations)) { if (rCminus) @@ -404,17 +409,11 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { Kr_bytes = Kr>>3; - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } + memcpy(ulsch_harq->b+offset, + ulsch_harq->c[r], + Kr_bytes - ((ulsch_harq->C>1)?3:0)); + offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); + } else { break; @@ -621,7 +620,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr &eNB->ulsch_tc_ext_stats, &eNB->ulsch_tc_intl1_stats, &eNB->ulsch_tc_intl2_stats); - + // Reassembly of Transport block here if (ret != (1+ulsch->max_turbo_iterations)) { diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 538f9e1126..16872ec879 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -713,12 +713,14 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin if (ue->mac_enabled==1){ // ask L2 for RACH transport if ((mode != rx_calib_ue) && (mode != rx_calib_ue_med) && (mode != rx_calib_ue_byp) && (mode != no_L2_connect) ) { + LOG_D(PHY,"Getting PRACH resources\n"); ue->prach_resources[eNB_id] = mac_xface->ue_get_rach(ue->Mod_id, ue->CC_id, frame_tx, eNB_id, subframe_tx); LOG_D(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[ue->Mod_id].radioResourceConfigCommon); + LOG_D(PHY,"Prach resources %p\n",ue->prach_resources[eNB_id]); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 9992e76150..605ff93f1f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1005,6 +1005,46 @@ int get_nCCE_offset(int *CCE_table, } } +void dump_CCE_table(int *CCE_table,const int nCCE,const unsigned short rnti,const int subframe,int L) { + + int nb_candidates = 0,i; + unsigned int Yk; + + for (i=0;irnti); for (j=0;j<=i;j++){ LOG_I(MAC,"DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", - i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci, + j,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci, DCI_pdu->dci_alloc[j].rnti,DCI_pdu->dci_alloc[j].format, 1<dci_alloc[j].L, nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols); } + dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,dci_alloc->L); + goto failed; } DCI_pdu->num_pdcch_symbols++; diff --git a/openair2/RRC/LITE/L2_interface.c b/openair2/RRC/LITE/L2_interface.c index 50e00e6a83..d45b69dcd8 100644 --- a/openair2/RRC/LITE/L2_interface.c +++ b/openair2/RRC/LITE/L2_interface.c @@ -291,10 +291,10 @@ mac_rrc_data_req( #endif //Rel10 } else { //This is an UE -#ifdef DEBUG_RRC + LOG_D(RRC,"[UE %d] Frame %d Filling CCCH SRB_ID %d\n",Mod_idP,frameP,Srb_id); LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size); -#endif + if( (UE_rrc_inst[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size > 0) ) { diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 94e180773d..b8b8123780 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -272,6 +272,7 @@ const char* eurecomFunctionsNames[] = { "phy_ue_ulsch_scrambling", "phy_eNB_dlsch_modulation", "phy_eNB_dlsch_encoding", + "phy_eNB_dlsch_encoding_w", "phy_eNB_dlsch_scrambling", /* MAC signals */ diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index 416ec6064e..6edd9c09d5 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -246,6 +246,7 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_SCRAMBLING, VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, + VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, /* MAC signals */ diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index cc19e20794..6d4652183e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -50,7 +50,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -32; + pdsch_referenceSignalPower = -29; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; @@ -70,7 +70,7 @@ eNBs = pusch_p0_Nominal = -96; pusch_alpha = "AL1"; - pucch_p0_Nominal = -103; + pucch_p0_Nominal = -100; msg3_delta_Preamble = 6; pucch_deltaF_Format1 = "deltaF2"; pucch_deltaF_Format1b = "deltaF3"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index 03dcabefe2..b18055ed22 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -70,7 +70,7 @@ eNBs = pusch_p0_Nominal = -96; pusch_alpha = "AL1"; - pucch_p0_Nominal = -103; + pucch_p0_Nominal = -100; msg3_delta_Preamble = 6; pucch_deltaF_Format1 = "deltaF2"; pucch_deltaF_Format1b = "deltaF3"; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index b8ce8dba57..d2be56a3a3 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -237,7 +237,7 @@ static inline void thread_top_init(char *thread_name, } memset(&sparam, 0, sizeof(sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); policy = SCHED_FIFO ; s = pthread_setschedparam(pthread_self(), policy, &sparam); @@ -1566,6 +1566,7 @@ int start_rf(PHY_VARS_eNB *eNB) { extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB); extern void eNB_fep_full(PHY_VARS_eNB *eNB); +extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB); extern void do_prach(PHY_VARS_eNB *eNB); void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params,int single_thread_flag) { @@ -1613,7 +1614,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case NGFI_RRU_IF4p5: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; + eNB->fep = (single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full; eNB->td = NULL; eNB->te = NULL; eNB->proc_uespec_rx = NULL; @@ -1642,9 +1643,9 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case eNodeB_3GPP: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; - eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2threads; + eNB->fep = (single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full; + eNB->td = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data; + eNB->te = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = NULL; @@ -1662,9 +1663,9 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst break; case eNodeB_3GPP_BBU: eNB->do_prach = do_prach; - eNB->fep = eNB_fep_full; - eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2threads; + eNB->fep = (single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full; + eNB->td = (single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data; + eNB->te = (single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_full; eNB->tx_fh = tx_fh_if5; @@ -1687,8 +1688,8 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst case NGFI_RCC_IF4p5: eNB->do_prach = do_prach; eNB->fep = NULL; - eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2threads; + eNB->td = (single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data; + eNB->te = (single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_high; eNB->tx_fh = tx_fh_if4p5; @@ -1710,8 +1711,9 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst case NGFI_RAU_IF4p5: eNB->do_prach = do_prach; eNB->fep = NULL; - eNB->td = ulsch_decoding_data_2thread; - eNB->te = dlsch_encoding_2threads; + + eNB->td = (single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data; + eNB->te = (single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding; eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX; eNB->proc_tx = proc_tx_high; eNB->tx_fh = tx_fh_if4p5; From 574fbd661cf2288b9064b4e5f874f533722ade03 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 23 Sep 2016 16:38:20 +0200 Subject: [PATCH 191/206] activate TX path of UE --- targets/RT/USER/lte-ue.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 190951bf00..e1438e3b27 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -851,10 +851,10 @@ void *UE_thread(void *arg) { static int UE_thread_retval; PHY_VARS_UE *UE = PHY_vars_UE_g[0][0]; // int tx_enabled = 0; - unsigned int rxs; + unsigned int rxs,txs; int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32))); openair0_timestamp timestamp,timestamp1; - void* rxp[2]; + void* rxp[2], *txp[2]; #ifdef NAS_UE MessageDef *message_p; @@ -863,6 +863,7 @@ void *UE_thread(void *arg) { int start_rx_stream = 0; int rx_off_diff = 0; int rx_correction_timer = 0; + int i; #ifdef DEADLINE_SCHEDULER @@ -1033,9 +1034,24 @@ void *UE_thread(void *arg) { else { UE->proc.proc_rxtx[0].frame_rx++; UE->proc.proc_rxtx[1].frame_rx++; - + for (int sf=0;sf<10;sf++) { - for (int i=0; iframe_parms.nb_antennas_rx; i++) + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + + for (i=0; iframe_parms.nb_antennas_tx; i++) + txp[i] = (void*)&UE->common_vars.txdata[i][((sf+4)%10)*UE->frame_parms.samples_per_tti]; + + txs = UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+(4*UE->frame_parms.samples_per_tti)-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0-openair0_cfg[0].tx_sample_advance, + txp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_tx, + 1); + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + + for (i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (void*)&rxdata[i][UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti)]; // grab signal for subframe VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); @@ -1047,7 +1063,7 @@ void *UE_thread(void *arg) { UE->frame_parms.samples_per_tti, UE->frame_parms.nb_antennas_rx); } - + else { rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, @@ -1056,10 +1072,10 @@ void *UE_thread(void *arg) { UE->frame_parms.nb_antennas_rx); // read in first symbol of next frame and adjust for timing drift rxs = UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp1, - (void**)rxdata, - UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 - rx_off_diff, - UE->frame_parms.nb_antennas_rx); + ×tamp1, + (void**)rxdata, + UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 - rx_off_diff, + UE->frame_parms.nb_antennas_rx); rx_off_diff = 0; } } From 1edceeb6ea7a3cee6eba163f42304450edabd1e5 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 24 Sep 2016 19:58:24 +0200 Subject: [PATCH 192/206] config files fix for new params in enhancement-10-harmony branch --- .../GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf | 3 +++ .../GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf | 3 +++ .../GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf | 5 ++++- .../GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf | 3 +++ .../GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf | 3 +++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf index d0488f2d37..ac3c5fa290 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf @@ -22,6 +22,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf index ba753fb6f3..f50101a3e9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf index 1954662a10..115082c530 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf @@ -22,6 +22,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; @@ -46,7 +49,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -23; + pdsch_referenceSignalPower = -26; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf index 2d634a863b..dc4e65f47d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf index a68c65146f..f41df6bb76 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf @@ -22,6 +22,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; From 2098dcdd0a5ce4e8ab2eac4cea0aa470db8f2fcf Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 24 Sep 2016 21:06:19 +0200 Subject: [PATCH 193/206] Gitlab CI: minor fix to how processes are terminated --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index eed2fffb77..86f8f605c5 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -588,7 +588,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , RRH_pre_exec_args = testcase.findtext('RRH_pre_exec_args',default='') RRH_main_exec = testcase.findtext('RRH_main_exec',default='') RRH_main_exec_args = testcase.findtext('RRH_main_exec_args',default='') - RRH_terminate_missing_procs = testcase.findtext('RRH_terminate_missing_procs',default='True') + RRH_terminate_missing_procs = testcase.findtext('RRH_terminate_missing_procs',default='False') eNBMachine = testcase.findtext('eNB',default='') @@ -601,7 +601,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , eNB_main_exec_args = testcase.findtext('eNB_main_exec_args',default='') eNB_traffic_exec = testcase.findtext('eNB_traffic_exec',default='') eNB_traffic_exec_args = testcase.findtext('eNB_traffic_exec_args',default='') - eNB_terminate_missing_procs = testcase.findtext('eNB_terminate_missing_procs',default='True') + eNB_terminate_missing_procs = testcase.findtext('eNB_terminate_missing_procs',default='False') eNB_search_expr_true = testcase.findtext('eNB_search_expr_true','') if re.compile('\w+').match(eNB_search_expr_true) != None: eNB_search_expr_true = eNB_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's' @@ -616,7 +616,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , UE_main_exec_args = testcase.findtext('UE_main_exec_args',default='') UE_traffic_exec = testcase.findtext('UE_traffic_exec',default='') UE_traffic_exec_args = testcase.findtext('UE_traffic_exec_args',default='') - UE_terminate_missing_procs = testcase.findtext('UE_terminate_missing_procs',default='True') + UE_terminate_missing_procs = testcase.findtext('UE_terminate_missing_procs',default='False') UE_search_expr_true = testcase.findtext('UE_search_expr_true','') UE_stop_script = testcase.findtext('UE_stop_script','') if re.compile('\w+').match(UE_search_expr_true) != None: @@ -637,7 +637,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , HSS_main_exec_args = testcase.findtext('HSS_main_exec_args',default='') EPC_traffic_exec = testcase.findtext('EPC_traffic_exec',default='') EPC_traffic_exec_args = testcase.findtext('EPC_traffic_exec_args',default='') - EPC_terminate_missing_procs = testcase.findtext('EPC_terminate_missing_procs',default='True') + EPC_terminate_missing_procs = testcase.findtext('EPC_terminate_missing_procs',default='False') EPC_search_expr_true = testcase.findtext('EPC_search_expr_true','') if re.compile('\w+').match(EPC_search_expr_true) != None: EPC_search_expr_true = EPC_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's' From a4d3ec8dc455d23ae03a2112b137192051e52aaa Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 24 Sep 2016 21:14:31 +0200 Subject: [PATCH 194/206] Gitlab CI:minor fix to log directory creation --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 86f8f605c5..91c46728f1 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1304,6 +1304,8 @@ logdirOpenaircnRepo = logdir + 'openair-cn/' if flag_remove_logdir == True: print "Removing directory: " + locallogdir os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) +else: + oa.system('mkdir -p ' + locallogdir) paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log') res=os.system(' echo > ' + paramiko_logfile) From e584ce06c49de03eea27fe8d4f90e8fd066f43bb Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 24 Sep 2016 21:16:10 +0200 Subject: [PATCH 195/206] Gitlab CI:minor type in python script --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 91c46728f1..d128765a90 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1305,7 +1305,7 @@ if flag_remove_logdir == True: print "Removing directory: " + locallogdir os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) else: - oa.system('mkdir -p ' + locallogdir) + os.system('mkdir -p ' + locallogdir) paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log') res=os.system(' echo > ' + paramiko_logfile) From 829ee59707605bc137cbeac1cef91aaf520cf4ee Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 24 Sep 2016 22:03:35 -0700 Subject: [PATCH 196/206] fixes for oaisim, testing TM2 --- openair1/PHY/LTE_ESTIMATION/adjust_gain.c | 6 +-- openair1/SCHED/phy_procedures_lte_ue.c | 3 +- openair1/SIMULATION/RF/dac.c | 1 + targets/SIMU/USER/channel_sim.c | 51 ++++++++++++----------- targets/SIMU/USER/oaisim.c | 10 +++-- targets/SIMU/USER/oaisim_functions.c | 18 +++++--- 6 files changed, 50 insertions(+), 39 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c index da07687a9e..6b6d9e671d 100644 --- a/openair1/PHY/LTE_ESTIMATION/adjust_gain.c +++ b/openair1/PHY/LTE_ESTIMATION/adjust_gain.c @@ -35,9 +35,9 @@ phy_adjust_gain (PHY_VARS_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id) { LOG_D(PHY,"Gain control: rssi %d (%d,%d)\n", - rx_power_fil_dB, - ue->measurements.rssi, - ue->measurements.rx_power_avg_dB[eNB_id] + rx_power_fil_dB, + ue->measurements.rssi, + ue->measurements.rx_power_avg_dB[eNB_id] ); // Gain control with hysterisis diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 16872ec879..a74d921fa4 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -2735,6 +2735,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin } } // for l=1..l2 + ue_measurement_procedures(l-1,ue,proc,eNB_id,abstraction_flag,mode); // If this is PMCH, call procedures and return if (pmch_flag == 1) { @@ -2748,7 +2749,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->rx_offset, 0, 0); - + // first slot has been processed (FFTs + Channel Estimation, PCFICH/PHICH/PDCCH) // do procedures for C-RNTI diff --git a/openair1/SIMULATION/RF/dac.c b/openair1/SIMULATION/RF/dac.c index ba67eb1f32..8636353595 100755 --- a/openair1/SIMULATION/RF/dac.c +++ b/openair1/SIMULATION/RF/dac.c @@ -121,6 +121,7 @@ double dac_fixed_gain(double s_re[2][30720], //printf("DL: amp1 %f dB (%d,%d), tx_power %f\n",20*log10(amp1),input_offset,input_offset_meas,txpwr_dBm); */ + for (i=0; inb_rx; // number of rx antennas at UE uint8_t nb_antennas_tx = eNB2UE[0][0][CC_id]->nb_tx; // number of tx antennas at eNB - double s_re[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; - double s_im[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; - double r_re0[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; - double r_im0[2][PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + double s_re[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + double s_im[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + double r_re0[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + double r_im0[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; + if (subframe==0) hold_channel = 0; else @@ -205,13 +206,13 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N } } // hold channel } - else { //abstraction_flag pthread_mutex_lock(&eNB_output_mutex[UE_id]); + if (eNB_output_mask[UE_id] == 0) { // This is the first eNodeB for this UE, clear the buffer - + for (aa=0; aasamples_per_tti)*sizeof(double)); memset((void*)r_im_DL[UE_id][aa],0,(frame_parms->samples_per_tti)*sizeof(double)); @@ -222,8 +223,8 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N for (eNB_id=0; eNB_idcommon_vars.txdata[0]; sf_offset = subframe*frame_parms->samples_per_tti; - tx_pwr = dac_fixed_gain((double**)s_re, - (double**)s_im, + tx_pwr = dac_fixed_gain(s_re, + s_im, txdata, sf_offset, nb_antennas_tx, @@ -243,7 +244,7 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N #endif //eNB2UE[eNB_id][UE_id]->path_loss_dB = 0; - multipath_channel(eNB2UE[eNB_id][UE_id][CC_id],(double**)s_re,(double**)s_im,(double**)r_re0,(double**)r_im0, + multipath_channel(eNB2UE[eNB_id][UE_id][CC_id],s_re,s_im,r_re0,r_im0, frame_parms->samples_per_tti,hold_channel); #ifdef DEBUG_SIM rx_pwr = signal_energy_fp2(eNB2UE[eNB_id][UE_id][CC_id]->ch[0], @@ -266,7 +267,7 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB); #ifdef DEBUG_SIM - rx_pwr = signal_energy_fp((double**)r_re0,(double**)r_im0,nb_antennas_rx, + rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx, frame_parms->ofdm_symbol_size, sf_offset)/(12.0*frame_parms->N_RB_DL); LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr %f dBm/RE (%f dBm RSSI)for subframe %d\n",UE_id, @@ -289,15 +290,15 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB-66.227,subframe); #endif - rf_rx_simple((double**)r_re0, - (double**)r_im0, + rf_rx_simple(r_re0, + r_im0, nb_antennas_rx, frame_parms->samples_per_tti, 1e3/eNB2UE[eNB_id][UE_id][CC_id]->sampling_rate, // sampling time (ns) (double)PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) #ifdef DEBUG_SIM - rx_pwr = signal_energy_fp((double**)r_re0,(double**)r_im0, + rx_pwr = signal_energy_fp(r_re0,r_im0, nb_antennas_rx, frame_parms->ofdm_symbol_size, sf_offset)/(12.0*frame_parms->N_RB_DL); @@ -326,8 +327,8 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N rxdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.rxdata; sf_offset = subframe*frame_parms->samples_per_tti; - adc((double**)r_re_DL[UE_id], - (double**)r_im_DL[UE_id], + adc(r_re_DL[UE_id], + r_im_DL[UE_id], 0, sf_offset, rxdata, @@ -383,10 +384,10 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N int ulfrrb2 ; uint8_t harq_pid; #endif - double s_re[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; - double s_im[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; - double r_re0[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; - double r_im0[2][PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_re[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_im[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_re0[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_im0[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; if (abstraction_flag!=0) { #ifdef PHY_ABSTRACTION_UL @@ -477,7 +478,7 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N hold_channel,UE2eNB[UE_id][eNB_id][CC_id]->channel_length, UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB); - rx_pwr = signal_energy_fp((double**)r_re0,(double**)r_im0,nb_antennas_rx,frame_parms->samples_per_tti,0); + rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx,frame_parms->samples_per_tti,0); LOG_D(OCM,"[SIM][UL] eNB %d : rx_pwr %f dBm (%f) for subframe %d, sptti %d\n", eNB_id,10*log10(rx_pwr),rx_pwr,subframe,frame_parms->samples_per_tti); @@ -497,23 +498,23 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N } } //UE_id - rf_rx_simple((double**)r_re_UL[eNB_id], - (double**)r_im_UL[eNB_id], + rf_rx_simple(r_re_UL[eNB_id], + r_im_UL[eNB_id], nb_antennas_rx, frame_parms->samples_per_tti, 1e3/UE2eNB[0][eNB_id][CC_id]->sampling_rate, // sampling time (ns) (double)PHY_vars_eNB_g[eNB_id][CC_id]->rx_total_gain_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) #ifdef DEBUG_SIM - rx_pwr = signal_energy_fp((double**)r_re_UL[eNB_id],(double**)r_im_UL[eNB_id],nb_antennas_rx,frame_parms->samples_per_tti,0)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); + rx_pwr = signal_energy_fp(r_re_UL[eNB_id],r_im_UL[eNB_id],nb_antennas_rx,frame_parms->samples_per_tti,0)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); LOG_D(OCM,"[SIM][UL] rx_pwr (ADC in) %f dB for subframe %d\n",10*log10(rx_pwr),subframe); #endif rxdata = PHY_vars_eNB_g[eNB_id][CC_id]->common_vars.rxdata[0]; sf_offset = subframe*frame_parms->samples_per_tti; - adc((double**)r_re_UL[eNB_id], - (double**)r_im_UL[eNB_id], + adc(r_re_UL[eNB_id], + r_im_UL[eNB_id], 0, sf_offset, rxdata, diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c index c8214a0c65..345af74d18 100644 --- a/targets/SIMU/USER/oaisim.c +++ b/targets/SIMU/USER/oaisim.c @@ -749,7 +749,7 @@ l2l1_task (void *args_p) (subframe_UE_mask_local == ((1<proc[slot >> 1].subframe_tx, PHY_vars_eNB_g[eNB_inst][0]->proc[slot >> 1].subframe_rx, PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.frame_type, PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.tdd_config, PHY_vars_eNB_g[eNB_inst][0]->lte_frame_parms.Nid_cell); + */ } for (eNB_inst = oai_emulation.info.first_enb_local; @@ -1825,7 +1827,7 @@ oai_shutdown (void) free(txdata); #endif */ - + /* for (int i = 0; i < 2; i++) { free (s_re[i]); free (s_im[i]); @@ -1840,7 +1842,7 @@ oai_shutdown (void) s_re = 0; s_im = 0; r_re = 0; - r_im = 0; + r_im = 0;*/ lte_sync_time_free (); } diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 88e8ea3ce0..674ca1312d 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -1050,10 +1050,11 @@ int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void * eNB_id, CC_id); - last_eNB_rx_timestamp[eNB_id][CC_id] += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti; sample_count += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti; } + + return(nsamps); } @@ -1070,9 +1071,10 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id]; - LOG_D(PHY,"UE_trx_read nsamps %d TS(%llu,%llu)\n",nsamps, + LOG_D(EMU,"UE_trx_read nsamps %d TS(%llu,%llu) antenna %d\n",nsamps, (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id], - (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id]); + (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id], + cc); if (nsamps < PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) read_size = nsamps; @@ -1083,7 +1085,7 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** while (current_UE_rx_timestamp[UE_id][CC_id] < (last_UE_rx_timestamp[UE_id][CC_id]+read_size)) { LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]); - + usleep(500); } @@ -1093,7 +1095,7 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** pthread_mutex_lock(&subframe_mutex); subframe_UE_mask|=(1<frame_parms.samples_per_tti)%10; @@ -1117,8 +1119,12 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** &PHY_vars_UE_g[UE_id][CC_id]->frame_parms, UE_id, CC_id); + + printf("Signaling main thread: UE subframe mask %x\n",subframe_UE_mask); + } - + + return(nsamps); } From 3124cb2c0038245c057f991d81b7efbd903876e2 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 25 Sep 2016 14:53:16 +0200 Subject: [PATCH 197/206] more fixes for oaisim, TM2. --- openair1/PHY/TOOLS/defs.h | 4 +- openair1/PHY/TOOLS/signal_energy.c | 2 +- openair1/SIMULATION/RF/adc.c | 4 +- openair1/SIMULATION/RF/dac.c | 8 +- openair1/SIMULATION/RF/defs.h | 16 ++-- openair1/SIMULATION/RF/rf.c | 4 +- openair1/SIMULATION/TOOLS/defs.h | 16 ++-- openair1/SIMULATION/TOOLS/multipath_channel.c | 8 +- ...band7.tm1.generic.oaisim.local_no_mme.conf | 3 + targets/SIMU/USER/channel_sim.c | 85 ++++++++++++++----- targets/SIMU/USER/oaisim_functions.c | 1 - 11 files changed, 97 insertions(+), 54 deletions(-) diff --git a/openair1/PHY/TOOLS/defs.h b/openair1/PHY/TOOLS/defs.h index 3a8a58b6f2..fceb5972ed 100644 --- a/openair1/PHY/TOOLS/defs.h +++ b/openair1/PHY/TOOLS/defs.h @@ -296,10 +296,10 @@ int32_t subcarrier_energy(int32_t *,uint32_t, int32_t* subcarrier_energy, uint16 */ int32_t signal_energy_nodc(int32_t *,uint32_t); -/*!\fn double signal_energy_fp(double s_re[2][30720], double s_im[2][30720],uint32_t, uint32_t,uint32_t); +/*!\fn double signal_energy_fp(double *s_re[2], double *s_im[2],uint32_t, uint32_t,uint32_t); \brief Computes the signal energy per subcarrier */ -double signal_energy_fp(double s_re[2][30720], double s_im[2][30720], uint32_t nb_antennas, uint32_t length,uint32_t offset); +double signal_energy_fp(double *s_re[2], double *s_im[2], uint32_t nb_antennas, uint32_t length,uint32_t offset); /*!\fn double signal_energy_fp2(struct complex *, uint32_t); \brief Computes the signal energy per subcarrier diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c index afd1c727f3..4c5a4976f6 100755 --- a/openair1/PHY/TOOLS/signal_energy.c +++ b/openair1/PHY/TOOLS/signal_energy.c @@ -255,7 +255,7 @@ int32_t signal_energy_nodc(int32_t *input,uint32_t length) } #endif -double signal_energy_fp(double s_re[2][30720],double s_im[2][30720],uint32_t nb_antennas,uint32_t length,uint32_t offset) +double signal_energy_fp(double *s_re[2],double *s_im[2],uint32_t nb_antennas,uint32_t length,uint32_t offset) { int32_t aa,i; diff --git a/openair1/SIMULATION/RF/adc.c b/openair1/SIMULATION/RF/adc.c index 3f89a3cfe5..fb94b506d9 100755 --- a/openair1/SIMULATION/RF/adc.c +++ b/openair1/SIMULATION/RF/adc.c @@ -26,8 +26,8 @@ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ -void adc(double r_re[2][30720], - double r_im[2][30720], +void adc(double *r_re[2], + double *r_im[2], unsigned int input_offset, unsigned int output_offset, unsigned int **output, diff --git a/openair1/SIMULATION/RF/dac.c b/openair1/SIMULATION/RF/dac.c index 8636353595..fe01ba3132 100755 --- a/openair1/SIMULATION/RF/dac.c +++ b/openair1/SIMULATION/RF/dac.c @@ -31,8 +31,8 @@ #include #include "PHY/TOOLS/defs.h" -void dac(double s_re[2][30720], - double s_im[2][30720], +void dac(double *s_re[2], + double *s_im[2], uint32_t **input, uint32_t input_offset, uint32_t nb_tx_antennas, @@ -81,8 +81,8 @@ void dac(double s_re[2][30720], } } -double dac_fixed_gain(double s_re[2][30720], - double s_im[2][30720], +double dac_fixed_gain(double *s_re[2], + double *s_im[2], uint32_t **input, uint32_t input_offset, uint32_t nb_tx_antennas, diff --git a/openair1/SIMULATION/RF/defs.h b/openair1/SIMULATION/RF/defs.h index 4bd9528dae..75b84f3609 100644 --- a/openair1/SIMULATION/RF/defs.h +++ b/openair1/SIMULATION/RF/defs.h @@ -64,16 +64,16 @@ void rf_rx(double **r_re, double IQ_imb_dB, double IQ_phase); -void rf_rx_simple(double r_re[2][30720], - double r_im[2][30720], +void rf_rx_simple(double *r_re[2], + double *r_im[2], unsigned int nb_rx_antennas, unsigned int length, double s_time, double rx_gain_dB); -void adc(double r_re[2][30720], - double r_im[2][30720], +void adc(double *r_re[2], + double *r_im[2], unsigned int input_offset, unsigned int output_offset, int **output, @@ -81,8 +81,8 @@ void adc(double r_re[2][30720], unsigned int length, unsigned char B); -void dac(double s_re[2][30720], - double s_im[2][30720], +void dac(double *s_re[2], + double *s_im[2], int **input, unsigned int input_offset, unsigned int nb_tx_antennas, @@ -92,8 +92,8 @@ void dac(double s_re[2][30720], unsigned int meas_length, unsigned int meas_offset); -double dac_fixed_gain(double s_re[2][30720], - double s_im[2][30720], +double dac_fixed_gain(double *s_re[2], + double *s_im[2], int **input, unsigned int input_offset, unsigned int nb_tx_antennas, diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c index 2bcb64727d..135576b871 100644 --- a/openair1/SIMULATION/RF/rf.c +++ b/openair1/SIMULATION/RF/rf.c @@ -206,8 +206,8 @@ void rf_rx(double **r_re, } } -void rf_rx_simple(double r_re[2][30720], - double r_im[2][30720], +void rf_rx_simple(double *r_re[2], + double *r_im[2], unsigned int nb_rx_antennas, unsigned int length, double s_time, diff --git a/openair1/SIMULATION/TOOLS/defs.h b/openair1/SIMULATION/TOOLS/defs.h index 3ebc8f523f..3113fb3df5 100644 --- a/openair1/SIMULATION/TOOLS/defs.h +++ b/openair1/SIMULATION/TOOLS/defs.h @@ -219,10 +219,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); /**\fn void multipath_channel(channel_desc_t *desc, - double tx_sig_re[2][30720*2], - double tx_sig_im[2][30720*2], - double rx_sig_re[2][30720*2], - double rx_sig_im[2][30720*2], + double tx_sig_re[2], + double tx_sig_im[2], + double rx_sig_re[2], + double rx_sig_im[2], uint32_t length, uint8_t keep_channel) @@ -237,10 +237,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); */ void multipath_channel(channel_desc_t *desc, - double tx_sig_re[2][30720*2], - double tx_sig_im[2][30720*2], - double rx_sig_re[2][30720*2], - double rx_sig_im[2][30720*2], + double *tx_sig_re[2], + double *tx_sig_im[2], + double *rx_sig_re[2], + double *rx_sig_im[2], uint32_t length, uint8_t keep_channel); /* diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index 9019f4224f..549075c7db 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -150,10 +150,10 @@ void multipath_channel(channel_desc_t *desc, #else void multipath_channel(channel_desc_t *desc, - double tx_sig_re[2][30720*2], - double tx_sig_im[2][30720*2], - double rx_sig_re[2][30720*2], - double rx_sig_im[2][30720*2], + double *tx_sig_re[2], + double *tx_sig_im[2], + double *rx_sig_re[2], + double *rx_sig_im[2], uint32_t length, uint8_t keep_channel) { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf index 22654ebdbb..ef7c1cc19c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf @@ -23,6 +23,9 @@ eNBs = component_carriers = ( { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; frame_type = "FDD"; tdd_config = 3; tdd_config_s = 0; diff --git a/targets/SIMU/USER/channel_sim.c b/targets/SIMU/USER/channel_sim.c index e01f3d9b2d..c4df766532 100644 --- a/targets/SIMU/USER/channel_sim.c +++ b/targets/SIMU/USER/channel_sim.c @@ -108,12 +108,28 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N uint8_t nb_antennas_rx = eNB2UE[0][0][CC_id]->nb_rx; // number of rx antennas at UE uint8_t nb_antennas_tx = eNB2UE[0][0][CC_id]->nb_tx; // number of tx antennas at eNB - double s_re[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; - double s_im[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; - double r_re0[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; - double r_im0[2][30720];//PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti]; - + double s_re0[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_re1[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *s_re[2]; + double s_im0[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_im1[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *s_im[2]; + double r_re00[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_re01[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *r_re0[2]; + double r_im00[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_im01[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *r_im0[2]; + s_re[0] = s_re0; + s_im[0] = s_im0; + s_re[1] = s_re1; + s_im[1] = s_im1; + + r_re0[0] = r_re00; + r_im0[0] = r_im00; + r_re0[1] = r_re01; + r_im0[1] = r_im01; if (subframe==0) hold_channel = 0; @@ -318,17 +334,21 @@ void do_DL_sig(channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_N if (eNB_output_mask[UE_id] == (1<ofdm_symbol_size,sf_offset)/(12.0*frame_parms->N_RB_DL); + rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,frame_parms->ofdm_symbol_size,sf_offset)/(12.0*frame_parms->N_RB_DL); LOG_D(OCM,"[SIM][DL] UE %d : ADC in %f dBm for subframe %d\n",UE_id,10*log10(rx_pwr),subframe); #endif rxdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.rxdata; sf_offset = subframe*frame_parms->samples_per_tti; - - adc(r_re_DL[UE_id], - r_im_DL[UE_id], + + + adc(r_re_p, + r_im_p, 0, sf_offset, rxdata, @@ -384,10 +404,28 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N int ulfrrb2 ; uint8_t harq_pid; #endif - double s_re[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; - double s_im[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; - double r_re0[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; - double r_im0[2][30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_re0[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_re1[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *s_re[2]; + double s_im0[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double s_im1[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *s_im[2]; + double r_re00[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_re01[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *r_re0[2]; + double r_im00[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double r_im01[30720];//PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti]; + double *r_im0[2]; + + s_re[0] = s_re0; + s_im[0] = s_im0; + s_re[1] = s_re1; + s_im[1] = s_im1; + + r_re0[0] = r_re00; + r_im0[0] = r_im00; + r_re0[1] = r_re01; + r_im0[1] = r_im01; if (abstraction_flag!=0) { #ifdef PHY_ABSTRACTION_UL @@ -447,7 +485,6 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe], subframe,sf_offset); } else { - tx_pwr = dac_fixed_gain((double**)s_re, (double**)s_im, txdata, @@ -466,8 +503,8 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe], subframe,sf_offset); - - multipath_channel(UE2eNB[UE_id][eNB_id][CC_id],(double**)s_re,(double**)s_im,(double**)r_re0,(double**)r_im0, + + multipath_channel(UE2eNB[UE_id][eNB_id][CC_id],s_re,s_im,r_re0,r_im0, frame_parms->samples_per_tti,hold_channel); @@ -498,23 +535,27 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N } } //UE_id - rf_rx_simple(r_re_UL[eNB_id], - r_im_UL[eNB_id], + double *r_re_p[2] = {r_re_UL[eNB_id][0],r_re_UL[eNB_id][1]}; + double *r_im_p[2] = {r_im_UL[eNB_id][0],r_im_UL[eNB_id][1]}; + + rf_rx_simple(r_re_p, + r_im_p, nb_antennas_rx, frame_parms->samples_per_tti, 1e3/UE2eNB[0][eNB_id][CC_id]->sampling_rate, // sampling time (ns) (double)PHY_vars_eNB_g[eNB_id][CC_id]->rx_total_gain_dB - 66.227); // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later) #ifdef DEBUG_SIM - rx_pwr = signal_energy_fp(r_re_UL[eNB_id],r_im_UL[eNB_id],nb_antennas_rx,frame_parms->samples_per_tti,0)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); + rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,frame_parms->samples_per_tti,0)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL); LOG_D(OCM,"[SIM][UL] rx_pwr (ADC in) %f dB for subframe %d\n",10*log10(rx_pwr),subframe); #endif rxdata = PHY_vars_eNB_g[eNB_id][CC_id]->common_vars.rxdata[0]; sf_offset = subframe*frame_parms->samples_per_tti; + - adc(r_re_UL[eNB_id], - r_im_UL[eNB_id], + adc(r_re_p, + r_im_p, 0, sf_offset, rxdata, diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c index 674ca1312d..97820d2886 100644 --- a/targets/SIMU/USER/oaisim_functions.c +++ b/targets/SIMU/USER/oaisim_functions.c @@ -1120,7 +1120,6 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void ** UE_id, CC_id); - printf("Signaling main thread: UE subframe mask %x\n",subframe_UE_mask); } From 2f00edeb8e13410a2694105bbee3d2695ea27221 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 26 Sep 2016 12:53:50 +0200 Subject: [PATCH 198/206] minor compilation fixes to BladeRF driver --- targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index 6cc1d8c5d2..48c24a0c04 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -902,8 +902,8 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t)); memset(brf, 0, sizeof(brf_state_t)); /* device specific */ - openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered - openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered + //openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered + //openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered openair0_cfg->iq_txshift = 0;// shift openair0_cfg->iq_rxrescale = 15;//rescale iqs @@ -912,22 +912,18 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { case 30720000: openair0_cfg->samples_per_packet = 2048; openair0_cfg->tx_sample_advance = 0; - openair0_cfg->tx_scheduling_advance = 8*openair0_cfg->samples_per_packet; break; case 15360000: openair0_cfg->samples_per_packet = 2048; openair0_cfg->tx_sample_advance = 0; - openair0_cfg->tx_scheduling_advance = 4*openair0_cfg->samples_per_packet; break; case 7680000: openair0_cfg->samples_per_packet = 1024; openair0_cfg->tx_sample_advance = 0; - openair0_cfg->tx_scheduling_advance = 4*openair0_cfg->samples_per_packet; break; case 1920000: openair0_cfg->samples_per_packet = 256; openair0_cfg->tx_sample_advance = 50; - openair0_cfg->tx_scheduling_advance = 8*openair0_cfg->samples_per_packet; break; default: printf("Error: unknown sampling rate %f\n",openair0_cfg->sample_rate); From ce9c87026dc061943ca6b30bde6d16f819924e9c Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 26 Sep 2016 13:05:48 +0200 Subject: [PATCH 199/206] minor compilation fixes to LMSSDR driver --- targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp index 4be796e588..485fe5c0b4 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -324,7 +324,7 @@ int trx_lms_start(openair0_device *device){ * \param card Index of the RF card to use * \returns 0 on success */ -int trx_lms_stop(int card) { +int trx_lms_stop(openair0_device *device) { /* LMS_DeviceClose(usbport); LMS_DeviceClose(comport); @@ -410,28 +410,24 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg){ openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].tx_bw = 30.72e6; openair0_cfg[0].rx_bw = 30.72e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 15360000: openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 45; openair0_cfg[0].tx_bw = 28e6; openair0_cfg[0].rx_bw = 10e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 7680000: openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 70; openair0_cfg[0].tx_bw = 28e6; openair0_cfg[0].rx_bw = 5.0e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 1920000: openair0_cfg[0].samples_per_packet = 256; openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].tx_bw = 1.25e6; openair0_cfg[0].rx_bw = 1.25e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; default: printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); From c7ae7540664f35800c490f020e5c9352d268e66d Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 26 Sep 2016 13:12:34 +0200 Subject: [PATCH 200/206] compilation fix for pbchsim --- openair1/SIMULATION/LTE_PHY/pbchsim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/pbchsim.c b/openair1/SIMULATION/LTE_PHY/pbchsim.c index 624ce7ad3e..c8d5b1161c 100644 --- a/openair1/SIMULATION/LTE_PHY/pbchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pbchsim.c @@ -353,8 +353,8 @@ int main(int argc, char **argv) eNB2->frame_parms.nushift=(Nid_cell+2)%6; eNB2->Mod_id=2; - phy_init_lte_eNB(eNB1,0,0,0); - phy_init_lte_eNB(eNB2,0,0,0); + phy_init_lte_eNB(eNB1,0,0); + phy_init_lte_eNB(eNB2,0,0); #ifdef XFORMS fl_initialize (&argc, argv, NULL, 0, 0); From 2d3333dd6b2522d2af7450178a538962f04f2ba8 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 26 Sep 2016 14:13:32 +0200 Subject: [PATCH 201/206] Gitlab CI: fix for cleaning memory only when critically low --- cmake_targets/autotests/tools/free_mem.bash | 22 ++++++++++++++++++++- cmake_targets/tools/build_helper | 3 ++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/tools/free_mem.bash b/cmake_targets/autotests/tools/free_mem.bash index 873d6121e7..f0a5b03d85 100755 --- a/cmake_targets/autotests/tools/free_mem.bash +++ b/cmake_targets/autotests/tools/free_mem.bash @@ -31,6 +31,26 @@ # \author Navid Nikaein, Rohit Gupta # To free unused memory else test setup runs out of memory -sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches ' + +mem_threshold=0.2 #If free memory is less than this threshold, then VM drop cache is called +mem_tot=`vmstat -s -S k |grep "total memory" | awk '{print $1}'` +mem_free=`vmstat -s -S k |grep "free memory" | awk '{print $1}'` + +mem_frac=`bc <<< "scale=4;$mem_free/$mem_tot"` +echo $mem_frac +#mem_frac=`bc <<< "scale=4;`echo $mem_free`/`echo $mem_tot`"` +echo "Total Memory = $mem_tot k " +echo "Free Memory = $mem_free k" +echo "Fraction free memory = $mem_frac " + +res=`bc <<< "$mem_frac < 0.2" ` + +echo "Comparison Result = $res" + +if [ "$res" == "1" ] +then + echo "Free memory less than threshold = $mem_threshold" + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches ' +fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 4ebe2be1b0..73df7cc640 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -284,7 +284,8 @@ check_install_additional_tools (){ wvdial \ python-numpy \ sshpass \ - nscd + nscd \ + bc $SUDO pip install paramiko $SUDO pip install pyroute2 From da100fb693eb5e30085eaf2e7944a3397a3ec71e Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 26 Sep 2016 14:21:35 +0200 Subject: [PATCH 202/206] add NTP for synch time between test setup machines --- cmake_targets/tools/build_helper | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 73df7cc640..b855b28e10 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -285,7 +285,8 @@ check_install_additional_tools (){ python-numpy \ sshpass \ nscd \ - bc + bc \ + ntp $SUDO pip install paramiko $SUDO pip install pyroute2 From 784c4e49410c7560c58cd2bc398491d38b494b45 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Mon, 26 Sep 2016 17:19:51 +0200 Subject: [PATCH 203/206] adding missing symbol to octave tools --- targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf.h | 1 + targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_config_exmimo.cc | 1 + targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc | 1 + .../EXMIMO/USERSPACE/OCTAVE/oarf_get_num_detected_cards.cc | 1 + targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_send_frame.cc | 1 + targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop.cc | 1 + .../ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop_without_reset.cc | 1 + targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m | 4 ++-- 8 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf.h diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf.h b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf.h new file mode 100644 index 0000000000..ba6f2b142f --- /dev/null +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf.h @@ -0,0 +1 @@ +volatile int oai_exit=0; diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_config_exmimo.cc b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_config_exmimo.cc index 4d0eef921b..367ac0b7f6 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_config_exmimo.cc +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_config_exmimo.cc @@ -36,6 +36,7 @@ #include #include "pcie_interface.h" +#include "oarf.h" extern "C" { #include "openair0_lib.h" diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc index 708910b4f7..c7190671eb 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc @@ -42,6 +42,7 @@ extern "C" { #include "openair0_lib.h" } +#include "oarf.h" #define FCNNAME "oarf_get_frame" diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_num_detected_cards.cc b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_num_detected_cards.cc index a26b6a0a67..b7d20d9d69 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_num_detected_cards.cc +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_num_detected_cards.cc @@ -39,6 +39,7 @@ extern "C" { #include "openair0_lib.h" } +#include "oarf.h" #define FCNNAME "oarf_get_num_detected_cards" diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_send_frame.cc b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_send_frame.cc index 75cdef67b2..659e6125be 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_send_frame.cc +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_send_frame.cc @@ -41,6 +41,7 @@ extern "C" { #include "openair0_lib.h" } +#include "oarf.h" #define FCNNAME "oarf_send_frame" diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop.cc b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop.cc index 03b4b5324d..8d5669e043 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop.cc +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop.cc @@ -40,6 +40,7 @@ extern "C" { #include "openair0_lib.h" } +#include "oarf.h" #define FCNNAME "oarf_stop" diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop_without_reset.cc b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop_without_reset.cc index 058a8bba3e..d6684b5c43 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop_without_reset.cc +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_stop_without_reset.cc @@ -39,6 +39,7 @@ extern "C" { #include "openair0_lib.h" } +#include "oarf.h" #define FCNNAME "oarf_stop_without_reset" diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m index ad33d26123..97fad27531 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m +++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m @@ -1,4 +1,4 @@ -fc = 1907600000; +fc = 2560000000 %fc = 1907600000; %fc = 859.5e6; @@ -6,7 +6,7 @@ rxgain=0; txgain=0; eNB_flag = 0; card = 0; -active_rf = [1 1 1 1]; +active_rf = [1 0 0 0]; autocal = [1 1 1 1]; resampling_factor = [2 2 2 2]; limeparms; From 265a2d01bdfa1ab8e3ad6e054b084746583b8cd9 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 26 Sep 2016 19:08:11 +0200 Subject: [PATCH 204/206] update USRP config files with calibration verified --- .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 2 +- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 2 +- .../CONF/enb.band7.tm1.usrpb210.conf | 2 +- .../CONF/enb.band7.tm2.100PRB.usrpb210.conf | 2 +- .../CONF/enb.band7.tm2.100PRB.usrpx310.conf | 2 +- .../CONF/enb.band7.tm2.50PRB.usrpb210.conf | 177 ++++++++++++++++++ .../CONF/enb.band7.tm2.50PRB.usrpx310.conf | 175 +++++++++++++++++ .../CONF/enb.band7.tm2.usrpb210.conf | 2 +- 8 files changed, 358 insertions(+), 6 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpx310.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index 6d4652183e..f4ed76a21e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -50,7 +50,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; + pdsch_referenceSignalPower = -30; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index b18055ed22..c3c88323aa 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -50,7 +50,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; + pdsch_referenceSignalPower = -27; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index b346a123e0..01cd014afc 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -50,7 +50,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; + pdsch_referenceSignalPower = -24; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf index f50101a3e9..325af1c830 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpb210.conf @@ -50,7 +50,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -32; + pdsch_referenceSignalPower = -33; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf index 115082c530..06b27ba63c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.100PRB.usrpx310.conf @@ -49,7 +49,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -26; + pdsch_referenceSignalPower = -24; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpb210.conf new file mode 100644 index 0000000000..39ff0481cc --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpb210.conf @@ -0,0 +1,177 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "94"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 2; + nb_antennas_tx = 2; + nb_antennas_rx = 2; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -30; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 2; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.171"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.150/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.150/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpx310.conf new file mode 100644 index 0000000000..71e4472306 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.50PRB.usrpx310.conf @@ -0,0 +1,175 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 2; + nb_antennas_tx = 2; + nb_antennas_rx = 2; + tx_gain = 32; + rx_gain = 116; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -21; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -108; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 2; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="debug"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf index dc4e65f47d..688840015d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf @@ -50,7 +50,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -28; + pdsch_referenceSignalPower = -27; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; From 460f01f6d3d6b0efd7d66988b2214ae451fcb7e2 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 27 Sep 2016 10:38:13 +0200 Subject: [PATCH 205/206] Gitlab CI test case modified file + disable cpu affinity --- cmake_targets/autotests/test_case_list.xml | 340 ++++++++++----------- cmake_targets/build_oai | 6 +- 2 files changed, 173 insertions(+), 173 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 947763e803..8235963c52 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -11,7 +11,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox exmimo_pci=`lspci -m | grep Xilinx`; if [ -n "$exmimo_pci" ] ; then $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; fi; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_huaweiE398_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue; uname -a; sudo -E dmesg 36000 - 010141 0102+ 010304 010305 0104+ 015502 015505 015508 015511 015514 015517 015518 015519 015520 015521 015522 015523 015602 015605 015702 015705 015802 015805 015808 015811 015814 015817 015818 015819 015820 015821 015822 015823 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 018502 018505 025502 025505 025508 025511 025514 025517 025518 025519 025520 025521 025522 025523 + 010141 0102+ 010301 010303 010304 010305 0104+ 015518 015519 015520 015521 015522 015523 015602 015605 015702 015705 015818 015819 015820 015821 015822 015823 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 018502 018505 025502 025518 025519 025520 025521 025522 025523 3 mozart hutch starsky stevens amerique calisson @@ -470,7 +470,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -s15 @@ -492,7 +492,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -a -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -a -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -a -s15 @@ -514,7 +514,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -s15 @@ -536,7 +536,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -a -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -a -s15 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -a -s15 @@ -558,7 +558,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -c26 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -c26 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -c26 @@ -580,7 +580,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -c26 -a -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -c26 -a -O $OPENAIR_LOGDIR/enb.band38.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -c26 -a @@ -601,7 +601,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -F -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -F -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -F -s15 @@ -622,7 +622,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -F -a -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -F -a -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -F -a -s15 @@ -643,7 +643,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -F -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -F -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -F -s15 @@ -664,7 +664,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -F -a -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -F -a -s15 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -F -a -s15 @@ -685,7 +685,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -F -c26 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -F -c26 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -F -c26 @@ -706,7 +706,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -F -c26 -a -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -F -c26 -a -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -F -c26 -a @@ -727,7 +727,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -l7 -Q3 -n 100 -b1 -u1 "Found MBSFNAreaConfiguration from eNB 0" segmentation fault|assertion|exiting|fatal @@ -743,7 +743,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -l7 -T mscbr -Q3 -n 100 -b1 -u1 "Received a multicast packet" segmentation fault|assertion|exiting|fatal @@ -759,7 +759,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -l7 -F -T mscbr -Q3 -n 100 -b1 -u1 "Received a multicast packet" segmentation fault|assertion|exiting|fatal @@ -775,7 +775,7 @@ --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash; $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 - $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 + sudo -E $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf -A AWGN -l7 -c43 -F -T mbvbr -Q4 -j1 -n120 "MTCH for sync area 1" segmentation fault|assertion|exiting|fatal @@ -791,7 +791,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_aes128_cmac_encrypt + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_aes128_cmac_encrypt --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -807,7 +807,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_aes128_ctr_decrypt + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_aes128_ctr_decrypt --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -823,7 +823,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_aes128_ctr_encrypt + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_aes128_ctr_encrypt --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -839,7 +839,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_kenb + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_kenb --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -855,7 +855,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -871,7 +871,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eea1 + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eea1 --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -887,7 +887,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eea2 + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eea2 --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -903,7 +903,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eia1 + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eia1 --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -919,7 +919,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eia1 + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_secu_knas_encrypt_eia1 --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -935,7 +935,7 @@ --core_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_kdf + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/test_kdf --verbose "finished with 0 errors" segmentation fault|assertion|exiting|fatal @@ -962,7 +962,7 @@ --phy_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/dlsim + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/dlsim -m5 -gF -s-1 -w1.0 -f.2 -n500 -B50 -c2 -z2 -O70 -L -m4 -gF -s0 -w1.0 -f.2 -n500 -B6 -c4 -z2 -O70 -m15 -gF -s6.7 -w1.0 -f.2 -n500 -B50 -c2 -z2 -O70 -L @@ -993,7 +993,7 @@ --phy_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/cmake_targets/lte-simulators/build/ulsim + $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte-simulators/build/ulsim -B25 -m5 -y1 -gN -x1 -s6 -w1.0 -e.1 -P -n500 -O70 -L -B25 -m16 -y1 -gN -x1 -s12 -w1.0 -e.1 -P -n500 -O70 -L -B50 -m5 -y1 -gN -x1 -s6 -w1.0 -e.1 -P -n500 -O70 -L @@ -1032,11 +1032,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -1107,11 +1107,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -1183,11 +1183,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -1257,11 +1257,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -1330,11 +1330,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -1405,11 +1405,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -1482,11 +1482,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -1559,11 +1559,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -1635,11 +1635,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -1711,11 +1711,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -1787,11 +1787,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -1864,11 +1864,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -1938,11 +1938,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -2013,11 +2013,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -2089,11 +2089,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -2163,11 +2163,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -2236,11 +2236,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -2311,11 +2311,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -2390,11 +2390,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -2467,11 +2467,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -2543,11 +2543,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -2619,11 +2619,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -2695,11 +2695,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -2772,11 +2772,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.19/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -3915,11 +3915,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -3987,11 +3987,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4059,11 +4059,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4131,11 +4131,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4202,11 +4202,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4241,7 +4241,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -b 33Mbits/s -i 1 -f m -u + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -b 32Mbits/s -i 1 -f m -u False @@ -4274,11 +4274,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4345,11 +4345,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4417,11 +4417,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4489,11 +4489,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4561,11 +4561,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4632,11 +4632,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4704,11 +4704,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf --single-thread @@ -4777,11 +4777,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -4851,11 +4851,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -4925,11 +4925,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -4999,11 +4999,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5072,11 +5072,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5146,11 +5146,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5219,11 +5219,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5293,11 +5293,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5367,11 +5367,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5441,11 +5441,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5514,11 +5514,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -5588,11 +5588,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + --eNB -w USRP -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpx310.conf --single-thread @@ -6145,17 +6145,17 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth6\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth6\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w EXMIMO -x -c + --eNB -w EXMIMO -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf --single-thread @@ -6223,11 +6223,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w EXMIMO -x -c + --eNB -w EXMIMO -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf --single-thread @@ -6368,11 +6368,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w EXMIMO -x -c + --eNB -w EXMIMO -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf --single-thread @@ -6387,7 +6387,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 10M -R + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m False sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue @@ -6407,7 +6407,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf3_script 5 lo -s -i 1 -f m + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -i 1 -u -f m -b 16M False @@ -6439,11 +6439,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w EXMIMO -x -c + --eNB -w EXMIMO -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf --single-thread @@ -6458,7 +6458,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 20M -R + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m False sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue @@ -6478,7 +6478,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf3_script 5 lo -s -i 1 -f m + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -i 1 -u -f m -b 32M False @@ -6510,11 +6510,11 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w EXMIMO -x -c + --eNB -w EXMIMO -x -c --disable-cpu-affinity $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf --single-thread @@ -6529,7 +6529,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m False sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue @@ -6549,7 +6549,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -u -b 10Mbits/s + OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -i 1 -u -f m -b 16M False @@ -8489,7 +8489,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -8564,7 +8564,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -8639,7 +8639,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -E + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -8713,7 +8713,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -8787,7 +8787,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -8823,7 +8823,7 @@ c /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -b 33Mbits/s -i 1 -f m -u + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 10 192.172.0.2 -c 192.172.0.2 -b 31Mbits/s -i 1 -f m -u False @@ -8862,7 +8862,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -E + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -8936,7 +8936,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -9011,7 +9011,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -9086,7 +9086,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -9160,7 +9160,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -9217,7 +9217,7 @@ c targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf N_RB_DL 50 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf downlink_frequency 2680000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf tx_gain 90 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf rx_gain 125 @@ -9234,7 +9234,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -9309,7 +9309,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -E -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf --single-thread @@ -9386,7 +9386,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -9463,7 +9463,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -9540,7 +9540,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -9616,7 +9616,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -9692,7 +9692,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -9769,7 +9769,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -9845,7 +9845,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -9923,7 +9923,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -10000,7 +10000,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -10076,7 +10076,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -10152,7 +10152,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread @@ -10229,7 +10229,7 @@ c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/cmake_targets/autotests/tools/run_gdb $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm2.usrpb210.conf --single-thread diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 63ce21f728..9a9209db2c 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -48,7 +48,7 @@ PRINT_STATS="False" VCD_TIMING="False" DEADLINE_SCHEDULER_FLAG_USER="False" FORCE_DEADLINE_SCHEDULER_FLAG_USER="" -CPU_AFFINITY_FLAG_USER="True" #Only valid when lowlatecy flag is set to False +CPU_AFFINITY_FLAG_USER="False" #Only valid when lowlatecy flag is set to False REL="Rel10" HW="None" TP="None" @@ -330,9 +330,9 @@ function main() { #By default: EXMIMO: enable if [ "$FORCE_DEADLINE_SCHEDULER_FLAG_USER" = "" ]; then if [ "$HW" = "EXMIMO" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="True" + DEADLINE_SCHEDULER_FLAG_USER="False" elif [ "$HW" = "ETHERNET" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="True" + DEADLINE_SCHEDULER_FLAG_USER="False" elif [ "$HW" = "OAI_USRP" ] ; then DEADLINE_SCHEDULER_FLAG_USER="False" elif [ "$HW" = "OAI_BLADERF" ] ; then From e08e2577f5033e887695fdb745cd3f799618f37f Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 27 Sep 2016 10:57:03 +0200 Subject: [PATCH 206/206] hotfix: bad copy from userspace by ExpressMIMO2 kernel driver The ExpressMIMO2 kernel driver did not use proper mechanisms to copy from user space. It is very surprising that it ever worked at all... This commit is a quick fix. It is not the end of the story and some more work may be needed if things don't work. The remaining issue is that we pass pointer addresses to the kernel as 32 bits values, but pointers are 64 bits values (on x86_64, our supported platform). Some checks have been put in place to detect if upper 32 bits of a pointer are not 0 and print a strong error message in case of problem, but no clean solution has been implemented. --- targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c | 41 +++++++++++++++---- .../EXMIMO/USERSPACE/OAI_FW_INIT/updatefw.c | 20 +++++++++ 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c b/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c index 4427f4c8af..ecedb562d7 100755 --- a/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c +++ b/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c @@ -179,6 +179,8 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd int tmp; + unsigned int user_args[4]; + static unsigned int update_firmware_command; static unsigned int update_firmware_address; static unsigned int update_firmware_length; @@ -328,15 +330,38 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd acknowledge with no limit */ #define MAX_IOCTL_ACK_CNT 500 - update_firmware_command = *((unsigned int*)arg); + /* 'arg' is an unsigned long and is supposed to be big enough + * to hold an address - this hypothesis is okay for i386 and x86_64 + * maybe not somewhere else + * this will probably fail with older kernels + * (works with 3.17 on x86_64) + */ + tmp = copy_from_user(&user_args, (void*)arg, 4*sizeof(unsigned int)); + if (tmp) { + printk("[openair][IOCTL] UPDATE_FIRMWARE: error copying parameters to kernel-space (%d bytes uncopied).\n", tmp); + return -1; + } + + update_firmware_command = user_args[0]; switch (update_firmware_command) { case UPDATE_FIRMWARE_TRANSFER_BLOCK: - update_firmware_address = ((unsigned int*)arg)[1]; - update_firmware_length = ((unsigned int*)arg)[2]; + update_firmware_address = user_args[1]; + update_firmware_length = user_args[2]; + + /* This is totally wrong on x86_64: a pointer is 64 bits and + * unsigned int is 32 bits. The userspace program has to ensure + * that its buffer address fits into 32 bits. + * If it proves a too strong requirement, we may change things + * in the future. + * The compiler emits a warning here. Do not remove this warning! + * This is to clearly remember this problem. + * If you require the compilation to work with zero warning, + * consider this one as an exception and find a proper workaround. + */ + update_firmware_ubuffer = user_args[3]; - update_firmware_ubuffer = (unsigned int*)((unsigned int*)arg)[3]; update_firmware_kbuffer = (unsigned int*)kmalloc(update_firmware_length * 4 /* 4 because kmalloc expects bytes */, GFP_KERNEL); @@ -390,8 +415,8 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd case UPDATE_FIRMWARE_CLEAR_BSS: - update_firmware_bss_address = ((unsigned int*)arg)[1]; - update_firmware_bss_size = ((unsigned int*)arg)[2]; + update_firmware_bss_address = user_args[1]; + update_firmware_bss_size = user_args[2]; sparc_tmp_0 = update_firmware_bss_address; sparc_tmp_1 = update_firmware_bss_size; @@ -411,8 +436,8 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd case UPDATE_FIRMWARE_START_EXECUTION: - update_firmware_start_address = ((unsigned int*)arg)[1]; - update_firmware_stack_pointer = ((unsigned int*)arg)[2]; + update_firmware_start_address = user_args[1]; + update_firmware_stack_pointer = user_args[2]; sparc_tmp_0 = update_firmware_start_address; sparc_tmp_1 = update_firmware_stack_pointer; diff --git a/targets/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT/updatefw.c b/targets/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT/updatefw.c index 692742c7cf..cd873725c0 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT/updatefw.c +++ b/targets/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT/updatefw.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include "openair_device.h" @@ -239,6 +240,18 @@ void find_and_transfer_section(char* section_name, unsigned int verboselevel) { /* Dynamically allocate a chunk of memory to store the section into. */ section_content = (char*)malloc(elf_Shdr.sh_size); + /* Fail if the address returned by malloc does not fit in 32 bits. + * The kernel driver gets this address as 32 bits and uses it to copy + * from userspace. If the address does not fit into 32 bits the kernel + * will copy garbage or fail to copy completely. + * To be reworked if things do not work on some setups. + */ + if (sizeof(char*) > 4 && (((uintptr_t)section_content)>>32)) { + fprintf(stderr, "FATAL ERROR: an internal serious problem has been encountered.\n"); + fprintf(stderr, "Contact the authors so as to solve this issue.\n"); + exit(-1); + } + if (!section_content) { fprintf(stderr, "Error: could not dynamically allocate %d bytes for section %s.\n", elf_Shdr.sh_size, SecNameStnTable + elf_Shdr.sh_name); @@ -281,6 +294,13 @@ void find_and_transfer_section(char* section_name, unsigned int verboselevel) { ioctl_params[0] = UPDATE_FIRMWARE_TRANSFER_BLOCK; ioctl_params[1] = elf_Shdr.sh_addr; ioctl_params[2] = elf_Shdr.sh_size / 4; + /* This is wrong on x86_64 because a pointer is 64 bits and + * an unsigned int is only 32 bits. + * The compiler emits a warning, but the test + * above on the value of section_content makes it work + * (hopefully). + * To be changed if things do not work. + */ ioctl_params[3] = (unsigned int)((unsigned int*)section_content); //invert4(ioctl_params[1]); //invert4(ioctl_params[2]);