diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index b371f6af207d6d4287f0eb690f81d278065eaef6..6ae75d71aed9d0a17a69a04e4f26028f2b391457 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -212,7 +212,7 @@ pipeline { steps { gitlabCommitStatus(name: "Build eNb-ethernet") { timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID}" } } } @@ -221,7 +221,7 @@ pipeline { steps { gitlabCommitStatus(name: "Build UE-ethernet") { timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID}" } } } diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh index aed449f180f59fe1d0ba49ecd3e98c9062d09243..ec774a00ea929a77d465e7f4c7010c92337b254f 100755 --- a/ci-scripts/buildOnVM.sh +++ b/ci-scripts/buildOnVM.sh @@ -94,14 +94,21 @@ function build_on_vm { echo "############################################################" echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" + acquire_vm_create_lock uvt-kvm create $VM_NAME release=xenial --memory $VM_MEMORY --cpu $VM_CPU --unsafe-caching --template ci-scripts/template-host.xml - fi + echo "Waiting for VM to be started" + uvt-kvm wait $VM_NAME --insecure - echo "Waiting for VM to be started" - uvt-kvm wait $VM_NAME --insecure + VM_IP_ADDR=`uvt-kvm ip $VM_NAME` + echo "$VM_NAME has for IP addr = $VM_IP_ADDR" + release_vm_create_lock + else + echo "Waiting for VM to be started" + uvt-kvm wait $VM_NAME --insecure - VM_IP_ADDR=`uvt-kvm ip $VM_NAME` - echo "$VM_NAME has for IP addr = $VM_IP_ADDR" + VM_IP_ADDR=`uvt-kvm ip $VM_NAME` + echo "$VM_NAME has for IP addr = $VM_IP_ADDR" + fi echo "############################################################" echo "Copying GIT repo into VM ($VM_NAME)" diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh index 192008d86723d357f7a6dcb1d75674f3cf657377..e693b07b913eadbf5b17cca0754545c025b89e9d 100755 --- a/ci-scripts/createVM.sh +++ b/ci-scripts/createVM.sh @@ -49,6 +49,35 @@ function create_usage { echo "" } +function acquire_vm_create_lock { + local FlockFile="/tmp/vmclone.lck" + local unlocked="0" + touch ${FlockFile} 2>/dev/null + if [[ $? -ne 0 ]] + then + echo "Cannot access lock file ${FlockFile}" + exit 2 + fi + while [ $unlocked -eq 0 ] + do + exec 5>${FlockFile} + flock -nx 5 + if [[ $? -ne 0 ]] + then + echo "Another instance of VM creation is running" + sleep 10 + else + unlocked="1" + fi + done + chmod 666 ${FlockFile} 2>/dev/null +} + +function release_vm_create_lock { + local FlockFile="/tmp/vmclone.lck" + rm -Rf ${FlockFile} +} + function create_vm { echo "############################################################" echo "OAI CI VM script" @@ -60,10 +89,12 @@ function create_vm { echo "############################################################" echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" + acquire_vm_create_lock uvt-kvm create $VM_NAME release=xenial --memory $VM_MEMORY --cpu $VM_CPU --unsafe-caching --template ci-scripts/template-host.xml echo "Waiting for VM to be started" uvt-kvm wait $VM_NAME --insecure VM_IP_ADDR=`uvt-kvm ip $VM_NAME` echo "$VM_NAME has for IP addr = $VM_IP_ADDR" + release_vm_create_lock } diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool index dda71d26064a0c64c6dde80eaf6e70a9d800496d..940bcd28523a7df9bbafbaf5a1cfcf3c1e6b6656 100755 --- a/ci-scripts/oai-ci-vm-tool +++ b/ci-scripts/oai-ci-vm-tool @@ -252,8 +252,9 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=7 + NB_PATTERN_FILES=8 BUILD_OPTIONS="--phy_simulators" + VM_MEMORY=4096 RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b" NBARGS=$[$NBARGS+256] shift @@ -330,8 +331,9 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=7 + NB_PATTERN_FILES=8 BUILD_OPTIONS="--phy_simulators" + VM_MEMORY=4096 RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b" NBARGS=$[$NBARGS+256] ;; diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 527fe48edb25655587bacbef98f669fb4c8938ab..da6649ed05d6fd9eb23da414afe7d6b292e0b9fe 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -441,10 +441,16 @@ function run_test_on_vm { echo "############################################################" echo "Creating test EPC VM ($EPC_VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" + acquire_vm_create_lock uvt-kvm create $EPC_VM_NAME release=xenial --unsafe-caching + echo "Waiting for VM to be started" + uvt-kvm wait $EPC_VM_NAME --insecure + release_vm_create_lock + else + echo "Waiting for VM to be started" + uvt-kvm wait $EPC_VM_NAME --insecure fi - uvt-kvm wait $EPC_VM_NAME --insecure EPC_VM_IP_ADDR=`uvt-kvm ip $EPC_VM_NAME` echo "$EPC_VM_NAME has for IP addr = $EPC_VM_IP_ADDR" scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$EPC_VM_IP_ADDR:/home/ubuntu diff --git a/ci-scripts/waitBuildOnVM.sh b/ci-scripts/waitBuildOnVM.sh index a6f4edace8b6c2197f7383030dc89ca462ce71e5..208bf06318828649b8f1a03717ba20d83492d7f7 100755 --- a/ci-scripts/waitBuildOnVM.sh +++ b/ci-scripts/waitBuildOnVM.sh @@ -165,6 +165,10 @@ function check_on_vm_build { fi done - if [ $NB_PATTERN_FILES -ne $NB_FOUND_FILES ]; then STATUS=-1; fi + if [ $NB_PATTERN_FILES -ne $NB_FOUND_FILES ] + then + echo "Expecting $NB_PATTERN_FILES log files and found $NB_FOUND_FILES" + STATUS=-1 + fi } diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index c54c3e33220de5427c1007ea5f393efafca772b8..2c47513c344aa4538eb5fea562ed6aa31528b7dc 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1057,26 +1057,65 @@ (Test2: PBCH and synchronization, 106PBR), (Test3: PBCH-only, 217 PRB), (Test4: PBCH and synchronization, 217 RPB), - (Test5: PBCH-only, 217 PRB), - (Test6: PBCH and synchronization, 217 PRB)</desc> + (Test5: PBCH-only, 273 PRB), + (Test6: PBCH and synchronization, 273 PRB)</desc> <pre_compile_prog></pre_compile_prog> <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog> <compile_prog_args> --phy_simulators -c </compile_prog_args> <pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash</pre_exec> <pre_exec_args></pre_exec_args> <main_exec> $OPENAIR_DIR/targets/bin/nr_pbchsim.Rel15</main_exec> - <main_exec_args>-s-11 -S-10 -n1000 -R106 - -s-11 -S-10 -n10 -I -R106 - -s-11 -S-10 -n1000 -R217 -N10 - -s-11 -S-10 -n10 -I -R217 -N10 - -s-11 -S-10 -n1000 -R273 -N20 - -s-11 -S-10 -n10 -I -R273 -N20</main_exec_args> - <tags>nr_pbchsim.test1 nr_pbchsim.test2</tags> + <main_exec_args>-s0 -S1 -n1000 -R106 + -s0 -S1 -n10 -I -R106 + -s0 -S1 -n1000 -R217 + -s0 -S1 -n10 -I -R217 + -s0 -S1 -n1000 -R273 + -s0 -S1 -n10 -I -R273</main_exec_args> + <tags>nr_pbchsim.test1 nr_pbchsim.test2 nr_pbchsim.test3 nr_pbchsim.test4 nr_pbchsim.test5 nr_pbchsim.test6</tags> <search_expr_true>PBCH test OK</search_expr_true> <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false> <nruns>3</nruns> </testCase> + + <testCase id="015105"> + <class>execution</class> + <desc>nr_dlsim Test cases. (Test1: 106 PRB), + (Test2: 217 PRB), + (Test3: 273 PRB)</desc> + <pre_compile_prog></pre_compile_prog> + <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog> + <compile_prog_args> --phy_simulators -c </compile_prog_args> + <pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash</pre_exec> + <pre_exec_args></pre_exec_args> + <main_exec> $OPENAIR_DIR/targets/bin/nr_dlsim.Rel15</main_exec> + <main_exec_args>-n100 -R106 + -n100 -R217 + -n100 -R273</main_exec_args> + <tags>nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3</tags> + <search_expr_true>PDCCH test OK</search_expr_true> + <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false> + <nruns>3</nruns> + </testCase> + <testCase id="015106"> + <class>execution</class> + <desc>nr_dlschsim Test cases. (Test1: 106 PRB), + (Test2: 217 PRB), + (Test3: 273 PRB)</desc> + <pre_compile_prog></pre_compile_prog> + <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog> + <compile_prog_args> --phy_simulators -c </compile_prog_args> + <pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash</pre_exec> + <pre_exec_args></pre_exec_args> + <main_exec> $OPENAIR_DIR/targets/bin/nr_dlschsim.Rel15</main_exec> + <main_exec_args>-R 106 -m9 -s13 -n100 + -R 217 -m15 -s15 -n100 + -R 273 -m19 -s20 -n100</main_exec_args> + <tags>nr_dlschsim.test1 nr_dlschsim.test2 nr_dlschsim.test3</tags> + <search_expr_true>PDSCH test OK</search_expr_true> + <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false> + <nruns>3</nruns> + </testCase> <testCase id="015110"> <class>execution</class> diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index f018e8c4220037e68c93c9c3dd81c4e50e67f46c..01ab01f0a7d07f524d892c5dfa150d71cb90d9a4 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -696,7 +696,7 @@ function main() { echo_info "Compiling unitary tests simulators" # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim #simlist="dlsim_tm4 dlsim ulsim pucchsim prachsim pdcchsim pbchsim mbmssim" - simlist="dlsim ulsim polartest ldpctest nr_pbchsim nr_dlschsim" + simlist="dlsim ulsim polartest ldpctest nr_pbchsim nr_dlschsim nr_dlsim" for f in $simlist ; do compilations \ phy_simulators $f \ diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 2040faf4a29dca0a722dfdf0208c90a9205242c5..0f316e7869a909f2ccef56cbd9a20c67c66bc108 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -467,33 +467,26 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f); void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f); -uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, - uint8_t *w, - uint8_t *e, - uint8_t C, - uint8_t rvidx, - uint8_t Qm, - uint8_t Nl, - uint8_t r); +int nr_rate_matching_ldpc(uint8_t Ilbrm, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + uint8_t *w, + uint8_t *e, + uint8_t C, + uint8_t rvidx, + uint32_t E); int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, int16_t *w, int16_t *soft_input, uint8_t C, uint8_t rvidx, uint8_t clear, - uint8_t Qm, - uint8_t Nl, - uint8_t r, - uint32_t *E_out); + uint32_t E); decoder_if_t phy_threegpplte_turbo_decoder; decoder_if_t phy_threegpplte_turbo_decoder8; diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index 01390f1f2ff991817ee443960fc5af7f9d7b351a..0bce31630f598e3a2f0b38acf278a582d313e215 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -63,55 +63,39 @@ void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) } -uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, - uint8_t *w, - uint8_t *e, - uint8_t C, - uint8_t rvidx, - uint8_t Qm, - uint8_t Nl, - uint8_t r) +int nr_rate_matching_ldpc(uint8_t Ilbrm, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + uint8_t *w, + uint8_t *e, + uint8_t C, + uint8_t rvidx, + uint32_t E) { - uint8_t Cprime; - uint32_t Ncb,E,ind,k,Nref,N; - //uint8_t *e2; + uint32_t Ncb,ind,k,Nref,N; - AssertFatal(Nl>0,"Nl is 0\n"); - AssertFatal(Qm>0,"Qm is 0\n"); + if (C==0) { + printf("nr_rate_matching: invalid parameters (C %d\n",C); + return -1; + } //Bit selection N = (BG==1)?(66*Z):(50*Z); if (Ilbrm == 0) - Ncb = N; + Ncb = N; else { Nref = 3*Tbslbrm/(2*C); //R_LBRM = 2/3 Ncb = min(N, Nref); } -#ifdef RM_DEBUG - printf("nr_rate_matching: Ncb %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",Ncb,rvidx, G, Qm,Nl,r); -#endif - - Cprime = C; //assume CBGTI not present - - if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - E = Nl*Qm*(G/(Nl*Qm*Cprime)); - else - E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; #ifdef RM_DEBUG - printf("nr_rate_matching: E %d, k0 %d Cprime %d modcprime %d\n",E,ind, Cprime,((G/(Nl*Qm))%Cprime)); + printf("nr_rate_matching_ldpc: E %d, k0 %d, Ncb %d, rvidx %d\n", E, ind, Ncb, rvidx); #endif - //e2 = e; - k=0; for (; (ind<Ncb)&&(k<E); ind++) { @@ -120,7 +104,6 @@ uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, printf("RM_TX k%d Ind: %d (%d)\n",k,ind,w[ind]); #endif - //if (w[ind] != NR_NULL) e2[k++]=w[ind]; if (w[ind] != NR_NULL) e[k++]=w[ind]; } @@ -131,79 +114,60 @@ uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, printf("RM_TX k%d Ind: %d (%d)\n",k,ind,w[ind]); #endif - //if (w[ind] != NR_NULL) e2[k++]=w[ind]; if (w[ind] != NR_NULL) e[k++]=w[ind]; } } - return(E); + return 0; } int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, int16_t *w, int16_t *soft_input, uint8_t C, uint8_t rvidx, uint8_t clear, - uint8_t Qm, - uint8_t Nl, - uint8_t r, - uint32_t *E_out) + uint32_t E) { - uint8_t Cprime; - uint32_t Ncb,E,ind,k,Nref,N; - - int16_t *soft_input2; + uint32_t Ncb,ind,k,Nref,N; #ifdef RM_DEBUG int nulled=0; #endif - if (C==0 || Qm==0 || Nl==0) { - printf("nr_rate_matching: invalid parameters (C %d, Qm %d, Nl %d\n",C,Qm,Nl); - return(-1); + if (C==0) { + printf("nr_rate_matching: invalid parameters (C %d\n",C); + return -1; } - AssertFatal(Nl>0,"Nl is 0\n"); - AssertFatal(Qm>0,"Qm is 0\n"); - //Bit selection N = (BG==1)?(66*Z):(50*Z); if (Ilbrm == 0) - Ncb = N; + Ncb = N; else { Nref = (3*Tbslbrm/(2*C)); //R_LBRM = 2/3 Ncb = min(N, Nref); } - Cprime = C; //assume CBGTI not present - - if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - E = Nl*Qm*(G/(Nl*Qm*Cprime)); - else - E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; #ifdef RM_DEBUG - printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, Ncb %d,rvidx %d, G %d, Qm %d, Nl%d, r %d\n",clear,E,Ncb,rvidx, G, Qm,Nl,r); + printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d\n", clear, E, ind, Ncb, rvidx); #endif if (clear==1) memset(w,0,Ncb*sizeof(int16_t)); - soft_input2 = soft_input; k=0; for (; (ind<Ncb)&&(k<E); ind++) { - if (soft_input2[ind] != NR_NULL) { - w[ind] += soft_input2[k++]; + if (soft_input[ind] != NR_NULL) { + w[ind] += soft_input[k++]; #ifdef RM_DEBUG printf("RM_RX k%d Ind: %d (%d)\n",k-1,ind,w[ind]); #endif @@ -220,10 +184,10 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, while(k<E) { for (ind=0; (ind<Ncb)&&(k<E); ind++) { - if (soft_input2[ind] != NR_NULL) { - w[ind] += soft_input2[k++]; + if (soft_input[ind] != NR_NULL) { + w[ind] += soft_input[k++]; #ifdef RM_DEBUG - printf("RM_RX k%d Ind: %d (%d)(soft in %d)\n",k-1,ind,w[ind],soft_input2[k-1]); + printf("RM_RX k%d Ind: %d (%d)(soft in %d)\n",k-1,ind,w[ind],soft_input[k-1]); #endif } @@ -237,7 +201,5 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, } } - *E_out = E; - return(0); - + return 0; } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 78d25b1bd15e8120f3bcd1ea10cc3686ccc801f1..1e1751fe24adabdeaf9ff76fa21a31f2b7f6daff 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -56,11 +56,17 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, unsigned int rx_offset; NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[Ns]][0]; uint16_t coreset_start_subcarrier = frame_parms->first_carrier_offset;//+((int)floor(frame_parms->ssb_start_subcarrier/NR_NB_SC_PER_RB)+pdcch_vars->coreset[0].rb_offset)*NR_NB_SC_PER_RB; - uint16_t nb_rb_coreset = 24; + uint16_t nb_rb_coreset = 0; uint16_t bwp_start_subcarrier = frame_parms->first_carrier_offset;//+516; uint16_t nb_rb_pdsch = 50; uint8_t p=0; - uint8_t l0 = 2; + uint8_t l0 = pdcch_vars->coreset[0].duration; + uint64_t coreset_freq_dom = pdcch_vars->coreset[0].frequencyDomainResources; + for (int i = 0; i < 45; i++) { + if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) nb_rb_coreset++; + } + nb_rb_coreset = 6 * nb_rb_coreset; + //printf("corset duration %d nb_rb_coreset %d\n", l0, nb_rb_coreset); void (*dft)(int16_t *,int16_t *, int); int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index 2f39f26ee475d2fcc1f2032d065bd438fa721be6..dc20ab24d7f8bbc9bdd08a597d24d0809529c4ea 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -137,7 +137,9 @@ int set_pss_nr(int ofdm_symbol_size); int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change); int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id); + int fo_flag, + int *eNB_id, + int *f_off); #endif #undef EXTERN diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 205eae7f8e57e046d1bdec54e6870cc312559098..06969eded03422b43f0454a63d4924bac2e79a6d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -90,6 +90,8 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch, @param nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs */ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16_t length_dmrs,uint8_t Qm, uint8_t Nl); +uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r); + void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 0d59207480643ab4a9dd9220f27869670668f2ad..8a2877cc178aa6de1e3c5f9e4e78d3285bcd1116 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -280,7 +280,7 @@ int nr_dlsch_encoding(unsigned char *a, uint32_t A, Z; uint32_t *pz = &Z; uint8_t mod_order = rel15.modulation_order; - uint16_t Kr=0,r,r_offset=0;//Kr_bytes + uint16_t Kr=0,r,r_offset=0,Kr_bytes; uint8_t *d_tmp[MAX_NUM_DLSCH_SEGMENTS]; uint8_t kb,BG=1; uint32_t E; @@ -346,7 +346,7 @@ int nr_dlsch_encoding(unsigned char *a, } Kr = dlsch->harq_processes[harq_pid]->K; - //Kr_bytes = Kr>>3; + Kr_bytes = Kr>>3; //printf("segment Z %d kb %d k %d Kr %d BG %d\n", *pz,kb,dlsch->harq_processes[harq_pid]->K,Kr,BG); @@ -403,25 +403,24 @@ int nr_dlsch_encoding(unsigned char *a, //start_meas(rm_stats); #ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx); + printf("rvidx in encoding = %d\n", rel15.redundancy_version); #endif - E = nr_rate_matching_ldpc(Ilbrm, - Tbslbrm, - BG, - *pz, - G, - dlsch->harq_processes[harq_pid]->d[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, - rel15.redundancy_version, - mod_order, - rel15.nb_layers, - r); + E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15.nb_layers, r); + + nr_rate_matching_ldpc(Ilbrm, + Tbslbrm, + BG, + *pz, + dlsch->harq_processes[harq_pid]->d[r], + dlsch->harq_processes[harq_pid]->e+r_offset, + dlsch->harq_processes[harq_pid]->C, + rel15.redundancy_version, + E); #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) - printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i], r_offset); + printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset); #endif //stop_meas(rm_stats); @@ -432,18 +431,15 @@ int nr_dlsch_encoding(unsigned char *a, dlsch->harq_processes[harq_pid]->f+r_offset); //stop_meas(i_stats); - r_offset += E; #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) - printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r*r_offset], r_offset); -#endif - -#ifdef DEBUG_DLSCH_CODING + printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset); if (r==dlsch->harq_processes[harq_pid]->C-1) - write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,r_offset,1,4); - + write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,G,1,4); #endif + + r_offset += E; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c index 0b8ab563293acbd71a8f51ec45a0c144dea78026..f8b74540679ac3ebb2eea5c3ff730d75d85d188b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -176,3 +176,18 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16 G = ((NR_NB_SC_PER_RB*nb_symb_sch)-(nb_re_dmrs*length_dmrs))*nb_rb*Qm*Nl; return(G); } + +uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r) { + uint32_t E; + uint8_t Cprime = C; //assume CBGTI not present + + AssertFatal(Nl>0,"Nl is 0\n"); + AssertFatal(Qm>0,"Qm is 0\n"); + + if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) + E = Nl*Qm*(G/(Nl*Qm*Cprime)); + else + E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); + + return E; +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index c702d63973acc48f749b0c5cd1271a66871f3367..be85499754a1c4fef3f4db1d0910940f4f4185ef 100755 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -821,8 +821,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol); - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) \n", - coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R); + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) scrambling_ID=(%d) \n", + coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R,pdcch_DMRS_scrambling_id); #endif // diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 610b8305df8a014cca0f26d7f7d3fe2fb2cc2741..2888a59606fc8b0c2b82f1f66b7f3ad7bab9e6ec 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -376,6 +376,22 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, for (r=0; r<harq_process->C; r++) { //printf("start rx segment %d\n",r); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); @@ -394,20 +410,15 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, #endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { - + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -419,27 +430,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, stop_meas(dlsch_rate_unmatching_stats); #endif } - r_offset += E; //for (int i =0; i<16; i++) - // printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); - -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); - //for (int i =0; i<16; i++) - // printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + r_offset += E; -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING - if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); @@ -979,6 +976,30 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + + /* + printf("Subblock deinterleaving, dlsch_llr %p, w %p\n", + dlsch_llr+r_offset, + &harq_process->w[r]); + */ +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + +#ifdef DEBUG_DLSCH_DECODING + for (int i =0; i<16; i++) + printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); +#endif + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -995,23 +1016,16 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -1023,34 +1037,18 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + //r_offset += E; //printf("main thread r_offset %d\n",r_offset); #ifdef DEBUG_DLSCH_DECODING for (int i =0; i<16; i++) - printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); #endif - /* - printf("Subblock deinterleaving, d %p w %p\n", - harq_process->d[r], - harq_process->w); - */ -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#ifdef DEBUG_DLSCH_DECODING - for (int i =0; i<16; i++) - printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); -#endif - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING if (r==0) { @@ -1526,6 +1524,23 @@ void *nr_dlsch_decoding_2thread0(void *arg) Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -1542,23 +1557,16 @@ void *nr_dlsch_decoding_2thread0(void *arg) harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -1570,23 +1578,13 @@ void *nr_dlsch_decoding_2thread0(void *arg) stop_meas(dlsch_rate_unmatching_stats); #endif } - //r_offset += E; //for (int i =0; i<16; i++) - // printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif -#ifdef DEBUG_DLSCH_DECODING + //r_offset += E; +#ifdef DEBUG_DLSCH_DECODING if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); @@ -2043,6 +2041,28 @@ void *nr_dlsch_decoding_2thread1(void *arg) Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + + /* + printf("Subblock deinterleaving, d %p w %p\n", + harq_process->d[r], + harq_process->w); + */ +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -2059,23 +2079,16 @@ void *nr_dlsch_decoding_2thread1(void *arg) harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, Tbslbrm, p_decParams->BG, p_decParams->Z, - G, + harq_process->d[r], harq_process->w[r], - dlsch_llr+r_offset, harq_process->C, harq_process->rvidx, (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -2087,23 +2100,12 @@ void *nr_dlsch_decoding_2thread1(void *arg) stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + //r_offset += E; - /* - printf("Subblock deinterleaving, d %p w %p\n", - harq_process->d[r], - harq_process->w); - */ -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 4a6e6423f61698c7d7375a0385ae2b8a645ddb44..e5f079ebc31616eee707a4d87077cfd7fbb33b67 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -39,6 +39,7 @@ //#include "SCHED/extern.h" #include "common_lib.h" +#include <math.h> #include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_REFSIG/sss_nr.h" @@ -56,6 +57,7 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int ret =-1; + #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id, ue->rx_offset); @@ -65,6 +67,7 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples; + //symbol 1 nr_slot_fep(ue, 1, @@ -143,6 +146,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) int32_t sync_pos, sync_pos_slot; // k_ssb, N_ssb_crb, sync_pos2, int32_t metric_tdd_ncp=0; uint8_t phase_tdd_ncp; + double im, re; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; int ret=-1; @@ -183,14 +187,14 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE); sync_pos_slot = (fp->samples_per_subframe/fp->slots_per_subframe) - 10*(fp->ofdm_symbol_size + fp->nb_prefix_samples); - + if (sync_pos >= fp->nb_prefix_samples){ ue->ssb_offset = sync_pos - fp->nb_prefix_samples;} else{ ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;} - ue->rx_offset = ue->ssb_offset - sync_pos_slot; - + ue->rx_offset = ue->ssb_offset - sync_pos_slot; + //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1); #ifdef DEBUG_INITIAL_SYNCH @@ -198,6 +202,25 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) LOG_I(PHY,"sync_pos %d ssb_offset %d sync_pos_slot %d \n",sync_pos,ue->ssb_offset,sync_pos_slot); #endif + // digital compensation of FFO for SSB symbols + if (ue->UE_fo_compensation){ + double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time + double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample + + int start = ue->ssb_offset; // start for offset correction is at ssb_offset (pss time position) + int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples); // loop over samples in 4 symbols (ssb size), including prefix + + for(int n=start; n<end; n++){ + for (int ar=0; ar<fp->nb_antennas_rx; ar++) { + re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]); + im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]); + ((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); + ((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle))); + } + } + } + + /* check that SSS/PBCH block is continuous inside the received buffer */ if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) { @@ -244,7 +267,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) ret = -1; } - /* Consider this is a false detection if the offset is > 1000 Hz */ + /* Consider this is a false detection if the offset is > 1000 Hz + Not to be used now that offest estimation is in place if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) ) { ret=-1; @@ -253,7 +277,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) #else LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset); #endif - } + }*/ if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters @@ -329,13 +353,13 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) printf("[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, ue->proc.proc_rxtx[0].frame_rx, - openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, + openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset, ue->common_vars.freq_offset); # else LOG_I(PHY, "[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, ue->proc.proc_rxtx[0].frame_rx, - openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, + openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset, ue->common_vars.freq_offset); # endif #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index cef55df281a46ed96f84111977867fae3f4c7566..9b09a846bbd6d4e909b215624ced6550ea192617 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -33,6 +33,7 @@ #include <stdio.h> #include <assert.h> #include <errno.h> +#include <math.h> #include "PHY/defs_nr_UE.h" @@ -662,6 +663,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int synchro_position; int **rxdata = NULL; + int fo_flag = PHY_vars_UE->UE_fo_compensation; // flag to enable freq offset estimation and compensation #ifdef DBG_PSS_NR @@ -705,7 +707,10 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) synchro_position = pss_search_time_nr(rxdata, frame_parms, - (int *)&PHY_vars_UE->common_vars.eNb_id); + fo_flag, + (int *)&PHY_vars_UE->common_vars.eNb_id, + (int *)&PHY_vars_UE->common_vars.freq_offset); + #if TEST_SYNCHRO_TIMING_PSS @@ -751,6 +756,15 @@ static inline int64_t abs64(int64_t x) return (((int64_t)((int32_t*)&x)[0])*((int64_t)((int32_t*)&x)[0]) + ((int64_t)((int32_t*)&x)[1])*((int64_t)((int32_t*)&x)[1])); } +static inline double angle64(int64_t x) +{ + + double re=((int32_t*)&x)[0]; + double im=((int32_t*)&x)[1]; + return (atan2(im,re)); +} + + /******************************************************************* * * NAME : pss_search_time_nr @@ -803,47 +817,28 @@ static inline int64_t abs64(int64_t x) #define DOT_PRODUCT_SCALING_SHIFT (17) -int max3(int64_t a, int64_t b, int64_t c) { - if (a>b) { - if (a>c) { - return(0); - } - else { - return(2); - } - } - else { - if (b>c) { - return(1); - } - else { - return(2); - } - } -} - - int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id) + int fo_flag, + int *eNB_id, + int *f_off) { - uint8_t L_max = 4; - unsigned int m, n, ar, n_peaks=0; - unsigned int peak_position[3*L_max], pss_source[3*L_max]; - int64_t peak_value, threshold; + unsigned int n, ar, peak_position, pss_source; + int64_t peak_value; int64_t result; int64_t avg[NUMBER_PSS_SEQUENCE]; - uint8_t found_peak=0; + double ffo_est=0; + unsigned int length = (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); /* 1 frame for now, it should be 2 TODO_NR */ AssertFatal(length>0,"illegal length %d\n",length); for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) AssertFatal(pss_corr_ue[i] != NULL,"pss_corr_ue[%d] not yet allocated! Exiting.\n", i); - for (int i=0;i<4;i++) { - peak_position[i] = length; //max possible value - pss_source[i] = 0; - } + + peak_value = 0; + peak_position = 0; + pss_source = 0; int maxval=0; for (int i=0;i<2*(frame_parms->ofdm_symbol_size);i++) { @@ -853,7 +848,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain maxval = max(maxval,-primary_synchro_time_nr[1][i]); maxval = max(maxval,primary_synchro_time_nr[2][i]); maxval = max(maxval,-primary_synchro_time_nr[2][i]); - } int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2); @@ -866,9 +860,9 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain memset(pss_corr_ue[pss_index],0,length*sizeof(int64_t)); } - for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) { + for (n=0; n < length; n+=4) { // - for (n=0; n < length; n+=4) { // + for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) { if ( n < (length - frame_parms->ofdm_symbol_size)) { @@ -881,7 +875,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain frame_parms->ofdm_symbol_size, shift); pss_corr_ue[pss_index][n] += abs64(result); - //((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */ //((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */ //((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */ @@ -889,43 +882,64 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain } } - + /* calculate the absolute value of sync_corr[n] */ avg[pss_index]+=pss_corr_ue[pss_index][n]; + if (pss_corr_ue[pss_index][n] > peak_value) { + peak_value = pss_corr_ue[pss_index][n]; + peak_position = n; + pss_source = pss_index; + +#ifdef DEBUG_PSS_NR + printf("pss_index %d: n %6d peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n]); +#endif + } } - - avg[pss_index]/=(length/4); } + + if (fo_flag){ + // fractional frequency offser computation according to Cross-correlation Synchronization Algorithm Using PSS + // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. + + int64_t result1,result2; + // Computing cross-correlation at peak on half the symbol size for first half of data + result1 = dot_product64((short*)primary_synchro_time_nr[pss_source], + (short*) &(rxdata[0][peak_position]), + frame_parms->ofdm_symbol_size>>1, + shift); + // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size + // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift + result2 = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size), + (short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size), + frame_parms->ofdm_symbol_size>>1, + shift); + + int64_t re1,re2,im1,im2; + re1=((int*) &result1)[0]; + re2=((int*) &result2)[0]; + im1=((int*) &result1)[1]; + im2=((int*) &result2)[1]; + + // estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi + ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI; - threshold = 10*avg[max3(avg[0],avg[1],avg[2])]; - peak_value = threshold; - - for (n=0; n < length; n+=4) { - - m = max3(pss_corr_ue[0][n],pss_corr_ue[1][n],pss_corr_ue[2][n]); - - if (pss_corr_ue[m][n] > peak_value) { - peak_value = pss_corr_ue[m][n]; - peak_position[n_peaks] = n; - pss_source[n_peaks] = m; - found_peak = 1; - } - - if ((peak_position[n_peaks]+4*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)<n) && - (found_peak==1)) { - //#ifdef DEBUG_PSS_NR - printf("peak %d found at pss_index %d, n %6d, peak_value %15llu\n", n_peaks, pss_source[n_peaks], peak_position[n_peaks], (unsigned long long)pss_corr_ue[ pss_source[n_peaks]][peak_position[n_peaks]]); - //#endif - peak_value = threshold; - found_peak = 0; - n_peaks++; - //if (n_peaks==L_max) break; - } +#ifdef DBG_PSS_NR + printf("ffo %lf\n",ffo_est); +#endif } - *eNB_id = pss_source[0]; + // computing absolute value of frequency offset + *f_off = ffo_est*frame_parms->subcarrier_spacing; + + for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) avg[pss_index]/=(length/4); + + *eNB_id = pss_source; + + LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est); + + if (peak_value < 5*avg[pss_source]) + return(-1); - //LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source])); #ifdef DBG_PSS_NR @@ -942,6 +956,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain #endif - return(peak_position[0]); + return(peak_position); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index 05ab023b00acc381f26a60bd1330c70c8b671a92..2327a5036bdf54718bdb9570f233eec3080a2bd6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -25,7 +25,7 @@ * \date 2018 * \version 0.1 * \company Eurecom -* \email: +* \email: * \note * \warning */ @@ -33,7 +33,7 @@ #include "PHY/impl_defs_nr.h" #include "PHY/defs_nr_common.h" #include "PHY/defs_nr_UE.h" -//#include "PHY/extern.h" +//#include "PHY/extern.h" //#include "LAYER2/MAC/extern.h" #include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -49,25 +49,25 @@ //#define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) void nr_group_sequence_hopping (//pucch_GroupHopping_t ue->pucch_config_common_nr.puch_GroupHopping, - //uint8_t PUCCH_GroupHopping, - PHY_VARS_NR_UE *ue, - //uint32_t n_id, - uint8_t n_hop, - int nr_tti_tx, - uint8_t *u, - uint8_t *v) { -/* - * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping - * The following variables are set by higher layers: - * - PUCCH_GroupHopping: - * - n_id: higher-layer parameter hoppingId - * - n_hop: frequency hopping index - * if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping - * n_hop=0 - * if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping - * n_hop=0 for the first hop - * n_hop=1 for the second hop - */ + //uint8_t PUCCH_GroupHopping, + PHY_VARS_NR_UE *ue, + //uint32_t n_id, + uint8_t n_hop, + int nr_tti_tx, + uint8_t *u, + uint8_t *v) { + /* + * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping + * The following variables are set by higher layers: + * - PUCCH_GroupHopping: + * - n_id: higher-layer parameter hoppingId + * - n_hop: frequency hopping index + * if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping + * n_hop=0 + * if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping + * n_hop=0 for the first hop + * n_hop=1 for the second hop + */ // depending on the value of the PUCCH_GroupHopping, we will obtain different values for u,v pucch_GroupHopping_t PUCCH_GroupHopping = ue->pucch_config_common_nr->pucch_GroupHopping; // from higher layers FIXME!!! // n_id defined as per TS 38.211 subclause 6.3.2.2.1 (is given by the higher-layer parameter hoppingId) @@ -75,43 +75,66 @@ void nr_group_sequence_hopping (//pucch_GroupHopping_t ue->pucch_config_common_n // Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled // Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) BIT STRING (SIZE (10)) uint16_t n_id = ue->pucch_config_common_nr->hoppingId; // from higher layers FIXME!!! - - - #ifdef DEBUG_NR_PUCCH_TX - // initialization to be removed - PUCCH_GroupHopping=neither; - n_id=10; - printf("\t\t [nr_group_sequence_hopping] initialization PUCCH_GroupHopping=%d, n_id=%d -> variable initializations TO BE REMOVED\n",PUCCH_GroupHopping,n_id); - #endif - - +#ifdef DEBUG_NR_PUCCH_TX + // initialization to be removed + PUCCH_GroupHopping=neither; + n_id=10; + printf("\t\t [nr_group_sequence_hopping] initialization PUCCH_GroupHopping=%d, n_id=%d -> variable initializations TO BE REMOVED\n",PUCCH_GroupHopping,n_id); +#endif uint8_t f_ss=0,f_gh=0; *u=0; *v=0; uint32_t c_init = (1<<5)*floor(n_id/30)+(n_id%30); // we initialize c_init to calculate u,v uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1 - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_group_sequence_hopping] calculating u,v -> "); - #endif + int l = 32, minShift = ((2*nr_tti_tx+n_hop)<<3); + int tmpShift =0; +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_group_sequence_hopping] calculating u,v -> "); +#endif - if (PUCCH_GroupHopping == neither){ // PUCCH_GroupHopping 'neither' + if (PUCCH_GroupHopping == neither) { // PUCCH_GroupHopping 'neither' f_ss = n_id%30; } - if (PUCCH_GroupHopping == enable){ // PUCCH_GroupHopping 'enabled' - for (int m=0; m<8; m++){ - f_gh = f_gh + ((1<<m)*((uint8_t)((s>>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!! + + if (PUCCH_GroupHopping == enable) { // PUCCH_GroupHopping 'enabled' + for (int m=0; m<8; m++) { + while(minShift >= l) { + s = lte_gold_generic(&x1, &c_init, 0); + l = l+32; + } + + tmpShift = (minShift&((1<<5)-1)); //minShift%32; + f_gh = f_gh + ((1<<m)*((uint8_t)((s>>tmpShift)&1))); + minShift ++; } + f_gh = f_gh%30; f_ss = n_id%30; + /* for (int m=0; m<8; m++){ + f_gh = f_gh + ((1<<m)*((uint8_t)((s>>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!! + } + f_gh = f_gh%30; + f_ss = n_id%30;*/ } - if (PUCCH_GroupHopping == disable){ // PUCCH_GroupHopping 'disabled' + + if (PUCCH_GroupHopping == disable) { // PUCCH_GroupHopping 'disabled' f_ss = n_id%30; - *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!! + l = 32, minShift = (2*nr_tti_tx+n_hop); + + while(minShift >= l) { + s = lte_gold_generic(&x1, &c_init, 0); + l = l+32; + } + + tmpShift = (minShift&((1<<5)-1)); //minShift%32; + *v = (uint8_t)((s>>tmpShift)&1); + // *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!! } + *u = (f_gh+f_ss)%30; - #ifdef DEBUG_NR_PUCCH_TX - printf("%d,%d\n",*u,*v); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("%d,%d\n",*u,*v); +#endif } double nr_cyclic_shift_hopping(PHY_VARS_NR_UE *ue, @@ -120,37 +143,47 @@ double nr_cyclic_shift_hopping(PHY_VARS_NR_UE *ue, uint8_t lnormal, uint8_t lprime, int nr_tti_tx) { -/* - * Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping - * - n_id: higher-layer parameter hoppingId - * - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config - * - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2 - * - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission - * - lprime: lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213] - */ + /* + * Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping + * - n_id: higher-layer parameter hoppingId + * - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config + * - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2 + * - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission + * - lprime: lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213] + */ // alpha_init initialized to 2*PI/12=0.5235987756 double alpha = 0.5235987756; uint32_t c_init = ue->pucch_config_common_nr->hoppingId; // we initialize c_init again to calculate n_cs - - #ifdef DEBUG_NR_PUCCH_TX - // initialization to be removed - c_init=10; - printf("\t\t [nr_cyclic_shift_hopping] initialization c_init=%d -> variable initialization TO BE REMOVED\n",c_init); - #endif - +#ifdef DEBUG_NR_PUCCH_TX + // initialization to be remo.ved + c_init=10; + printf("\t\t [nr_cyclic_shift_hopping] initialization c_init=%d -> variable initialization TO BE REMOVED\n",c_init); +#endif uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1 uint8_t n_cs=0; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%d -> ",c_init); - #endif - for (int m=0; m<8; m++){ + int l = 32, minShift = (14*8*nr_tti_tx )+ 8*(lnormal+lprime); + int tmpShift =0; +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%d -> \n",c_init); +#endif + + for (int m=0; m<8; m++) { + while(minShift >= l) { + s = lte_gold_generic(&x1, &c_init, 0); + l = l+32; + } + + tmpShift = (minShift&((1<<5)-1)); //minShift%32; + minShift ++; + n_cs = n_cs+((1<<m)*((uint8_t)((s>>tmpShift)&1))); // calculating n_cs (Not sure we have to use nr_tti_tx FIXME!!!) - n_cs = n_cs+((1<<m)*((uint8_t)((s>>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1))); + // n_cs = n_cs+((1<<m)*((uint8_t)((s>>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1))); } + alpha = (alpha * (double)((m0+mcs+n_cs)%12)); - #ifdef DEBUG_NR_PUCCH_TX - printf("n_cs=%d -> %lf\n",n_cs,alpha); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("n_cs=%d -> %lf\n",n_cs,alpha); +#endif return(alpha); } void nr_generate_pucch0(PHY_VARS_NR_UE *ue, @@ -164,18 +197,16 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, uint8_t nrofSymbols, uint8_t startingSymbolIndex, uint16_t startingPRB) { - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] start function at slot(nr_tti_tx)=%d\n",nr_tti_tx); - #endif - +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] start function at slot(nr_tti_tx)=%d\n",nr_tti_tx); +#endif /* * Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation * */ - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] sequence generation\n"); - #endif - +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] sequence generation\n"); +#endif /* * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 */ @@ -187,13 +218,11 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, //uint8_t lprime; // mcs is provided by TC 38.213 subclauses 9.2.3, 9.2.4, 9.2.5 FIXME! //uint8_t mcs; - /* * in TS 38.213 Subclause 9.2.1 it is said that: * for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift * is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift */ - /* * Implementing TS 38.211 Subclause 6.3.2.3.1, the sequence x(n) shall be generated according to: * x(l*12+n) = r_u_v_alpha_delta(n) @@ -207,70 +236,78 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, // n_hop = 1 for second hop uint8_t n_hop = 0; //uint8_t PUCCH_Frequency_Hopping; // from higher layers FIXME!! - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n"); + printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n"); #endif - // x_n contains the sequence r_u_v_alpha_delta(n) int16_t x_n_re[24],x_n_im[24]; + // we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2 - for (int l=0; l<nrofSymbols; l++){ + for (int l=0; l<nrofSymbols; l++) { // if frequency hopping is enabled n_hop = 1 for second hop. Not sure frequency hopping concerns format 0. FIXME!!! // if ((PUCCH_Frequency_Hopping == 1)&&(l == (nrofSymbols-1))) n_hop = 1; nr_group_sequence_hopping(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value alpha = nr_cyclic_shift_hopping(ue,m0,mcs,l,startingSymbolIndex,nr_tti_tx); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u,v,alpha,l); - #endif - for (int n=0; n<12; n++){ +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u,v,alpha,l); +#endif + + for (int n=0; n<12; n++) { x_n_re[(12*l)+n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) - - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha + - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha x_n_im[(12*l)+n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) - + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n", - u,v,alpha,l,n,x_n_re[(12*l)+n],x_n_im[(12*l)+n]); - #endif + + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n", + u,v,alpha,l,n,x_n_re[(12*l)+n],x_n_im[(12*l)+n]); +#endif } } + /* * Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources FIXME! */ //int32_t *txptr; uint32_t re_offset=0; + for (int l=0; l<nrofSymbols; l++) { if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))); } + if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6; } + if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + //txptr = &txdataF[0][re_offset]; - for (int n=0; n<12; n++){ + for (int n=0; n<12; n++) { if ((n==6) && (startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB) re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size); } + ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)(((int32_t)(amp) * x_n_re[(12*l)+n])>>15); ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)(((int32_t)(amp) * x_n_im[(12*l)+n])>>15); //((int16_t *)txptr[0][re_offset])[0] = (int16_t)((int32_t)amp * x_n_re[(12*l)+n])>>15; //((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15; //txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif re_offset++; } } @@ -292,41 +329,45 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, uint8_t nr_bit) { #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%d m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", - nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); #endif - /* * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation * */ // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): int16_t d_re=0, d_im=0; + if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 if (((payload&1)==0) && (((payload>>1)&1)==0)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==0) && (((payload>>1)&1)==1)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==0)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==1)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im); +#endif /* * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 */ @@ -346,7 +387,6 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, * for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift * is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift */ - /* * the complex-valued symbol d_0 shall be multiplied with a sequence r_u_v_alpha_delta(n): y(n) = d_0 * r_u_v_alpha_delta(n) */ @@ -363,57 +403,63 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, // otherwise no intra-slot frequency hopping shall be assumed //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers uint8_t intraSlotFrequencyHopping = 0; - if (startingPRB != startingPRB_intraSlotHopping){ + + if (startingPRB != startingPRB_intraSlotHopping) { intraSlotFrequencyHopping=1; } + #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping); #endif -/* - * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources - */ + /* + * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources + */ //int32_t *txptr; uint32_t re_offset=0; int i=0; - #define MAX_SIZE_Z 168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n +#define MAX_SIZE_Z 168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n int16_t z_re[MAX_SIZE_Z],z_im[MAX_SIZE_Z]; int16_t z_dmrs_re[MAX_SIZE_Z],z_dmrs_im[MAX_SIZE_Z]; for (int l=0; l<nrofSymbols; l++) { - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n", - l,lprime); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n", + l,lprime); +#endif // y_n contains the complex value d multiplied by the sequence r_u_v int16_t y_n_re[12],y_n_im[12]; + if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", - n_hop,nr_tti_tx); - #endif + +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", + n_hop,nr_tti_tx); +#endif nr_group_sequence_hopping(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value alpha = nr_cyclic_shift_hopping(ue,m0,mcs,l,lprime,nr_tti_tx); - for (int n=0; n<12; n++){ + + for (int n=0; n<12; n++) { r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) - - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha + - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha r_u_v_alpha_delta_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) - + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha + + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) - - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of DMRS base sequence shifted by alpha + - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of DMRS base sequence shifted by alpha r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) - + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of DMRS base sequence shifted by alpha + + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of DMRS base sequence shifted by alpha r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_re[n]))>>15); r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_im[n]))>>15); // PUCCH sequence = DM-RS sequence multiplied by d(0) y_n_re[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15) - - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n) + - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n) y_n_im[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15) - + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n", - u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]); - #endif + + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n", + u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]); +#endif } + /* * The block of complex-valued symbols y(n) shall be block-wise spread with the orthogonal sequence wi(m) * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im) @@ -439,202 +485,222 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, uint8_t N_SF_mprime0_PUCCH_DMRS_1; // mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping uint8_t mprime = 0; + if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n", + intraSlotFrequencyHopping); +#endif N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (PUCCH) N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (DM-RS) N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (PUCCH) N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (DM-RS) - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n", - w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); - #endif - for (int m=0; m < N_SF_mprime_PUCCH_1; m++){ - for (int n=0; n<12 ; n++){ +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n", + w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); +#endif + + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + for (int n=0; n<12 ; n++) { z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", - mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], - z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); - #endif + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif } } - for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++){ - for (int n=0; n<12 ; n++){ + + for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + for (int n=0; n<12 ; n++) { z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", - mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], - z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); - #endif + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif } } } + if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n", + intraSlotFrequencyHopping); +#endif N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n", - w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); - #endif - for (int m=0; m < N_SF_mprime_PUCCH_1; m++){ - for (mprime = 0; mprime<2; mprime++){ // mprime can get values {0,1} - for (int m=0; m < N_SF_mprime_PUCCH_1; m++){ - for (int n=0; n<12 ; n++){ - z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); - z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); -#ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", - mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], - z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n", + w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); #endif + + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1} + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + for (int n=0; n<12 ; n++) { + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); + z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif + } } - } - for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++){ - for (int n=0; n<12 ; n++){ - z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); - z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); -#ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", - mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], - z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); + + for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + for (int n=0; n<12 ; n++) { + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); + z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); #endif + } } + + N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) + N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) } - N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) - N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) - } } } + if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB startingPRB = startingPRB + startingPRB_intraSlotHopping; } + if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))); } + if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6; } + if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } - //txptr = &txdataF[0][re_offset]; - for (int n=0; n<12; n++){ + for (int n=0; n<12; n++) { if ((n==6) && (startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB) re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size); } + if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1 ((int16_t *)&txdataF[0][re_offset])[0] = z_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + if (l%2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1 ((int16_t *)&txdataF[0][re_offset])[0] = z_dmrs_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_dmrs_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + re_offset++; } + if (l%2 == 1) i+=12; } } #if 0 void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, - int32_t **txdataF, - NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, - int16_t amp, - int nr_tti_tx, - uint8_t m0, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t timeDomainOCC, - uint8_t nr_bit) { + int32_t **txdataF, + NR_DL_FRAME_PARMS *frame_parms, + PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, + uint64_t payload, + int16_t amp, + int nr_tti_tx, + uint8_t m0, + uint8_t nrofSymbols, + uint8_t startingSymbolIndex, + uint16_t startingPRB, + uint16_t startingPRB_intraSlotHopping, + uint8_t timeDomainOCC, + uint8_t nr_bit) { #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%d m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", - nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); #endif - /* * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation * */ // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): int16_t d_re, d_im; + if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 if (((payload&1)==0) && (((payload>>1)&1)==0)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==0) && (((payload>>1)&1)==1)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==0)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==1)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im); +#endif /* * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 */ @@ -654,7 +720,6 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, * for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift * is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift */ - /* * the complex-valued symbol d_0 shall be multiplied with a sequence r_u_v_alpha_delta(n): y(n) = d_0 * r_u_v_alpha_delta(n) */ @@ -671,11 +736,12 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, // otherwise no intra-slot frequency hopping shall be assumed //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers uint8_t intraSlotFrequencyHopping = 0; - if (startingPRB != startingPRB_intraSlotHopping){ + + if (startingPRB != startingPRB_intraSlotHopping) { intraSlotFrequencyHopping=1; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); +#endif // n_hop = 1 for second hop; // FIXME // When hopping will be activated we have to implement this function differently as PUCH signal generation depends on n_hop value for u,v calculation @@ -683,30 +749,32 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, // y_n contains the complex value d multiplied by the sequence r_u_v int16_t y_n_re[12],y_n_im[12]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", - n_hop,nr_tti_tx); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", + n_hop,nr_tti_tx); +#endif nr_group_sequence_hopping(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value alpha = nr_cyclic_shift_hopping(ue,m0,mcs,lnormal,lprime,nr_tti_tx); - for (int n=0; n<12; n++){ + + for (int n=0; n<12; n++) { r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) - - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha + - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha r_u_v_alpha_delta_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) - + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha + + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha // PUCCH sequence = DM-RS sequence multiplied by d(0) y_n_re[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15) - - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n) + - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n) y_n_im[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15) - + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) + + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) // DM-RS sequence r_u_v_alpha_delta_re[n] = (int16_t)(((int32_t)amp*r_u_v_alpha_delta_re[n])>>15); r_u_v_alpha_delta_im[n] = (int16_t)(((int32_t)amp*r_u_v_alpha_delta_im[n])>>15); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n", - u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n", + u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]); +#endif } + /* * The block of complex-valued symbols y(n) shall be block-wise spread with the orthogonal sequence wi(m) * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im) @@ -736,124 +804,144 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, uint8_t N_SF_mprime0_PUCCH_DMRS_1; // mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping uint8_t mprime = 0; + if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n", + intraSlotFrequencyHopping); +#endif N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (PUCCH) N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (DM-RS) N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (PUCCH) N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (DM-RS) - for (int m=0; m < N_SF_mprime_PUCCH_1; m++){ - for (int n=0; n<12 ; n++){ + + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + for (int n=0; n<12 ; n++) { z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t z_pucch[%d] \t= ((%d \t* %d \t-%d \t* %d), (%d \t* %d \t+%d \t*%d)) = (%d,%d)\n", - (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], - z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); - #endif + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t z_pucch[%d] \t= ((%d \t* %d \t-%d \t* %d), (%d \t* %d \t+%d \t*%d)) = (%d,%d)\n", + (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif } } - for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++){ - for (int n=0; n<12 ; n++){ + + for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + for (int n=0; n<12 ; n++) { z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15)); + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15)); z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15)); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t z_dm-rs[%d] = ((),()) =(%d,%d)\n", - (mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n,z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); - #endif + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t z_dm-rs[%d] = ((),()) =(%d,%d)\n", + (mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n,z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif } } } + if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n", + intraSlotFrequencyHopping); +#endif N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) - for (mprime = 0; mprime<2; mprime++){ // mprime can get values {0,1} - for (int m=0; m < N_SF_mprime_PUCCH_1; m++){ - for (int n=0; n<12 ; n++){ + + for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1} + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + for (int n=0; n<12 ; n++) { z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); } } - for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++){ - for (int n=0; n<12 ; n++){ + + for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + for (int n=0; n<12 ; n++) { z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15)); + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15)); z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15)); + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15)); } } + N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) } } -/* - * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources - */ + + /* + * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources + */ int32_t *txptr; uint32_t re_offset; int i=0; + for (int l=0; l<nrofSymbols; l++) { if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new PRB, FIXME!!! startingPRB = startingPRB + startingPRB_intraSlotHopping; } + if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))); } + if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6; } + if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; } + txptr = &txdataF[0][re_offset]; - for (int n=0; n<12; n++){ + + for (int n=0; n<12; n++) { if ((n==6) && (startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB) re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size); } + if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1 ((int16_t *)&txdataF[0][re_offset])[0] = z_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + if (l%2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1 ((int16_t *)&txdataF[0][re_offset])[0] = z_dmrs_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_dmrs_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + re_offset++; } + if (l%2 == 1) i+=12; } } @@ -861,7 +949,6 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint32_t B,uint8_t *btilde) __attribute__((always_inline)); inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint32_t B,uint8_t *btilde) { - uint32_t x1, x2, s=0; int i; uint8_t c; @@ -869,20 +956,21 @@ inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id, //x2 = (rnti) + ((uint32_t)(1+nr_tti_tx)<<16)*(1+(fp->Nid_cell<<1)); x2 = ((rnti)<<15)+n_id; s = lte_gold_generic(&x1, &x2, 1); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%lx\n",s); - #endif - for (i=0;i<M_bit;i++) { +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%lx\n",s); +#endif + + for (i=0; i<M_bit; i++) { c = (uint8_t)((s>>i)&1); btilde[i] = (((B>>i)&1) ^ c); - #ifdef DEBUG_NR_PUCCH_TX - //printf("\t\t\t btilde[%d]=%lx from scrambled bit %d\n",i,btilde[i],((B>>i)&1)); - #endif +#ifdef DEBUG_NR_PUCCH_TX + //printf("\t\t\t btilde[%d]=%lx from scrambled bit %d\n",i,btilde[i],((B>>i)&1)); +#endif } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_pucch2_3_4_scrambling] scrambling M_bit=%d bits\n", M_bit); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_pucch2_3_4_scrambling] scrambling M_bit=%d bits\n", M_bit); +#endif } void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, @@ -899,79 +987,90 @@ void nr_uci_encoding(uint64_t payload, * Implementing TS 38.212 Subclause 6.3.1.2 * */ - // A is the payload size, to be provided in function call uint8_t A = nr_bit; // L is the CRC size uint8_t L; // E is the rate matching output sequence length as given in TS 38.212 subclause 6.3.1.4.1 uint16_t E=0,E_init; + if (fmt == pucch_format2_nr) E = 16*nrofSymbols*nrofPRB; - if (fmt == pucch_format3_nr){ + + if (fmt == pucch_format3_nr) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; + if (nrofSymbols == 4) { E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)*nrofPRB):((E_init*(nrofSymbols-1)*nrofPRB)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 3 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); +#endif } + if (nrofSymbols > 4) { E = E_init*(nrofSymbols-2)*nrofPRB; - #ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 3 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); +#endif } + if (nrofSymbols > 9) { E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)*nrofPRB):((E_init*(nrofSymbols-4)*nrofPRB)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 3 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); +#endif } } - if (fmt == pucch_format4_nr){ + + if (fmt == pucch_format4_nr) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; + if (nrofSymbols == 4) { E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)/n_SF_PUCCH_s):((E_init*(nrofSymbols-1)/n_SF_PUCCH_s)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 4 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); +#endif } + if (nrofSymbols > 4) { E = E_init*(nrofSymbols-2)/n_SF_PUCCH_s; - #ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 4 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); +#endif } + if (nrofSymbols > 9) { E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)/n_SF_PUCCH_s):((E_init*(nrofSymbols-4)/n_SF_PUCCH_s)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 4 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); +#endif } } + *M_bit = E; int I_seg; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_uci_encoding] start function with fmt=%d, encoding A=%d bits into M_bit=%d (where nrofSymbols=%d,nrofPRB=%d)\n",fmt,A,*M_bit,nrofSymbols,nrofPRB); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_uci_encoding] start function with fmt=%d, encoding A=%d bits into M_bit=%d (where nrofSymbols=%d,nrofPRB=%d)\n",fmt,A,*M_bit,nrofSymbols,nrofPRB); +#endif - if (A<=11){ + if (A<=11) { // procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2) // CRC bits are not attached, and coding small block lengths (subclause 5.3.3) - } else if (A>=12){ + } else if (A>=12) { // procedure in subclause 6.3.1.2.1 (UCI encoded by Polar code -> subclause 6.3.1.3.1) - if ((A>=360 && E>=1088)||(A>=1013)){ + if ((A>=360 && E>=1088)||(A>=1013)) { I_seg = 1; } else { I_seg = 0; } - if (A>=20){ + + if (A>=20) { // parity bits (subclause 5.2.1) computed by setting L=11 and using generator polynomial gCRC11(D) (subclause 5.1) L=11; - } else if (A<=19){ + } else if (A<=19) { // parity bits (subclause 5.2.1) computed by setting L=6 and using generator polynomial gCRC6(D) (subclause 5.1) L=6; } + // code block segmentation and CRC attachment is performed according to subclause 5.2.1 // polar coding subclause 5.3.1 } @@ -990,15 +1089,14 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint8_t nrofPRB, uint16_t startingPRB, uint8_t nr_bit) { - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n",nr_tti_tx, payload, nr_bit); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n",nr_tti_tx, payload, nr_bit); +#endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b; // M_bit is the number of bits of block b (payload after encoding) uint16_t M_bit; nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,&b,&M_bit); - /* * Implementing TS 38.211 * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2) @@ -1011,53 +1109,52 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, * n_id = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured * n_id = N_ID_cell if higher layer parameter not configured */ - uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI uint16_t rnti=crnti, n_id=0; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch2] rnti = %d ,\n",rnti); #endif - /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde); - /* * Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2 * btilde shall be modulated as described in subclause 5.1 using QPSK * resulting in a block of complex-valued modulation symbols d(0),...,d(m_symbol) where m_symbol=M_bit/2 */ - -//#define ONE_OVER_SQRT2_S 23171 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) - + //#define ONE_OVER_SQRT2_S 23171 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) // complex-valued symbol d(0) int16_t *d_re = malloc(sizeof(int16_t)*M_bit); int16_t *d_im = malloc(sizeof(int16_t)*M_bit); uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1; - for (int i=0; i < m_symbol; i++){ // QPSK modulation subclause 5.1.3 + + for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3 if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] modulation of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]); - #endif - } +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] modulation of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]); +#endif + } /* * Implementing TS 38.211 Subclause 6.3.2.5.3 Mapping to physical resources @@ -1067,58 +1164,76 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint32_t x1, x2, s=0; int i=0; int m=0; + for (int l=0; l<nrofSymbols; l++) { x2 = (((1<<17)*((14*nr_tti_tx) + (l+startingSymbolIndex) + 1)*((2*n_id) + 1)) + (2*n_id))%(1<<31); // c_init calculation according to TS38.211 subclause s = lte_gold_generic(&x1, &x2, 1); - for (int rb=0; rb<nrofPRB; rb++){ + m = 0; + + for (int rb=0; rb<nrofPRB; rb++) { //startingPRB = startingPRB + rb; if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; } + if (((rb+startingPRB) >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))); } + if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; } + if (((rb+startingPRB) > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6; } + if (((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; } + //txptr = &txdataF[0][re_offset]; int k=0; int kk=0; - for (int n=0; n<12; n++){ + + for (int n=0; n<12; n++) { if ((n==6) && ((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB) re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size); } + if (n%3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3 ((int16_t *)&txdataF[0][re_offset])[0] = d_re[i+k]; ((int16_t *)&txdataF[0][re_offset])[1] = d_im[i+k]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] (n=%d,i=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+k,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] (n=%d,i=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+k,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif k++; } + if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2 ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>(2*m))&1)))))>>15); ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>((2*m)+1))&1)))))>>15); m++; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] (n=%d,i=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+kk,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] (n=%d,i=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+kk,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif kk++; } + re_offset++; } + i+=8; + + if ((m&((1<<4)-1))==0) { + s = lte_gold_generic(&x1, &x2, 0); + m = 0; + } } } } @@ -1140,10 +1255,9 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, uint8_t nr_bit, uint8_t occ_length_format4, uint8_t occ_index_format4) { - - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n", nr_tti_tx, payload, nr_bit); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n", nr_tti_tx, payload, nr_bit); +#endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b; // M_bit is the number of bits of block b (payload after encoding) @@ -1156,19 +1270,21 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, // otherwise no intra-slot frequency hopping shall be assumed //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers uint8_t intraSlotFrequencyHopping = 0; - if (startingPRB != startingPRB_intraSlotHopping){ + + if (startingPRB != startingPRB_intraSlotHopping) { intraSlotFrequencyHopping=1; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); +#endif } + // add_dmrs indicates if we are using or not Additional DM-RS for formats 3 and 4. From higher layers. FIXME!!! uint8_t add_dmrs = 0; + //nrofPRB = 2; // only for test purposes if (fmt == pucch_format4_nr) nrofPRB = 1; nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,&b,&M_bit); - /* * Implementing TS 38.211 * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) @@ -1181,19 +1297,16 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, * n_id = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured * n_id = N_ID_cell if higher layer parameter not configured */ - uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI uint16_t rnti=crnti, n_id=0; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] rnti = %d ,\n",rnti); #endif - /* * Implementing TS 38.211 Subclause 6.3.2.6.1 scrambling formats 3 and 4 */ nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde); - /* * Implementing TS 38.211 Subclause 6.3.2.6.2 modulation formats 3 and 4 * @@ -1204,53 +1317,64 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, int16_t *d_re = malloc(sizeof(int16_t)*M_bit); int16_t *d_im = malloc(sizeof(int16_t)*M_bit); uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1; - if (is_pi_over_2_bpsk_enabled == 0){ + + if (is_pi_over_2_bpsk_enabled == 0) { // using QPSK if PUCCH format 3,4 and pi/2-BPSK is not configured, according to subclause 6.3.2.6.2 - for (int i=0; i < m_symbol; i++){ // QPSK modulation subclause 5.1.3 + for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3 if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - #ifdef DEBUG_NR_PUCCH_TX + +#ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] modulation QPSK of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]); - #endif +#endif } } - if (is_pi_over_2_bpsk_enabled == 1){ + + if (is_pi_over_2_bpsk_enabled == 1) { // using PI/2-BPSK if PUCCH format 3,4 and pi/2-BPSK is configured, according to subclause 6.3.2.6.2 m_symbol = M_bit; - for (int i=0; i<m_symbol; i++){ // PI/2-BPSK modulation subclause 5.1.1 - if (((btilde[i]&1)==0) && (i%2 == 0)){ + + for (int i=0; i<m_symbol; i++) { // PI/2-BPSK modulation subclause 5.1.1 + if (((btilde[i]&1)==0) && (i%2 == 0)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (((btilde[i]&1)==0) && (i%2 == 1)){ + + if (((btilde[i]&1)==0) && (i%2 == 1)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (((btilde[i]&1)==1) && (i%2 == 0)){ + + if (((btilde[i]&1)==1) && (i%2 == 0)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (((btilde[i]&1)==1) && (i%2 == 1)){ + + if (((btilde[i]&1)==1) && (i%2 == 1)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - #ifdef DEBUG_NR_PUCCH_TX + +#ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] modulation PI/2-BPSK of bit btilde(%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[i]&1),m_symbol,i,d_re[i],d_im[i]); - #endif +#endif } } @@ -1269,67 +1393,76 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, // Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1) // k={0,..11} n={0,1,2,3} // parameter PUCCH-F4-preDFT-OCC-index set of {0,1,2,3} -> n - uint16_t table_6_3_2_6_3_1_Wn_Re[2][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1}}; + uint16_t table_6_3_2_6_3_1_Wn_Re[2][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1} + }; // Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1) // k={0,..11} n={0,1} uint16_t table_6_3_2_6_3_1_Wn_Im[2][12] = {{0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0}}; + {0,0,0,0,0,0,0,0,0,0,0,0} + }; // Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2) // k={0,..11} n={0,1,2.3} uint16_t table_6_3_2_6_3_2_Wn_Re[4][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}, - {1, 1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1}, - {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}}; + {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}, + {1, 1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1}, + {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0} + }; // Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2) // k={0,..11} n={0,1,2,3} uint16_t table_6_3_2_6_3_2_Wn_Im[4][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0,-1,-1,-1, 0, 0, 0, 1, 1, 1}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1}}; + {0, 0, 0,-1,-1,-1, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1} + }; //uint8_t occ_Length = occ_length_format4; // higher layer parameter occ-Length uint8_t occ_Index = occ_index_format4; // higher layer parameter occ-Index -//occ_Index = 1; //only for testing purposes; to be removed FIXME!!! - if (fmt == pucch_format3_nr){ // no block-wise spreading for format 3 + + //occ_Index = 1; //only for testing purposes; to be removed FIXME!!! + if (fmt == pucch_format3_nr) { // no block-wise spreading for format 3 n_SF_PUCCH_s = 1; - for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++){ - for (int k=0; k < (12*nrofPRB); k++){ + + for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++) { + for (int k=0; k < (12*nrofPRB); k++) { y_n_re[l*(12*nrofPRB)+k] = d_re[l*(12*nrofPRB)+k]; y_n_im[l*(12*nrofPRB)+k] = d_im[l*(12*nrofPRB)+k]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] block-wise spreading for format 3 (no block-wise spreading): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", - l,k,l*(12*nrofPRB)+k,d_re[l*(12*nrofPRB)+k],d_im[l*(12*nrofPRB)+k]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] block-wise spreading for format 3 (no block-wise spreading): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", + l,k,l*(12*nrofPRB)+k,d_re[l*(12*nrofPRB)+k],d_im[l*(12*nrofPRB)+k]); +#endif } } } - if (fmt == pucch_format4_nr){ + + if (fmt == pucch_format4_nr) { nrofPRB = 1; - for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++){ - for (int k=0; k < (12*nrofPRB); k++){ - if (n_SF_PUCCH_s == 2){ + + for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) { + for (int k=0; k < (12*nrofPRB); k++) { + if (n_SF_PUCCH_s == 2) { y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k]) - - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); + - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k]) - + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 2) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", - occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); -// printf("\t\t d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); -// printf("\t\t d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); -// printf("\t\t table_6_3_2_6_3_1_Wn_Re[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Re[occ_Index][k]); -// printf("\t\t table_6_3_2_6_3_1_Wn_Im[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Im[occ_Index][k]); - #endif + + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 2) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", + occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); + // printf("\t\t d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); + // printf("\t\t d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); + // printf("\t\t table_6_3_2_6_3_1_Wn_Re[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Re[occ_Index][k]); + // printf("\t\t table_6_3_2_6_3_1_Wn_Im[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Im[occ_Index][k]); +#endif } - if (n_SF_PUCCH_s == 4){ + + if (n_SF_PUCCH_s == 4) { y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k]) - - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); + - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k]) - + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 4) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", - occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); - #endif + + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 4) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", + occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); +#endif } } } @@ -1340,37 +1473,40 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, */ int16_t *z_re = malloc(sizeof(int16_t)*4*M_bit); // 4 is the maximum number n_SF_PUCCH_s int16_t *z_im = malloc(sizeof(int16_t)*4*M_bit); - #define M_PI 3.14159265358979323846 // pi +#define M_PI 3.14159265358979323846 // pi + //int16_t inv_sqrt_nrofPRBs = (int16_t)round(32767/sqrt(12*nrofPRB)); - for (int l=0; l<floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++){ - for (int k=0; k<(12*nrofPRB); k++){ + for (int l=0; l<floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) { + for (int k=0; k<(12*nrofPRB); k++) { z_re[l*(12*nrofPRB)+k] = 0; z_im[l*(12*nrofPRB)+k] = 0; -// int16_t z_re_tmp[240] = {0}; -// int16_t z_im_tmp[240] = {0}; - for (int m=0; m<(12*nrofPRB); m++){ + + // int16_t z_re_tmp[240] = {0}; + // int16_t z_im_tmp[240] = {0}; + for (int m=0; m<(12*nrofPRB); m++) { //z_re[l*(12*nrofPRB)+k] = y_n_re[l*(12*nrofPRB)+m] * (int16_t)(round(32767*cos((2*M_PI*m*k)/(12*nrofPRB)))); -// z_re_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) -// + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); -// z_im_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) -// - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); + // z_re_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + // + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); + // z_im_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + // - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); z_re[l*(12*nrofPRB)+k] = z_re[l*(12*nrofPRB)+k] - + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) - + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); + + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); z_im[l*(12*nrofPRB)+k] = z_im[l*(12*nrofPRB)+k] - + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) - - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); - #ifdef DEBUG_NR_PUCCH_TX -// printf("\t\t z_re_tmp[%d] = %d\n",m,z_re_tmp[m]); -// printf("\t\t z_im_tmp[%d] = %d\n",m,z_im_tmp[m]); -// printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k,m)=(%d,%d,%d)\tz(%d) = \t(%d, %d)\n", -// l,k,m,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); - #endif + + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); +#ifdef DEBUG_NR_PUCCH_TX + // printf("\t\t z_re_tmp[%d] = %d\n",m,z_re_tmp[m]); + // printf("\t\t z_im_tmp[%d] = %d\n",m,z_im_tmp[m]); + // printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k,m)=(%d,%d,%d)\tz(%d) = \t(%d, %d)\n", + // l,k,m,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); +#endif } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k)=(%d,%d)\tz(%d) = \t(%d, %d)\n", - l,k,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); - #endif + +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k)=(%d,%d)\tz(%d) = \t(%d, %d)\n", + l,k,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); +#endif } } @@ -1392,160 +1528,178 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, // m0 is the cyclic shift index calculated depending on the Orthogonal sequence index n, according to table 6.4.1.3.3.1-1 from TS 38.211 subclause 6.4.1.3.3.1 uint8_t m0; uint8_t mcs=0; + if (fmt == pucch_format3_nr) m0 = 0; + if (fmt == pucch_format4_nr) { if (n_SF_PUCCH_s == 2) { m0 = (occ_Index == 0) ? 0 : 6; } + if (n_SF_PUCCH_s == 4) { m0 = (occ_Index == 3) ? 9 : ((occ_Index == 2) ? 3 : ((occ_Index == 1) ? 6 : 0)); } } + double alpha; uint8_t N_ZC = 12*nrofPRB; int16_t *r_u_v_base_re = malloc(sizeof(int16_t)*12*nrofPRB); int16_t *r_u_v_base_im = malloc(sizeof(int16_t)*12*nrofPRB); //int16_t *r_u_v_alpha_delta_re = malloc(sizeof(int16_t)*12*nrofPRB); //int16_t *r_u_v_alpha_delta_im = malloc(sizeof(int16_t)*12*nrofPRB); - // Next we proceed to mapping to physical resources according to TS 38.211, subclause 6.3.2.6.5 dor PUCCH formats 3 and 4 and subclause 6.4.1.3.3.2 for DM-RS //int32_t *txptr; uint32_t re_offset=0; //uint32_t x1, x2, s=0; // intraSlotFrequencyHopping // uint8_t intraSlotFrequencyHopping = 0; - uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] ={ - {(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4 - {1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5 - {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 6 - {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 7 - {0,1,0,0,0,1,0,0,0,0,0,0,0,0}, // PUCCH length = 8 - {0,1,0,0,0,0,1,0,0,0,0,0,0,0}, // PUCCH length = 9 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,0,0,0}, // PUCCH length = 10 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0,0}, // PUCCH length = 11 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0}, // PUCCH length = 12 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13 - {0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0} // PUCCH length = 14 + uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] = { + {(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4 + {1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5 + {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 6 + {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 7 + {0,1,0,0,0,1,0,0,0,0,0,0,0,0}, // PUCCH length = 8 + {0,1,0,0,0,0,1,0,0,0,0,0,0,0}, // PUCCH length = 9 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,0,0,0}, // PUCCH length = 10 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0,0}, // PUCCH length = 11 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0}, // PUCCH length = 12 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13 + {0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0} // PUCCH length = 14 }; uint16_t k=0; - for (int l=0; l<nrofSymbols; l++) { + for (int l=0; l<nrofSymbols; l++) { if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop - nr_group_sequence_hopping(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value + nr_group_sequence_hopping(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value // Next we proceed to calculate base sequence for DM-RS signal, according to TS 38.211 subclause 6.4.1.33 if (nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies int i = 4; + while (list_of_prime_numbers[i] < (12*nrofPRB)) i++; + N_ZC = list_of_prime_numbers[i+1]; // N_ZC is given by the largest prime number such that N_ZC < (12*nrofPRB) double q_base = (N_ZC*(u+1))/31; int8_t q = (uint8_t)floor(q_base + (1/2)); q = ((uint8_t)floor(2*q_base)%2 == 0 ? q+v : q-v); - for (int n=0; n<(12*nrofPRB); n++){ + + for (int n=0; n<(12*nrofPRB); n++) { r_u_v_base_re[n] = (int16_t)(((int32_t)amp*(int16_t)(32767*cos(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15); r_u_v_base_im[n] = -(int16_t)(((int32_t)amp*(int16_t)(32767*sin(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d >= 3: r_u_v_base[n=%d]=(%d,%d)\n", - nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d >= 3: r_u_v_base[n=%d]=(%d,%d)\n", + nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); +#endif } } + if (nrofPRB == 2) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-4) applies - for (int n=0; n<(12*nrofPRB); n++){ + for (int n=0; n<(12*nrofPRB); n++) { r_u_v_base_re[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_4_Re[u][n])>>15); r_u_v_base_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_4_Im[u][n])>>15); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 2: r_u_v_base[n=%d]=(%d,%d)\n", - nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 2: r_u_v_base[n=%d]=(%d,%d)\n", + nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); +#endif } } + if (nrofPRB == 1) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-2) applies - for (int n=0; n<(12*nrofPRB); n++){ + for (int n=0; n<(12*nrofPRB); n++) { r_u_v_base_re[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_2_Re[u][n])>>15); r_u_v_base_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_2_Im[u][n])>>15); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 1: r_u_v_base[n=%d]=(%d,%d)\n", - nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 1: r_u_v_base[n=%d]=(%d,%d)\n", + nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); +#endif } } - - uint16_t j=0; alpha = nr_cyclic_shift_hopping(ue,m0,mcs,l,startingSymbolIndex,nr_tti_tx); - for (int rb=0; rb<nrofPRB; rb++){ + + for (int rb=0; rb<nrofPRB; rb++) { if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB startingPRB = startingPRB + startingPRB_intraSlotHopping; } + //startingPRB = startingPRB + rb; if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; - #ifdef DEBUG_NR_PUCCH_TX - printf("1 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("1 "); +#endif } + if (((rb+startingPRB) >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))); - #ifdef DEBUG_NR_PUCCH_TX - printf("2 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("2 "); +#endif } + if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; - #ifdef DEBUG_NR_PUCCH_TX - printf("3 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("3 "); +#endif } + if (((rb+startingPRB) > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6; - #ifdef DEBUG_NR_PUCCH_TX - printf("4 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("4 "); +#endif } + if (((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; - #ifdef DEBUG_NR_PUCCH_TX - printf("5 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("5 "); +#endif } - #ifdef DEBUG_NR_PUCCH_TX - printf("re_offset=%d,(rb+startingPRB)=%d\n",re_offset,(rb+startingPRB)); - #endif + +#ifdef DEBUG_NR_PUCCH_TX + printf("re_offset=%d,(rb+startingPRB)=%d\n",re_offset,(rb+startingPRB)); +#endif + //txptr = &txdataF[0][re_offset]; - for (int n=0; n<12; n++){ + for (int n=0; n<12; n++) { if ((n==6) && ((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB) re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size); } + if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 0) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3 ((int16_t *)&txdataF[0][re_offset])[0] = z_re[n+k]; ((int16_t *)&txdataF[0][re_offset])[1] = z_im[n+k]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(z(l=%d,n=%d)=(%d,%d))\n", - l,rb,n,k,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+k,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(z(l=%d,n=%d)=(%d,%d))\n", + l,rb,n,k,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+k,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2 ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15) - - (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15)); + - (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15)); ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15) - + (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15)); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(r_u_v(l=%d,n=%d)=(%d,%d))\n", - l,rb,n,j,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+j,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif + + (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(r_u_v(l=%d,n=%d)=(%d,%d))\n", + l,rb,n,j,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+j,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + re_offset++; } + if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 0) k+=12; + if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) j+=12; } } - } diff --git a/openair1/PHY/TOOLS/cdot_prod.c b/openair1/PHY/TOOLS/cdot_prod.c index 06546467b1c7eeab52adfa6789538d8903c1272e..843a9605f11e229de07d4acfcffe1119dd43a1ce 100644 --- a/openair1/PHY/TOOLS/cdot_prod.c +++ b/openair1/PHY/TOOLS/cdot_prod.c @@ -180,14 +180,13 @@ int64_t dot_product64(int16_t *x, for (n=0; n<(N>>2); n++) { // printf("n=%d, x128=%p, y128=%p\n",n,x128,y128); - // print_shorts("x",&x128[0]); - // print_shorts("y",&y128[0]); + // print_shorts("x",&x128[0]); + // print_shorts("y",&y128[0]); // this computes Re(z) = Re(x)*Re(y) + Im(x)*Im(y) mmtmp1 = _mm_madd_epi16(x128[0],y128[0]); // print_ints("retmp",&mmtmp1); // mmtmp1 contains real part of 4 consecutive outputs (32-bit) - // shift and accumulate results mmtmp1 = _mm_srai_epi32(mmtmp1,output_shift); mmcumul_re = _mm_add_epi32(mmcumul_re,mmtmp1); @@ -205,7 +204,6 @@ int64_t dot_product64(int16_t *x, mmtmp3 = _mm_madd_epi16(x128[0],mmtmp2); //print_ints("imtmp",&mmtmp3); // mmtmp3 contains imag part of 4 consecutive outputs (32-bit) - // shift and accumulate results mmtmp3 = _mm_srai_epi32(mmtmp3,output_shift); mmcumul_im = _mm_add_epi32(mmcumul_im,mmtmp3); @@ -218,13 +216,10 @@ int64_t dot_product64(int16_t *x, // this gives Re Re Im Im mmcumul = _mm_hadd_epi32(mmcumul_re,mmcumul_im); //print_ints("cumul1",&mmcumul); - // this gives Re Im Re Im mmcumul = _mm_hadd_epi32(mmcumul,mmcumul); - //print_ints("cumul2",&mmcumul); - //mmcumul = _mm_srai_epi32(mmcumul,output_shift); // extract the lower half result = _mm_extract_epi64(mmcumul,0); diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 0100dd44c405665182b55445f9d9e0781dc43472..3dd16ff0dad7c738379fbab06cc3be07b752692b 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -498,10 +498,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, float **rxsig_t_dB; float *time; float *corr; - /* int16_t **chest_t; int16_t **chest_f; - */ int16_t *pdsch_llr; int16_t *pdsch_comp; //int16_t *pdsch_mag; @@ -519,10 +517,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, int coded_bits_per_codeword = num_re*Qm; int symbol, first_symbol,nb_re; int nb_rb_pdsch =50; + float ymax=1; + float **chest_t_abs; + float Re,Im; + float *chest_f_abs; + float *freq; + static int overlay = 0; /* - float Re,Im,ymax=1; - float **chest_t_abs, *chest_f_abs; - float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx; int mcs = 0; unsigned char harq_pid = 0; @@ -565,15 +566,15 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, */ I = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float)); Q = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float)); - /* + chest_t_abs = (float**) malloc(nb_antennas_rx*sizeof(float*)); for (arx=0; arx<nb_antennas_rx; arx++) { chest_t_abs[arx] = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); } - chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); - */ + chest_f_abs = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); + freq = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero bit = malloc(coded_bits_per_codeword*sizeof(float)); @@ -589,10 +590,9 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, time = calloc(samples_per_frame,sizeof(float)); corr = calloc(samples_per_frame,sizeof(float)); - /* chest_t = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id]; chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id]; - */ + pbch_llr = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; @@ -628,29 +628,37 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } if (phy_vars_ue->is_synchronized==0) { - for (ind=0;ind<3;ind++) { - if (pss_corr_ue[ind]) { - for (i=0; i<samples_per_frame; i++) { - corr[i] = (float) pss_corr_ue[ind][i]; - time[i] = (float) i; + for (ind=0;ind<3;ind++) { + if (pss_corr_ue[ind]) { + for (i=0; i<samples_per_frame; i++) { + corr[i] = (float) pss_corr_ue[ind][i]; + time[i] = (float) i; + } + + if (ind==0) + fl_set_xyplot_data(form->chest_t,time,corr,samples_per_frame,"","",""); + else + fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]); + + overlay = 1; } - - if (ind==0) - fl_set_xyplot_data(form->chest_t,time,corr,samples_per_frame,"","",""); - else - fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]); } - } + } + else { + + if (overlay) { //there was a previous overlay + fl_clear_xyplot(form->chest_t); + overlay = 0; } - /* - // Channel Impulse Response (still repeated format) + // Channel Impulse Response if (chest_t != NULL) { ymax = 0; if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { - chest_t_abs[0][i] = (float) (chest_t[0][4*i]*chest_t[0][4*i]+chest_t[0][4*i+1]*chest_t[0][4*i+1]); + chest_t_abs[0][i] = (float) (chest_t[0][2*i]*chest_t[0][2*i]+chest_t[0][2*i+1]*chest_t[0][2*i+1]); + time[i] = (float) i; if (chest_t_abs[0][i] > ymax) ymax = chest_t_abs[0][i]; @@ -658,7 +666,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_data(form->chest_t,time,chest_t_abs[0],(frame_parms->ofdm_symbol_size>>3),"","",""); } - + /* for (arx=1; arx<nb_antennas_rx; arx++) { if (chest_t[arx] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { @@ -672,11 +680,12 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT); } } - + */ // Avoid flickering effect // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); // Does not always work... fl_set_xyplot_ybounds(form->chest_t,0,(double) ymax); } + } // Channel Frequency Response (includes 5 complex sample for filter) if (chest_f != NULL) { @@ -685,7 +694,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, for (atx=0; atx<nb_antennas_tx; atx++) { for (arx=0; arx<nb_antennas_rx; arx++) { if (chest_f[(atx<<1)+arx] != NULL) { - for (k=0; k<nsymb_ce; k++) { + for (k=0; k<frame_parms->ofdm_symbol_size; k++) { freq[ind] = (float)ind; Re = (float)(chest_f[(atx<<1)+arx][(2*k)]); Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]); @@ -698,12 +707,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } // tx antenna 0 - fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); + //fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); - fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); - fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); + //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); + fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,frame_parms->ofdm_symbol_size,"","",""); + /* for (arx=1; arx<nb_antennas_rx; arx++) { fl_add_xyplot_overlay(form->chest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } @@ -722,8 +732,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } } + */ } - */ // PBCH LLRs if (pbch_llr != NULL) { @@ -735,10 +745,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_data(form->pbch_llr,bit_pbch,llr_pbch,864,"","",""); } - if (phy_vars_ue->is_synchronized==1) - first_symbol=5; - else - first_symbol=1; + first_symbol=1; // PBCH I/Q of MF Output if (pbch_comp!=NULL) { diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 3d56147c8eecf5dac2e0afeb3711ec5a57ee761a..2823a58f39a16f8694a34d17bbbc521751770819 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -983,6 +983,8 @@ typedef struct { int UE_scan; /// \brief Indicator that UE should perform coarse scanning around carrier int UE_scan_carrier; + /// \brief Indicator that UE should enable estimation and compensation of frequency offset + int UE_fo_compensation; /// \brief Indicator that UE is synchronized to an eNB int is_synchronized; /// Data structure for UE process scheduling diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h index ae17c4853386d34f9a3e1052f39f07718d655d11..05e14f5e8d92c9f72e62140733362bd544bd7d86 100644 --- a/openair1/PHY/impl_defs_nr.h +++ b/openair1/PHY/impl_defs_nr.h @@ -736,7 +736,7 @@ typedef struct { -- Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) hoppingId BIT STRING (SIZE (10)) OPTIONAL, -- Need R */ - uint16_t hoppingId; + uint32_t hoppingId; /* -- Power control parameter P0 for PUCCH transmissions. Value in dBm. Only even values (step size 2) allowed. -- Corresponds to L1 parameter 'p0-nominal-pucch' (see 38.213, section 7.2) diff --git a/openair1/SCHED_NR/phy_procedures_nr_common.c b/openair1/SCHED_NR/phy_procedures_nr_common.c old mode 100644 new mode 100755 diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 7cbb70242efb939ed510d23a4db715ece84bc647..a7f8ef68840ffa041361b0770e809c79a6f66f08 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -138,20 +138,22 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) { LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol); nr_generate_pss(gNB->d_pss, txdataF[0], AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(gNB->d_sss, txdataF[0], AMP_OVER_2, ssb_start_symbol, cfg, fp); + nr_generate_sss(gNB->d_sss, txdataF[0], AMP, ssb_start_symbol, cfg, fp); if (!(frame&7)){ LOG_D(PHY,"%d.%d : pbch_configured %d\n",frame,slot,gNB->pbch_configured); if (gNB->pbch_configured != 1)return; gNB->pbch_configured = 0; } - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP_OVER_2, ssb_start_symbol, cfg, fp); + + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp); + nr_generate_pbch(&gNB->pbch, gNB->nrPolar_params, pbch_pdu, gNB->nr_pbch_interleaver, txdataF[0], - AMP_OVER_2, + AMP, ssb_start_symbol, n_hf,Lmax,ssb_index, frame, cfg, fp); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 0aeab29f97101d1cf1dd17104f6853b0c8426665..ca30ab1cec789a8f2fe05d2e3f39f9a82b13b72f 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -48,11 +48,13 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ /// component carrier id uint8_t cc_id = scheduled_response->CC_id; uint32_t i; + int slot = scheduled_response->slot; + uint8_t thread_id = PHY_vars_UE_g[module_id][cc_id]->current_thread_id[slot]; if(scheduled_response != NULL){ // Note: we have to handle the thread IDs for this. To be revisited completely. - NR_UE_PDCCH *pdcch_vars2 = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[0][0]; - NR_UE_DLSCH_t *dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[0][0][0]; + NR_UE_PDCCH *pdcch_vars2 = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0]; + NR_UE_DLSCH_t *dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[thread_id][0][0]; NR_UE_ULSCH_t *ulsch0 = PHY_vars_UE_g[module_id][cc_id]->ulsch[0]; NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms; PRACH_RESOURCES_t *prach_resources = PHY_vars_UE_g[module_id][cc_id]->prach_resources[0]; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 3b7d86f16bd8fd5a47c2d6fe0b58f8caf966dbe7..3c48e73889bd84d06f783c13b92dc89bfcea4cf3 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2781,8 +2781,6 @@ void nr_ue_measurement_procedures( */ eNB_id = 0; - - LOG_D(PHY,"start adjust sync l = %d slot = %d no timing %d\n",l, slot, ue->no_timing_correction); if (ue->no_timing_correction==0) nr_adjust_synch_ue(&ue->frame_parms, @@ -2791,7 +2789,6 @@ void nr_ue_measurement_procedures( nr_tti_rx, 0, 16384); - } @@ -4969,95 +4966,20 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN int frame_rx = proc->frame_rx; int nr_tti_rx = proc->nr_tti_rx; + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][0]; uint16_t nb_symb_sch = 8; // to be updated by higher layer - uint8_t nb_symb_pdcch =2; - //proc->decoder_switch = 0; - //int counter_decoder = 0; + uint8_t nb_symb_pdcch = pdcch_vars->coreset[0].duration; - LOG_D(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx%1024, nr_tti_rx); uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); -#if 0 - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); - -#if T_TRACER - T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx)); - - T(T_UE_PHY_INPUT_SIGNAL, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx), T_INT(0), - T_BUFFER(&ue->common_vars.rxdata[0][nr_tti_rx*ue->frame_parms.samples_per_subframe], - ue->frame_parms.samples_per_subframe * 4)); -#endif - - // start timers - //#ifdef UE_DEBUG_TRACE - LOG_I(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); - //#endif - -#if UE_TIMING_TRACE - start_meas(&ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]]); - start_meas(&ue->generic_stat); -#endif - - if (do_pdcch_flag) { - // deactivate reception until we scan pdcch - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]) - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 0; - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]) - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]->active = 0; - - if (ue->dlsch_SI[eNB_id]) - ue->dlsch_SI[eNB_id]->active = 0; - if (ue->dlsch_p[eNB_id]) - ue->dlsch_p[eNB_id]->active = 0; - if (ue->dlsch_ra[eNB_id]) - ue->dlsch_ra[eNB_id]->active = 0; - } - -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[%s %d] Frame %d nr_tti_rx %d: Doing phy_procedures_UE_RX\n", - (r_type == multicast_relay) ? "RN/UE" : "UE", - ue->Mod_id,frame_rx, nr_tti_rx); -#endif - - - if (ue->frame_parms.Ncp == 0) { // normal prefix - pilot1 = 4; - } else { // extended prefix - pilot1 = 3; - } - - /* - if (nr_subframe_select(&ue->frame_parms,nr_tti_rx) == SF_S) { // S-subframe, do first 5 symbols only - l2 = 5; - } else */ - { // normal nr_tti_rx, last symbol to be processed is the first of the second slot - l2 = (ue->frame_parms.symbols_per_tti/2)-1; - } - - int prev_nr_tti_rx = (nr_tti_rx - 1)<0? 9: (nr_tti_rx - 1);/* - if (nr_subframe_select(&ue->frame_parms,prev_nr_tti_rx) != SF_DL) { - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // RX processing of symbols l=0...l2 - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - l=0; - } else */ - { - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch) - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - l=1; - } - - LOG_D(PHY," ------ slot 0 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); -#endif - #ifdef NR_PDCCH_SCHED - //nr_gold_pdcch(ue,0, 2); + nr_gold_pdcch(ue,0, 2); //if (nr_tti_rx==1){ + LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); for (uint16_t l=0; l<nb_symb_pdcch; l++) { #if UE_TIMING_TRACE @@ -5088,16 +5010,16 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN //} #endif //NR_PDCCH_SCHED - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); if (nr_tti_rx==1){ + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); //to update from pdsch config nr_gold_pdsch(ue,nb_symb_pdcch,0, 1); for (uint16_t m=nb_symb_pdcch;m<=(nb_symb_sch+nb_symb_pdcch-1) ; m++){ nr_slot_fep(ue, m, //to be updated from higher layer - nr_tti_rx<<1, + nr_tti_rx, 0, 0, 1, @@ -5108,7 +5030,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN } //set active for testing, to be removed - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 1; + ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 0; } else ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 0; @@ -5131,7 +5053,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); } - LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); // do procedures for SI-RNTI if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); @@ -5173,62 +5094,12 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN ue->frame_parms.symbols_per_tti>>1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); } -//#if 0 - LOG_D(PHY," ------ slot 1 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - - /*if (nr_subframe_select(&ue->frame_parms,nr_tti_rx) != SF_S)*/ - { // do front-end processing for second slot, and first symbol of next nr_tti_rx - for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) { -#if UE_TIMING_TRACE - start_meas(&ue->ofdm_demod_stats); -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - /*nr_slot_fep(ue, - l, - 1+(nr_tti_rx<<1), - 0, - 0, - 0, - NR_PDSCH_EST);*/ - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); - -#if UE_TIMING_TRACE - stop_meas(&ue->ofdm_demod_stats); -#endif - - - //ue_measurement_procedures(l-1,ue,proc,eNB_id,1+(nr_tti_rx<<1),abstraction_flag,mode); - } // for l=1..l2 - - // do first symbol of next downlink nr_tti_rx for channel estimation - int next_nr_tti_rx = (1+nr_tti_rx)%10; - /* if (nr_subframe_select(&ue->frame_parms,next_nr_tti_rx) != SF_UL)*/ - { - /*nr_slot_fep(ue, - 0, - (next_nr_tti_rx<<1), - 0, - 0, - 0, - NR_PDSCH_EST);*/ - } - } // not an S-subframe -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat); -#if DISABLE_LOG_X - printf("[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#endif - -#endif - //LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); if ( (nr_tti_rx == 0) && (ue->decode_MIB == 1)) { + LOG_D(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); for (int i=0; i<3; i++) nr_slot_fep(ue, (5+i), //mu=1 case B @@ -5242,7 +5113,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN } // do procedures for C-RNTI - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 1c2b2305d6934606d0433f08588d35ebec381fcf..4a7699e6d18f8b26ad6c87d06661182ea2644f7c 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -144,7 +144,7 @@ int main(int argc, char **argv) { //char input_val_str[50],input_val_str2[50]; //uint16_t NB_RB=25; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; - uint8_t N_RB_DL = 106, mu = 1; + uint16_t N_RB_DL = 106, mu = 1; unsigned char frame_type = 0; unsigned char pbch_phase = 0; int frame = 0, subframe = 0; @@ -362,9 +362,10 @@ int main(int argc, char **argv) { if (snr1set == 0) snr1 = snr0 + 10; - gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, 61.44e6, //N_RB2sampling_rate(N_RB_DL), - 40e6, //N_RB2channel_bandwidth(N_RB_DL), - 0, 0, 0); + gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, + 61.44e6, //N_RB2sampling_rate(N_RB_DL), + 40e6, //N_RB2channel_bandwidth(N_RB_DL), + 0, 0, 0); if (gNB2UE == NULL) { msg("Problem generating channel model. Exiting.\n"); @@ -599,8 +600,10 @@ int main(int argc, char **argv) { (float) n_errors / (float) n_trials, (float) n_false_positive / (float) n_trials); - if ((float) n_errors / (float) n_trials < target_error_rate) - break; + if ((float) n_errors / (float) n_trials < target_error_rate) { + printf("PDSCH test OK\n"); + break; + } } /*LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f39c12165c3091badab50a31c2202b1a22edb868..7a08ede7135c108eb30671fc11f836dc40129489 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -154,7 +154,7 @@ int main(int argc, char **argv) unsigned char frame_type = 0; unsigned char pbch_phase = 0; - int frame=0,slot=0; + int frame=0,slot=1; int frame_length_complex_samples; int frame_length_complex_samples_no_prefix; int slot_length_complex_samples_no_prefix; @@ -543,18 +543,20 @@ int main(int argc, char **argv) if (gNB->frame_parms.nb_antennas_tx>1) LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1); + int tx_offset = slot*frame_parms->samples_per_slot; + //TODO: loop over slots for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) { if (gNB_config->subframe_config.dl_cyclic_prefix_type.value == 1) { PHY_ofdm_mod(gNB->common_vars.txdataF[aa], - txdata[aa], + &txdata[aa][tx_offset], frame_parms->ofdm_symbol_size, 12, frame_parms->nb_prefix_samples, CYCLIC_PREFIX); } else { nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], - txdata[aa], + &txdata[aa][tx_offset], 14, frame_parms); } diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index f71cb7d147b156a6dfe3756151d1340e4fc067e3..214a33fb73758b7e5ea6d05b827f9dab9f1eafcd 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -87,11 +87,13 @@ int main(int argc, char **argv) int i,aa;//,l; double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0; + double cfo=0; uint8_t snr1set=0; int **txdata; double **s_re,**s_im,**r_re,**r_im; - //double iqim = 0.0; - //unsigned char pbch_pdu[6]; + double iqim = 0.0; + double ip =0.0; + unsigned char pbch_pdu[6]; // int sync_pos, sync_pos_slot; // FILE *rx_frame_file; FILE *output_fd = NULL; @@ -146,7 +148,7 @@ int main(int argc, char **argv) randominit(0); - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:o:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) { switch (c) { case 'f': write_output_file=1; @@ -212,6 +214,11 @@ int main(int argc, char **argv) n_trials = atoi(optarg); break; + case 'o': + cfo = atof(optarg); + msg("Setting CFO to %f Hz\n",cfo); + break; + case 's': snr0 = atof(optarg); msg("Setting SNR0 to %f\n",snr0); @@ -325,6 +332,7 @@ int main(int argc, char **argv) printf("-z Number of RX antennas used in UE\n"); printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n"); printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n"); + printf("-o Carrier frequency offset in Hz\n"); printf("-N Nid_cell\n"); printf("-R N_RB_DL\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); @@ -356,30 +364,49 @@ int main(int argc, char **argv) frame_parms->nb_antennas_rx = n_rx; frame_parms->N_RB_DL = N_RB_DL; frame_parms->N_RB_UL = N_RB_DL; + frame_parms->Nid_cell = Nid_cell; nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell); phy_init_nr_gNB(gNB,0,0); - double fs,bw; + double fs,bw,scs,eps; if (mu == 1 && N_RB_DL == 217) { fs = 122.88e6; bw = 80e6; + scs = 30000; } else if (mu == 1 && N_RB_DL == 245) { fs = 122.88e6; bw = 90e6; + scs = 30000; } else if (mu == 1 && N_RB_DL == 273) { fs = 122.88e6; bw = 100e6; + scs = 30000; } else if (mu == 1 && N_RB_DL == 106) { fs = 61.44e6; bw = 40e6; + scs = 30000; } else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL); + // cfo with respect to sub-carrier spacing + eps = cfo/scs; + + // computation of integer and fractional FO to compare with estimation results + int IFO; + if(eps!=0.0){ + printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000)); + if (eps>0) + IFO=(int)(eps+0.5); + else + IFO=(int)(eps-0.5); + printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO); + } + gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, @@ -435,6 +462,9 @@ int main(int argc, char **argv) UE->perfect_ce = 0; + if(eps!=0.0) + UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation + if (init_nr_ue_signal(UE, 1, 0) != 0) { printf("Error at UE NR initialisation\n"); @@ -492,6 +522,7 @@ int main(int argc, char **argv) // printf("txlev %d (%f)\n",txlev,10*log10(txlev)); + for (i=0; i<frame_length_complex_samples; i++) { for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); @@ -510,11 +541,32 @@ int main(int argc, char **argv) //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0); //AWGN - sigma2_dB = 10*log10((double)txlev)-SNR; + sigma2_dB = 20*log10((double)AMP/4)-SNR; sigma2 = pow(10,sigma2_dB/10); - // printf("sigma2 %f (%f dB)\n",sigma2,sigma2_dB); - - for (i=0; i<frame_parms->samples_per_subframe; i++) { + //printf("sigma2 %f (%f dB), tx_lev %f (%f dB)\n",sigma2,sigma2_dB,txlev,10*log10((double)txlev)); + + if(eps!=0.0) + rf_rx(r_re, // real part of txdata + r_im, // imag part of txdata + NULL, // interference real part + NULL, // interference imag part + 0, // interference power + frame_parms->nb_antennas_rx, // number of rx antennas + frame_length_complex_samples, // number of samples in frame + 1.0e9/fs, //sampling time (ns) + cfo, // frequency offset in Hz + 0.0, // drift (not implemented) + 0.0, // noise figure (not implemented) + 0.0, // rx gain in dB ? + 200, // 3rd order non-linearity in dB ? + &ip, // initial phase + 30.0e3, // phase noise cutoff in kHz + -500.0, // phase noise amplitude in dBc + 0.0, // IQ imbalance (dB), + 0.0); // IQ phase imbalance (rad) + + + for (i=0; i<frame_length_complex_samples; i++) { for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { ((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt index 5d718a1911c4130fd9042662c7b5304878160ac8..836af4540a680edce6fa80c48b59aa26d5bd12d6 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt @@ -96,3 +96,8 @@ target_link_libraries(pucch_uci_test -Wl,--start-group UTIL SCHED_NR_UE_LIB PHY PHY_COMMON PHY_UE PHY_NR_UE -Wl,--end-group pthread m ${ATLAS_LIBRARIES} ) +add_executable(pucch_uci_generator_test ${OPENAIR1_DIR}/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c ${SRC_UNIT_TESTS} ) +target_link_libraries(pucch_uci_generator_test + -Wl,--start-group UTIL SCHED_NR_UE_LIB PHY PHY_COMMON PHY_UE PHY_NR_UE -Wl,--end-group + pthread m ${ATLAS_LIBRARIES} + ) \ No newline at end of file diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c index 24a86425f3d22583afb45fae86209a8d26b4e078..fa243d1eb040a728bc4b7ac03e9a36a63d2ca241 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c @@ -192,11 +192,10 @@ int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf) { retu void * get_shlibmodule_fptr(char *modname, char *fname) { return(NULL) ; } -void exit_fun(const char* s) -{ +/*void exit_fun (const char *s) { VOID_PARAMETER s; undefined_function(__FUNCTION__); -} +}*/ uint32_t ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, rnti_t rnti, sub_frame_t subframe){ diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c index c33571c6ea6453ee630683fa8c84600d7a79f2d5..9a4df025c73f5ce4bb286b8df0a44e1b70c45d39 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c @@ -66,7 +66,7 @@ /*************** LOCAL VARIABLES***********************************/ static nfapi_config_request_t config_t; -static nfapi_config_request_t* config =&config_t; +static nfapi_config_request_t *config =&config_t; /*************** FUNCTIONS ****************************************/ @@ -86,8 +86,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_eNB, uint8_t abstract * *********************************************************************/ -void phase_shift_samples(int16_t *samples, int length, int16_t phase_shift_re, int16_t phase_shift_im) -{ +void phase_shift_samples(int16_t *samples, int length, int16_t phase_shift_re, int16_t phase_shift_im) { int16_t sample_re, sample_im; for (int i = 0; i < length; i++) { @@ -112,22 +111,23 @@ void phase_shift_samples(int16_t *samples, int length, int16_t phase_shift_re, i * *********************************************************************/ -void display_data(int pss_sequence_number, int16_t *rxdata, int position) -{ +void display_data(int pss_sequence_number, int16_t *rxdata, int position) { #ifdef DEBUG_TEST_PSS int16_t *pss_sequence[NUMBER_PSS_SEQUENCE] = {primary_synch0_time, primary_synch1_time, primary_synch2_time}; int16_t *pss_sequence_time = pss_sequence[pss_sequence_number]; printf(" pss %6d data \n", pss_sequence_number); + for (int i = 0; i < 4; i++) { if (pss_sequence_number < NUMBER_PSS_SEQUENCE) { printf("[i %6d] : %4d [i %6d] : %8i at address : %p \n", i, pss_sequence_time[2*i], (i + position), rxdata[2*i + (position*2)], &(rxdata[2*i + (position*2)])); printf("[q %6d] : %4d [q %6d] : %8i at address : %p \n", i, pss_sequence_time[2*i+1], (i + position), rxdata[2*i + 1 + (position*2)], &(rxdata[2*i + 1 + (position*2)])); - } - else { + } else { printf("[i %6d] : Undef [i %6d] : %8i at address : %p \n", i, (i + position), rxdata[2*i + (position*2)], &(rxdata[2*i + (position*2)])); printf("[q %6d] : Undef [q %6d] : %8i at address : %p \n", i, (i + position), rxdata[2*i + 1 + (position*2)], &(rxdata[2*i + 1 + (position*2)])); } - }nr_init_frame_parms + } + + nr_init_frame_parms printf(" ... ... \n"); #else (void) pss_sequence_number; @@ -149,11 +149,9 @@ void display_data(int pss_sequence_number, int16_t *rxdata, int position) * *********************************************************************/ -void display_test_configuration_pss(int position, int pss_sequence_number) -{ +void display_test_configuration_pss(int position, int pss_sequence_number) { const char next_test_text[] = "------------------------------------------------\n"; const char test_text_pss[] = "Test nr pss with Nid2 %i at position %i \n"; - printf(next_test_text); printf(test_text_pss, pss_sequence_number, position); } @@ -171,8 +169,7 @@ void display_test_configuration_pss(int position, int pss_sequence_number) * *********************************************************************/ -void display_test_configuration_sss(int sss_sequence_number) -{ +void display_test_configuration_sss(int sss_sequence_number) { const char test_text_sss[] = "Test nr sss with Nid1 %i \n"; printf(test_text_sss, sss_sequence_number); } @@ -191,8 +188,7 @@ void display_test_configuration_sss(int sss_sequence_number) * *********************************************************************/ -void undefined_function(const char *function) -{ +void undefined_function(const char *function) { printf("%s undefined \n", function); printf("Warning: function \"%s\" has been replaced by an empty function for avoiding undefined function error at build \n", function); } @@ -210,34 +206,22 @@ void undefined_function(const char *function) *********************************************************************/ int init_test(unsigned char N_tx, unsigned char N_rx, unsigned char transmission_mode, - unsigned char extended_prefix_flag, uint8_t frame_type, uint16_t Nid_cell, uint8_t N_RB_DL) -{ + unsigned char extended_prefix_flag, uint8_t frame_type, uint16_t Nid_cell, uint8_t N_RB_DL) { (void) transmission_mode; NR_DL_FRAME_PARMS *frame_parms; - int log_level = OAILOG_TRACE; - logInit(); - // enable these lines if you need debug info //set_comp_log(PHY,LOG_DEBUG,LOG_HIGH,1); set_glog(log_level); - #ifndef NR_UNIT_TEST - cpuf = get_cpu_freq_GHz(); - - LOG_I(PHY, "[CONFIG] Test of UE synchronisation \n"); - + //LOG_I(PHY, "[CONFIG] Test of UE synchronisation \n"); set_component_filelog(USIM); // file located in /tmp/testSynchroue.txt - #endif - //randominit(0); //set_taus_seed(0); - printf("Start lte_param_init, frame_type %d, extended_prefix %d\n",frame_type,extended_prefix_flag); - PHY_vars_UE = malloc(sizeof(PHY_VARS_NR_UE)); bzero(PHY_vars_UE, sizeof(PHY_VARS_NR_UE)); @@ -245,7 +229,6 @@ int init_test(unsigned char N_tx, unsigned char N_rx, unsigned char transmission return(-1); frame_parms = &(PHY_vars_UE->frame_parms); - frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz frame_parms->N_RB_UL = N_RB_DL; frame_parms->Ncp = extended_prefix_flag; @@ -257,38 +240,35 @@ int init_test(unsigned char N_tx, unsigned char N_rx, unsigned char transmission frame_parms->nb_antenna_ports_eNB = 1; frame_parms->threequarter_fs = 0; frame_parms->numerology_index = NUMEROLOGY_INDEX_MAX_NR; - - nr_init_frame_parms_ue(frame_parms); - + int mu = 1; + int n_ssb_crb = 0; + int ssb_subcarrier_offset = 0; + nr_init_frame_parms_ue(frame_parms, mu, extended_prefix_flag, N_RB_DL, n_ssb_crb, ssb_subcarrier_offset); PHY_vars_UE->frame_parms.Nid_cell = (3 * N_ID_1_NUMBER) + N_ID_2_NUMBER; /* set to unvalid value */ //phy_init_nr_top(frame_parms); - if (init_nr_ue_signal(PHY_vars_UE, 1, 0) != 0) - { + if (init_nr_ue_signal(PHY_vars_UE, 1, 0) != 0) { LOG_E(PHY,"Error at UE NR initialisation : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return (0); } -/* dummy initialisation of global structure PHY_vars_UE_g */ - + /* dummy initialisation of global structure PHY_vars_UE_g */ unsigned char NB_UE_INST=1; - - PHY_vars_UE_g = (PHY_VARS_NR_UE***)calloc( NB_UE_INST, sizeof(PHY_VARS_NR_UE**)); - - for (int UE_id=0; UE_id<NB_UE_INST; UE_id++) { - PHY_vars_UE_g[UE_id] = (PHY_VARS_NR_UE**) calloc( MAX_NUM_CCs, sizeof(PHY_VARS_NR_UE*)); - - for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - //(frame_parms[CC_id])->nb_antennas_tx = 1; - //(frame_parms[CC_id])->nb_antennas_rx = nb_antennas_rx_ue; - // PHY_vars_UE_g[UE_id][CC_id] = init_lte_UE(frame_parms[CC_id], UE_id,abstraction_flag); - - PHY_vars_UE_g[UE_id][CC_id] = calloc(1, sizeof(PHY_VARS_NR_UE)); - PHY_vars_UE_g[UE_id][CC_id]->Mod_id=UE_id; - PHY_vars_UE_g[UE_id][CC_id]->CC_id=CC_id; - } - } + PHY_vars_UE_g = (PHY_VARS_NR_UE ** *)calloc( NB_UE_INST, sizeof(PHY_VARS_NR_UE **)); + + for (int UE_id=0; UE_id<NB_UE_INST; UE_id++) { + PHY_vars_UE_g[UE_id] = (PHY_VARS_NR_UE **) calloc( MAX_NUM_CCs, sizeof(PHY_VARS_NR_UE *)); + + for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + //(frame_parms[CC_id])->nb_antennas_tx = 1; + //(frame_parms[CC_id])->nb_antennas_rx = nb_antennas_rx_ue; + // PHY_vars_UE_g[UE_id][CC_id] = init_lte_UE(frame_parms[CC_id], UE_id,abstraction_flag); + PHY_vars_UE_g[UE_id][CC_id] = calloc(1, sizeof(PHY_VARS_NR_UE)); + PHY_vars_UE_g[UE_id][CC_id]->Mod_id=UE_id; + PHY_vars_UE_g[UE_id][CC_id]->CC_id=CC_id; + } + } return (0); } @@ -318,73 +298,66 @@ typedef enum { #define FREQUENCY_15_MHZ (15360000L) #define FREQUENCY (FREQUENCY_15_MHZ) /* to generate a frequency with a sampling of 30,72 MHz 5 gives 770 KHz, 20 gives 1,5 MHz, 40 gives 3 MHz */ -void set_random_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int amp) -{ -NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); -int samples_for_frame = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); -int16_t random; -int16_t *data_p; -random_data_format_t data_format = SINUSOIDAL_DATA; - +void set_random_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int amp) { + NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); + int samples_for_frame = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); + int16_t random; + int16_t *data_p; + random_data_format_t data_format = SINUSOIDAL_DATA; /* reinitialise random for always getting same data */ srand(0); - double n = 0; - for (int aa=0;aa<PHY_vars_UE->frame_parms.nb_antennas_rx;aa++) { - + for (int aa=0; aa<PHY_vars_UE->frame_parms.nb_antennas_rx; aa++) { data_p = (int16_t *) &(PHY_vars_UE->common_vars.rxdata[aa][0]); - int frequency_switch = samples_for_frame/LTE_NUMBER_OF_SUBFRAMES_PER_FRAME; int frequency_step = 0; double beat = (2*M_PI*FREQUENCY_15_MHZ)/(SAMPLING_RATE); for (int i=0; i< samples_for_frame; i++) { switch(data_format) { - case ZERO_DATA: - { + case ZERO_DATA: { /* all data are forced to zero */ random = 0; break; } - case SINUSOIDAL_DATA: - { + + case SINUSOIDAL_DATA: { /* sinusoidal signal */ n = cos(beat*i); random = n * (amp * SCALING_SINUSOIDAL_DATA); frequency_step++; + if (frequency_step == frequency_switch) { beat = beat/2; /* frequency is divided by 2 */ //printf("frequency %f at %d\n", (beat/2*M_PI), i); - frequency_step = 0; + frequency_step = 0; } + //printf("%d : cos %d %d \n", i, n, random); break; } - case RANDOM_DATA: - { + + case RANDOM_DATA: { /* random data can take any value between -SHRT_MAX and SHRT_MAX */ /* in this case one can use maxim value for uint16 because there is no saturation */ - #define SCALING_RANDOM_DATA (24) /* 48 is max value without decimation */ - #define RANDOM_MAX_AMP (amp * SCALING_RANDOM_DATA) - +#define SCALING_RANDOM_DATA (24) /* 48 is max value without decimation */ +#define RANDOM_MAX_AMP (amp * SCALING_RANDOM_DATA) random = ((rand() % RANDOM_MAX_AMP) - RANDOM_MAX_AMP/2); break; } - case RANDOM_MAX_DATA: - { + + case RANDOM_MAX_DATA: { /* random data can take only two value (-RANDOM_MAX) or RANDOM_MAX */ /* In this case saturation can occur with value of scaling_value greater than 23 */ - #define SCALING_RANDOM_MAX_DATA (8) - #define RANDOM_VALUE (amp * SCALING_RANDOM_DATA) - +#define SCALING_RANDOM_MAX_DATA (8) +#define RANDOM_VALUE (amp * SCALING_RANDOM_DATA) const int random_number[2] = {-1,+1}; - random = random_number[rand()%2] * RANDOM_VALUE; break; } - default: - { + + default: { printf("Format of data is undefined \n"); assert(0); break; @@ -393,12 +366,13 @@ random_data_format_t data_format = SINUSOIDAL_DATA; data_p[2*i] = random; data_p[2*i+1] = random; - #if 0 + if (i < 10) { - printf("random %d \n", random); + printf("random %d \n", random); printf("data[%d] : %d %d at address %p \n", i, data_p[2*i], data_p[2*i+1], &data_p[2*i]); } + #endif } } @@ -418,23 +392,22 @@ random_data_format_t data_format = SINUSOIDAL_DATA; * *********************************************************************/ -int set_pss_in_rx_buffer_from_external_buffer(PHY_VARS_NR_UE *PHY_vars_UE, short *input_buffer) -{ +int set_pss_in_rx_buffer_from_external_buffer(PHY_VARS_NR_UE *PHY_vars_UE, short *input_buffer) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int samples_for_frame = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe; /* both i and q */ - for (int aa=0;aa<PHY_vars_UE->frame_parms.nb_antennas_rx;aa++) { + for (int aa=0; aa<PHY_vars_UE->frame_parms.nb_antennas_rx; aa++) { for (int i = 0; i < samples_for_frame; i++) { - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[2*i] = input_buffer[2*i]; /* real part */ - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1] = input_buffer[2*i+1]; /* imaginary part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i] = input_buffer[2*i]; /* real part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1] = input_buffer[2*i+1]; /* imaginary part */ } } /* check that sequence has been properly copied */ - for (int aa=0;aa<PHY_vars_UE->frame_parms.nb_antennas_rx;aa++) { + for (int aa=0; aa<PHY_vars_UE->frame_parms.nb_antennas_rx; aa++) { for (int i=0; i<samples_for_frame; i++) { - if ((input_buffer[2*i] != ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[2*i]) - || (input_buffer[2*i+1] != ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1])) { + if ((input_buffer[2*i] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i]) + || (input_buffer[2*i+1] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1])) { printf("Sequence pss was not properly copied into received buffer at index %d \n", i); exit(-1); } @@ -466,15 +439,13 @@ int set_pss_in_rx_buffer_from_external_buffer(PHY_VARS_NR_UE *PHY_vars_UE, short * *********************************************************************/ -int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) -{ +int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int samples_for_frame = frame_parms->samples_per_frame; int16_t *pss_sequence_time; if ((position_symbol > samples_for_frame) - || ((position_symbol + frame_parms->ofdm_symbol_size) > samples_for_frame)) - { + || ((position_symbol + frame_parms->ofdm_symbol_size) > samples_for_frame)) { printf("This pss sequence can not be fully written in the received window \n"); return (-1); } @@ -486,18 +457,18 @@ int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int p pss_sequence_time = primary_synchro_time_nr[pss_sequence_number]; - for (int aa=0;aa<PHY_vars_UE->frame_parms.nb_antennas_rx;aa++) { + for (int aa=0; aa<PHY_vars_UE->frame_parms.nb_antennas_rx; aa++) { for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)] = pss_sequence_time[2*i]; /* real part */ - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)] = pss_sequence_time[2*i+1]; /* imaginary part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)] = pss_sequence_time[2*i]; /* real part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)] = pss_sequence_time[2*i+1]; /* imaginary part */ } } /* check that sequence has been properly copied */ - for (int aa=0;aa<PHY_vars_UE->frame_parms.nb_antennas_rx;aa++) { + for (int aa=0; aa<PHY_vars_UE->frame_parms.nb_antennas_rx; aa++) { for (int i=0; i<(frame_parms->ofdm_symbol_size); i++) { - if ((pss_sequence_time[2*i] != ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)]) - || (pss_sequence_time[2*i+1] != ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)])) { + if ((pss_sequence_time[2*i] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)]) + || (pss_sequence_time[2*i+1] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)])) { printf("Sequence pss was not properly copied into received buffer at index %d \n", i); exit(-1); } @@ -525,11 +496,9 @@ int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int p * *********************************************************************/ -void set_sequence_pss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) -{ +void set_sequence_pss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int samples_for_frame = frame_parms->samples_per_frame; - /* initialise received ue data with random */ set_random_rx_buffer(PHY_vars_UE, AMP); @@ -543,6 +512,7 @@ void set_sequence_pss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_ printf("This position for pss sequence %d is not supported because it exceeds the frame length %d!\n", position_symbol, samples_for_frame); exit(0); } + if (set_pss_in_rx_buffer(PHY_vars_UE, position_symbol, pss_sequence_number) != 0) printf("Warning: pss sequence can not be properly written into received buffer !\n"); } diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c new file mode 100644 index 0000000000000000000000000000000000000000..ab3ede4b8f305e6829b4a74380026da232014bcf --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c @@ -0,0 +1,166 @@ +#include "../../unit_tests/src/pss_util_test.h" +#include "PHY/defs_nr_UE.h" +#include "PHY/INIT/init_extern.h" +#include "PHY/phy_extern_nr_ue.h" + +/* +#include "SCHED_NR_UE/defs.h" +#include "SCHED_NR/extern.h" + +#include "SCHED_NR_UE/harq_nr.h" +*/ +#include "SCHED_NR_UE/pucch_uci_ue_nr.h" + +/**************** define **************************************/ + +#define TST_GNB_ID_0 (0) /* first index of gNB */ +#define TST_THREAD_ID (0) + + +int test_pucch_generators(PHY_VARS_NR_UE *ue) { + int gNB_id = TST_GNB_ID_0; + int thread_number = TST_THREAD_ID; + int TB_identifier = 0; + int v_return = 0; + pucch_format_nr_t format = pucch_format2_nr; + uint8_t starting_symbol_index; + uint8_t nb_symbols_total = 4; + uint16_t starting_prb = 0;; /* it can be considered as first hop on case of pucch hopping */ + uint16_t second_hop = 0; /* second part for pucch for hopping */ + uint8_t nb_of_prbs = 1; + + switch (format) { + case pucch_format0_nr: + nb_symbols_total = 2; + nb_of_prbs = 1; + starting_symbol_index = 0; + break; + + case pucch_format1_nr: + nb_symbols_total = 5; + nb_of_prbs = 1; + starting_symbol_index = 0; + break; + + case pucch_format2_nr: + nb_symbols_total = 2; + nb_of_prbs = 16; + starting_symbol_index = 0; + break; + } + + int m_0 = 0; /* format 0 only */ + int m_CS = 0; /* for all format except for format 0 */ + int index_additional_dmrs = I_PUCCH_NO_ADDITIONAL_DMRS; + int index_hopping = I_PUCCH_NO_HOPPING; + int time_domain_occ = 0; + int occ_length = 0; + int occ_Index = 0; + uint64_t pucch_payload = 0; + int tx_amp = 512; + int nr_tti_tx = 0; + int N_UCI = 0; /* size in bits for Uplink Control Information */ + + switch(format) { + case pucch_format0_nr: { + nr_generate_pucch0(ue,ue->common_vars.txdataF, + &ue->frame_parms, + &ue->pucch_config_dedicated_nr[gNB_id], + tx_amp, + nr_tti_tx, + (uint8_t)m_0, + (uint8_t)m_CS, + nb_symbols_total, + starting_symbol_index, + starting_prb); + break; + } + + case pucch_format1_nr: { + nr_generate_pucch1(ue,ue->common_vars.txdataF, + &ue->frame_parms, + &ue->pucch_config_dedicated_nr[gNB_id], + pucch_payload, + tx_amp, + nr_tti_tx, + (uint8_t)m_0, + nb_symbols_total, + starting_symbol_index, + starting_prb, + second_hop, + (uint8_t)time_domain_occ, + (uint8_t)N_UCI); + break; + } + + case pucch_format2_nr: { + nr_generate_pucch2(ue, + ue->pdcch_vars[ue->current_thread_id[nr_tti_tx]][gNB_id]->crnti, + ue->common_vars.txdataF, + &ue->frame_parms, + &ue->pucch_config_dedicated_nr[gNB_id], + pucch_payload, + tx_amp, + nr_tti_tx, + nb_symbols_total, + starting_symbol_index, + nb_of_prbs, + starting_prb, + (uint8_t)N_UCI); + break; + } + + case pucch_format3_nr: + case pucch_format4_nr: { + nr_generate_pucch3_4(ue, + ue->pdcch_vars[ue->current_thread_id[nr_tti_tx]][gNB_id]->crnti, + ue->common_vars.txdataF, + &ue->frame_parms, + format, + &ue->pucch_config_dedicated_nr[gNB_id], + pucch_payload, + tx_amp, + nr_tti_tx, + nb_symbols_total, + starting_symbol_index, + nb_of_prbs, + starting_prb, + second_hop, + (uint8_t)N_UCI, + (uint8_t)occ_length, + (uint8_t)occ_Index); + break; + } + } + + return (v_return); +} + + +int main(int argc, char *argv[]) { + uint8_t transmission_mode = 1; + uint8_t nb_antennas_tx = 1; + uint8_t nb_antennas_rx = 1; + uint8_t frame_type = FDD; + uint8_t N_RB_DL=106; + lte_prefix_type_t extended_prefix_flag = NORMAL; + int Nid_cell[] = {(3*1+3)}; + VOID_PARAMETER argc; + VOID_PARAMETER argv; + printf(" PUCCH TEST \n"); + printf("-----------\n"); + + if (init_test(nb_antennas_tx, nb_antennas_rx, transmission_mode, extended_prefix_flag, frame_type, Nid_cell[0], N_RB_DL) != 0) { + printf("Initialisation problem for test \n"); + exit(-1);; + } + + if (test_pucch_generators(PHY_vars_UE) != 0) { + printf("\nTest PUCCH is fail \n"); + } else { + printf("\nTest PUCCH is pass \n"); + } + + free_context_synchro_nr(); + return(0); +} diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c index e317fbd154034017a40521e23ae1281318aa0f74..bff3453de0c30ae3df4696a756b0202dbe80be62 100644 --- a/openair1/SIMULATION/RF/rf.c +++ b/openair1/SIMULATION/RF/rf.c @@ -107,10 +107,10 @@ void rf_rx(double **r_re, exit(-1); } - if (fabs(f_off) > 10000.0) { +/* if (fabs(f_off) > 10000.0) { printf("rf.c: Illegal f_off %f\n",f_off); exit(-1); - } + }*/ if (fabs(drift) > 1000.0) { printf("rf.c: Illegal drift %f\n",drift); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index ec89e67dd3c83720c3010fd6dc880100a7348cdc..79939efdf52cc41ef895b82b78d393e8e0d48f65 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -437,7 +437,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, /*if (slotP==2) nr_schedule_css_dlsch_phytest(module_idP, frameP, slotP);*/ - if (slotP==2) + if (slotP==1) nr_schedule_uss_dlsch_phytest(module_idP, frameP, slotP); /* diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index e302291a611c4049a5e6b71f0491584b123cb209..a0b07c4fbd04bb4fa886353c889d7dfaa6bdf1bd 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -292,7 +292,7 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { uint32_t number_of_search_space_per_slot=1; uint32_t first_symbol_index=0; - uint32_t search_space_duration=1; // element of search space + uint32_t search_space_duration=0; // element of search space uint32_t coreset_duration; // element of coreset coreset_duration = num_symbols * number_of_search_space_per_slot; diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c index 7d3c7539908d1cca0c0ef28075835246374fc6ec..ce56bc95ff0a455b9b598de426531b24074ca082 100644 --- a/targets/RT/USER/nr-ue.c +++ b/targets/RT/USER/nr-ue.c @@ -444,6 +444,7 @@ static void *UE_thread_synch(void *arg) { //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (10*UE->frame_parms.samples_per_slot), 1, 1); + freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_slot; printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", hw_slot_offset, @@ -457,16 +458,13 @@ static void *UE_thread_synch(void *arg) { // rerun with new cell parameters and frequency-offset for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - if (UE->UE_scan_carrier == 1) { if (freq_offset >= 0) - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset); + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); else - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset); + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset); openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; - freq_offset=0; - } } // reconfigure for potentially different bandwidth @@ -602,7 +600,7 @@ static void *UE_thread_synch(void *arg) { phy_scope_UE(form_ue[0], PHY_vars_UE_g[0][0], - 0,0,7); + 0,0,1); } #endif @@ -693,6 +691,7 @@ static void *UE_thread_rxn_txnp4(void *arg) { NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); UE_mac->scheduled_response.dl_config = &UE->dcireq.dl_config_req; + UE_mac->scheduled_response.slot = proc->nr_tti_rx; nr_ue_scheduled_response(&UE_mac->scheduled_response); #ifdef UE_SLOT_PARALLELISATION @@ -920,7 +919,7 @@ void *UE_thread(void *arg) { if(thread_idx>=RX_NB_TH) thread_idx = 0; - printf("slot_nr %d nb slot frame %d\n",slot_nr, nb_slot_frame); + //printf("slot_nr %d nb slot frame %d\n",slot_nr, nb_slot_frame); slot_nr++; slot_nr %= nb_slot_frame; @@ -1110,6 +1109,7 @@ void *UE_thread(void *arg) { NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); UE_mac->scheduled_response.dl_config = &UE->dcireq.dl_config_req; + UE_mac->scheduled_response.slot = proc->nr_tti_rx; nr_ue_scheduled_response(&UE_mac->scheduled_response); //write_output("uerxdata_frame.m", "uerxdata_frame", UE->common_vars.rxdata[0], UE->frame_parms.samples_per_frame, 1, 1); diff --git a/targets/RT/USER/nr-uesoftmodem.c b/targets/RT/USER/nr-uesoftmodem.c index 81f46d31b393212f83de1643b2454f5094767f90..d3d660e7f5584814a9c6443bcbe7616d8a07ad44 100644 --- a/targets/RT/USER/nr-uesoftmodem.c +++ b/targets/RT/USER/nr-uesoftmodem.c @@ -130,6 +130,7 @@ static char *itti_dump_file = NULL; int UE_scan = 0; int UE_scan_carrier = 0; +int UE_fo_compensation = 0; runmode_t mode = normal_txrx; FILE *input_fd=NULL; @@ -978,6 +979,7 @@ int main( int argc, char **argv ) { UE[CC_id]->UE_scan = UE_scan; UE[CC_id]->UE_scan_carrier = UE_scan_carrier; + UE[CC_id]->UE_fo_compensation = UE_fo_compensation; UE[CC_id]->mode = mode; printf("UE[%d]->mode = %d\n",CC_id,mode); diff --git a/targets/RT/USER/nr-uesoftmodem.h b/targets/RT/USER/nr-uesoftmodem.h index 816e7530869e285ac5af1ca46bd60d544629bd13..7f96480b2bfe5be8969b5e67c1aa8c8e25af2baa 100644 --- a/targets/RT/USER/nr-uesoftmodem.h +++ b/targets/RT/USER/nr-uesoftmodem.h @@ -55,6 +55,7 @@ #define CONFIG_HLP_UENANTR "set UE number of rx antennas\n" #define CONFIG_HLP_UENANTT "set UE number of tx antennas\n" #define CONFIG_HLP_UESCAN "set UE to scan around carrier\n" +#define CONFIG_HLP_UEFO "set UE to enable estimation and compensation of frequency offset\n" #define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n" #define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" #define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n" @@ -135,6 +136,7 @@ {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \ {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \ {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \ +{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&UE_fo_compensation, defintval:0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ {"r" , CONFIG_HLP_PRB, 0, iptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \