RAR and MSG3 scheduling in TDD [Issue-ID: ODUHIGH-342]
[o-du/l2.git] / src / 5gnrsch / sch_rach.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /************************************************************************
20  
21      Name:     sch_rach.c
22   
23      Type:     C source file
24   
25      Desc:     C source code for rach handling functions
26   
27      File:     sch_rach.c
28   
29 **********************************************************************/
30
31 /** @file sch_rach.c
32 @brief This file implements the rach handling.
33 */
34 #include "common_def.h"
35 #include "tfu.h"
36 #include "lrg.h"
37 #include "tfu.x"
38 #include "lrg.x"
39 #include "du_log.h"
40 #include "du_app_mac_inf.h"
41 #include "mac_sch_interface.h"
42 #include "sch.h"
43 #include "sch_utils.h"
44
45 SchCb schCb[SCH_MAX_INST];
46 uint8_t puschDeltaTable[MAX_MU_PUSCH];
47
48 /**
49  * @brief calculate ra-rnti function. 
50  *
51  * @details
52  *
53  *     Function : calculateRaRnti
54  *     
55  *     This function calculates ra-rnti
56  *     
57  *  @param[in]  symbol index
58  *  @param[in]  slot index
59  *  @param[in]  frequency index
60  *  @return  ra-rnti
61  **/
62 uint16_t calculateRaRnti(uint8_t symbolIdx, uint8_t slotIdx, uint8_t freqIdx)
63 {
64    uint16_t raRnti = 0;
65    uint8_t  ulCarrierIdx = 0; /* Uplink carrier used for MSG1 transmission. 0:NUL carrier; 1:SUL carrier */
66    
67    /* Refer to spec 38.321, section 5.1.3 */
68    raRnti = (1 + symbolIdx + (14*slotIdx) + (14*80*freqIdx) + (14*80*8*ulCarrierIdx));
69    return raRnti;
70 }
71
72 /**
73  * @brief create raCb function. 
74  *
75  * @details
76  *
77  *     Function : createSchRaCb
78  *     
79  *     This function create raCb
80  *     
81  *  @param[in]  tcrnti
82  *  @param[in]  shed instance
83  *  @return  void
84  **/
85 void createSchRaCb(uint16_t tcrnti, Inst schInst)
86 {
87    uint8_t ueIdx = 0;
88
89    GET_UE_IDX(tcrnti, ueIdx);
90    schCb[schInst].cells[schInst]->raCb[ueIdx -1].tcrnti = tcrnti;
91 }
92
93 /**
94  * @brief resource allocation for msg3 PUSCH
95  *
96  * @details
97  *
98  *     Function : schAllocMsg3Pusch 
99  *     
100  *     This function handles msg3 PUSCH allocation
101  *     
102  *  @param[in]  Inst schInst, SCH instance
103  *  @param[in]  slot, current slot
104  *  @param[out]  msg3StartRb
105  *  @param[out]  msg3NumRb
106  *  @return  void
107  **/
108 SchPuschInfo* schAllocMsg3Pusch(Inst schInst, uint16_t crnti, uint8_t k2Index, uint16_t msg3Slot)
109 {
110    SchCellCb      *cell          = NULLP;
111    SchUlSlotInfo  *schUlSlotInfo = NULLP;
112    uint8_t    startSymb     = 0;
113    uint8_t    symbLen       = 0; 
114    uint8_t    startRb       = 0;
115    uint8_t    numRb         = 0;
116    uint8_t    idx           = 0;
117    uint8_t    mcs            = 4;
118    uint8_t    numPdschSymbols= 11;
119    uint16_t   tbSize         = 0;
120
121    cell = schCb[schInst].cells[schInst];
122    if(cell == NULL)
123    {
124       DU_LOG("\n\nERROR  -->  SCH :  Failed to find cell in schAllocMsg3Pusch");
125       return RFAILED;
126    }
127
128    startSymb = cell->cellCfg.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].startSymbol;
129    symbLen = cell->cellCfg.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].symbolLength;
130
131    startRb = cell->schUlSlotInfo[msg3Slot]->puschCurrentPrb;
132    tbSize = schCalcTbSize(8); /* 6 bytes msg3  and 2 bytes header */
133    numRb = schCalcNumPrb(tbSize, mcs, numPdschSymbols);
134
135    /* allocating 1 extra RB for now */
136    numRb++;
137    /* increment PUSCH PRB */
138    cell->schUlSlotInfo[msg3Slot]->puschCurrentPrb += numRb;
139
140    for(idx=startSymb; idx<symbLen; idx++)
141    {
142       cell->schUlSlotInfo[msg3Slot]->assignedPrb[idx] = startRb + numRb;
143    }
144    schUlSlotInfo = cell->schUlSlotInfo[msg3Slot];
145
146    SCH_ALLOC(schUlSlotInfo->schPuschInfo, sizeof(SchPuschInfo));
147    if(!schUlSlotInfo->schPuschInfo)
148    {
149       DU_LOG("\nERROR  -->  SCH :  Memory allocation failed in schAllocMsg3Pusch");
150       return NULLP;
151    }
152    tbSize = 0;  /* since nPrb has been incremented, recalculating tbSize */
153    tbSize = schCalcTbSizeFromNPrb(numRb, mcs, numPdschSymbols);
154    tbSize = tbSize / 8 ; /*bits to byte conversion*/
155    schUlSlotInfo->schPuschInfo->crnti             = crnti;
156    schUlSlotInfo->schPuschInfo->harqProcId        = SCH_HARQ_PROC_ID;
157    schUlSlotInfo->schPuschInfo->resAllocType      = SCH_ALLOC_TYPE_1;
158    schUlSlotInfo->schPuschInfo->fdAlloc.startPrb  = startRb;
159    schUlSlotInfo->schPuschInfo->fdAlloc.numPrb    = numRb;
160    schUlSlotInfo->schPuschInfo->tdAlloc.startSymb = startSymb;
161    schUlSlotInfo->schPuschInfo->tdAlloc.numSymb   = symbLen;
162    schUlSlotInfo->schPuschInfo->tbInfo.qamOrder   = QPSK_MODULATION;  /* QPSK modulation */
163    schUlSlotInfo->schPuschInfo->tbInfo.mcs           = mcs;
164    schUlSlotInfo->schPuschInfo->tbInfo.mcsTable   = SCH_MCS_TABLE_QAM_64;
165    schUlSlotInfo->schPuschInfo->tbInfo.ndi        = NEW_TRANSMISSION; /* new transmission */
166    schUlSlotInfo->schPuschInfo->tbInfo.rv               = 0;
167    schUlSlotInfo->schPuschInfo->tbInfo.tbSize     = tbSize; /*Considering 2 PRBs */
168    schUlSlotInfo->schPuschInfo->dmrsMappingType   = DMRS_MAP_TYPE_A;  /* Setting Type-A */
169    schUlSlotInfo->schPuschInfo->nrOfDmrsSymbols   = NUM_DMRS_SYMBOLS;
170    schUlSlotInfo->schPuschInfo->dmrsAddPos        = DMRS_ADDITIONAL_POS;
171
172    return schUlSlotInfo->schPuschInfo;
173 }
174
175 /**
176  * @brief Check if a time frame is in RA Response window
177  *
178  * @details
179  *
180  *     Function : isInRaRspWindow
181  *
182  *     Check if a time frame is in RA Response window
183  *
184  *  @param[in]  RA request
185  *  @param[in]  Time frame to check
186  *  @param[in]  Total number of slot per radio frame
187  *  @return  true 
188  *  @return  false
189  **/
190 RaRspWindowStatus isInRaRspWindow(SchRaReq *raReq, SlotTimingInfo frameToCheck, uint16_t numSlotsPerSystemFrame)
191 {
192    uint32_t winStartTime, winEndTime, timeToCheck;
193    
194    winStartTime = (raReq->winStartTime.sfn * numSlotsPerSystemFrame) + raReq->winStartTime.slot;
195    winEndTime = (raReq->winEndTime.sfn * numSlotsPerSystemFrame) + raReq->winEndTime.slot;
196    timeToCheck = (frameToCheck.sfn * numSlotsPerSystemFrame) + frameToCheck.slot;
197
198    /* TODO : check how to handle the wrap around scenario of MAX_SFN */
199    if((timeToCheck >= winStartTime) && (timeToCheck <= winEndTime))
200       return WITHIN_WINDOW;
201    else if(timeToCheck < winStartTime)
202       return WINDOW_YET_TO_START;
203       
204    return WINDOW_EXPIRED;
205 }
206
207 /**
208  * @brief Processes any pending RA request
209  *
210  * @details
211  *
212  *     Function : schProcessRaReq
213  *
214  *     This function process pending RA request
215  *
216  *  @param[in]  Current timing of the cell
217  *  @return  ROK
218  **/
219 void schProcessRaReq(SlotTimingInfo currTime, SchCellCb *cell)
220 {
221    bool      k2Found = false;
222    uint8_t   ueIdx = 0, k0TblIdx = 0, k2TblIdx = 0;
223    uint8_t   k0Index = 0, k2Index = 0;
224    uint8_t   k0 = 0, k2 = 0;
225    uint8_t   puschMu = 0;
226    uint8_t   msg3Delta = 0, msg3MinSchTime = 0;
227 #ifdef NR_TDD
228    uint8_t   totalCfgSlot = 0;
229 #endif
230    uint16_t  dciSlot = 0, rarSlot = 0, msg3Slot = 0;
231    SlotTimingInfo dciTime, rarTime;
232    RarAlloc *dciSlotAlloc = NULLP;  /* Stores info for transmission of PDCCH for RAR */
233    RarAlloc *rarSlotAlloc = NULLP;  /* Stores info for transmission of RAR PDSCH */
234    SchPuschInfo *msg3PuschInfo = NULLP;          /* Stores MSG3 PUSCH scheduling information */
235    PduTxOccsaion  ssbOccasion=0, sib1Occasion=0;
236    SchK0K1TimingInfoTbl *k0K1InfoTbl=NULLP;    
237    SchK2TimingInfoTbl *msg3K2InfoTbl=NULLP;
238    RaRspWindowStatus windowStatus=0;
239
240    while(ueIdx < MAX_NUM_UE)
241    {
242       if(cell->raReq[ueIdx] == NULLP)
243       {
244          ueIdx++;
245          continue;
246       }
247
248 #ifdef NR_TDD
249       totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbSchCfg.scsCommon, cell->cellCfg.tddCfg.tddPeriod);
250 #endif
251       k0K1InfoTbl = &cell->cellCfg.schInitialDlBwp.k0K1InfoTbl;
252       msg3K2InfoTbl = &cell->cellCfg.schInitialUlBwp.msg3K2InfoTbl;
253       puschMu = cell->cellCfg.numerology;
254       msg3Delta = puschDeltaTable[puschMu];
255       msg3MinSchTime = minMsg3SchTime[cell->cellCfg.numerology];
256
257       /* Calculating time frame to send DCI for RAR */
258       ADD_DELTA_TO_TIME(currTime, dciTime, PHY_DELTA_DL + SCHED_DELTA);
259       dciSlot = dciTime.slot;
260 #ifdef NR_TDD
261       /* Consider this slot for sending DCI, only if it is a DL slot */
262       if(schGetSlotSymbFrmt(dciSlot, cell->slotFrmtBitMap) == DL_SLOT)
263 #endif
264       {
265          
266          /* Check if this slot is within RA response window */
267          windowStatus = isInRaRspWindow(cell->raReq[ueIdx], dciTime, cell->numSlots);
268          if(windowStatus == WITHIN_WINDOW)
269          {
270             /* For all k0 values, search for a suitable k2 value to schedule MSG3.
271              * RAR DCI, RAR PDSCH and MSG3 is scheduled only if one such k0-k2 combination
272              * is found. Else no scheduling happens. 
273              */
274             for(k0TblIdx = 0; k0TblIdx < k0K1InfoTbl->k0k1TimingInfo[dciSlot].numK0; k0TblIdx++)
275             {
276                k0Index = k0K1InfoTbl->k0k1TimingInfo[dciSlot].k0Indexes[k0TblIdx].k0Index;
277                k0 = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
278
279                /* Calculating time frame to send RAR PDSCH */
280                ADD_DELTA_TO_TIME(dciTime, rarTime, k0);
281                rarSlot = rarTime.slot;
282
283                for(k2TblIdx = 0; k2TblIdx < msg3K2InfoTbl->k2TimingInfo[rarSlot].numK2; k2TblIdx++)
284                {
285                   k2Index = msg3K2InfoTbl->k2TimingInfo[rarSlot].k2Indexes[k2TblIdx];
286                   k2 = cell->cellCfg.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].k2;
287
288                   /* Delta is added to the slot allocation for msg3 based on 38.214 section 6.1.2.1 */
289                   k2 = k2 + msg3Delta;
290                   if(k2 >= msg3MinSchTime)
291                   {
292                      msg3Slot = (rarSlot + k2) % cell->numSlots;
293 #ifdef NR_TDD
294                      if(schGetSlotSymbFrmt(msg3Slot % totalCfgSlot, cell->slotFrmtBitMap) == DL_SLOT)
295                         continue;
296 #endif
297                      k2Found = true;
298                      break;
299                   }
300                }
301                if(k2Found)
302                   break;
303             }
304          }
305          else if(windowStatus == WINDOW_EXPIRED)
306          {
307             SCH_FREE(cell->raReq[ueIdx]->rachInd, sizeof(RachIndInfo));
308             SCH_FREE(cell->raReq[ueIdx], sizeof(SchRaReq));
309             ueIdx++;
310             continue;
311          }
312
313          /* If K0-K2 combination not found, no scheduling happens */
314          if(!k2Found)
315          {
316             ueIdx++;
317             continue;
318          }
319
320          /* Allocate memory for RAR PDCCH slot, pointer will be checked at schProcessSlotInd() */
321          SCH_ALLOC(dciSlotAlloc, sizeof(RarAlloc));
322          if(dciSlotAlloc == NULLP)
323          {
324             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciSlotAlloc");
325             return;
326          }
327          cell->schDlSlotInfo[dciSlot]->rarAlloc = dciSlotAlloc;
328
329          /* Check if RAR PDSCH occasion same as SSB and SIB1 occasion */
330          ssbOccasion = schCheckSsbOcc(rarTime, cell);
331          sib1Occasion = schCheckSib1Occ(rarTime, cell);
332
333          /* Fill PDCCH and PDSCH scheduling information for RAR */
334          schFillRar(dciSlotAlloc, cell->raReq[ueIdx]->raRnti,
335             cell->cellCfg.phyCellId, cell->cellCfg.ssbSchCfg.ssbOffsetPointA, k0Index,
336             ssbOccasion, sib1Occasion);
337
338          /* Allocate resources for msg3 */
339          msg3PuschInfo = schAllocMsg3Pusch(cell->instIdx, cell->raReq[ueIdx]->rachInd->crnti, k2Index, msg3Slot);
340          if(msg3PuschInfo)
341          {
342             /* Fill RAR info */
343             dciSlotAlloc->rarInfo.raRnti = cell->raReq[ueIdx]->raRnti;
344             dciSlotAlloc->rarInfo.tcrnti = cell->raReq[ueIdx]->rachInd->crnti;
345             dciSlotAlloc->rarInfo.RAPID = cell->raReq[ueIdx]->rachInd->preambleIdx;
346             dciSlotAlloc->rarInfo.ta = cell->raReq[ueIdx]->rachInd->timingAdv;
347             dciSlotAlloc->rarInfo.ulGrant.bwpSize = cell->cellCfg.schInitialUlBwp.bwp.freqAlloc.numPrb;
348             /* Spec 38.213, section 8.2, 0 : MSG3 PUSCH will be transmitted without frequency hopping */
349             dciSlotAlloc->rarInfo.ulGrant.freqHopFlag = 0;
350             dciSlotAlloc->rarInfo.ulGrant.msg3FreqAlloc.startPrb = msg3PuschInfo->fdAlloc.startPrb;
351             dciSlotAlloc->rarInfo.ulGrant.msg3FreqAlloc.numPrb = msg3PuschInfo->fdAlloc.numPrb;
352             dciSlotAlloc->rarInfo.ulGrant.k2Index = k2Index;
353             dciSlotAlloc->rarInfo.ulGrant.mcs = msg3PuschInfo->tbInfo.mcs;
354             dciSlotAlloc->rarInfo.ulGrant.tpc = 3;  /* TODO : Check appropriate value to be filled */
355             /* Spec 38.213, section 8.2 : In a contention based random access
356              * procedure, the CSI request field is reserved. */
357             dciSlotAlloc->rarInfo.ulGrant.csiReq = 0;
358          }
359
360          /* Check if both DCI and RAR are sent in the same slot.
361           * If not, allocate memory RAR PDSCH slot to store RAR info
362           */
363          if(dciSlot == rarSlot)
364             dciSlotAlloc->pduPres = BOTH;
365          else
366          {
367             /* Allocate memory to schedule rarSlot to send RAR, pointer will be checked at schProcessSlotInd() */
368             SCH_ALLOC(rarSlotAlloc, sizeof(RarAlloc));
369             if(rarSlotAlloc == NULLP)
370             {
371                DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for rarSlotAlloc");
372                SCH_FREE(dciSlotAlloc, sizeof(RarAlloc));
373                return;
374             }
375             cell->schDlSlotInfo[rarSlot]->rarAlloc = rarSlotAlloc;
376
377             /* Copy all RAR info */
378             memcpy(rarSlotAlloc, dciSlotAlloc, sizeof(RarAlloc));
379             rarSlotAlloc->rarPdcchCfg.dci.pdschCfg = &rarSlotAlloc->rarPdschCfg;
380
381             /* Assign correct PDU types in corresponding slots */
382             rarSlotAlloc->pduPres = PDSCH_PDU;
383             dciSlotAlloc->pduPres = PDCCH_PDU;
384             dciSlotAlloc->pdschSlot = rarSlot;  
385          }
386
387          /* Create raCb at SCH */
388          createSchRaCb(cell->raReq[ueIdx]->rachInd->crnti, cell->instIdx);
389
390          SCH_FREE(cell->raReq[ueIdx]->rachInd, sizeof(RachIndInfo));
391          SCH_FREE(cell->raReq[ueIdx], sizeof(SchRaReq));
392       }
393       ueIdx++;
394    } /* End of while(ueIdx < MAX_NUM_UE) */
395 }
396
397 /**
398  * @brief process rach indication function. 
399  *
400  * @details
401  *
402  *     Function : schProcessRachInd
403  *     
404  *     This function process rach indication
405  *     
406  *  @param[in]  rachInd parameters
407  *  @param[in]  shed instance
408  *  @return  ROK
409  **/
410 uint8_t schProcessRachInd(RachIndInfo *rachInd, Inst schInst)
411 {
412    SchCellCb *cell = schCb[schInst].cells[schInst];
413    SchRaReq  *raReq = NULLP;
414    float    slotDuration;
415    uint8_t  winNumSlots;
416    uint8_t  ueIdx;
417
418    if(cell == NULLP)
419    {
420       DU_LOG("\nERROR  -->  SCH: Failed to find cell in schProcessRachInd");
421       return RFAILED;
422    }
423
424    /* Storing RA request in cellCb */
425    GET_UE_IDX(rachInd->crnti, ueIdx);
426    if(ueIdx <= 0)
427    {
428       DU_LOG("\nERROR  -->  SCH: Invalid CRNTI [%d]", rachInd->crnti);
429       return RFAILED;
430    }
431
432    SCH_ALLOC(raReq, sizeof(SchRaReq));
433    if(!raReq)
434    {
435       DU_LOG("\nERROR  -->  SCH : Memory allocation failure in schProcessRachInd");
436       SCH_FREE(rachInd, sizeof(RachIndInfo));
437       return RFAILED;
438    }
439
440    /* calculate the ra-rnti value */
441    raReq->raRnti = calculateRaRnti(rachInd->symbolIdx, rachInd->slotIdx, rachInd->freqIdx);
442    raReq->rachInd = rachInd;
443    raReq->winStartTime.sfn = rachInd->timingInfo.sfn;
444    raReq->winStartTime.slot = rachInd->timingInfo.slot;
445   
446    /* Converting window size from ms to number of slots */
447    slotDuration = (1 / pow(2, cell->cellCfg.numerology));
448    winNumSlots = (float)cell->cellCfg.schRachCfg.raRspWindow / slotDuration;
449    
450    /* Adding window size to window start time to get window end time */
451    ADD_DELTA_TO_TIME(raReq->winStartTime, raReq->winEndTime, winNumSlots);
452
453    cell->raReq[ueIdx -1] = raReq;
454
455    return ROK;
456 }
457
458 /**
459  * @brief fill RAR info function. 
460  *
461  * @details
462  *
463  *     Function : calculateRaRnti
464  *     
465  *     This function fills pdcch and pdsch info for RAR
466  *     
467  *  @param[in]  rar Allocation info
468  *  @param[in]  ra-rnti
469  *  @param[in]  PCI
470  *  @param[in]  offset to pointA to determine freq alloc
471  *  @return  ROK
472  **/
473 uint8_t schFillRar(RarAlloc *rarAlloc, uint16_t raRnti, uint16_t pci, uint8_t offsetPointA, \
474 uint8_t k0Index, bool ssbPresent, bool sib1Present)
475 {
476    Inst inst = 0;
477    uint8_t coreset0Idx = 0;
478    uint8_t numRbs = 0;
479    uint8_t firstSymbol = 0;
480    uint8_t numSymbols = 0;
481    uint8_t offset = 0;
482    uint8_t FreqDomainResource[6] = {0};
483    uint16_t tbSize = 0;
484    uint8_t mcs = 4;  /* MCS fixed to 4 */
485
486    if(schCb[inst].cells[inst] == NULL)
487    {
488       DU_LOG("\nERROR  -->  SCH: Cell not found");
489       return RFAILED;
490    }
491
492    SchBwpDlCfg *initialBwp = &schCb[inst].cells[inst]->cellCfg.schInitialDlBwp;
493    PdcchCfg *pdcch = &rarAlloc->rarPdcchCfg;
494    PdschCfg *pdsch = &rarAlloc->rarPdschCfg;
495    BwpCfg *bwp = &rarAlloc->bwp;
496    FreqDomainAlloc *sib1PdschFreqAlloc = NULL;
497
498    coreset0Idx     = initialBwp->pdcchCommon.commonSearchSpace.coresetId;
499
500    /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
501    numRbs        = coresetIdxTable[coreset0Idx][1];
502    numSymbols    = coresetIdxTable[coreset0Idx][2];
503    offset        = coresetIdxTable[coreset0Idx][3];
504
505    /* calculate time domain parameters */
506    // note: since slot value is made sl1, RAR can be sent at all slots
507    uint16_t mask = 0x2000;
508    for(firstSymbol=0; firstSymbol<14;firstSymbol++)
509    {
510       if(initialBwp->pdcchCommon.commonSearchSpace.monitoringSymbol & mask)
511          break;
512       else
513          mask = mask>>1;
514    }
515
516    /* calculate the PRBs */
517    freqDomRscAllocType0(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
518
519    /* fill BWP */
520    bwp->freqAlloc.numPrb   = initialBwp->bwp.freqAlloc.numPrb;
521    bwp->freqAlloc.startPrb = initialBwp->bwp.freqAlloc.startPrb;
522    bwp->subcarrierSpacing  = initialBwp->bwp.scs;
523    bwp->cyclicPrefix       = initialBwp->bwp.cyclicPrefix;
524
525    /* fill the PDCCH PDU */
526    pdcch->coresetCfg.startSymbolIndex = firstSymbol;
527    pdcch->coresetCfg.durationSymbols = numSymbols;
528    memcpy(pdcch->coresetCfg.freqDomainResource, FreqDomainResource, FREQ_DOM_RSRC_SIZE);
529    pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
530    pdcch->coresetCfg.regBundleSize = 6;    /* spec-38.211 sec 7.3.2.2 */
531    pdcch->coresetCfg.interleaverSize = 2;  /* spec-38.211 sec 7.3.2.2 */
532    pdcch->coresetCfg.coreSetType = 0;
533    pdcch->coresetCfg.shiftIndex = pci;
534    pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
535    pdcch->numDlDci = 1;
536    pdcch->dci.rnti = raRnti; /* RA-RNTI */
537    pdcch->dci.scramblingId = pci;
538    pdcch->dci.scramblingRnti = 0;
539    pdcch->dci.cceIndex = 4; /* considering SIB1 is sent at cce 0-1-2-3 */
540    pdcch->dci.aggregLevel = 4;
541    pdcch->dci.beamPdcchInfo.numPrgs = 1;
542    pdcch->dci.beamPdcchInfo.prgSize = 1;
543    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
544    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
545    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
546    pdcch->dci.txPdcchPower.powerValue = 0;
547    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
548    pdcch->dci.pdschCfg = pdsch;
549
550    /* fill the PDSCH PDU */
551    uint8_t cwCount = 0;
552    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
553    pdsch->rnti = raRnti; /* RA-RNTI */
554    pdsch->pduIndex = 0;
555    pdsch->numCodewords = 1;
556    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
557    {
558       pdsch->codeword[cwCount].targetCodeRate = 308;
559       pdsch->codeword[cwCount].qamModOrder = 2;
560       pdsch->codeword[cwCount].mcsIndex = mcs; /* mcs configured to 4 */
561       pdsch->codeword[cwCount].mcsTable = 0;   /* notqam256 */
562       pdsch->codeword[cwCount].rvIndex = 0;
563       /* RAR PDU length and FAPI payload header length */
564       tbSize = schCalcTbSize(RAR_PAYLOAD_SIZE + TX_PAYLOAD_HDR_LEN);
565       pdsch->codeword[cwCount].tbSize = tbSize;
566    }
567    pdsch->dataScramblingId = pci;
568    pdsch->numLayers = 1;
569    pdsch->transmissionScheme = 0;
570    pdsch->refPoint = 0;
571    pdsch->dmrs.dlDmrsSymbPos = 4;  /* Bitmap value 00000000000100 i.e. using 3rd symbol for PDSCH DMRS */
572    pdsch->dmrs.dmrsConfigType = 0; /* type-1 */
573    pdsch->dmrs.dlDmrsScramblingId = pci;
574    pdsch->dmrs.scid = 0;
575    pdsch->dmrs.numDmrsCdmGrpsNoData = 1;
576    pdsch->dmrs.dmrsPorts = 0;
577    pdsch->dmrs.mappingType      = DMRS_MAP_TYPE_A;  /* Type-A */
578    pdsch->dmrs.nrOfDmrsSymbols  = NUM_DMRS_SYMBOLS;
579    pdsch->dmrs.dmrsAddPos       = DMRS_ADDITIONAL_POS;
580    pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
581    /* The RB numbering starts from coreset0 */ 
582    pdsch->pdschFreqAlloc.freqAlloc.startPrb = PDSCH_START_RB;
583    if(ssbPresent)
584    {
585       /* PDSCH is always above SSB */
586       pdsch->pdschFreqAlloc.freqAlloc.startPrb = offsetPointA + SCH_SSB_NUM_PRB + 1;
587    }
588    if(sib1Present)
589    {
590       /* Must not overlap with SIB1 */
591       sib1PdschFreqAlloc = &schCb[inst].cells[inst]->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc;
592       pdsch->pdschFreqAlloc.freqAlloc.startPrb = sib1PdschFreqAlloc->startPrb + sib1PdschFreqAlloc->numPrb + 1; 
593    }
594    pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, mcs, \
595       initialBwp->pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol);
596    pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
597    pdsch->pdschTimeAlloc.timeAlloc.startSymb = initialBwp->pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
598    pdsch->pdschTimeAlloc.timeAlloc.numSymb = initialBwp->pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
599    pdsch->beamPdschInfo.numPrgs = 1;
600    pdsch->beamPdschInfo.prgSize = 1;
601    pdsch->beamPdschInfo.digBfInterfaces = 0;
602    pdsch->beamPdschInfo.prg[0].pmIdx = 0;
603    pdsch->beamPdschInfo.prg[0].beamIdx[0] = 0;
604    pdsch->txPdschPower.powerControlOffset = 0;
605    pdsch->txPdschPower.powerControlOffsetSS = 0;
606
607    return ROK;
608 }
609
610 /**********************************************************************
611          End of file
612 **********************************************************************/