/* * 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: nr_rate_matching.c purpose: Procedures for rate matching/interleaving for NR LDPC author: hongzhi.wang@tcl.com */ #include "PHY/defs_gNB.h" #include "PHY/defs_nr_UE.h" //#define RM_DEBUG 1 uint8_t index_k0[2][4] = {{0,17,33,56},{0,13,25,43}}; void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) { uint32_t EQm; EQm = E/Qm; memset(f,0,E*sizeof(uint8_t)); for (int j = 0; j< EQm; j++){ for (int i = 0; i< Qm; i++){ f[(i+j*Qm)] = e[(i*EQm + j)]; } } } void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) { uint32_t EQm; EQm = E/Qm; for (int j = 0; j< EQm; j++){ for (int i = 0; i< Qm; i++){ e[(i*EQm + j)] = f[(i+j*Qm)]; } } } 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) { uint8_t Cprime; uint32_t Ncb,E,ind,k,Nref,N; uint8_t *e2; 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; 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)); #endif e2 = e; k=0; for (; (ind<Ncb)&&(k<E); ind++) { #ifdef RM_DEBUG printf("RM_TX k%d Ind: %d (%d)\n",k,ind,w[ind]); #endif if (w[ind] != NR_NULL) e2[k++]=w[ind]; } while(k<E) { for (ind=0; (ind<Ncb)&&(k<E); ind++) { #ifdef RM_DEBUG printf("RM_TX k%d Ind: %d (%d)\n",k,ind,w[ind]); #endif if (w[ind] != NR_NULL) e2[k++]=w[ind]; } } return(E); } int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, uint32_t Tbslbrm, uint8_t BG, uint16_t Z, uint32_t G, 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) { uint8_t Cprime; uint32_t Ncb,E,ind,k,Nref,N; int16_t *soft_input2; #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); } 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; 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); #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++]; #ifdef RM_DEBUG printf("RM_RX k%d Ind: %d (%d)\n",k-1,ind,w[ind]); #endif } #ifdef RM_DEBUG else { printf("RM_RX Ind: %d NULL %d\n",ind,nulled); nulled++; } #endif } while(k<E) { for (ind=0; (ind<Ncb)&&(k<E); ind++) { if (soft_input2[ind] != NR_NULL) { w[ind] += soft_input2[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]); #endif } #ifdef RM_DEBUG else { printf("RM_RX Ind: %d NULL %d\n",ind,nulled); nulled++; } #endif } } *E_out = E; return(0); }