/* * 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 */ /********************************************************************** * * FILENAME : dmrs_nr.c * * MODULE : demodulation reference signals * * DESCRIPTION : generation of dmrs sequences * 3GPP TS 38.211 * ************************************************************************/ #include "PHY/NR_REFSIG/ss_pbch_nr.h" #include "PHY/NR_REFSIG/dmrs_nr.h" uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k, uint16_t start_sc, uint8_t numDmrsCdmGrpsNoData, uint8_t dmrs_type) { uint8_t delta; uint16_t diff; if (k>start_sc) diff = k-start_sc; else diff = start_sc-k; for (int i = 0; i> n) & 0x1; } for (n = 0; n < (NC + M_PN); n++) { x1[n+31] = (x1[n+3] + x1[n])%2; x2[n+31] = (x2[n+3] + x2[n+2] + x2[n+1] + x2[n])%2; } for (int n = 0; n < M_PN; n++) { c[n] = (x1[n+NC] + x2[n+NC])%2; } free(x1); free(x2); return 0; } /******************************************************************* * * NAME : pseudo_random_sequence_optimised * * PARAMETERS : * * RETURN : generate pseudo-random sequence which is a length-31 Gold sequence * * DESCRIPTION : 3GPP TS 38.211 5.2.1 Pseudo-random sequence generation * Sequence generation is a length-31 Gold sequence * This is an optimized function based on bitmap variables * * x1(0)=1,x1(1)=0,...x1(30)=0,x1(31)=1 * x2 <=> cinit, x2(31) = x2(3)+x2(2)+x2(1)+x2(0) * x2 <=> cinit = sum_{i=0}^{30} x2(i)2^i * c(n) = x1(n+Nc) + x2(n+Nc) mod 2 * * equivalent to * x1(n+31) = (x1(n+3)+x1(n))mod 2 <=> x1(n) = x1(n-28) + x1(n-31) * x2(n+31) = (x2(n+3)+x2(n+2)+x2(n+1)+x2(n))mod 2 <=> x2(n) = x2(n-28) + x2(n-29) + x2(n-30) + x2(n-31) * *********************************************************************/ void pseudo_random_sequence_optimised(unsigned int size, uint32_t *c, uint32_t cinit) { unsigned int n,x1,x2; /* init of m-sequences */ x1 = 1+ (1<<31); x2 = cinit; x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); /* skip first 50 double words of uint32_t (1600 bits) */ for (n=1; n<50; n++) { x1 = (x1>>1) ^ (x1>>4); x1 = x1 ^ (x1<<31) ^ (x1<<28); x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); } for (n=0; n>1) ^ (x1>>4); x1 = x1 ^ (x1<<31) ^ (x1<<28); x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); c[n] = x1^x2; } } /******************************************************************* * * NAME : lte_gold_new * * PARAMETERS : * * RETURN : generate pseudo-random sequence which is a length-31 Gold sequence * * DESCRIPTION : This function is the same as "lte_gold" function in file lte_gold.c * It allows checking that optimization works fine. * generated sequence is given in an array as a bit map. * *********************************************************************/ #define CELL_DMRS_LENGTH (224*2) #define CHECK_GOLD_SEQUENCE void lte_gold_new(LTE_DL_FRAME_PARMS *frame_parms, uint32_t lte_gold_table[20][2][14], uint16_t Nid_cell) { unsigned char ns,l,Ncp=1-frame_parms->Ncp; uint32_t cinit; #ifdef CHECK_GOLD_SEQUENCE uint32_t dmrs_bitmap[20][2][14]; uint32_t *dmrs_sequence = calloc(CELL_DMRS_LENGTH, sizeof(uint32_t)); if (dmrs_sequence == NULL) { msg("Fatal error: memory allocation problem \n"); assert(0); } else { printf("Check of demodulation reference signal of pbch sequence \n"); } #endif /* for each slot number */ for (ns=0; ns<20; ns++) { /* for each ofdm position */ for (l=0; l<2; l++) { cinit = Ncp + (Nid_cell<<1) + (((1+(Nid_cell<<1))*(1 + (((frame_parms->Ncp==0)?4:3)*l) + (7*(1+ns))))<<10); pseudo_random_sequence_optimised(14, &(lte_gold_table[ns][l][0]), cinit); #ifdef CHECK_GOLD_SEQUENCE pseudo_random_sequence(CELL_DMRS_LENGTH, dmrs_sequence, cinit); int j = 0; int k = 0; /* format for getting bitmap from uint32_t */ for (int i=0; i<14; i++) { dmrs_bitmap[ns][l][i] = 0; for (; j < k + 32; j++) { dmrs_bitmap[ns][l][i] |= (dmrs_sequence[j]<>4) + 1))<<11) + ((_i_ssb + 1)<<6) + (Nid_cell%4); pseudo_random_sequence_optimised(DMRS_BITMAP_SIZE, &(dmrs_pbch_bitmap[i_ssb][n_hf][0]), cinit); #ifdef CHECK_DMRS_PBCH_SEQUENCE /* it allows checking generated with standard generation code */ pseudo_random_sequence(DMRS_BITMAP_SIZE*sizeof(uint32_t), dmrs_sequence, cinit); int j = 0; int k = 0; /* format for getting bitmap from uint32_t */ for (int i=0; i>symbol)&0x01 ) { return symbol; } return 0; } /* return the total number of dmrs symbol in a slot */ uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb) { uint8_t tmp = 0; for (int i = 0; i < nb_symb; i++) { tmp += (l_prime_mask >> i) & 0x01; } return tmp; }