diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 1ef0bac9d2..39abbc8f29 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1282,6 +1282,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c @@ -1324,7 +1325,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_tools_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pucch_nr.c - ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch.c + ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c new file mode 100644 index 0000000000..67a02bc7dc --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -0,0 +1,57 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_TRANSPORT/nr_ulsch.c +* \brief Top-level routines for the reception of the PUSCH TS 38.211 v 15.4.0 +* \author Ahmed Hussein +* \date 2019 +* \version 0.1 +* \company Fraunhofer IIS +* \email: ahmed.hussein@iis.fraunhofer.de +* \note +* \warning +*/ + +#include +#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_TRANSPORT/nr_ulsch.h" + +void nr_ulsch_unscrambling(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI) +{ + uint8_t reset; + uint32_t x1, x2, s=0; + + reset = 1; + x2 = (n_RNTI<<15) + Nid; + + for (uint32_t i=0; i>(i&0x1f))&1)==1) + llr[i] = -llr[i]; + } +} \ No newline at end of file diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index 77cc101679..b4c1b9822c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -36,6 +36,19 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch); NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag); + +/*! \brief Perform PUSCH decoding. TS 38.212 V15.4.0 subclause 6.2 + @param phy_vars_gNB, Pointer to PHY data structure for gNB + @param UE_id, ID of UE transmitting this PUSCH + @param ulsch_llr, Pointer to received llr in ulsch + @param frame_parms, Pointer to frame descriptor structure + @param nb_symb_sch, number of symbols used in the uplink shared channel + @param nr_tti_rx, current received TTI + @param harq_pid, harq process id + @param is_crnti + @param llr8_flag If 1, indicate that the 8-bit decoder should be used +*/ + uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t UE_id, short *ulsch_llr, @@ -47,3 +60,18 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t is_crnti, uint8_t llr8_flag); + +/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 + @param llr, Pointer to llr bits + @param size, length of llr bits + @param q, codeword index (0,1) + @param Nid, cell id + @param n_RNTI, CRNTI +*/ + +void nr_ulsch_unscrambling(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI); + diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c similarity index 99% rename from openair1/PHY/NR_UE_TRANSPORT/nr_ulsch.c rename to openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 8f842804ca..40eac485f3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -65,4 +65,4 @@ void nr_pusch_codeword_scrambling(uint8_t *in, //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out); } -} \ No newline at end of file +} diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 13f8df4865..9b2987bef9 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -141,15 +141,13 @@ int main(int argc, char **argv) { channel_desc_t *gNB2UE; uint8_t extended_prefix_flag = 0; //int8_t interf1 = -21, interf2 = -21; - FILE *input_fd = NULL, *pbch_file_fd = NULL; + FILE *input_fd = NULL; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; //unsigned char frame_type = 0; - unsigned char pbch_phase = 0; - int frame = 0, subframe = 0, slot = 1; + int frame = 0, subframe = 0; int frame_length_complex_samples; NR_DL_FRAME_PARMS *frame_parms; - uint32_t Nsoft = 0; double sigma; unsigned char qbits = 8; int ret; @@ -159,12 +157,6 @@ int main(int argc, char **argv) { uint16_t nb_symb_sch = 12; uint16_t nb_rb = 50; uint8_t Imcs = 9; - uint16_t n_dmrs; - uint8_t dmrs_TypeA_Position; - int l0; - uint32_t ***pusch_dmrs; - - PUSCH_TimeDomainResourceAllocation_t pusch_time_alloc; cpuf = get_cpu_freq_GHz(); @@ -441,12 +433,12 @@ int main(int argc, char **argv) { uint8_t is_crnti = 0, llr8_flag = 0; unsigned int TBS = 8424; unsigned int available_bits; - uint8_t nb_re_dmrs = 6; + uint8_t nb_re_dmrs = 6; uint16_t length_dmrs = 1; - uint8_t N_PRB_oh; + uint8_t N_PRB_oh; uint16_t N_RE_prime; unsigned char mod_order; - uint8_t Nl = 1; + uint8_t Nl = 1; uint8_t rvidx = 0; uint8_t UE_id = 1; @@ -455,17 +447,12 @@ int main(int argc, char **argv) { NR_UE_ULSCH_t *ulsch_ue = UE->ulsch[0][0][0]; - mod_order = nr_get_Qm(Imcs, 1); + mod_order = nr_get_Qm(Imcs, 1); available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1); - TBS = nr_compute_tbs(Imcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, Nl); + TBS = nr_compute_tbs(Imcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, Nl); + printf("available bits %d TBS %d mod_order %d\n", available_bits, TBS, mod_order); - /////////// setting PUSCH_TimeDomainResourceAllocation_t parameters /////////// - - pusch_time_alloc.mappingType = typeA; - - /////////////////////////////////////////////////// - /////////// setting rel15_ul parameters /////////// rel15_ul->number_rbs = nb_rb; rel15_ul->number_symbols = nb_symb_sch; @@ -475,26 +462,30 @@ int main(int argc, char **argv) { rel15_ul->n_layers = Nl; /////////////////////////////////////////////////// - double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc - short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384); - short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384); - unsigned int errors_bit_uncoded = 0; - // unsigned char *estimated_output; + + double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc + short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384); + short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384); + + uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; unsigned char *estimated_output_bit; unsigned char *test_input_bit; - unsigned int errors_bit = 0; - - test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); - // estimated_output = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); - estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); - unsigned char *test_input; - test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8); + unsigned int errors_bit_uncoded; + unsigned int errors_bit; + uint8_t bit_index; + uint32_t errors_scrambling; + uint32_t scrambling_index; + + + test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8); + test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); + estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); + for (i = 0; i < TBS / 8; i++) - test_input[i] = (unsigned char) rand(); + test_input[i] = 1;//(unsigned char) rand(); - // estimated_output = ulsch_gNB->harq_processes[harq_pid]->b; /////////////////////////[adk] preparing NR_UE_ULSCH_t parameters///////////////////////// A HOT FIX until creating nfapi_nr_ul_config_ulsch_pdu_rel15_t /////////// @@ -504,6 +495,7 @@ int main(int argc, char **argv) { /////////// //////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////[adk] preparing UL harq_process parameters///////////////////////// /////////// NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; @@ -530,11 +522,6 @@ int main(int argc, char **argv) { for (i = 0; i < TBS / 8; i++) printf("test_input[i]=%d \n",test_input[i]); #endif - /*for (int i=0; i0x%08x\n",crc24c(test_input, 32)); - // generate signal /////////////////////////ULSCH coding///////////////////////// /////////// @@ -546,23 +533,20 @@ int main(int argc, char **argv) { /////////// //////////////////////////////////////////////////////////////////// + /////////////////////////ULSCH scrambling///////////////////////// /////////// - uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; - uint16_t encoded_length; - - encoded_length = harq_process_ul_ue->num_of_mod_symbols*mod_order; - for (int q=0; q>5)*sizeof(uint32_t)); + memset(scrambled_output[q], 0, ((available_bits>>5)+1)*sizeof(uint32_t)); } - + nr_pusch_codeword_scrambling(ulsch_ue->g, - encoded_length, + available_bits, Nid_cell, ulsch_ue->rnti, scrambled_output[0]); // assume one codeword for the moment + ///////////// ////////////////////////////////////////////////////////////////////////// @@ -571,34 +555,25 @@ int main(int argc, char **argv) { /////////// nr_modulation(scrambled_output[0], // assume one codeword for the moment - encoded_length, + available_bits, mod_order, ulsch_ue->d); /////////// //////////////////////////////////////////////////////////////////////// - /////////////////////////PUSCH DMRS///////////////////////// - /////////// - pusch_dmrs = UE->nr_gold_pusch_dmrs[slot]; - dmrs_TypeA_Position = 2; // This parameter is given by dmrs_TypeA_Position which is located in MIB. - n_dmrs = nb_re_dmrs<<1; - int16_t mod_dmrs[n_dmrs<<1]; - - l0 = get_l0(pusch_time_alloc.mappingType, dmrs_TypeA_Position);//config.pdsch_config.dmrs_typeA_position.value); - nr_modulation(pusch_dmrs[l0][0], n_dmrs, MOD_QPSK, mod_dmrs); // currently only codeword 0 is modulated - - /////////// - //////////////////////////////////////////////////////////////////////// - - for (SNR = snr0; SNR < snr1; SNR += snr_step) { - n_errors = 0; - n_false_positive = 0; + for (SNR = snr0; SNR < snr1; SNR += snr_step) { + n_errors = 0; + n_false_positive = 0; + for (trial = 0; trial < n_trials; trial++) { errors_bit_uncoded = 0; + errors_scrambling = 0; + errors_bit = 0; + scrambling_index = 0; for (i = 0; i < available_bits; i++) { @@ -606,22 +581,27 @@ int main(int argc, char **argv) { if ((i&0xf)==0) printf("\ne %d..%d: ",i,i+15); #endif - /* - if (i<16){ - printf("ulsch_encoder output f[%d] = %d\n",i,ulsch_ue->harq_processes[0]->f[i]); - } - */ - if (ulsch_ue->harq_processes[0]->f[i] == 0) - modulated_input[i] = 1.0; ///sqrt(2); //QPSK + +//////////////////////////////////////////// +// Modulate bit-wise the scrambled output // +//////////////////////////////////////////// + + bit_index = i & 0x1f; + + if ((bit_index == 0) && (i != 0)) { + scrambling_index++; + } + + if(((scrambled_output[0][scrambling_index] >> bit_index) & 1) == 0) + modulated_input[i] = 1.0; ///sqrt(2); //QPSK else - modulated_input[i] = -1.0; ///sqrt(2); - - //if (i<16) printf("modulated_input[%d] = %d\n",i,modulated_input[i]); - //SNR =10; + modulated_input[i] = -1.0; ///sqrt(2); +//////////////////////////////////////////// + SNR_lin = pow(10, SNR / 10.0); - sigma = 1.0 / sqrt(2 * SNR_lin); + sigma = 1.0 / sqrt(2 * SNR_lin); #if 1 channel_output_fixed[i] = (short) quantize(sigma / 4.0 / 4.0, modulated_input[i] + sigma * gaussdouble(0.0, 1.0), @@ -634,39 +614,70 @@ int main(int argc, char **argv) { //Uncoded BER if (channel_output_fixed[i] < 0) - channel_output_uncoded[i] = 1; //QPSK demod + channel_output_uncoded[i] = 1; //QPSK demod else - channel_output_uncoded[i] = 0; + channel_output_uncoded[i] = 0; - if (channel_output_uncoded[i] != ulsch_ue->harq_processes[harq_pid]->f[i]) - errors_bit_uncoded = errors_bit_uncoded + 1; + if (channel_output_uncoded[i] != ((scrambled_output[0][scrambling_index] >> bit_index) & 1)) { + errors_bit_uncoded = errors_bit_uncoded + 1; + } } - printf("errors bits uncoded %u\n", errors_bit_uncoded); + printf("errors bits uncoded = %u\n", errors_bit_uncoded); + #ifdef DEBUG_CODER printf("\n"); exit(-1); #endif + - ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, - frame, nb_symb_sch, subframe, harq_pid, is_crnti, llr8_flag); + //////////////////////////////////////////////////////////// + //////////////////// ULSCH unscrambling //////////////////// + //////////////////////////////////////////////////////////// + + nr_ulsch_unscrambling(channel_output_fixed, available_bits, 0, Nid_cell, n_rnti); + + //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////// + ////////////////////// ULSCH decoding ////////////////////// + //////////////////////////////////////////////////////////// + + ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, frame, + nb_symb_sch, subframe, harq_pid, is_crnti, llr8_flag); if (ret > ulsch_gNB->max_ldpc_iterations) n_errors++; - //count errors - errors_bit = 0; + //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////// + /////////////////////// count errors /////////////////////// + //////////////////////////////////////////////////////////// for (i = 0; i < TBS; i++) { + + if(((ulsch_ue->g[i] == 0) && (channel_output_fixed[i] < 0)) || ((ulsch_ue->g[i] == 1) && (channel_output_fixed[i] >= 0))) { + errors_scrambling++; + } + estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); - test_input_bit[i] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + test_input_bit[i] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { errors_bit++; } + } + //////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////// + if (errors_bit > 0) { n_false_positive++; if (n_trials == 1)