diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c new file mode 100644 index 0000000000000000000000000000000000000000..b02afcc9b74f8b1da7c0b83d1a215dae46cd32b8 --- /dev/null +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -0,0 +1,158 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_REFSIG/nr_dl_dmrs.c +* \brief Top-level routines for generating DMRS from 38-211 +* \author +* \date 2018 +* \version 0.1 +* \company Eurecom +* \email: +* \note +* \warning +*/ + +//#define DEBUG_DL_DMRS +//#define NR_PBCH_DMRS_LENGTH_DWORD 5 +//#define NR_PBCH_DMRS_LENGTH 144 + +#ifdef USER_MODE +#include <stdio.h> +#include <stdlib.h> +#endif + +#include "refsig_defs_ue.h" +#include "PHY/defs_nr_UE.h" +#include "log.h" + +/*Table 7.4.1.1.2-1/2 from 38.211 */ +int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}}; +int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}}; +int wf2[12][2] = {{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 wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}}; + +short nr_mod_table[14] = {0,0,23170,23170,-23170,-23170,23170,23170,23170,-23170,-23170,23170,-23170,-23170}; +//extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; + + +int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue, + unsigned int ncp, + unsigned int Ns, + unsigned int nr_gold_pdsch[2][20][2][21], + int32_t *output, + unsigned short p, + int length_dmrs, + unsigned short nb_pdsch_rb) +{ + int32_t qpsk[4],nqpsk[4],*qpsk_p, n; + int w,mprime,ind,l,ind_dword,ind_qpsk_symb,kp,lp, config_type, k; + short pamp; + + typedef int array_of_w[2]; + array_of_w *wf; + array_of_w *wt; + + config_type = 1; + printf("dmrs config type %d port %d\n", config_type, p); + + // Compute the correct pilot amplitude, sqrt_rho_b = Q3.13 + pamp = 23170; //ONE_OVER_SQRT2_Q15; + + // This includes complex conjugate for channel estimation + ((short *)&qpsk[0])[0] = pamp; + ((short *)&qpsk[0])[1] = -pamp; + ((short *)&qpsk[1])[0] = -pamp; + ((short *)&qpsk[1])[1] = -pamp; + ((short *)&qpsk[2])[0] = pamp; + ((short *)&qpsk[2])[1] = pamp; + ((short *)&qpsk[3])[0] = -pamp; + ((short *)&qpsk[3])[1] = pamp; + + ((short *)&nqpsk[0])[0] = -pamp; + ((short *)&nqpsk[0])[1] = pamp; + ((short *)&nqpsk[1])[0] = pamp; + ((short *)&nqpsk[1])[1] = pamp; + ((short *)&nqpsk[2])[0] = -pamp; + ((short *)&nqpsk[2])[1] = -pamp; + ((short *)&nqpsk[3])[0] = pamp; + ((short *)&nqpsk[3])[1] = -pamp; + + wf = (config_type==0) ? wf1 : wf2; + wt = (config_type==0) ? wt1 : wt2; + + if (config_type > 1) + LOG_E(PHY,"Bad PDSCH DMRS config type %d\n", config_type); + + if ((p>=1000) && (p<((config_type==0) ? 1008 : 1012))) { + if (/*ue->frame_parms.Ncp == NORMAL*/ncp ==0) { + + // r_n from 38.211 7.4.1.1 + for (n=0; n<nb_pdsch_rb*((config_type==0) ? 3:2); n++) { + for (lp =0; lp<length_dmrs; lp++){ + for (kp=0; kp<2; kp++){ + w = (wf[p-1000][kp])*(wt[p-1000][lp]); + qpsk_p = (w==1) ? qpsk : nqpsk; + + ind = 2*n+kp; + ind_dword = ind>>4; + ind_qpsk_symb = ind&0xf; + + output[k] = qpsk_p[(ue->nr_gold_pdsch[0][Ns][lp][ind_dword]>>(2*ind_qpsk_symb))&3]; + + +#ifdef DEBUG_DL_DMRS + LOG_I(PHY,"Ns %d, p %d, ind_dword %d, ind_qpsk_symbol %d\n", + Ns,p,idx_dword,idx_qpsk_symb); + LOG_I(PHY,"index = %d\n",(nr_gold_pdsch[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3); +#endif + + k++; + } + } + } + } else { + LOG_E(PHY,"extended cp not supported for PDSCH DMRS yet\n"); + } + } else { + LOG_E(PHY,"Illegal p %d PDSCH DMRS port\n",p); + } + + return(0); +} + +int nr_pbch_dmrs_rx(unsigned int *nr_gold_pbch, + int32_t *output ) +{ + int m; + + /// BPSK modulation + for (m=0; m<NR_PBCH_DMRS_LENGTH; m++) { + output[m<<1] = nr_mod_table[((1 + ((nr_gold_pbch[m>>5]&(1<<(m&0x1f)))>>(m&0x1f)))<<1)]; + output[(m<<1)+1] = nr_mod_table[((1 + ((nr_gold_pbch[m>>5]&(1<<(m&0x1f)))>>(m&0x1f)))<<1) + 1]; +#ifdef DEBUG_PBCH + printf("nr_gold_pbch[m>>5] %x\n",nr_gold_pbch[m>>5]); + printf("m %d output %d %d\n", m, output[2*m], output[2*m+1]); +#endif + } + + return(0); +} + diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c new file mode 100644 index 0000000000000000000000000000000000000000..48187714f471203a957696d3d03dbb963b611602 --- /dev/null +++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c @@ -0,0 +1,115 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "refsig_defs_ue.h" + +void nr_gold_pbch(PHY_VARS_NR_UE* ue) +{ + + unsigned int n, x1, x2; + unsigned char Nid, i_ssb, i_ssb2; + unsigned char Lmax, l, n_hf, N_hf; + + Nid = ue->frame_parms.Nid_cell; + + Lmax = 8; //(fp->dl_CarrierFreq < 3e9)? 4:8; + N_hf = (Lmax == 4)? 2:1; + + for (n_hf = 0; n_hf < N_hf; n_hf++) { + + for (l = 0; l < Lmax ; l++) { + i_ssb = l & (Lmax-1); + i_ssb2 = (i_ssb<<2) + n_hf; + + x1 = 1 + (1<<31); + x2 = (1<<11) * (i_ssb2 + 1) * ((Nid>>2) + 1) + (1<<6) * (i_ssb2 + 1) + (Nid&3); + x2 = x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); + + // skip first 50 double words (1600 bits) + for (n = 1; n < 50; n++) { + x1 = (x1>>1) ^ (x1>>4); + x1 = x1 ^ (x1<<31) ^ (x1<<28); + x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); + x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); + } + + for (n=0; n<NR_PBCH_DMRS_LENGTH_DWORD; n++) { + x1 = (x1>>1) ^ (x1>>4); + x1 = x1 ^ (x1<<31) ^ (x1<<28); + x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); + x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); + ue->nr_gold_pbch[n_hf][l][n] = x1 ^ x2; + } + + } + } + +} + +void nr_gold_pdsch(/*LTE_DL_FRAME_PARMS *frame_parms*/unsigned short lbar,unsigned int nr_gold_pdsch[2][20][2][21],unsigned int Nid_cell, unsigned short *n_idDMRS, unsigned short length_dmrs) +{ + + unsigned char ns,l; + unsigned int n,x1,x2,x2tmp0,x2tmp1, x2tmp2,x2s; + int nscid; + unsigned int nid; + + /// to be updated from higher layer + unsigned short lbar = 0; + + for (nscid=0; nscid<2; nscid++) { + if (n_idDMRS) + nid = n_idDMRS[nscid]; + else + nid = Nid_cell; + + for (ns=0; ns<20; ns++) { + + for (l=0; l<length_dmrs; l++) { + + x2tmp0 = ((14*ns+(lbar+l)+1)*((nid<<1)+1))<<17; + x2 = (x2tmp0+(nid<<1))%(1<<31); //cinit + + x1 = 1+ (1<<31); + x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); + + // skip first 50 double words (1600 bits) + for (n=1; n<50; n++) { + x1 = (x1>>1) ^ (x1>>4); + x1 = x1 ^ (x1<<31) ^ (x1<<28); + x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); + x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); + //printf("x1 : %x, x2 : %x\n",x1,x2); + } + + for (n=0; n<14; n++) { + x1 = (x1>>1) ^ (x1>>4); + x1 = x1 ^ (x1<<31) ^ (x1<<28); + x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); + x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); + nr_gold_pdsch[nscid][ns][l][n] = x1^x2; + //printf("n=%d : c %x\n",n,x1^x2); + } + + } + } + } +} diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h new file mode 100644 index 0000000000000000000000000000000000000000..4cbc2e0db701c3501b1f4011fd87e2d752311681 --- /dev/null +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -0,0 +1,43 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* Definitions for LTE Reference signals */ +/* Author R. Knopp / EURECOM / OpenAirInterface.org */ +#ifndef __NR_REFSIG_DEFS__H__ +#define __NR_REFSIG_DEFS__H__ +#include "PHY/defs_nr_UE.h" + + +/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS. +@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables + */ +int nr_pbch_dmrs_rx(unsigned int *nr_gold_pbch, int32_t *output ); + +/*int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue, + unsigned int ncp, + unsigned int Ns, + unsigned int nr_gold_pdsch[2][20][2][21], + int32_t *output, + unsigned short p, + int length_dmrs, + unsigned short nb_pdsch_rb);*/ + +#endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h new file mode 100644 index 0000000000000000000000000000000000000000..a37a591d2f57d3f79439fc85c9e42bbb9e28ee05 --- /dev/null +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h @@ -0,0 +1,86 @@ +short filt16a_l0[16] = { +16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_r0[16] = { +0,0,0,0,0,4096,8192,12288,16384,20480,24576,28672,0,0,0,0}; + +short filt16a_m0[16] = { +0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,-12288,0,0,0,0}; + +short filt16a_l1[16] = { +20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_r1[16] = { +0,0,0,0,0,0,4096,8192,12288,16384,20480,24576,0,0,0,0}; + +short filt16a_m1[16] = { +-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,0,0,0,0}; + +short filt16a_l2[16] = { +24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_r2[16] = { +0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0}; + +short filt16a_m2[16] = { +-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,0,0,0,0}; + +short filt16a_l3[16] = { +28672,24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0}; + +short filt16a_r3[16] = { +0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0}; + +short filt16a_m3[16] = { +-12288,-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0}; + +short filt16a_l0_dc[16] = { +16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_r0_dc[16] = { +0,0,0,0,0,3276,9830,13107,16384,19660,22937,26214,0,0,0,0}; + +short filt16a_m0_dc[16] = { +0,4096,8192,12288,16384,13107,6553,3276,0,-3277,-6554,-9831,0,0,0,0}; + +short filt16a_l1_dc[16] = { +16384,12288,8192,4096,0,-4096,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_r1_dc[16] = { +0,0,0,0,0,0,6553,9830,13107,16384,19660,22937,0,0,0,0}; + +short filt16a_m1_dc[16] = { +-4096,0,4096,8192,12288,16384,9830,6553,3276,0,-3277,-6554,0,0,0,0}; + +short filt16a_l2_dc[16] = { +26214,22937,19660,16384,13107,9830,6553,0,0,0,0,0,0,0,0,0}; + +short filt16a_r2_dc[16] = { +0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0}; + +short filt16a_m2_dc[16] = { +-6554,-3277,0,3276,6553,6553,16384,12288,8192,4096,0,-4096,0,0,0,0}; + +short filt16a_l3_dc[16] = { +26214,22937,19660,16384,13107,9830,3276,0,0,0,0,0,0,0,0,0}; + +short filt16a_r3_dc[16] = { +0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0}; + +short filt16a_m3_dc[16] = { +-9831,-6554,-3277,0,3276,6553,9830,16384,12288,8192,4096,0,0,0,0,0}; + +short filt16a_1[16] = { +16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384}; + +short filt16a_2l0[16] = { +16384,12288,8192,4096,-4096,0,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_2r0[16] = { +0,4096,8192,12288,16384,20480,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_2l1[16] = { +20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0}; + +short filt16a_2r1[16] = { +-4096,0,4096,8192,12288,16384,0,0,0,0,0,0,0,0,0,0}; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c new file mode 100644 index 0000000000000000000000000000000000000000..2a9b847e1e60af22f18ef84c455b9f3bcdadb20f --- /dev/null +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -0,0 +1,262 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifdef USER_MODE +#include <string.h> +#endif +//#include "defs.h" +//#include "SCHED/defs.h" +#include "PHY/defs_nr_UE.h" +#include "filt16a_32.h" +#include "T.h" +#define DEBUG_CH + +int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, + uint8_t eNB_id, + uint8_t eNB_offset, + unsigned char Ns, + unsigned char p, + unsigned char l, + unsigned char symbol) +{ + int pilot[2][200] __attribute__((aligned(16))); + unsigned char nu,aarx; + unsigned short k; + unsigned int rb,pilot_cnt; + int16_t ch[2],*pil,*rxF,*dl_ch,*dl_ch_prev,*fl,*fm,*f2l,*fr,f1,*f2r,*fl_dc,*fm_dc,*fr_dc; + int ch_offset,symbol_offset; + + uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; + + uint8_t nushift; + uint8_t previous_thread_id = ue->current_thread_id[Ns>>1]==0 ? (RX_NB_TH-1):(ue->current_thread_id[Ns>>1]-1); + int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset]; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF; + + + // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation + nushift = Nid_cell%4; + + 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 = ue->frame_parms.ofdm_symbol_size*symbol; + + symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; + + k = nushift; + +#ifdef DEBUG_CH + printf("PBCH Channel Estimation : ThreadId %d, eNB_offset %d cell_id %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d\n",ue->current_thread_id[Ns>>1], eNB_offset,Nid_cell,ch_offset,ue->frame_parms.ofdm_symbol_size, + ue->frame_parms.Ncp,l,Ns,k); +#endif + + switch (k) { + case 0: + fl = filt16a_l0; + fm = filt16a_m0; + fr = filt16a_r0; + fl_dc = filt16a_l0; + fm_dc = filt16a_m0; + fr_dc = filt16a_r0; + f1 = filt16a_1; + f2l = filt16a_2l0; + f2r = filt16a_2r0; + break; + + case 1: + fl = filt16a_l1; + fm = filt16a_m1; + fr = filt16a_r1; + fl_dc = filt16a_l1; + fm_dc = filt16a_m1; + fr_dc = filt16a_r1; + f1 = filt16a_1; + f2l = filt16a_2l1; + f2r = filt16a_2r1; + break; + + case 2: + fl = filt16a_l2; + fm = filt16a_m2; + fr = filt16a_r2; + fl_dc = filt16a_l2; + fm_dc = filt16a_m2; + fr_dc = filt16a_r2; + f1 = filt16a_1; + f2l = filt16a_2l0; + f2r = filt16a_2r0; + break; + + case 3: + fl = filt16a_l3; + fm = filt16a_m3; + fr = filt16a_r3; + fl_dc = filt16a_l3; + fm_dc = filt16a_m3; + fr_dc = filt16a_r3; + f1 = filt16a_1; + f2l = filt16a_2l1; + f2r = filt16a_2r1; + break; + + default: + msg("pbch_channel_estimation: k=%d -> ERROR\n",k); + return(-1); + break; + } + + + + // generate pilot + nr_pbch_dmrs_rx(ue->nr_gold_pbch, + &pilot[p][0]); + + for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) { + + pil = (int16_t *)&pilot[p][0]; + 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]; + + 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,ue->frame_parms.first_carrier_offset); +#endif + if ((ue->frame_parms.N_RB_DL&1)==0) { + + // Treat first 2 pilots specially (left edge) + 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); +#ifdef DEBUG_CH + printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + printf("pilot 0 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fl, + ch, + dl_ch, + 16); + pil+=2; + rxF+=8; + for (int i= 0; i<8; i++) + printf("dl_ch %d %d\n", dl_ch+i, *(dl_ch+i)); + //dl_ch+=6; + printf("after dl_ch %d %d\n", dl_ch, *(dl_ch)); + + 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); +#ifdef DEBUG_CH + printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fm, + ch, + dl_ch, + 16); + //printf("after dl_ch %d %d\n", dl_ch, *(dl_ch)); + for (int i= 0; i<16; i++) + printf("dl_ch %d %d\n", dl_ch+i, *(dl_ch+i)); + + pil+=2; + rxF+=8; + //dl_ch+=6; + printf("after 6 dl_ch %d %d\n", dl_ch, *(dl_ch)); + + 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); + + #ifdef DEBUG_CH + printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + #endif + + multadd_real_vector_complex_scalar(fr, + ch, + dl_ch, + 16); + pil+=2; + rxF+=8; + dl_ch+=16; + + for (pilot_cnt=6; pilot_cnt<((ue->frame_parms.N_RB_DL)-1); pilot_cnt+=6) { + + + + 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); +#ifdef DEBUG_CH + printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fl, + ch, + dl_ch, + 16); + + for (int i= 0; i<8; i++) + printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); + + pil+=2; + rxF+=8; + //dl_ch+=6; + + 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); +#ifdef DEBUG_CH + printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fm, + ch, + dl_ch, + 16); + pil+=2; + rxF+=8; + //dl_ch+=6; + + 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); + + #ifdef DEBUG_CH + printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + #endif + + multadd_real_vector_complex_scalar(fr, + ch, + dl_ch, + 16); + pil+=2; + rxF+=8; + dl_ch+=16; + + } + + + } + + + printf("dl_ch %d\n", dl_ch); + + + } + + return(0); +} + diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h new file mode 100644 index 0000000000000000000000000000000000000000..7ec222727b7381fb22d742c05487f69b61bb214d --- /dev/null +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -0,0 +1,60 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef __LTE_ESTIMATION_DEFS__H__ +#define __LTE_ESTIMATION_DEFS__H__ + + +#include "PHY/defs_nr_UE.h" +#include "PHY/defs_gNB.h" +/** @addtogroup _PHY_PARAMETER_ESTIMATION_BLOCKS_ + * @{ + */ + +/*!\brief Timing drift hysterisis in samples*/ +#define SYNCH_HYST 2 + +/*! +\brief This function performs channel estimation including frequency and temporal interpolation +\param phy_vars_ue Pointer to UE PHY variables +\param eNB_id Index of target eNB +\param eNB_offset Offset for interfering eNB (in terms cell ID mod 3) +\param Ns slot number (0..19) +\param p antenna port +\param l symbol within slot +\param symbol symbol within frame +*/ +int nr_dl_channel_estimation(PHY_VARS_NR_UE *ue, + uint8_t eNB_id, + uint8_t eNB_offset, + unsigned char Ns, + unsigned char p, + unsigned char l, + unsigned char symbol); + +int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, + uint8_t eNB_id, + uint8_t eNB_offset, + unsigned char Ns, + unsigned char p, + unsigned char l, + unsigned char symbol); +#endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index a2373b8ef22e5f9d767182b87b3c9afda8cc7b75..ccc031ed8434e762c67cb7217a2891f0a8c7776e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -257,7 +257,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) set_default_frame_parms_single(config,&ue->frame_parms); nr_init_frame_parms_ue(config,&ue->frame_parms); - //generate_dmrs_pbch(ue->dmrs_pbch_bitmap_nr, frame_parms->Nid_cell); + + nr_gold_pbch(ue); ret = pbch_detection(ue,mode); // write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);