/******************************************************************************* Eurecom OpenAirInterface Copyright(c) 1999 - 2011 Eurecom This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information Openair Admin: openair_admin@eurecom.fr Openair Tech : openair_tech@eurecom.fr Forums : http://forums.eurecom.fsr/openairinterface Address : Eurecom, 2229, route des crĂȘtes, 06560 Valbonne Sophia Antipolis, France *******************************************************************************/ /*! \file PHY/LTE_TRANSPORT/dci.c * \brief Implements PDCCH physical channel TX/RX procedures (36.211) and DCI encoding/decoding (36.212/36.213). Current LTE compliance V8.6 2009-03. * \author R. Knopp * \date 2011 * \version 0.1 * \company Eurecom * \email: knopp@eurecom.fr * \note * \warning */ #ifdef USER_MODE #include #include #include #endif #include "PHY/defs.h" #include "PHY/extern.h" #include "SCHED/defs.h" #include "SIMULATION/TOOLS/defs.h" // for taus #include #include #ifdef __SSE3__ #include #include #endif #include "assertions.h" //#define DEBUG_DCI_ENCODING 1 //#define DEBUG_DCI_DECODING 1 //#define DEBUG_PHY //#undef ALL_AGGREGATION #ifndef __SSE3__ __m128i zero2; #define _mm_abs_epi16(xmmx) _mm_xor_si128((xmmx),_mm_cmpgt_epi16(zero2,(xmmx))) #define _mm_sign_epi16(xmmx,xmmy) _mm_xor_si128((xmmx),_mm_cmpgt_epi16(zero2,(xmmy))) #endif //extern uint16_t phich_reg[MAX_NUM_PHICH_GROUPS][3]; //extern uint16_t pcfich_reg[4]; uint32_t check_phich_reg(LTE_DL_FRAME_PARMS *frame_parms,uint32_t kprime,uint8_t lprime,uint8_t mi) { uint16_t i; uint16_t Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48; uint16_t mprime; uint16_t *pcfich_reg = frame_parms->pcfich_reg; if ((lprime>0) && (frame_parms->Ncp==0) ) return(0); // printf("check_phich_reg : mi %d\n",mi); // compute REG based on symbol if ((lprime == 0)|| ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4))) mprime = kprime/6; else mprime = kprime>>2; // check if PCFICH uses mprime if ((lprime==0) && ((mprime == pcfich_reg[0]) || (mprime == pcfich_reg[1]) || (mprime == pcfich_reg[2]) || (mprime == pcfich_reg[3]))) { #ifdef DEBUG_DCI_ENCODING msg("[PHY] REG %d allocated to PCFICH\n",mprime); #endif return(1); } // handle Special subframe case for TDD !!! // printf("Checking phich_reg %d\n",mprime); if (mi > 0) { if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0) Ngroup_PHICH++; if (frame_parms->Ncp == 1) { Ngroup_PHICH<<=1; } for (i=0;iphich_reg[i][0]) || (mprime == frame_parms->phich_reg[i][1]) || (mprime == frame_parms->phich_reg[i][2])) { #ifdef DEBUG_DCI_ENCODING msg("[PHY] REG %d (lprime %d) allocated to PHICH\n",mprime,lprime); #endif return(1); } } } return(0); } uint16_t extract_crc(uint8_t *dci,uint8_t dci_len) { uint16_t crc16; // uint8_t i; /* uint8_t crc; crc = ((uint16_t *)dci)[DCI_LENGTH>>4]; printf("crc1: %x, shift %d (DCI_LENGTH %d)\n",crc,DCI_LENGTH&0xf,DCI_LENGTH); crc = (crc>>(DCI_LENGTH&0xf)); // clear crc bits ((uint16_t *)dci)[DCI_LENGTH>>4] &= (0xffff>>(16-(DCI_LENGTH&0xf))); printf("crc2: %x, dci0 %x\n",crc,((int16_t *)dci)[DCI_LENGTH>>4]); crc |= (((uint16_t *)dci)[1+(DCI_LENGTH>>4)])<<(16-(DCI_LENGTH&0xf)); // clear crc bits (((uint16_t *)dci)[1+(DCI_LENGTH>>4)]) = 0; printf("extract_crc: crc %x\n",crc); */ #ifdef DEBUG_DCI_DECODING msg("dci_crc (%x,%x,%x), dci_len&0x7=%d\n",dci[dci_len>>3],dci[1+(dci_len>>3)],dci[2+(dci_len>>3)], dci_len&0x7); #endif if ((dci_len&0x7) > 0) { ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)]<<(dci_len&0x7) | dci[2+(dci_len>>3)]>>(8-(dci_len&0x7)); ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)]<<(dci_len&0x7) | dci[1+(dci_len>>3)]>>(8-(dci_len&0x7)); } else { ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)]; ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)]; } #ifdef DEBUG_DCI_DECODING msg("dci_crc =>%x\n",crc16); #endif // dci[(dci_len>>3)]&=(0xffff<<(dci_len&0xf)); // dci[(dci_len>>3)+1] = 0; // dci[(dci_len>>3)+2] = 0; return((uint16_t)crc16); } static uint8_t d[3*(MAX_DCI_SIZE_BITS + 16) + 96]; static uint8_t w[3*3*(MAX_DCI_SIZE_BITS+16)]; void dci_encoding(uint8_t *a, uint8_t A, uint16_t E, uint8_t *e, uint16_t rnti) { uint8_t D = (A + 16); uint32_t RCC; #ifdef DEBUG_DCI_ENCODING int32_t i; #endif // encode dci #ifdef DEBUG_DCI_ENCODING msg("Doing DCI encoding for %d bits, e %p, rnti %x\n",A,e,rnti); #endif memset((void *)d,LTE_NULL,96); ccodelte_encode(A,2,a,d+96,rnti); #ifdef DEBUG_DCI_ENCODING for (i=0;i<16+A;i++) msg("%d : (%d,%d,%d)\n",i,*(d+96+(3*i)),*(d+97+(3*i)),*(d+98+(3*i))); #endif #ifdef DEBUG_DCI_ENCODING msg("Doing DCI interleaving for %d coded bits, e %p\n",D*3,e); #endif RCC = sub_block_interleaving_cc(D,d+96,w); #ifdef DEBUG_DCI_ENCODING msg("Doing DCI rate matching for %d channel bits, RCC %d, e %p\n",E,RCC,e); #endif lte_rate_matching_cc(RCC,E,w,e); } uint8_t *generate_dci0(uint8_t *dci, uint8_t *e, uint8_t DCI_LENGTH, uint8_t aggregation_level, uint16_t rnti) { uint16_t coded_bits; uint8_t dci_flip[8]; if (aggregation_level>3) { msg("dci.c: generate_dci FATAL, illegal aggregation_level %d\n",aggregation_level); return NULL; } coded_bits = 72 * (1<>5), ND; uint32_t row,col,Kpi,index; int32_t i,k,a; #ifdef RM_DEBUG int32_t nulled=0; #endif // msg("[PHY] PDCCH Interleaving Mquad %d (Nsymb %d)\n",Mquad,n_symbols_pdcch); if ((Mquad&0x1f) > 0) RCC++; Kpi = (RCC<<5); ND = Kpi - Mquad; k=0; for (col=0;col<32;col++) { index = bitrev_cc_dci[col]; for (row=0;row=ND) { for (a=0;anb_antennas_tx_eNB;a++){ //msg("a %d k %d\n",a,k); wptr = &wtemp[a][k<<2]; zptr = &z[a][(index-ND)<<2]; //msg("wptr=%p, zptr=%p\n",wptr,zptr); wptr[0] = zptr[0]; wptr[1] = zptr[1]; wptr[2] = zptr[2]; wptr[3] = zptr[3]; } k++; } index+=32; } } // permutation for (i=0;inb_antennas_tx_eNB;a++) { //wptr = &wtemp[a][i<<2]; //wptr2 = &wbar[a][((i+frame_parms->Nid_cell)%Mquad)<<2]; wptr = &wtemp[a][((i+frame_parms->Nid_cell)%Mquad)<<2]; wptr2 = &wbar[a][i<<2]; wptr2[0] = wptr[0]; wptr2[1] = wptr[1]; wptr2[2] = wptr[2]; wptr2[3] = wptr[3]; } } } void pdcch_demapping(uint16_t *llr,uint16_t *wbar,LTE_DL_FRAME_PARMS *frame_parms,uint8_t num_pdcch_symbols,uint8_t mi) { uint32_t i, lprime; uint16_t kprime,kprime_mod12,mprime,symbol_offset,tti_offset,tti_offset0; int16_t re_offset,re_offset0; // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5 int Msymb2; switch (frame_parms->N_RB_DL) { case 100: Msymb2 = Msymb; break; case 75: Msymb2 = 3*Msymb/4; break; case 50: Msymb2 = Msymb>>1; break; case 25: Msymb2 = Msymb>>2; break; case 15: Msymb2 = Msymb*15/100; break; case 6: Msymb2 = Msymb*6/100; break; default: Msymb2 = Msymb>>2; break; } mprime=0; re_offset = 0; re_offset0 = 0; // counter for symbol with pilots (extracted outside!) for (kprime=0;kprimeN_RB_DL*12;kprime++) { for (lprime=0;lprimeN_RB_DL*12*lprime; tti_offset = symbol_offset + re_offset; tti_offset0 = symbol_offset + re_offset0; // if REG is allocated to PHICH, skip it if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) { //msg("dci_demapping : skipping REG %d\n",(lprime==0)?kprime/6 : kprime>>2); if ((lprime == 0)&&((kprime%6)==0)) re_offset0+=4; } else { // not allocated to PHICH/PCFICH // msg("dci_demapping: REG %d\n",(lprime==0)?kprime/6 : kprime>>2); if (lprime == 0) { // first symbol, or second symbol+4 TX antennas skip pilots kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 6)) { // kprime represents REG for (i=0;i<4;i++) { wbar[mprime] = llr[tti_offset0+i]; #ifdef DEBUG_DCI_DECODING msg("[PHY] PDCCH demapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset0,symbol_offset,re_offset0,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime])); #endif mprime++; re_offset0++; } } } else if ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4)) { // LATER!!!! } else { // no pilots in this symbol kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) { // kprime represents REG for (i=0;i<4;i++) { wbar[mprime] = llr[tti_offset+i]; #ifdef DEBUG_DCI_DECODING msg("[PHY] PDCCH demapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime])); #endif mprime++; } } // is representative } // no pilots case } // not allocated to PHICH/PCFICH // Stop when all REGs are copied in if (mprime>=Msymb2) break; } //lprime loop re_offset++; } // kprime loop } static uint16_t wtemp_rx[Msymb]; void pdcch_deinterleaving(LTE_DL_FRAME_PARMS *frame_parms,uint16_t *z, uint16_t *wbar,uint8_t number_pdcch_symbols,uint8_t mi) { uint16_t *wptr,*zptr,*wptr2; uint16_t Mquad=get_nquad(number_pdcch_symbols,frame_parms,mi); uint32_t RCC = (Mquad>>5), ND; uint32_t row,col,Kpi,index; int32_t i,k; // printf("Mquad %d, RCC %d\n",Mquad,RCC); if (!z) { msg("dci.c: pdcch_deinterleaving: FATAL z is Null\n"); return; } // undo permutation for (i=0;iNid_cell)%Mquad)<<2]; wptr = &wtemp_rx[((i+frame_parms->Nid_cell)%Mquad)<<2]; wptr2 = &wbar[i<<2]; wptr[0] = wptr2[0]; wptr[1] = wptr2[1]; wptr[2] = wptr2[2]; wptr[3] = wptr2[3]; /* msg("pdcch_deinterleaving (%p,%p): quad %d -> (%d,%d %d,%d %d,%d %d,%d)\n",wptr,wptr2,i, ((char*)wptr2)[0], ((char*)wptr2)[1], ((char*)wptr2)[2], ((char*)wptr2)[3], ((char*)wptr2)[4], ((char*)wptr2)[5], ((char*)wptr2)[6], ((char*)wptr2)[7]); */ } if ((Mquad&0x1f) > 0) RCC++; Kpi = (RCC<<5); ND = Kpi - Mquad; k=0; for (col=0;col<32;col++) { index = bitrev_cc_dci[col]; for (row=0;row=ND) { wptr = &wtemp_rx[k<<2]; zptr = &z[(index-ND)<<2]; zptr[0] = wptr[0]; zptr[1] = wptr[1]; zptr[2] = wptr[2]; zptr[3] = wptr[3]; /* printf("deinterleaving ; k %d, index-Nd %d => (%d,%d,%d,%d,%d,%d,%d,%d)\n",k,(index-ND), ((int8_t *)wptr)[0], ((int8_t *)wptr)[1], ((int8_t *)wptr)[2], ((int8_t *)wptr)[3], ((int8_t *)wptr)[4], ((int8_t *)wptr)[5], ((int8_t *)wptr)[6], ((int8_t *)wptr)[7]); */ k++; } index+=32; } } for (i=0;i (%d,%d,%d,%d,%d,%d,%d,%d)\n",i, ((int8_t *)zptr)[0], ((int8_t *)zptr)[1], ((int8_t *)zptr)[2], ((int8_t *)zptr)[3], ((int8_t *)zptr)[4], ((int8_t *)zptr)[5], ((int8_t *)zptr)[6], ((int8_t *)zptr)[7]); */ } } int32_t pdcch_qpsk_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int32_t **rxdataF_comp_i, int32_t **rho_i, int16_t *pdcch_llr16, int16_t *pdcch_llr8in, uint8_t symbol) { __m128i *rxF=(__m128i*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; __m128i *rxF_i=(__m128i*)&rxdataF_comp_i[0][(symbol*frame_parms->N_RB_DL*12)]; __m128i *rho=(__m128i*)&rho_i[0][(symbol*frame_parms->N_RB_DL*12)]; __m128i *llr128; int32_t i; char *pdcch_llr8; int16_t *pdcch_llr; pdcch_llr8 = (char *)&pdcch_llr8in[symbol*frame_parms->N_RB_DL*12]; pdcch_llr = &pdcch_llr16[symbol*frame_parms->N_RB_DL*12]; // printf("dlsch_qpsk_qpsk: symbol %d\n",symbol); llr128 = (__m128i*)pdcch_llr; if (!llr128) { msg("dlsch_qpsk_qpsk_llr: llr is null, symbol %d\n",symbol); return -1; } qpsk_qpsk((int16_t *)rxF, (int16_t *)rxF_i, (int16_t *)llr128, (int16_t *)rho, frame_parms->N_RB_DL*12); //prepare for Viterbi which accepts 8 bit, but prefers 4 bit, soft input. for (i=0;i<(frame_parms->N_RB_DL*24);i++) { if (*pdcch_llr>7) *pdcch_llr8=7; else if (*pdcch_llr<-8) *pdcch_llr8=-8; else *pdcch_llr8 = (char)(*pdcch_llr); pdcch_llr++; pdcch_llr8++; } return(0); } int32_t pdcch_llr(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, char *pdcch_llr, uint8_t symbol) { int16_t *rxF= (int16_t*) &rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; int32_t i; char *pdcch_llr8; pdcch_llr8 = &pdcch_llr[2*symbol*frame_parms->N_RB_DL*12]; if (!pdcch_llr8) { msg("pdcch_qpsk_llr: llr is null, symbol %d\n",symbol); return(-1); } // msg("pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llr8-pdcch_llr); for (i=0;i<(frame_parms->N_RB_DL*((symbol==0) ? 16 : 24));i++) { if (*rxF>31) *pdcch_llr8=31; else if (*rxF<-32) *pdcch_llr8=-32; else *pdcch_llr8 = (char)(*rxF); // printf("%d %d => %d\n",i,*rxF,*pdcch_llr8); rxF++; pdcch_llr8++; } return(0); } __m128i avg128P; //compute average channel_level on each (TX,RX) antenna pair void pdcch_channel_level(int32_t **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, int32_t *avg, uint8_t nb_rb) { int16_t rb; uint8_t aatx,aarx; __m128i *dl_ch128; for (aatx=0;aatxnb_antennas_tx_eNB;aatx++) for (aarx=0;aarxnb_antennas_rx;aarx++) { //clear average level avg128P = _mm_xor_si128(avg128P,avg128P); dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][frame_parms->N_RB_DL*12]; for (rb=0;rbnb_antennas_rx;aarx++) { dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128i = (__m128i *)&dl_ch_estimates_ext_i[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_rho128 = (__m128i *)&dl_ch_rho_ext[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rbN_RB_DL;rb++) { // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128i[0]); // print_ints("re",&mmtmpPD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpPD1); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); // print_ints("re(shift)",&mmtmpPD0); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); // print_ints("im(shift)",&mmtmpPD1); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); // print_ints("c0",&mmtmpPD2); // print_ints("c1",&mmtmpPD3); dl_ch_rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rho128); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[1]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); dl_ch_rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rho128+1); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[2]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); dl_ch_rho128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rho128+2); dl_ch128+=3; dl_ch128i+=3; dl_ch_rho128+=3; } } _mm_empty(); _m_empty(); } void pdcch_detection_mrc_i(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int32_t **rxdataF_comp_i, int32_t **rho, int32_t **rho_i, uint8_t symbol) { uint8_t aatx; __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1; int32_t i; if (frame_parms->nb_antennas_rx>1) { for (aatx=0;aatxnb_antennas_tx_eNB;aatx++) { //if (frame_parms->mode1_flag && (aatx>0)) break; rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb on MF output for (i=0;iN_RB_DL*3;i++) { rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); } } rho128_0 = (__m128i *) &rho[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12]; for (i=0;iN_RB_DL*3;i++) { rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); } rho128_i0 = (__m128i *) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; rho128_i1 = (__m128i *) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i0 = (__m128i *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i1 = (__m128i *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb on MF and rho for (i=0;iN_RB_DL*3;i++) { rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i1[i],1)); rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1)); } } _mm_empty(); _m_empty(); } void pdcch_extract_rbs_single(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, uint8_t symbol, LTE_DL_FRAME_PARMS *frame_parms) { uint16_t rb,nb_rb=0; uint8_t i,j,aarx; int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; int nushiftmod3 = frame_parms->nushift%3; uint8_t symbol_mod; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; #ifdef DEBUG_DCI_DECODING msg("[PHY] extract_rbs_single: symbol_mod %d\n",symbol_mod); #endif for (aarx=0;aarxnb_antennas_rx;aarx++) { dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; #ifndef NEW_FFT rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs for (rb=0;rbN_RB_DL;rb++) { // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { #ifndef NEW_FFT rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif //dl_ch0++; } if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); for (i=0;i<12;i++) { #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif } nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { j=0; for (i=0;i<12;i++) { if ((i!=nushiftmod3) && (i!=(nushiftmod3+3)) && (i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } } } else { // Odd number of RBs for (rb=0;rbN_RB_DL>>1;rb++) { if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { j=0; for (i=0;i<12;i++) { if ((i!=nushiftmod3) && (i!=(nushiftmod3+3)) && (i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } } // Do middle RB (around DC) // msg("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); if (symbol_mod==0) { j=0; for (i=0;i<6;i++) { if ((i!=nushiftmod3) && (i!=(nushiftmod3+3))){ dl_ch0_ext[j]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[i<<1]; #else rxF_ext[j++]=rxF[i]; #endif // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif for (;i<12;i++) { if ((i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))){ dl_ch0_ext[j]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[(1+i-6)<<1]; #else rxF_ext[j++]=rxF[(1+i-6)]; #endif // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; #ifndef NEW_FFT rxF+=14; #else rxF+=7; #endif rb++; } else { for (i=0;i<6;i++) { dl_ch0_ext[i]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif } #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif for (;i<12;i++) { dl_ch0_ext[i]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[(1+i-6)<<1]; #else rxF_ext[i]=rxF[(1+i-6)]; #endif } nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; #ifndef NEW_FFT rxF+=14; #else rxF+=7; #endif rb++; } for (;rbN_RB_DL;rb++) { if (symbol_mod > 0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { j=0; for (i=0;i<12;i++) { if ((i!=(nushiftmod3)) && (i!=(nushiftmod3+3)) && (i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } } } } _mm_empty(); _m_empty(); } void pdcch_extract_rbs_dual(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, uint8_t symbol, LTE_DL_FRAME_PARMS *frame_parms) { uint16_t rb,nb_rb=0; uint8_t i,aarx,j; int32_t *dl_ch0,*dl_ch0_ext,*dl_ch1,*dl_ch1_ext,*rxF,*rxF_ext; uint8_t symbol_mod; int nushiftmod3 = frame_parms->nushift%3; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; for (aarx=0;aarxnb_antennas_rx;aarx++) { dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; dl_ch1 = &dl_ch_estimates[2+aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch1_ext = &dl_ch_estimates_ext[2+aarx][symbol*(frame_parms->N_RB_DL*12)]; // msg("pdcch extract_rbs: rxF_ext pos %d\n",symbol*(frame_parms->N_RB_DL*12)); rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; #ifndef NEW_FFT rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs for (rb=0;rbN_RB_DL;rb++) { // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { #ifndef NEW_FFT rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif //dl_ch0++; //dl_ch1++; } if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); /* msg("rb %d\n",rb); for (i=0;i<12;i++) msg("(%d %d)",((int16_t *)dl_ch)[i<<1],((int16_t*)dl_ch)[1+(i<<1)]); msg("\n");*/ for (i=0;i<12;i++) { #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif // msg("%d : (%d,%d)\n",(rxF+(2*i)-&rxdataF[aarx][( (symbol*(frame_parms->ofdm_symbol_size)))*2])/2, // ((int16_t*)&rxF[i<<1])[0],((int16_t*)&rxF[i<<1])[0]); } nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; } else { j=0; for (i=0;i<12;i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+9)) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { // Odd number of RBs for (rb=0;rbN_RB_DL>>1;rb++) { // msg("rb %d: %d\n",rb,rxF-&rxdataF[aarx][(symbol*(frame_parms->ofdm_symbol_size))*2]); if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { j=0; for (i=0;i<12;i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+9)) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } } // Do middle RB (around DC) if (symbol_mod > 0) { for (i=0;i<6;i++) { dl_ch0_ext[i]=dl_ch0[i]; dl_ch1_ext[i]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif } #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif for (;i<12;i++) { dl_ch0_ext[i]=dl_ch0[i]; dl_ch1_ext[i]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[(1+i)<<1]; #else rxF_ext[i]=rxF[(1+i)]; #endif } nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=14; #else rxF+=7; #endif rb++; } else { j=0; for (i=0;i<6;i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3)){ dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[i<<1]; #else rxF_ext[j++]=rxF[i]; #endif // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif for (;i<12;i++) { if ((i!=nushiftmod3+6) && (i!=nushiftmod3+9)){ dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[(1+i-6)<<1]; #else rxF_ext[j++]=rxF[(1+i-6)]; #endif // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=14; #else rxF+=7; #endif rb++; } for (;rbN_RB_DL;rb++) { if (symbol_mod>0) { // msg("rb %d: %d\n",rb,rxF-&rxdataF[aarx][(symbol*(frame_parms->ofdm_symbol_size))*2]); memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { j=0; for (i=0;i<12;i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+9)) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } } } } _mm_empty(); _m_empty(); } void pdcch_channel_compensation(int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, int32_t **rxdataF_comp, int32_t **rho, LTE_DL_FRAME_PARMS *frame_parms, uint8_t symbol, uint8_t output_shift) { uint16_t rb; __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; __m128i *dl_ch128_2, *rho128; uint8_t aatx,aarx,pilots=0; #ifndef __SSE3__ zero2 = _mm_xor_si128(zero2,zero2); #endif #ifdef DEBUG_DCI_DECODING msg("[PHY] PDCCH comp: symbol %d\n",symbol); #endif if (symbol==0) pilots=1; for (aatx=0;aatxnb_antennas_tx_eNB;aatx++) { //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antennas_tx_eNB for (aarx=0;aarxnb_antennas_rx;aarx++) { dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rbN_RB_DL;rb++) { // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); // print_ints("re",&mmtmpPD0); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpPD1); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[0]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); // print_ints("re(shift)",&mmtmpPD0); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); // print_ints("im(shift)",&mmtmpPD1); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); // print_ints("c0",&mmtmpPD2); // print_ints("c1",&mmtmpPD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[1]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rxdataF_comp128+1); // multiply by conjugated channel if (pilots == 0) { mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[2]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); } // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch128+2); // print_shorts("pack:",rxdataF_comp128+2); if (pilots==0) { dl_ch128+=3; rxdataF128+=3; rxdataF_comp128+=3; } else { dl_ch128+=2; rxdataF128+=2; rxdataF_comp128+=2; } } } } if (rho) { for (aarx=0;aarxnb_antennas_rx;aarx++) { rho128 = (__m128i *)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_2 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rbN_RB_DL;rb++) { // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128_2[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpPD1); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[0]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); // print_ints("c0",&mmtmpPD2); // print_ints("c1",&mmtmpPD3); rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rho128); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128_2[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rho128+1); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128_2[2]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[2]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rho128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rho128+2); dl_ch128+=3; dl_ch128_2+=3; rho128+=3; } } } _mm_empty(); _m_empty(); } void pdcch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, uint8_t symbol) { uint8_t aatx; __m128i *rxdataF_comp128_0,*rxdataF_comp128_1; int32_t i; if (frame_parms->nb_antennas_rx>1) { for (aatx=0;aatxnb_antennas_tx_eNB;aatx++) { rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb for (i=0;iN_RB_DL*3;i++) { rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); } } } _mm_empty(); _m_empty(); } void pdcch_siso(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, uint8_t l) { uint8_t rb,re,jj,ii; jj=0; ii=0; for (rb=0;rbN_RB_DL;rb++) { for (re=0;re<12;re++) { rxdataF_comp[0][jj++] = rxdataF_comp[0][ii]; ii++; } } } void pdcch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, uint8_t symbol){ int16_t *rxF0,*rxF1; uint8_t rb,re; int32_t jj=(symbol*frame_parms->N_RB_DL*12); rxF0 = (int16_t*)&rxdataF_comp[0][jj]; //tx antenna 0 h0*y rxF1 = (int16_t*)&rxdataF_comp[2][jj]; //tx antenna 1 h1*y for (rb=0;rbN_RB_DL;rb++) { for (re=0;re<12;re+=2) { // Alamouti RX combining rxF0[0] = rxF0[0] + rxF1[2]; rxF0[1] = rxF0[1] - rxF1[3]; rxF0[2] = rxF0[2] - rxF1[0]; rxF0[3] = rxF0[3] + rxF1[1]; rxF0+=4; rxF1+=4; } } _mm_empty(); _m_empty(); } int32_t avgP[4]; int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars, LTE_UE_PDCCH **lte_ue_pdcch_vars, LTE_DL_FRAME_PARMS *frame_parms, uint8_t subframe, uint8_t eNB_id, MIMO_mode_t mimo_mode, uint8_t is_secondary_ue) { uint8_t log2_maxh,aatx,aarx; #ifdef MU_RECEIVER 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 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, s, 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 s, 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, s, 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, s, frame_parms); } } pdcch_channel_level(lte_ue_pdcch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avgP, frame_parms->N_RB_DL); avgs = 0; for (aatx=0;aatxnb_antennas_tx_eNB;aatx++) for (aarx=0;aarxnb_antennas_rx;aarx++) avgs = cmax(avgs,avgP[(aarx<<1)+aatx]); log2_maxh = (log2_approx(avgs)/2) + 2 + frame_parms->nb_antennas_rx - 1; #ifdef DEBUG_PHY msg("[PDCCH] log2_maxh = %d (%d,%d)\n",log2_maxh,avgP[0],avgs); #endif 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, frame_parms, s, log2_maxh); // log2_maxh+I0_shift #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); #endif #ifdef MU_RECEIVER 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, 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); #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, log2_maxh); } #endif //MU_RECEIVER if (frame_parms->nb_antennas_rx > 1) { #ifdef MU_RECEIVER 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, 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); #endif } else #endif //MU_RECEIVER pdcch_detection_mrc(frame_parms, lte_ue_pdcch_vars[eNB_id]->rxdataF_comp, s); } if (mimo_mode == SISO) pdcch_siso(frame_parms,lte_ue_pdcch_vars[eNB_id]->rxdataF_comp,s); else pdcch_alamouti(frame_parms,lte_ue_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, 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("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); #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, 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); #endif #ifdef MU_RECEIVER } #endif //MU_RECEIVER } // decode pcfich here n_pdcch_symbols = rx_pcfich(frame_parms, subframe, lte_ue_pdcch_vars[eNB_id], mimo_mode); if (n_pdcch_symbols>3) n_pdcch_symbols=1; #ifdef DEBUG_DCI_DECODING msg("[PDCCH] subframe %d n_pdcch_symbols from PCFICH =%d\n",subframe,n_pdcch_symbols); msg("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, 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, n_pdcch_symbols, mi); pdcch_unscrambling(frame_parms, subframe, lte_ue_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; return(0); } void pdcch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, uint8_t subframe, uint8_t *e, uint32_t length) { int i; uint8_t reset; uint32_t x1, x2, s=0; reset = 1; // x1 is set in lte_gold_generic x2 = (subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 for (i=0; i>(i&0x1f))&1)); if (e[i] != 2) // element is 2 e[i] = (e[i]&1) ^ ((s>>(i&0x1f))&1); } } void pdcch_unscrambling(LTE_DL_FRAME_PARMS *frame_parms, uint8_t subframe, int8_t* llr, uint32_t length) { int i; uint8_t reset; uint32_t x1, x2, s=0; reset = 1; // x1 is set in first call to lte_gold_generic x2 = (subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 for (i=0; i>(i&0x1f))&1)); if (((s>>(i%32))&1)==0) llr[i] = -llr[i]; } } uint8_t get_num_pdcch_symbols(uint8_t num_dci, DCI_ALLOC_t *dci_alloc, LTE_DL_FRAME_PARMS *frame_parms, uint8_t subframe) { uint16_t numCCE = 0; uint8_t i; uint8_t nCCEmin = 0; // check pdcch duration imposed by PHICH duration (Section 6.9 of 36-211) if (frame_parms->Ncp==1) { // extended prefix if ((frame_parms->frame_type == TDD) && ((frame_parms->tdd_config<3)||(frame_parms->tdd_config==6)) && ((subframe==1) || (subframe==6))) // subframes 1 and 6 (S-subframes) for 5ms switching periodicity are 2 symbols nCCEmin = 2; else { // 10ms switching periodicity is always 3 symbols, any DL-only subframe is 3 symbols nCCEmin = 3; } } // compute numCCE for (i=0;i %d\n",i,dci_alloc[i].L); numCCE += (1<<(dci_alloc[i].L)); } //if ((9*numCCE) <= (frame_parms->N_RB_DL*2)) if (numCCE <= get_nCCE(1, frame_parms, get_mi(frame_parms, subframe))) return(cmax(1,nCCEmin)); //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 4 : 5))) else if (numCCE < get_nCCE(2, frame_parms, get_mi(frame_parms, subframe))) return(cmax(2,nCCEmin)); //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 7 : 8))) else if (numCCE < get_nCCE(3, frame_parms, get_mi(frame_parms, subframe))) return(cmax(3,nCCEmin)); else if (frame_parms->N_RB_DL<=10) { if (frame_parms->Ncp == 0) { // normal CP if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 10 : 11))) return(4); } else { // extended CP if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 9 : 10))) return(4); } } msg("[PHY] dci.c: get_num_pdcch_symbols subframe %d FATAL, illegal numCCE %d (num_dci %d)\n",subframe,numCCE,num_dci); //for (i=0;inushift%3; int Msymb2; int split_flag=0; switch (frame_parms->N_RB_DL) { case 100: Msymb2 = Msymb; break; case 75: Msymb2 = 3*Msymb/4; break; case 50: Msymb2 = Msymb>>1; break; case 25: Msymb2 = Msymb>>2; break; case 15: Msymb2 = Msymb*15/100; break; case 6: Msymb2 = Msymb*6/100; break; default: Msymb2 = Msymb>>2; break; } num_pdcch_symbols = get_num_pdcch_symbols(num_ue_spec_dci+num_common_dci,dci_alloc,frame_parms,subframe); // printf("subframe %d in generate_dci_top num_pdcch_symbols = %d, num_dci %d\n", // subframe,num_pdcch_symbols,num_ue_spec_dci+num_common_dci); generate_pcfich(num_pdcch_symbols, amp, frame_parms, txdataF, subframe); wbar[0] = &wbar0[0]; wbar[1] = &wbar1[0]; y[0] = &yseq0[0]; y[1] = &yseq1[0]; // reset all bits to , here we set elements as 2 //memset(e, 2, DCI_BITS_MAX); // here we interpred NIL as a random QPSK sequence. That makes power estimation easier. for (i=0;i=0;L--) { for (i=0;imode1_flag==1) gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15); else gain_lin_QPSK = amp/2; e_ptr = e; if (frame_parms->mode1_flag) { //SISO for (i=0;i>2); #endif // first antenna position n -> x0 ((int16_t*)&y[0][i])[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; ((int16_t*)&y[0][i])[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; // second antenna position n -> -x1* ((int16_t*)&y[1][i])[0] = (*e_ptr == 1) ? gain_lin_QPSK : -gain_lin_QPSK; e_ptr++; ((int16_t*)&y[1][i])[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; // fill in the rest of the ALAMOUTI precoding ((int16_t*)&y[0][i+1])[0] = -((int16_t*)&y[1][i])[0]; ((int16_t*)&y[0][i+1])[1] = ((int16_t*)&y[1][i])[1]; ((int16_t*)&y[1][i+1])[0] = ((int16_t*)&y[0][i])[0]; ((int16_t*)&y[1][i+1])[1] = -((int16_t*)&y[0][i])[1]; } } #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH Interleaving\n"); #endif // msg("y %p (%p,%p), wbar %p (%p,%p)\n",y,y[0],y[1],wbar,wbar[0],wbar[1]); // This is the interleaving procedure defined in 36-211, first part of Section 6.8.5 pdcch_interleaving(frame_parms,&y[0],&wbar[0],num_pdcch_symbols,mi); mprime=0; nsymb = (frame_parms->Ncp==0) ? 14:12; re_offset = frame_parms->first_carrier_offset; // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5 // printf("DCI (SF %d) : txdataF %p (0 %p)\n",subframe,&txdataF[0][512*14*subframe],&txdataF[0][0]); for (kprime=0;kprimeN_RB_DL*12;kprime++) { for (lprime=0;lprimeofdm_symbol_size*(lprime+(subframe*nsymb)); tti_offset = symbol_offset + re_offset; (re_offset==(frame_parms->ofdm_symbol_size-2)) ? (split_flag=1) : (split_flag=0); // printf("kprime %d, lprime %d => REG %d (symbol %d)\n",kprime,lprime,(lprime==0)?(kprime/6) : (kprime>>2),symbol_offset); // if REG is allocated to PHICH, skip it if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) { #ifdef DEBUG_DCI_ENCODING msg("generate_dci: skipping REG %d (kprime %d, lprime %d)\n",(lprime==0)?(kprime/6) : (kprime>>2),kprime,lprime); #endif } else { // Copy REG to TX buffer if ((lprime == 0)|| ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4))) { // first symbol, or second symbol+4 TX antennas skip pilots kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 6)) { // kprime represents REG for (i=0;i<6;i++) { if ((i!=(nushiftmod3))&&(i!=(nushiftmod3+3))) { txdataF[0][tti_offset+i] = wbar[0][mprime]; if (frame_parms->nb_antennas_tx_eNB > 1) txdataF[1][tti_offset+i] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; } } } } else { // no pilots in this symbol kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) { // kprime represents REG if (split_flag==0) { for (i=0;i<4;i++) { txdataF[0][tti_offset+i] = wbar[0][mprime]; if (frame_parms->nb_antennas_tx_eNB > 1) txdataF[1][tti_offset+i] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; } } else { txdataF[0][tti_offset+0] = wbar[0][mprime]; if (frame_parms->nb_antennas_tx_eNB > 1) txdataF[1][tti_offset+0] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; txdataF[0][tti_offset+1] = wbar[0][mprime]; if (frame_parms->nb_antennas_tx_eNB > 1) txdataF[1][tti_offset+1] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+1,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[0][mprime]; if (frame_parms->nb_antennas_tx_eNB > 1) txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+3,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[0][mprime]; if (frame_parms->nb_antennas_tx_eNB > 1) txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+4,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; } } } if (mprime>=Msymb2) return(num_pdcch_symbols); } // check_phich_reg } //lprime loop re_offset++; if (re_offset == (frame_parms->ofdm_symbol_size)) re_offset = 1; } // kprime loop return(num_pdcch_symbols); } #ifdef PHY_ABSTRACTION uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB, uint8_t num_ue_spec_dci, uint8_t num_common_dci, DCI_ALLOC_t *dci_alloc, uint8_t subframe){ int n_dci, n_dci_dl; uint8_t ue_id; 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, subframe); eNB_transport_info[phy_vars_eNB->Mod_id].cntl.cfi=num_pdcch_symbols; memcpy(phy_vars_eNB->dci_alloc[subframe&1],dci_alloc,sizeof(DCI_ALLOC_t)*(num_ue_spec_dci+num_common_dci)); phy_vars_eNB->num_ue_spec_dci[subframe&1]=num_ue_spec_dci; phy_vars_eNB->num_common_dci[subframe&1]=num_common_dci; eNB_transport_info[phy_vars_eNB->Mod_id].num_ue_spec_dci = num_ue_spec_dci; eNB_transport_info[phy_vars_eNB->Mod_id].num_common_dci = num_common_dci; LOG_D(PHY,"[eNB %d][DCI][EMUL] num spec dci %d num comm dci %d num PMCH %d \n", phy_vars_eNB->Mod_id, num_ue_spec_dci,num_common_dci, eNB_transport_info[phy_vars_eNB->Mod_id].num_pmch); if (eNB_transport_info[phy_vars_eNB->Mod_id].cntl.pmch_flag == 1 ) n_dci_dl = eNB_transport_info[phy_vars_eNB->Mod_id].num_pmch; else n_dci_dl = 0; for (n_dci =0 ; n_dci < (eNB_transport_info[phy_vars_eNB->Mod_id].num_ue_spec_dci+ eNB_transport_info[phy_vars_eNB->Mod_id].num_common_dci); n_dci++) { 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]->dlsch_eNB_SI; eNB_transport_info[phy_vars_eNB->Mod_id].dlsch_type[n_dci_dl] = 0;//SI; eNB_transport_info[phy_vars_eNB->Mod_id].harq_pid[n_dci_dl] = 0; eNB_transport_info[phy_vars_eNB->Mod_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].tbs[n_dci_dl],n_dci_dl, eNB_transport_info[phy_vars_eNB->Mod_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]->dlsch_eNB_ra; eNB_transport_info[phy_vars_eNB->Mod_id].dlsch_type[n_dci_dl] = 1;//RA; eNB_transport_info[phy_vars_eNB->Mod_id].harq_pid[n_dci_dl] = 0; eNB_transport_info[phy_vars_eNB->Mod_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[0]->TBS>>3; LOG_D(PHY,"[DCI][EMUL] RA tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id].tbs[n_dci_dl],n_dci_dl, eNB_transport_info[phy_vars_eNB->Mod_id].harq_pid[n_dci_dl]); } else { ue_id = find_ue(dci_alloc[n_dci_dl].rnti,PHY_vars_eNB_g[phy_vars_eNB->Mod_id]); dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id]->dlsch_eNB[ue_id][0]; eNB_transport_info[phy_vars_eNB->Mod_id].dlsch_type[n_dci_dl] = 2;//TB0; eNB_transport_info[phy_vars_eNB->Mod_id].harq_pid[n_dci_dl] = dlsch_eNB->current_harq_pid; eNB_transport_info[phy_vars_eNB->Mod_id].ue_id[n_dci_dl] = ue_id; eNB_transport_info[phy_vars_eNB->Mod_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[dlsch_eNB->current_harq_pid]->TBS>>3; LOG_D(PHY,"[DCI][EMUL] TB1 tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id].tbs[n_dci_dl],n_dci_dl, eNB_transport_info[phy_vars_eNB->Mod_id].harq_pid[n_dci_dl]); // check for TB1 later } } n_dci_dl++; } memcpy((void *)&eNB_transport_info[phy_vars_eNB->Mod_id].dci_alloc, (void *)dci_alloc, n_dci*sizeof(DCI_ALLOC_t)); return(num_pdcch_symbols); } #endif void dci_decoding(uint8_t DCI_LENGTH, uint8_t aggregation_level, int8_t *e, uint8_t *decoded_output) { uint8_t dummy_w_rx[3*(MAX_DCI_SIZE_BITS+16+64)]; int8_t w_rx[3*(MAX_DCI_SIZE_BITS+16+32)],d_rx[96+(3*(MAX_DCI_SIZE_BITS+16))]; uint16_t RCC; uint16_t D=(DCI_LENGTH+16+64); uint16_t coded_bits; #ifdef DEBUG_DCI_DECODING int32_t i; #endif if (aggregation_level>3) { LOG_I(PHY," dci.c: dci_decoding FATAL, illegal aggregation_level %d\n",aggregation_level); return; } coded_bits = 72 * (1<>3)); #ifdef DEBUG_DCI_DECODING msg("Before Viterbi\n"); for (i=0;i<16+DCI_LENGTH;i++) msg("%d : (%d,%d,%d)\n",i,*(d_rx+96+(3*i)),*(d_rx+97+(3*i)),*(d_rx+98+(3*i))); #endif //debug_msg("Doing DCI Viterbi \n"); phy_viterbi_lte_sse2(d_rx+96,decoded_output,16+DCI_LENGTH); //debug_msg("Done DCI Viterbi \n"); } static uint8_t dci_decoded_output[(MAX_DCI_SIZE_BITS+64)/8]; uint16_t get_nCCE(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uint8_t mi) { return(get_nquad(num_pdcch_symbols,frame_parms,mi)/9); } uint16_t get_nquad(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uint8_t mi) { uint16_t Nreg=0; uint8_t 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) Ngroup_PHICH++; if (frame_parms->Ncp == 1) { Ngroup_PHICH<<=1; } Ngroup_PHICH*=mi; if ((num_pdcch_symbols>0) && (num_pdcch_symbols<4)) switch (frame_parms->N_RB_DL) { case 6: Nreg=12+(num_pdcch_symbols-1)*18; break; case 25: Nreg=50+(num_pdcch_symbols-1)*75; break; case 50: Nreg=100+(num_pdcch_symbols-1)*150; break; case 100: Nreg=200+(num_pdcch_symbols-1)*300; break; default: return(0); } // printf("Nreg %d (%d)\n",Nreg,Nreg - 4 - (3*Ngroup_PHICH)); return(Nreg - 4 - (3*Ngroup_PHICH)); } uint16_t get_nCCE_max(uint8_t Mod_id) { // check for eNB only ! return(get_nCCE(3,&PHY_vars_eNB_g[Mod_id]->lte_frame_parms,1)); // 5, 15,21 } void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars,int do_common,uint8_t subframe, DCI_ALLOC_t *dci_alloc, int16_t eNB_id, LTE_DL_FRAME_PARMS *frame_parms, uint8_t mi, uint16_t si_rnti, uint16_t ra_rnti, uint8_t L, uint8_t format_si, uint8_t format_ra, uint8_t format_c, uint8_t sizeof_bits, uint8_t sizeof_bytes, uint8_t *dci_cnt, uint8_t *format0_found, uint8_t *format_c_found, uint32_t *CCEmap0, uint32_t *CCEmap1, uint32_t *CCEmap2) { uint16_t crc,CCEind,nCCE; uint32_t *CCEmap=NULL,CCEmap_mask=0; int L2=(1<num_pdcch_symbols,frame_parms,mi); if (nCCE > get_nCCE(3,frame_parms,1)) return; if (nCCEcrnti; for (i=0;i<=subframe;i++) Yk = (Yk*39827)%65537; Yk = Yk % (nCCE/L2); switch (L2) { case 1: case 2: nb_candidates = 6; break; case 4: case 8: nb_candidates = 2; break; default: DevParam(L2, do_common, eNB_id); break; } } /* for (CCEind=0; CCEind nCCE) nb_candidates = nCCE/L2; for (m=0;me_rx[CCEind*72], dci_decoded_output); /* for (i=0;i<3+(sizeof_bits>>3);i++) printf("dci_decoded_output[%d] => %x\n",i,dci_decoded_output[i]); */ crc = (crc16(dci_decoded_output,sizeof_bits)>>16) ^ extract_crc(dci_decoded_output,sizeof_bits); #ifdef DEBUG_DCI_DECODING msg("crc =>%x\n",crc); #endif if (((L>1) && ((crc == si_rnti)|| (crc == ra_rnti)))|| (crc == lte_ue_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; dci_alloc[*dci_cnt].nCCE = CCEind; if (sizeof_bytes<=4) { dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[0]; dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[1]; dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[2]; dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[3]; #ifdef DEBUG_DCI_DECODING msg("DCI => %x,%x,%x,%x\n",dci_decoded_output[0],dci_decoded_output[1],dci_decoded_output[2],dci_decoded_output[3]); #endif } else { dci_alloc[*dci_cnt].dci_pdu[7] = dci_decoded_output[0]; dci_alloc[*dci_cnt].dci_pdu[6] = dci_decoded_output[1]; dci_alloc[*dci_cnt].dci_pdu[5] = dci_decoded_output[2]; dci_alloc[*dci_cnt].dci_pdu[4] = dci_decoded_output[3]; dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[4]; dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[5]; dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[6]; dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[7]; } if (crc==si_rnti) { dci_alloc[*dci_cnt].format = format_si; *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 lte_ue_pdcch_vars[eNB_id]->nCCE[subframe]=CCEind; *dci_cnt = *dci_cnt+1; } else if (crc==lte_ue_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; } } 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; } 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; } } } // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); switch (1<crnti) // return; } // rnti match } // CCEmap_cand == 0 } // candidate loop } uint16_t dci_decoding_procedure(PHY_VARS_UE *phy_vars_ue, DCI_ALLOC_t *dci_alloc, int do_common, int16_t eNB_id, uint8_t subframe) { 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); 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 frame_type = frame_parms->frame_type; uint8_t format1A_size_bits,format1A_size_bytes; uint8_t format0_size_bits,format0_size_bytes; uint8_t format1_size_bits,format1_size_bytes; switch (frame_parms->N_RB_DL) { case 6: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_1_5MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); format0_size_bits = sizeof_DCI0_1_5MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_1_5MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_1_5MHz_TDD_t; format1_size_bytes = sizeof(DCI1_1_5MHz_TDD_t); } else { format1A_size_bits = sizeof_DCI1A_1_5MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_1_5MHz_FDD_t); format0_size_bits = sizeof_DCI0_1_5MHz_FDD_t; format0_size_bytes = sizeof(DCI0_1_5MHz_FDD_t); format1_size_bits = sizeof_DCI1_1_5MHz_FDD_t; format1_size_bytes = sizeof(DCI1_1_5MHz_FDD_t); } break; case 25: default: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_5MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); format0_size_bits = sizeof_DCI0_5MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_5MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_5MHz_TDD_t; format1_size_bytes = sizeof(DCI1_5MHz_TDD_t); } else { format1A_size_bits = sizeof_DCI1A_5MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_5MHz_FDD_t); format0_size_bits = sizeof_DCI0_5MHz_FDD_t; format0_size_bytes = sizeof(DCI0_5MHz_FDD_t); format1_size_bits = sizeof_DCI1_5MHz_FDD_t; format1_size_bytes = sizeof(DCI1_5MHz_FDD_t); } break; case 50: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_10MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); format0_size_bits = sizeof_DCI0_10MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_10MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_10MHz_TDD_t; format1_size_bytes = sizeof(DCI1_10MHz_TDD_t); } else { format1A_size_bits = sizeof_DCI1A_10MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_10MHz_FDD_t); format0_size_bits = sizeof_DCI0_10MHz_FDD_t; format0_size_bytes = sizeof(DCI0_10MHz_FDD_t); format1_size_bits = sizeof_DCI1_10MHz_FDD_t; format1_size_bytes = sizeof(DCI1_10MHz_FDD_t); } break; case 100: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_20MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); format0_size_bits = sizeof_DCI0_20MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_20MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_20MHz_TDD_t; format1_size_bytes = sizeof(DCI1_20MHz_TDD_t); } else { format1A_size_bits = sizeof_DCI1A_20MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_20MHz_FDD_t); format0_size_bits = sizeof_DCI0_20MHz_FDD_t; format0_size_bytes = sizeof(DCI0_20MHz_FDD_t); format1_size_bits = sizeof_DCI1_20MHz_FDD_t; format1_size_bytes = sizeof(DCI1_20MHz_FDD_t); } break; } if (do_common == 1) { #ifdef DEBUG_DCI_DECODING 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; // First check common search spaces at aggregation 8 (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_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 2, format1A, format1A, format0, format1A_size_bits, format1A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff) || ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); //#ifdef ALL_AGGREGATION // Disabled for performance // Now check common search spaces at aggregation 8 (SI_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 printf("[DCI search] doing common search/format0 aggregation 8\n"); #endif dci_decoding_procedure0(lte_ue_pdcch_vars,1,subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 3, format1A, format1A, format0, format1A_size_bits, format1A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); //#endif } if (phy_vars_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; // 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, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 3, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); // 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, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 2, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); // 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, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 1, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); // 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, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 0, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); // These are for CRNTI based on transmission mode 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_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 0, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff) || (format_c_found==1)) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // 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_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 1, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| (format_c_found==1)) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // 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_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 2, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#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_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 3, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#endif //ALL_AGGREGATION } else if (tmode == 4) { // Now check UE_SPEC format 2_2A_M10PRB search spaces at aggregation 1 dci_decoding_procedure0(lte_ue_pdcch_vars,0, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 0, format1A, format1A, format2_2A_M10PRB, sizeof_DCI2_5MHz_2A_M10PRB_TDD_t, sizeof(DCI2_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 2_2A_M10PRB search spaces at aggregation 2 dci_decoding_procedure0(lte_ue_pdcch_vars,0, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 1, format1A, format1A, format2_2A_M10PRB, sizeof_DCI2_5MHz_2A_M10PRB_TDD_t, sizeof(DCI2_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 2_2A_M10PRB search spaces at aggregation 4 dci_decoding_procedure0(lte_ue_pdcch_vars,0, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 2, format1A, format1A, format2_2A_M10PRB, sizeof_DCI2_5MHz_2A_M10PRB_TDD_t, sizeof(DCI2_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 2_2A_M10PRB search spaces at aggregation 8 dci_decoding_procedure0(lte_ue_pdcch_vars,0, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 3, format1A, format1A, format2_2A_M10PRB, sizeof_DCI2_5MHz_2A_M10PRB_TDD_t, sizeof(DCI2_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //#endif } else if (tmode >=5) { // This is MU-MIMO // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 1 #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, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 0, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 2 dci_decoding_procedure0(lte_ue_pdcch_vars,0, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 1, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 4 dci_decoding_procedure0(lte_ue_pdcch_vars,0, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 2, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 1E_2A_M10PRB search spaces at aggregation 8 dci_decoding_procedure0(lte_ue_pdcch_vars,0, subframe, dci_alloc, eNB_id, frame_parms, mi, SI_RNTI, ra_rnti, 3, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#endif //ALL_AGGREGATION } return(dci_cnt); } #ifdef PHY_ABSTRACTION uint16_t dci_decoding_procedure_emul(LTE_UE_PDCCH **lte_ue_pdcch_vars, uint8_t num_ue_spec_dci, uint8_t num_common_dci, DCI_ALLOC_t *dci_alloc_tx, DCI_ALLOC_t *dci_alloc_rx, int16_t eNB_id) { uint8_t dci_cnt=0,i; memcpy(dci_alloc_rx,dci_alloc_tx,num_common_dci*sizeof(DCI_ALLOC_t)); dci_cnt = num_common_dci; 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, dci_alloc_tx[i].dci_pdu[0]&0x80); if (dci_alloc_tx[i].rnti == lte_ue_pdcch_vars[eNB_id]->crnti) { memcpy(dci_alloc_rx+dci_cnt,dci_alloc_tx+i,sizeof(DCI_ALLOC_t)); dci_cnt++; } } return(dci_cnt); } #endif