Automatic PRB allocation using bitmap in Downlink [Issue-ID: ODUHIGH-380]
[o-du/l2.git] / src / 5gnrsch / sch_common.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:     5G NR SCH layer
22
23 Type:     C source file
24
25 Desc:     C source code for Entry point fucntions
26
27 File:     sch_common.c
28
29  **********************************************************************/
30
31 /** @file sch_common.c
32   @brief This module performs common scheduling
33  */
34 #include "common_def.h"
35 #include "tfu.h"
36 #include "lrg.h"
37
38 #include "tfu.x"
39 #include "lrg.x"
40 #include "du_log.h"
41 #include "du_app_mac_inf.h"
42 #include "mac_sch_interface.h"
43 #include "sch.h"
44 #include "sch_utils.h"
45
46 SchCb schCb[SCH_MAX_INST];
47 uint16_t prachCfgIdxTable[MAX_PRACH_CONFIG_IDX][8];
48 uint16_t numRbForPrachTable[MAX_RACH_NUM_RB_IDX][5];
49 uint8_t pucchResourceSet[MAX_PUCCH_RES_SET_IDX][4];
50 uint8_t puschDeltaTable[MAX_MU_PUSCH];
51
52 SchMacUlSchInfoFunc schMacUlSchInfoOpts[] =
53 {
54    packSchMacUlSchInfo,
55    MacProcUlSchInfo,
56    packSchMacUlSchInfo
57 };
58
59 /**
60  * @brief common resource allocation for SSB
61  *
62  * @details
63  *
64  *     Function : schBroadcastSsbAlloc
65  *     
66  *     This function handles common scheduling for SSB
67  *     
68  *  @param[in]  SchCellCb *cell, cell cb
69  *  @param[in]  DlBrdcstAlloc *dlBrdcstAlloc, DL brdcst allocation
70  *  @return  void
71  **/
72 uint8_t schBroadcastSsbAlloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstAlloc *dlBrdcstAlloc)
73 {
74    /* schedule SSB */
75    uint8_t ssbStartSymb, idx;
76    uint16_t ssbStartPrb;
77    SchDlSlotInfo *schDlSlotInfo;
78    SsbInfo ssbInfo;
79
80    schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
81    ssbStartPrb = cell->cellCfg.ssbSchCfg.ssbOffsetPointA; //+Kssb
82    ssbStartSymb = cell->ssbStartSymbArr[dlBrdcstAlloc->ssbIdxSupported-1]; /*since we are
83                                                                              supporting only 1 ssb beam */
84
85    /* Assign interface structure */
86    for(idx=0; idx<dlBrdcstAlloc->ssbIdxSupported; idx++)
87    {
88       ssbInfo.ssbIdx              = idx;
89       ssbInfo.fdAlloc.startPrb    = ssbStartPrb;
90       ssbInfo.fdAlloc.numPrb      = SCH_SSB_NUM_PRB;
91       ssbInfo.tdAlloc.startSymb   = ssbStartSymb;
92       ssbInfo.tdAlloc.numSymb     = SCH_SSB_NUM_SYMB;
93       dlBrdcstAlloc->ssbInfo[idx] = ssbInfo;
94       schDlSlotInfo->ssbInfo[idx] = ssbInfo;
95    }
96
97    if((allocatePrbDl(cell, slotTime, ssbStartSymb, SCH_SSB_NUM_SYMB, &ssbInfo.fdAlloc.startPrb, ssbInfo.fdAlloc.numPrb)) != ROK)
98    {
99        DU_LOG("\nERROR  -->  SCH: PRB allocation failed for SSB in SFN:SLOT [%d : %d]", slotTime.sfn, slotTime.slot);
100        return RFAILED;
101    }
102
103
104    schDlSlotInfo->ssbPres = true;
105    schDlSlotInfo->ssbIdxSupported = dlBrdcstAlloc->ssbIdxSupported;
106    return ROK;
107 }
108
109 /**
110  * @brief common resource allocation for SIB1
111  *
112  * @details
113  *
114  *     Function : schBroadcastSib1Alloc
115  *     
116  *     This function handles common scheduling for SIB1
117  *     
118  *  @param[in]  SchCellCb *cell, cell cb
119  *  @param[in]  DlBrdcstAlloc *dlBrdcstAlloc, DL brdcst allocation
120  *  @return  void
121  **/
122 uint8_t schBroadcastSib1Alloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstAlloc *dlBrdcstAlloc)
123 {
124    FreqDomainAlloc freqAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc;
125    TimeDomainAlloc timeAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschTimeAlloc.timeAlloc;
126    SchDlSlotInfo *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
127
128    if((allocatePrbDl(cell, slotTime, timeAlloc.startSymb, timeAlloc.numSymb, &freqAlloc.startPrb, freqAlloc.numPrb)) != ROK)
129    {
130        DU_LOG("\nERROR  -->  SCH: PRB allocation failed for SIB1 in SFN:Slot [%d : %d]", slotTime.sfn, slotTime.slot);
131        return RFAILED;
132    }
133
134    memcpy(&dlBrdcstAlloc->sib1Alloc.bwp, &cell->cellCfg.sib1SchCfg.bwp, sizeof(BwpCfg)); 
135    memcpy(&dlBrdcstAlloc->sib1Alloc.sib1PdcchCfg, &cell->cellCfg.sib1SchCfg.sib1PdcchCfg, sizeof(PdcchCfg)); 
136    memcpy(&dlBrdcstAlloc->sib1Alloc.sib1PdschCfg, &cell->cellCfg.sib1SchCfg.sib1PdschCfg, sizeof(PdschCfg)); 
137    dlBrdcstAlloc->sib1Alloc.sib1PdcchCfg.dci.pdschCfg = &dlBrdcstAlloc->sib1Alloc.sib1PdschCfg;
138    schDlSlotInfo->sib1Pres = true;
139    return ROK;
140 }
141
142 /*******************************************************************
143  *
144  * @brief Handles sending UL scheduler info to MAC 
145  *
146  * @details
147  *
148  *    Function : sendUlSchInfoToMac
149  *
150  *    Functionality:
151  *     Sends UL Sch info to MAC from SCH
152  *
153  * @params[in] 
154  * @return ROK     - success
155  *         RFAILED - failure
156  *
157  * ****************************************************************/
158 int sendUlSchInfoToMac(UlSchedInfo *ulSchedInfo, Inst inst)
159 {
160    Pst pst;
161
162    memset(&pst, 0, sizeof(Pst));
163    FILL_PST_SCH_TO_MAC(pst, inst);
164    pst.event = EVENT_UL_SCH_INFO;
165
166    return(*schMacUlSchInfoOpts[pst.selector])(&pst, ulSchedInfo);
167 }
168 /**
169  * @brief resource allocation for PRACH
170  *
171  * @details
172  *
173  *     Function : schPrachResAlloc
174  *     
175  *     This function handles PRACH allocation
176  *     
177  *  @param[in]  SchCellCb *cell, cell cb
178  *  @param[in]  UlSchedInfo *ulSchedInfo, UL scheduling info
179  *  @return  void
180  **/
181 void schPrachResAlloc(SchCellCb *cell, UlSchedInfo *ulSchedInfo, SlotTimingInfo prachOccasionTimingInfo)
182 {
183    uint8_t  puschScs;
184    uint8_t  numPrachRb = 0;
185    uint8_t  numRa = 0;
186    uint8_t  freqStart = 0;
187    uint8_t  prachCfgIdx = 0;
188    uint8_t  prachFormat = 0;
189    uint8_t  x = 0;
190    uint8_t  y = 0;
191    uint16_t prachSubframe = 0;
192    uint8_t  prachStartSymbol = 0;
193    uint8_t  prachOcas = 0;
194    uint8_t  dataType = 0;
195    uint8_t  idx = 0;
196    uint8_t  subFrame = 0;
197    SchUlSlotInfo *schUlSlotInfo = NULLP;
198
199    puschScs      = cell->cellCfg.schInitialUlBwp.bwp.scs;
200    schUlSlotInfo = cell->schUlSlotInfo[prachOccasionTimingInfo.slot];
201    prachCfgIdx   = cell->cellCfg.schRachCfg.prachCfgIdx;
202
203    /* derive the prachCfgIdx table paramters */
204    x                = prachCfgIdxTable[prachCfgIdx][1];
205    y                = prachCfgIdxTable[prachCfgIdx][2];
206    prachSubframe    = prachCfgIdxTable[prachCfgIdx][3];
207
208    if((prachOccasionTimingInfo.sfn%x) == y)
209    {
210 #ifdef NR_TDD
211       subFrame = prachOccasionTimingInfo.slot/2;
212 #else
213       subFrame = prachOccasionTimingInfo.slot;
214 #endif
215       /* check for subFrame number */
216       if ((1 << subFrame) & prachSubframe)
217       {
218          /* prach ocassion present in this subframe */
219 #ifdef NR_TDD
220          if(UL_SLOT != schGetSlotSymbFrmt(prachOccasionTimingInfo.slot%cell->numSlotsInPeriodicity,\
221          cell->slotFrmtBitMap))
222          {
223             DU_LOG("\nERROR  --> SCH : PrachCfgIdx %d doesn't support UL slot", prachCfgIdx);
224          }
225          else
226 #endif
227          {
228             prachFormat      = prachCfgIdxTable[prachCfgIdx][0];
229             prachStartSymbol = prachCfgIdxTable[prachCfgIdx][4];
230             prachOcas        = prachCfgIdxTable[prachCfgIdx][6];
231
232             /* freq domain resource determination for RACH*/
233             freqStart = cell->cellCfg.schRachCfg.msg1FreqStart;
234             /* numRa determined as 𝑛 belonging {0,1,.., M − 1}, 
235              * where M is given by msg1Fdm */
236             numRa = (cell->cellCfg.schRachCfg.msg1Fdm - 1);
237             for(idx=0; idx<MAX_RACH_NUM_RB_IDX; idx++)
238             {
239                if(numRbForPrachTable[idx][0] == cell->cellCfg.schRachCfg.rootSeqLen)
240                {
241                   if(numRbForPrachTable[idx][1] == cell->cellCfg.schRachCfg.prachSubcSpacing)
242                   {
243                      if(numRbForPrachTable[idx][2] == puschScs)
244                      {
245                         break;
246                      }
247                   }
248                }
249             }
250             numPrachRb = numRbForPrachTable[idx][3];
251             dataType |= SCH_DATATYPE_PRACH;
252             /* Considering first slot in the frame for PRACH */
253             idx = 0;
254             //schUlSlotInfo->assignedPrb[idx] = freqStart+numPrachRb;
255          }
256          ulSchedInfo->dataType = dataType;
257          /* prach info */
258          ulSchedInfo->prachSchInfo.numPrachOcas   = prachOcas;
259          ulSchedInfo->prachSchInfo.prachFormat    = prachFormat;
260          ulSchedInfo->prachSchInfo.numRa          = numRa;
261          ulSchedInfo->prachSchInfo.prachStartSymb = prachStartSymbol;
262          DU_LOG("\nINFO  --> SCH : RACH occassion set for slot %d", prachOccasionTimingInfo.slot);
263       }
264    }
265 }
266
267
268 /**
269  * @brief Function to fill Pucch Format 0
270  *
271  * @details
272  *
273  *     Function : fillPucchFormat0
274  *     
275  *     Function to fill Pucch format 0
276  *     
277  *  @param[in]  SchPucchInfo pointer, SchPucchResrcInfo pointer
278  *  @return  void
279  **/
280
281 void fillPucchFormat0(SchPucchInfo *ulSchedPucch, SchPucchResrcInfo *resrcInfo)
282 {
283    if(resrcInfo->SchPucchFormat.format0)
284    {
285       ulSchedPucch->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
286       ulSchedPucch->pucchFormat  = PUCCH_FORMAT_0;
287       ulSchedPucch->initialCyclicShift =  resrcInfo->SchPucchFormat.format0->initialCyclicShift;
288       ulSchedPucch->tdAlloc.numSymb = resrcInfo->SchPucchFormat.format0->numSymbols;
289       ulSchedPucch->tdAlloc.startSymb = resrcInfo->SchPucchFormat.format0->startSymbolIdx;
290    }
291 }
292
293 /**
294  * @brief Function to fill Pucch Format 1
295  *
296  * @details
297  *
298  *     Function : fillPucchFormat1
299  *     
300  *     Function to fill Pucch format 1
301  *     
302  *  @param[in]  SchPucchInfo pointer, SchPucchResrcInfo pointer
303  *  @return  void
304  **/
305
306 void fillPucchFormat1(SchPucchInfo *ulSchedPucch, SchPucchResrcInfo *resrcInfo)
307 {
308    if(resrcInfo->SchPucchFormat.format1)
309    {
310       ulSchedPucch->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
311       ulSchedPucch->pucchFormat  = PUCCH_FORMAT_1;
312       ulSchedPucch->initialCyclicShift =  resrcInfo->SchPucchFormat.format1->initialCyclicShift;
313       ulSchedPucch->tdAlloc.numSymb = resrcInfo->SchPucchFormat.format1->numSymbols;
314       ulSchedPucch->tdAlloc.startSymb = resrcInfo->SchPucchFormat.format1->startSymbolIdx;
315       ulSchedPucch->timeDomOCC =  resrcInfo->SchPucchFormat.format1->timeDomOCC;
316   }
317 }
318
319 /**
320  * @brief Function to fill Pucch format for UL Sched Info
321  *
322  * @details
323  *
324  *     Function : fillUlSchedPucchFormat
325  *     
326  *     Function to fill Pucch format for UL Sched Info
327  *     
328  *  @param[in]  pucchFormat , SchPucchInfo pointer,
329  *  @param[in]  SchPucchFormatCfg pointer, SchPucchResrcInfo pointer
330  *  @return  void
331  **/
332
333 uint8_t fillUlSchedPucchFormat(uint8_t pucchFormat, SchPucchInfo *ulSchedPucch,\
334    SchPucchResrcInfo *resrcInfo, SchPucchFormatCfg *formatCfg)
335 {
336    uint8_t ret = ROK;
337
338    switch(pucchFormat)
339    {
340       case PUCCH_FORMAT_0:
341          {
342             if(resrcInfo)
343                fillPucchFormat0(ulSchedPucch, resrcInfo);
344             return ret;
345          }
346       case PUCCH_FORMAT_1:
347          {
348             if(resrcInfo)
349             {
350                fillPucchFormat1(ulSchedPucch, resrcInfo);
351             }
352             if(formatCfg)
353             {
354                memcpy(&ulSchedPucch->cmnFormatCfg, formatCfg, sizeof(SchPucchFormatCfg));
355             }
356             return ret;
357          }/* To Add support for more Pucch Format */
358       
359       default:
360          DU_LOG("\nERROR  --> SCH : Invalid PUCCH format[%d] in fillUlSchedPucchFormatCfg()", pucchFormat);
361          ret = RFAILED;
362          return ret;
363    }
364    return ret;
365 }
366
367 /**
368  * @brief Function to fill Pucch Dedicated Cfg for UL Sched Info
369  *
370  * @details
371  *
372  *     Function : fillUlSchedPucchDedicatedCfg
373  *     
374  *     Function to fill Pucch Dedicated Cfg for UL Sched Info
375  *     
376  *  @param[in]  pucchFormat to be filled
377  *  @param[in]  SchPucchFormatCfg pointer, SchPucchCfg pointer
378  *  @return  void
379  **/
380
381 uint8_t fillUlSchedPucchDedicatedCfg(uint16_t numSlots, SchPucchCfg *pucchDedCfg,\
382    SlotTimingInfo *slotInfo, SchPucchInfo *ulSchedPucch)
383 {
384    uint8_t ret, resrcSetIdx, resrcIdx, schedReqIdx, srPeriodicity = 0;
385    uint16_t srOffset = 0;
386
387    ret = ROK;
388    if(pucchDedCfg->resrcSet && pucchDedCfg->resrc)
389    {
390       //Assuming one entry in the list
391       for(resrcSetIdx = 0; resrcSetIdx < pucchDedCfg->resrcSet->resrcSetToAddModListCount; resrcSetIdx++)
392       {
393          for(resrcIdx = 0; resrcIdx < pucchDedCfg->resrc->resrcToAddModListCount; resrcIdx++)
394          {
395             if(pucchDedCfg->resrcSet->resrcSetToAddModList[resrcSetIdx].resrcList[resrcSetIdx] ==\
396                pucchDedCfg->resrc->resrcToAddModList[resrcIdx].resrcId)
397             {
398                ulSchedPucch->intraFreqHop = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].intraFreqHop;
399                ulSchedPucch->secondPrbHop = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].secondPrbHop;
400                ulSchedPucch->fdAlloc.startPrb = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].startPrb;
401                ulSchedPucch->pucchFormat = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].pucchFormat;
402                ret = fillUlSchedPucchFormat(ulSchedPucch->pucchFormat, ulSchedPucch,\
403                         &pucchDedCfg->resrc->resrcToAddModList[resrcIdx], NULLP);
404                if(ret == RFAILED)
405                   return ret;
406             }
407          }
408       }
409    }
410    if(pucchDedCfg->format1)
411    {
412       memset(&ulSchedPucch->cmnFormatCfg, 0, sizeof(SchPucchFormatCfg));
413       ret = fillUlSchedPucchFormat(ulSchedPucch->pucchFormat, ulSchedPucch, NULLP, pucchDedCfg->format1);
414       if(ret == RFAILED)
415          return ret;
416    }
417    
418    /* setting SR and UCI flag */
419    if(pucchDedCfg->schedReq)
420    {
421       for(schedReqIdx = 0; schedReqIdx < pucchDedCfg->schedReq->schedAddModListCount; schedReqIdx++)
422       {
423          srPeriodicity = pucchDedCfg->schedReq->schedAddModList[schedReqIdx].periodicity;
424          srOffset      = pucchDedCfg->schedReq->schedAddModList[schedReqIdx].offset;
425          break;
426       }
427       if(((numSlots * slotInfo->sfn + slotInfo->slot - srOffset) % srPeriodicity) == 0)
428       {
429          ulSchedPucch->srFlag  = true;
430          ulSchedPucch->uciFlag = true;
431       }
432    }
433    return ret;
434 }
435
436 /**
437  * @brief Function to fill Pucch Resource Info
438  *
439  * @details
440  *
441  *     Function : fillPucchResourceInfo
442  *     
443  *     Function to fill Pucch Resource Info
444  *     
445  *  @param[in]  SchPucchInfo *schPucchInfo, Inst inst
446  *  @return  ROK/RFAILED
447  **/
448
449 uint16_t fillPucchResourceInfo(SchPucchInfo *schPucchInfo, Inst inst)
450 {
451    uint8_t ret = ROK, ueIdx = 0, pucchIdx = 0;
452    SchCellCb  *cell = schCb[inst].cells[inst];
453    SchPucchCfgCmn *pucchCfg = NULLP;
454    SchBwpParams *ulBwp = NULLP;
455
456    GET_UE_IDX(schPucchInfo->rnti, ueIdx);
457    if(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfgPres)
458    {
459       /* fill pucch dedicated cfg */
460       ret = fillUlSchedPucchDedicatedCfg(cell->numSlots,\
461        &cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg, &cell->slotInfo, schPucchInfo);
462       if(ret == RFAILED)
463       {
464          memset(schPucchInfo, 0, sizeof(SchPucchInfo));
465          DU_LOG("\nERROR  --> SCH : Filling PUCCH dedicated cfg failed at fillPucchResourceInfo()");
466          return ret;
467       }
468    }
469    else
470    {
471       /* fill pucch common cfg */
472       /* derive pucchResourceSet from schCellCfg */
473       pucchCfg = &cell->cellCfg.schInitialUlBwp.pucchCommon;
474       pucchIdx = pucchCfg->pucchResourceCommon;
475       ulBwp = &cell->cellCfg.schInitialUlBwp.bwp;
476       schPucchInfo->fdAlloc.startPrb = ulBwp->freqAlloc.startPrb + pucchResourceSet[pucchIdx][3];
477       schPucchInfo->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
478       schPucchInfo->tdAlloc.startSymb = pucchResourceSet[pucchIdx][1];
479       schPucchInfo->tdAlloc.numSymb = pucchResourceSet[pucchIdx][2];
480       schPucchInfo->pucchFormat = pucchResourceSet[pucchIdx][0];
481
482       /* set SR and UCI flag to false */
483       schPucchInfo->srFlag  = true;
484       schPucchInfo->uciFlag = true;
485    }
486    /* set HARQ flag to true */
487    schPucchInfo->harqFlag = true;
488    schPucchInfo->numHarqBits = 1; /* 1 bit for HARQ */
489
490    return ROK;
491 }
492
493 /**
494  * @brief resource allocation for UL
495  *
496  * @details
497  *
498  *     Function : schUlResAlloc
499  *     
500  *     This function handles UL Resource allocation
501  *     
502  *  @param[in]  SchCellCb *cell, cellCb
503  *  @return  void
504  **/
505 uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst)
506 {
507    int ret = ROK;
508    UlSchedInfo ulSchedInfo;
509    SchUlSlotInfo  *schUlSlotInfo = NULLP;
510    SlotTimingInfo ulTimingInfo;
511    memset(&ulSchedInfo, 0, sizeof(UlSchedInfo));
512
513    /* add PHY delta */
514    ADD_DELTA_TO_TIME(cell->slotInfo,ulTimingInfo,PHY_DELTA_UL+SCHED_DELTA);
515
516    ulSchedInfo.cellId = cell->cellId;
517    ulSchedInfo.slotIndInfo.cellId = ulSchedInfo.cellId;
518    ulSchedInfo.slotIndInfo.sfn = ulTimingInfo.sfn;
519    ulSchedInfo.slotIndInfo.slot = ulTimingInfo.slot;
520
521    /* Schedule resources for PRACH */
522    if(cell->firstSib1Transmitted)
523     schPrachResAlloc(cell, &ulSchedInfo, ulTimingInfo);
524
525    schUlSlotInfo = cell->schUlSlotInfo[ulTimingInfo.slot]; 
526    if(schUlSlotInfo->schPuschInfo)
527    {
528       ulSchedInfo.crnti = schUlSlotInfo->schPuschInfo->crnti;
529       ulSchedInfo.dataType |= SCH_DATATYPE_PUSCH;
530       memcpy(&ulSchedInfo.schPuschInfo, schUlSlotInfo->schPuschInfo,
531             sizeof(SchPuschInfo));
532       SCH_FREE(schUlSlotInfo->schPuschInfo, sizeof(SchPuschInfo));
533       schUlSlotInfo->schPuschInfo = NULL;
534    }
535
536    if(schUlSlotInfo->pucchPres)
537    {
538       ulSchedInfo.dataType |= SCH_DATATYPE_UCI;
539       fillPucchResourceInfo(&schUlSlotInfo->schPucchInfo, schInst);
540       memcpy(&ulSchedInfo.schPucchInfo, &schUlSlotInfo->schPucchInfo,
541             sizeof(SchPucchInfo));
542       memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
543    }
544
545    //send msg to MAC
546    ret = sendUlSchInfoToMac(&ulSchedInfo, schInst);
547    if(ret != ROK)
548    {
549       DU_LOG("\nERROR  -->  SCH : Sending UL Sch info from SCH to MAC failed");
550    }
551
552    schInitUlSlot(schUlSlotInfo);
553    return ret;
554 }
555
556 /*******************************************************************
557  *
558  * @brief Fills pdcch and pdsch info for msg4
559  *
560  * @details
561  *
562  *    Function : schDlRsrcAllocMsg4
563  *
564  *    Functionality:
565  *       Fills pdcch and pdsch info for msg4
566  *
567  * @params[in] 
568  * @return ROK     - success
569  *         RFAILED - failure
570  *
571  * ****************************************************************/
572 uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo slotTime, DlMsgAlloc *msg4Alloc)
573 {
574    uint8_t coreset0Idx = 0;
575    uint8_t numRbs = 0;
576    uint8_t firstSymbol = 0;
577    uint8_t numSymbols = 0;
578    uint8_t offset = 0;
579    uint8_t offsetPointA;
580    uint8_t FreqDomainResource[6] = {0};
581    uint16_t tbSize = 0;
582    uint8_t mcs = 4;                         /* MCS fixed to 4 */
583    SchBwpDlCfg *initialBwp;
584
585    PdcchCfg *pdcch = &msg4Alloc->dlMsgPdcchCfg;
586    PdschCfg *pdsch = &msg4Alloc->dlMsgPdschCfg;
587    BwpCfg *bwp = &msg4Alloc->bwp;
588
589    initialBwp   = &cell->cellCfg.schInitialDlBwp;
590    offsetPointA = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
591    coreset0Idx  = initialBwp->pdcchCommon.commonSearchSpace.coresetId;
592
593    /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
594    numRbs        = coresetIdxTable[coreset0Idx][1];
595    numSymbols    = coresetIdxTable[coreset0Idx][2];
596    offset        = coresetIdxTable[coreset0Idx][3];
597
598    /* calculate time domain parameters */
599    uint16_t mask = 0x2000;
600    for(firstSymbol=0; firstSymbol<14;firstSymbol++)
601    {
602       if(initialBwp->pdcchCommon.commonSearchSpace.monitoringSymbol & mask)
603          break;
604       else
605          mask = mask>>1;
606    }
607
608    /* calculate the PRBs */
609    freqDomRscAllocType0(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
610
611    /* fill BWP */
612    bwp->freqAlloc.numPrb   = initialBwp->bwp.freqAlloc.numPrb;
613    bwp->freqAlloc.startPrb = initialBwp->bwp.freqAlloc.startPrb;
614    bwp->subcarrierSpacing  = initialBwp->bwp.scs;
615    bwp->cyclicPrefix       = initialBwp->bwp.cyclicPrefix;
616
617    /* fill the PDCCH PDU */
618    pdcch->coresetCfg.startSymbolIndex = firstSymbol;
619    pdcch->coresetCfg.durationSymbols = numSymbols;
620    memcpy(pdcch->coresetCfg.freqDomainResource,FreqDomainResource,6);
621    pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
622    pdcch->coresetCfg.regBundleSize = 6;    /* spec-38.211 sec 7.3.2.2 */
623    pdcch->coresetCfg.interleaverSize = 2;  /* spec-38.211 sec 7.3.2.2 */
624    pdcch->coresetCfg.coreSetType = 0;
625    pdcch->coresetCfg.coreSetSize = numRbs;
626    pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
627    pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
628    pdcch->numDlDci = 1;
629    pdcch->dci.rnti = cell->schDlSlotInfo[slotTime.slot]->dlMsgInfo->crnti;
630    pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
631    pdcch->dci.scramblingRnti = 0;
632    pdcch->dci.cceIndex = 4; /* considering SIB1 is sent at cce 0-1-2-3 */
633    pdcch->dci.aggregLevel = 4;
634    pdcch->dci.beamPdcchInfo.numPrgs = 1;
635    pdcch->dci.beamPdcchInfo.prgSize = 1;
636    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
637    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
638    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
639    pdcch->dci.txPdcchPower.powerValue = 0;
640    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
641
642    /* fill the PDSCH PDU */
643    uint8_t cwCount = 0;
644    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
645    pdsch->rnti = cell->schDlSlotInfo[slotTime.slot]->dlMsgInfo->crnti;
646    pdsch->pduIndex = 0;
647    pdsch->numCodewords = 1;
648    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
649    {
650       pdsch->codeword[cwCount].targetCodeRate = 308;
651       pdsch->codeword[cwCount].qamModOrder = 2;
652       pdsch->codeword[cwCount].mcsIndex = mcs; /* mcs configured to 4 */
653       pdsch->codeword[cwCount].mcsTable = 0; /* notqam256 */
654       pdsch->codeword[cwCount].rvIndex = 0;
655       tbSize = schCalcTbSize(msg4Alloc->dlMsgInfo.dlMsgPduLen + TX_PAYLOAD_HDR_LEN); /* MSG4 size + FAPI header size*/
656       pdsch->codeword[cwCount].tbSize = tbSize;
657    }
658    pdsch->dataScramblingId = cell->cellCfg.phyCellId;
659    pdsch->numLayers = 1;
660    pdsch->transmissionScheme = 0;
661    pdsch->refPoint = 0;
662    pdsch->dmrs.dlDmrsSymbPos = 4; /* Bitmap value 00000000000100 i.e. using 3rd symbol for PDSCH DMRS */
663    pdsch->dmrs.dmrsConfigType = 0; /* type-1 */
664    pdsch->dmrs.dlDmrsScramblingId = cell->cellCfg.phyCellId;
665    pdsch->dmrs.scid = 0;
666    pdsch->dmrs.numDmrsCdmGrpsNoData = 1;
667    pdsch->dmrs.dmrsPorts = 0;
668    pdsch->dmrs.mappingType      = DMRS_MAP_TYPE_A; /* Setting to Type-A */
669    pdsch->dmrs.nrOfDmrsSymbols  = NUM_DMRS_SYMBOLS;
670    pdsch->dmrs.dmrsAddPos       = DMRS_ADDITIONAL_POS;
671
672    pdsch->pdschTimeAlloc.timeAlloc.startSymb = 3; /* spec-38.214, Table 5.1.2.1-1 */
673    pdsch->pdschTimeAlloc.timeAlloc.numSymb = NUM_PDSCH_SYMBOL;
674
675    pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
676    pdsch->pdschFreqAlloc.freqAlloc.startPrb = MAX_NUM_RB;
677    pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, mcs, NUM_PDSCH_SYMBOL);
678    pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
679
680    /* Allocate the number of PRBs required for RAR PDSCH */
681    if((allocatePrbDl(cell, slotTime, pdsch->pdschTimeAlloc.timeAlloc.startSymb, pdsch->pdschTimeAlloc.timeAlloc.numSymb,\
682       &pdsch->pdschFreqAlloc.freqAlloc.startPrb, pdsch->pdschFreqAlloc.freqAlloc.numPrb)) != ROK)
683    {
684       DU_LOG("\nERROR  --> SCH : Resource allocation failed for MSG4");
685       return RFAILED;
686    }
687
688    pdsch->beamPdschInfo.numPrgs = 1;
689    pdsch->beamPdschInfo.prgSize = 1;
690    pdsch->beamPdschInfo.digBfInterfaces = 0;
691    pdsch->beamPdschInfo.prg[0].pmIdx = 0;
692    pdsch->beamPdschInfo.prg[0].beamIdx[0] = 0;
693    pdsch->txPdschPower.powerControlOffset = 0;
694    pdsch->txPdschPower.powerControlOffsetSS = 0;
695
696    pdcch->dci.pdschCfg = pdsch;
697
698    return ROK;
699 }
700  
701 uint16_t schAllocPucchResource(SchCellCb *cell, uint16_t crnti, uint16_t slot)
702 {
703    uint8_t k1 = SCH_DEFAULT_K1, ueIdx = 0, dlToUlAckIdx;
704    uint16_t pucchSlot = 0;
705    SchUlSlotInfo  *schUlSlotInfo = NULLP;
706    SchPucchCfg    *schPucchCfg = NULLP;
707
708    GET_UE_IDX(crnti, ueIdx);
709    if(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfgPres)
710    {
711       schPucchCfg = &(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg);
712      if(schPucchCfg->dlDataToUlAck)
713      {
714         for(dlToUlAckIdx = 0; dlToUlAckIdx < schPucchCfg->dlDataToUlAck->dlDataToUlAckListCount; dlToUlAckIdx++)
715         {
716            //For now considering only the first value in the list
717            k1 = schPucchCfg->dlDataToUlAck->dlDataToUlAckList[dlToUlAckIdx];
718            break;
719         }
720      }
721    }
722    
723    pucchSlot = (slot + k1)  % cell->numSlots;
724    schUlSlotInfo = cell->schUlSlotInfo[pucchSlot];
725    memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
726
727    schUlSlotInfo->pucchPres = true;
728    schUlSlotInfo->schPucchInfo.rnti = crnti;
729
730    return ROK;
731 }
732
733 /*******************************************************************
734  *
735  * @brief Fills pdcch and pdsch info for dedicated DL msg
736  *
737  * @details
738  *
739  *    Function : schDlRsrcAllocDlMsg
740  *
741  *    Functionality:
742  *       Fills pdcch and pdsch info for dl msg
743  *
744  * @params[in]
745  * @return ROK     - success
746  *         RFAILED - failure
747  *
748  * ****************************************************************/
749 uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,
750       uint32_t *accumalatedSize, DlMsgAlloc *dlMsgAlloc)
751 {
752    uint8_t ueIdx;
753    uint16_t tbSize = 0;
754    PdcchCfg *pdcch = NULLP;
755    PdschCfg *pdsch = NULLP;
756    BwpCfg *bwp = NULLP;
757    SchUeCb ueCb;
758    SchControlRsrcSet coreset1;
759    SchPdschConfig pdschCfg;
760
761    pdcch = &dlMsgAlloc->dlMsgPdcchCfg;
762    pdsch = &dlMsgAlloc->dlMsgPdschCfg;
763    bwp = &dlMsgAlloc->bwp;
764
765    GET_UE_IDX(crnti, ueIdx);
766    ueCb  = cell->ueCb[ueIdx-1];
767    coreset1 = ueCb.ueCfg.spCellCfg.servCellCfg.initDlBwp.pdcchCfg.cRSetToAddModList[0];
768    pdschCfg = ueCb.ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg;
769
770    /* fill BWP */
771    bwp->freqAlloc.numPrb = MAX_NUM_RB;
772    bwp->freqAlloc.startPrb = 0;
773    bwp->subcarrierSpacing = cell->cellCfg.sib1SchCfg.bwp.subcarrierSpacing;
774    bwp->cyclicPrefix = cell->cellCfg.sib1SchCfg.bwp.cyclicPrefix;
775
776    /* fill the PDCCH PDU */
777    //Considering coreset1 also starts from same symbol as coreset0
778    pdcch->coresetCfg.startSymbolIndex = coresetIdxTable[0][3];
779    pdcch->coresetCfg.durationSymbols = coreset1.duration;
780    memcpy(pdcch->coresetCfg.freqDomainResource, coreset1.freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
781    pdcch->coresetCfg.cceRegMappingType = coreset1.cceRegMappingType; /* non-interleaved */
782    pdcch->coresetCfg.regBundleSize = 6;   /* must be 6 for non-interleaved */
783    pdcch->coresetCfg.interleaverSize = 0; /* NA for non-interleaved */
784    pdcch->coresetCfg.coreSetType = 1; /* non PBCH coreset */
785    //Considering number of RBs in coreset1 is same as coreset0
786    pdcch->coresetCfg.coreSetSize = coresetIdxTable[0][1];
787    pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
788    pdcch->coresetCfg.precoderGranularity =  coreset1.precoderGranularity;
789    pdcch->numDlDci = 1;
790    pdcch->dci.rnti = ueCb.crnti;
791    pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
792    pdcch->dci.scramblingRnti = 0;
793    pdcch->dci.cceIndex = 0; /* 0-3 for UL and 4-7 for DL */
794    pdcch->dci.aggregLevel = 4;
795    pdcch->dci.beamPdcchInfo.numPrgs = 1;
796    pdcch->dci.beamPdcchInfo.prgSize = 1;
797    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
798    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
799    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
800    pdcch->dci.txPdcchPower.powerValue = 0;
801    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
802
803    /* fill the PDSCH PDU */
804    uint8_t cwCount = 0;
805    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
806    pdsch->rnti = ueCb.crnti;
807    pdsch->pduIndex = 0;
808    pdsch->numCodewords = 1;
809    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
810    {
811       pdsch->codeword[cwCount].targetCodeRate = 308;
812       pdsch->codeword[cwCount].qamModOrder = ueCb.ueCfg.dlModInfo.modOrder;
813       pdsch->codeword[cwCount].mcsIndex = ueCb.ueCfg.dlModInfo.mcsIndex;
814       pdsch->codeword[cwCount].mcsTable = ueCb.ueCfg.dlModInfo.mcsTable;
815       pdsch->codeword[cwCount].rvIndex = 0;
816       tbSize = schCalcTbSize(*accumalatedSize + TX_PAYLOAD_HDR_LEN);
817       if(tbSize < *accumalatedSize)
818          *accumalatedSize = tbSize - TX_PAYLOAD_HDR_LEN;
819       pdsch->codeword[cwCount].tbSize = tbSize;
820    }
821    pdsch->dataScramblingId = cell->cellCfg.phyCellId;
822    pdsch->numLayers = 1;
823    pdsch->transmissionScheme = 0;
824    pdsch->refPoint = 0;
825    pdsch->dmrs.dlDmrsSymbPos = 4; /* Bitmap value 00000000000100 i.e. using 3rd symbol for PDSCH DMRS */
826    pdsch->dmrs.dmrsConfigType = 0; /* type-1 */
827    pdsch->dmrs.dlDmrsScramblingId = cell->cellCfg.phyCellId;
828    pdsch->dmrs.scid = 0;
829    pdsch->dmrs.numDmrsCdmGrpsNoData = 1;
830    pdsch->dmrs.dmrsPorts = 0;
831    pdsch->dmrs.mappingType      = DMRS_MAP_TYPE_A; /* Setting to Type-A */
832    pdsch->dmrs.nrOfDmrsSymbols  = NUM_DMRS_SYMBOLS;
833    pdsch->dmrs.dmrsAddPos       = pdschCfg.dmrsDlCfgForPdschMapTypeA.addPos;
834
835    pdsch->pdschTimeAlloc.timeAlloc.startSymb = pdschCfg.timeDomRsrcAllociList[0].startSymbol;
836    pdsch->pdschTimeAlloc.timeAlloc.numSymb = pdschCfg.timeDomRsrcAllociList[0].symbolLength;
837
838    pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
839    pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
840    pdsch->pdschFreqAlloc.freqAlloc.startPrb = MAX_NUM_RB;
841    pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, ueCb.ueCfg.dlModInfo.mcsIndex, \
842                    pdschCfg.timeDomRsrcAllociList[0].symbolLength);
843
844    /* Allocate the number of PRBs required for DL PDSCH */
845    if((allocatePrbDl(cell, slotTime, pdsch->pdschTimeAlloc.timeAlloc.startSymb, pdsch->pdschTimeAlloc.timeAlloc.numSymb,\
846       &pdsch->pdschFreqAlloc.freqAlloc.startPrb, pdsch->pdschFreqAlloc.freqAlloc.numPrb)) != ROK)
847    {
848       DU_LOG("\nERROR  --> SCH : allocatePrbDl() failed for DL MSG");
849       return RFAILED;
850    }
851
852    pdsch->beamPdschInfo.numPrgs = 1;
853    pdsch->beamPdschInfo.prgSize = 1;
854    pdsch->beamPdschInfo.digBfInterfaces = 0;
855    pdsch->beamPdschInfo.prg[0].pmIdx = 0;
856    pdsch->beamPdschInfo.prg[0].beamIdx[0] = 0;
857    pdsch->txPdschPower.powerControlOffset = 0;
858    pdsch->txPdschPower.powerControlOffsetSS = 0;
859
860    pdcch->dci.pdschCfg = pdsch;
861    return ROK;
862 }
863
864 /*******************************************************************
865  *
866  * @brief Fills k0 and k1 information table for FDD 
867  *
868  * @details
869  *
870  *    Function : BuildK0K1TableForFdd 
871  *
872  *    Functionality:
873  *      Fills k0 and k1 information table for FDD
874  *
875  * @params[in] SchCellCb *cell,SchK0K1TimingInfoTbl *k0K1InfoTbl,bool
876  * pdschCfgCmnPres,uint8_t numTimeDomAlloc, SchPdschCfgCmnTimeDomRsrcAlloc
877  * cmnTimeDomRsrcAllocList[], SchPdschTimeDomRsrcAlloc
878  * dedTimeDomRsrcAllocList[], uint8_t ulAckListCount, uint8_t *UlAckTbl
879  * @return ROK     - success
880  *         RFAILED - failure
881  *
882  * ****************************************************************/
883 void BuildK0K1TableForFdd(SchCellCb *cell, SchK0K1TimingInfoTbl *k0K1InfoTbl, bool pdschCfgCmnPres,SchPdschCfgCmn pdschCmnCfg,\
884 SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
885 {
886    
887    uint8_t k1TmpVal =0, cfgIdx=0;
888    uint8_t slotIdx=0, k0Index=0, k1Index=0, numK0=0, numK1=0, numTimeDomAlloc=0;
889    
890    /* TODO Commented these below lines for resolving warnings. Presently these variable are not 
891     * required but this will require for harq processing */
892    // uint8_t k0TmpVal = 0; 
893    // SchPdschCfgCmnTimeDomRsrcAlloc cmnTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
894    // SchPdschTimeDomRsrcAlloc dedTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
895
896    /* Initialization the structure and storing the total slot values. */
897    memset(k0K1InfoTbl, 0, sizeof(SchK0K1TimingInfoTbl));
898    k0K1InfoTbl->tblSize = cell->numSlots;
899    
900    /* Storing time domain resource allocation list based on common or dedicated configuration. */
901    if(pdschCfgCmnPres == true)
902    {
903       numTimeDomAlloc = pdschCmnCfg.numTimeDomAlloc;
904       for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
905       {
906          /*TODO uncomment this line during harq processing */
907          //cmnTimeDomRsrcAllocList[cfgIdx] = pdschCmnCfg.timeDomRsrcAllocList[cfgIdx];
908       }
909    }
910    else
911    {
912       numTimeDomAlloc = pdschDedCfg.numTimeDomRsrcAlloc;
913       for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
914       {
915          /*TODO uncomment this line during harq processing */
916          //dedTimeDomRsrcAllocList[cfgIdx] = pdschDedCfg.timeDomRsrcAllociList[cfgIdx];
917       }
918    }
919    
920    /* Checking all the slots for K0 and K1 values. */
921    for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
922    {
923       numK0 = 0;
924       /* Storing the values of k0 based on time domain resource
925        * allocation list. If the value is unavailable then fill default values,
926        * As per 38.331 PDSCH-TimeDomainResourceAllocation field descriptions. */
927       for(k0Index = 0; ((k0Index < numTimeDomAlloc) && (k0Index < MAX_NUM_K0_IDX));  k0Index++)
928       {
929          /* TODO These if 0 we will remove during harq processing */
930 #if 0
931          if(pdschCfgCmnPres == true)
932          {
933             k0TmpVal = cmnTimeDomRsrcAllocList[k0Index].k0;
934          }
935          else
936          {
937             if(dedTimeDomRsrcAllocList[k0Index].k0 != NULLP)
938             {
939                k0TmpVal = *(dedTimeDomRsrcAllocList[k0Index].k0);
940             }
941             else
942             { 
943                k0TmpVal = DEFAULT_K0_VALUE;
944             }
945          }
946 #endif         
947          /* Checking all the Ul Alloc values. If value is less than MIN_NUM_K1_IDX
948           * then skip else continue storing the values. */
949          numK1 = 0;
950          for(k1Index = 0; k1Index < ulAckListCount; k1Index++)
951          {
952             k1TmpVal = UlAckTbl[k1Index];
953             if(k1TmpVal <= MIN_NUM_K1_IDX)
954             {
955                continue;
956             }
957
958             k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.k1Indexes[numK1++] = k1Index;
959             /* TODO Store K1 index where harq feedback will be received in harq table. */ 
960          }
961          if(numK1)
962          {
963             k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.numK1 = numK1;
964             k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k0Index = k0Index;
965             numK0++;
966          }
967       }
968       if(numK0)
969       {
970          k0K1InfoTbl->k0k1TimingInfo[slotIdx].numK0 = numK0;
971       }
972    }
973 }
974
975 /*******************************************************************
976  *
977  * @brief Fills k0 and k1 information table  
978  *
979  * @details
980  *
981  *    Function : BuildK0K1Table
982  *
983  *    Functionality:
984  *       Fills K0 and k1 information table 
985  *
986  * @params[in] SchCellCb *cell,SchK0K1TimingInfoTbl *k0K1InfoTbl,bool
987  * pdschCfgCmnPres,uint8_t numTimeDomAlloc, SchPdschCfgCmnTimeDomRsrcAlloc
988  * cmnTimeDomRsrcAllocList[], SchPdschTimeDomRsrcAlloc
989  * dedTimeDomRsrcAllocList[], uint8_t ulAckListCount, uint8_t *UlAckTbl
990  * @return ROK     - success
991  *         RFAILED - failure
992  *
993  * ****************************************************************/
994 void BuildK0K1Table(SchCellCb *cell, SchK0K1TimingInfoTbl *k0K1InfoTbl, bool pdschCfgCmnPres, SchPdschCfgCmn pdschCmnCfg,\
995 SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
996 {
997
998 #ifdef NR_TDD
999    SlotConfig  slotCfg;
1000    bool ulSlotPresent = false;
1001    uint8_t k0TmpVal = 0, k1TmpVal =0, tmpSlot=0, startSymbol=0, endSymbol=0, checkSymbol=0;
1002    uint8_t slotIdx=0, k0Index=0, k1Index=0, numK0=0, numK1=0, cfgIdx=0, numTimeDomAlloc =0, totalCfgSlot =0;
1003    SchPdschCfgCmnTimeDomRsrcAlloc cmnTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
1004    SchPdschTimeDomRsrcAlloc dedTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
1005 #endif
1006
1007    if(cell->cellCfg.dupMode == DUPLEX_MODE_FDD)
1008    {
1009       BuildK0K1TableForFdd(cell, k0K1InfoTbl, pdschCfgCmnPres, pdschCmnCfg, pdschDedCfg, ulAckListCount, UlAckTbl);
1010    }
1011    else
1012    {
1013 #ifdef NR_TDD
1014       
1015       /* Initialization the K0K1 structure, total num of slot and calculating the slot pattern length. */
1016       memset(k0K1InfoTbl, 0, sizeof(SchK0K1TimingInfoTbl));
1017       k0K1InfoTbl->tblSize = cell->numSlots;
1018       totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbSchCfg.scsCommon, cell->cellCfg.tddCfg.tddPeriod);
1019       
1020       /* Storing time domain resource allocation list based on common or 
1021        * dedicated configuration availability. */
1022       if(pdschCfgCmnPres == true)
1023       {
1024          numTimeDomAlloc = pdschCmnCfg.numTimeDomAlloc;
1025          for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1026          {
1027             cmnTimeDomRsrcAllocList[cfgIdx] = pdschCmnCfg.timeDomRsrcAllocList[cfgIdx];
1028          }
1029       }
1030       else
1031       {
1032          numTimeDomAlloc = pdschDedCfg.numTimeDomRsrcAlloc;
1033          for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1034          {
1035             dedTimeDomRsrcAllocList[cfgIdx] = pdschDedCfg.timeDomRsrcAllociList[cfgIdx];
1036          }
1037       }
1038
1039       /* Checking all possible indexes for K0 and K1 values. */
1040       for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1041       {
1042          /* If current slot is UL or FLEXI then Skip because PDCCH is sent only in DL slots. */
1043          slotCfg = schGetSlotSymbFrmt(slotIdx%totalCfgSlot, cell->slotFrmtBitMap);
1044          if(slotCfg == UL_SLOT || slotCfg == FLEXI_SLOT)
1045          {
1046             continue;
1047          }
1048          
1049          /* Storing K0 , start symbol and length symbol for further processing.
1050           * If K0 value is not available then we can fill the default values
1051           * given in spec 38.331. */
1052          numK0 = 0;
1053          for(k0Index = 0; ((k0Index < numTimeDomAlloc) && (k0Index < MAX_NUM_K0_IDX)); k0Index++)
1054          {
1055             if(pdschCfgCmnPres == true)
1056             {
1057                k0TmpVal = cmnTimeDomRsrcAllocList[k0Index].k0;
1058                startSymbol = cmnTimeDomRsrcAllocList[k0Index].startSymbol;
1059                endSymbol = startSymbol + cmnTimeDomRsrcAllocList[k0Index].lengthSymbol;
1060             }
1061             else
1062             {
1063                if(dedTimeDomRsrcAllocList[k0Index].k0 != NULLP)
1064                {
1065                   k0TmpVal =  *(dedTimeDomRsrcAllocList[k0Index].k0);
1066                }
1067                else
1068                {
1069                   k0TmpVal = DEFAULT_K0_VALUE;
1070                }
1071                startSymbol = dedTimeDomRsrcAllocList[k0Index].startSymbol;
1072                endSymbol = startSymbol + dedTimeDomRsrcAllocList[k0Index].symbolLength;
1073             }
1074             
1075             /* If current slot + k0 is UL then skip the slot
1076              * else if it is DL slot then continue the next steps
1077              * else if it is a FLEXI slot then check symbols of slot, It should not
1078              * contain any UL slot. */
1079             tmpSlot = (slotIdx+k0TmpVal) % totalCfgSlot;
1080             slotCfg = schGetSlotSymbFrmt(tmpSlot, cell->slotFrmtBitMap);
1081             if(slotCfg == UL_SLOT)
1082             {
1083                continue;
1084             }
1085             if(slotCfg == FLEXI_SLOT)
1086             {
1087                for(checkSymbol = startSymbol; checkSymbol<endSymbol; checkSymbol ++)
1088                {
1089                   slotCfg = cell->cellCfg.tddCfg.slotCfg[tmpSlot][checkSymbol];
1090                   if(slotCfg == UL_SLOT)
1091                   {
1092                      continue;
1093                   }
1094                }
1095             }
1096
1097             /* If current slot + k0 + k1 is a DL slot then skip the slot
1098              * else if it is UL slot then store the information 
1099              * else if it is FLEXI slot then check the symbols, it must have
1100              * at least one UL symbol. */
1101             numK1 = 0;
1102             for(k1Index = 0; k1Index < ulAckListCount; k1Index++)
1103             {
1104                k1TmpVal = UlAckTbl[k1Index];
1105                if(k1TmpVal > MIN_NUM_K1_IDX)
1106                {
1107                   tmpSlot = (slotIdx+k0TmpVal+k1TmpVal) % totalCfgSlot;
1108                   slotCfg =  schGetSlotSymbFrmt(tmpSlot, cell->slotFrmtBitMap);
1109                   if(slotCfg == DL_SLOT) 
1110                   {
1111                      continue;
1112                   }   
1113                   if(slotCfg == FLEXI_SLOT)
1114                   {
1115                      for(checkSymbol = 0; checkSymbol<SCH_SYMBOL_PER_SLOT;checkSymbol++)
1116                      {
1117                         if(cell->cellCfg.tddCfg.slotCfg[tmpSlot][checkSymbol] == UL_SLOT)
1118                         {
1119                            ulSlotPresent = true;
1120                            break;
1121                         }
1122                      }
1123                   }
1124                   if(ulSlotPresent == true || slotCfg ==  UL_SLOT)
1125                   {
1126                      k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.k1Indexes[numK1++] = k1Index;
1127                      /* TODO Store K1 index where harq feedback will be received
1128                       * in harq table. */
1129                   }
1130                }
1131             }
1132             
1133             /* Store all the values if all condition satisfies. */
1134             if(numK1)
1135             {
1136                k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.numK1 = numK1;
1137                k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k0Index = k0Index;
1138                numK0++;
1139             }
1140          }
1141          if(numK0)
1142          {
1143             k0K1InfoTbl->k0k1TimingInfo[slotIdx].numK0 = numK0;
1144          }
1145       }
1146 #endif
1147    }
1148 }
1149
1150 /*******************************************************************
1151 *
1152 * @brief Fills K2 information table for FDD
1153 *
1154 * @details
1155 *
1156 *    Function : BuildK2InfoTableForFdd 
1157 *
1158 *    Functionality:
1159 *       Fills K2 information table for FDD
1160 *
1161 * @params[in] SchCellCb *cell,SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[],
1162 * uint16_t puschSymTblSize,SchK2TimingInfoTbl *k2InfoTbl
1163 * @return ROK     - success
1164 *         RFAILED - failure
1165 *
1166 * ****************************************************************/
1167 void BuildK2InfoTableForFdd(SchCellCb *cell, SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[], uint16_t puschSymTblSize,\
1168 SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
1169 {
1170    uint16_t slotIdx=0, k2Index=0, k2TmpIdx=0, msg3K2TmpIdx=0;
1171
1172    /* Initialization the structure and storing the total slot values. */
1173    memset(k2InfoTbl, 0, sizeof(SchK2TimingInfoTbl));
1174    k2InfoTbl->tblSize = cell->numSlots;
1175    if(msg3K2InfoTbl)
1176       msg3K2InfoTbl->tblSize = cell->numSlots;
1177    
1178    /* Checking all possible indexes for K2. */
1179    for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1180    {
1181       /* Storing K2 values. */
1182       for(k2Index = 0; ((k2Index < puschSymTblSize) && (k2Index < MAX_NUM_K2_IDX)); k2Index++)
1183       {
1184          k2TmpIdx= k2InfoTbl->k2TimingInfo[slotIdx].numK2;
1185          k2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[k2TmpIdx] = k2Index;
1186          k2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1187
1188          /* Updating K2 values for MSG3 */
1189          if(msg3K2InfoTbl)
1190          {
1191             msg3K2TmpIdx = msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2;
1192             msg3K2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[msg3K2TmpIdx] = k2Index;
1193             msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1194          }
1195       }
1196    }
1197 }
1198
1199 /*******************************************************************
1200  *
1201  * @brief Fills K2 information table
1202  *
1203  * @details
1204  *
1205  *    Function : BuildK2InfoTable 
1206  *
1207  *    Functionality:
1208  *       Fills K2 information table
1209  *
1210  * @params[in] SchCellCb *cell,SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[],
1211  * uint16_t puschSymTblSize, SchK2TimingInfoTbl *k2InfoTbl
1212  * @return ROK     - success
1213  *         RFAILED - failure
1214  *
1215  * ****************************************************************/
1216 void BuildK2InfoTable(SchCellCb *cell, SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[], uint16_t puschSymTblSize,\
1217 SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
1218 {
1219
1220 #ifdef NR_TDD
1221    bool dlSymbolPresent = false;
1222    uint8_t slotIdx=0, k2Index=0, k2Val=0, k2TmpVal=0, msg3K2TmpVal=0, msg3Delta=0, numK2 =0, currentSymbol =0;
1223    uint8_t startSymbol =0, endSymbol =0, checkSymbol=0, totalCfgSlot=0, slotCfg=0;
1224    SlotConfig currentSlot;
1225 #endif
1226
1227    if(cell->cellCfg.dupMode == DUPLEX_MODE_FDD)
1228    {
1229       BuildK2InfoTableForFdd(cell, timeDomRsrcAllocList, puschSymTblSize, msg3K2InfoTbl, k2InfoTbl);
1230    }
1231    else
1232    {
1233 #ifdef NR_TDD
1234
1235       /* Initialization the structure and storing the total slot values. */
1236       memset(k2InfoTbl, 0, sizeof(SchK2TimingInfoTbl));
1237       k2InfoTbl->tblSize = cell->numSlots;
1238       if(msg3K2InfoTbl)
1239          msg3K2InfoTbl->tblSize = cell->numSlots;
1240       totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbSchCfg.scsCommon, cell->cellCfg.tddCfg.tddPeriod);
1241
1242       /* Checking all possible indexes for K2. */
1243       for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1244       {
1245          currentSlot = schGetSlotSymbFrmt(slotIdx % totalCfgSlot, cell->slotFrmtBitMap);
1246          
1247          /* If current slot is UL then skip because PDCCH is sent only in DL slots */
1248          if(currentSlot != UL_SLOT)
1249          {
1250             for(k2Index = 0; ((k2Index < puschSymTblSize) && (k2Index < MAX_NUM_K2_IDX)); k2Index++)
1251             {
1252                /* Storing k2, startSymbol, endSymbol information for further processing.
1253                 * If k2 is absent then fill the default values given in spec 38.331
1254                 * PUSCH-TimeDomainResourceAllocationList field descriptions */
1255                k2Val = timeDomRsrcAllocList[k2Index].k2;
1256                if(!k2Val)
1257                {
1258                   switch(cell->cellCfg.ssbSchCfg.scsCommon)
1259                   {
1260                      case SCS_15KHZ:
1261                         k2Val = DEFAULT_K2_VALUE_FOR_SCS15;
1262                         break;
1263                      case SCS_30KHZ:
1264                         k2Val = DEFAULT_K2_VALUE_FOR_SCS30;
1265                         break;
1266                      case SCS_60KHZ:
1267                         k2Val = DEFAULT_K2_VALUE_FOR_SCS60;
1268                         break;
1269                      case SCS_120KHZ:
1270                         k2Val = DEFAULT_K2_VALUE_FOR_SCS120;
1271                         break;
1272                   }
1273                }
1274                
1275                /* Current slot + k2 should be either UL or FLEXI slot.
1276                 * If slot is FLEXI then check all the symbols of that slot,
1277                 * it should not contain any DL or FLEXI slot */
1278                k2TmpVal = (slotIdx + k2Val) % totalCfgSlot;
1279                slotCfg = schGetSlotSymbFrmt(k2TmpVal, cell->slotFrmtBitMap);
1280                if(slotCfg != DL_SLOT)
1281                {
1282                   if(slotCfg == FLEXI_SLOT)
1283                   {
1284                      startSymbol =  timeDomRsrcAllocList[k2Index].startSymbol;
1285                      endSymbol   =  startSymbol+ timeDomRsrcAllocList[k2Index].symbolLength;
1286                      dlSymbolPresent = false;
1287                      for(checkSymbol= startSymbol; checkSymbol<endSymbol; checkSymbol++)
1288                      {
1289                         currentSymbol = cell->cellCfg.tddCfg.slotCfg[k2TmpVal][checkSymbol];
1290                         if(currentSymbol == DL_SLOT || currentSymbol == FLEXI_SLOT)
1291                         {
1292                            dlSymbolPresent = true;
1293                            break;
1294                         }
1295                      }
1296                   }
1297                   /* Store all the values if all condition satisfies. */
1298                   if(dlSymbolPresent != true || slotCfg == UL_SLOT)
1299                   {
1300                      numK2 = k2InfoTbl->k2TimingInfo[slotIdx].numK2;
1301                      k2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[numK2] = k2Index;
1302                      k2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1303                   }
1304                }
1305
1306                if(msg3K2InfoTbl)
1307                {
1308                    msg3Delta = puschDeltaTable[cell->cellCfg.numerology];
1309
1310                   /* Check for K2 for MSG3 */
1311                   /* Current slot + k2 should be either UL or FLEXI slot.
1312                    * If slot is FLEXI then check all the symbols of that slot,
1313                    * it should not contain any DL or FLEXI slot */
1314                   msg3K2TmpVal = (slotIdx + k2Val + msg3Delta) % totalCfgSlot;
1315                   slotCfg = schGetSlotSymbFrmt(msg3K2TmpVal, cell->slotFrmtBitMap);
1316                   if(slotCfg != DL_SLOT)
1317                   {
1318                      if(slotCfg == FLEXI_SLOT)
1319                      {
1320                         startSymbol =  timeDomRsrcAllocList[k2Index].startSymbol;
1321                         endSymbol   =  startSymbol+ timeDomRsrcAllocList[k2Index].symbolLength;
1322                         dlSymbolPresent = false;
1323                         for(checkSymbol= startSymbol; checkSymbol<endSymbol; checkSymbol++)
1324                         {
1325                            currentSymbol = cell->cellCfg.tddCfg.slotCfg[msg3K2TmpVal][checkSymbol];
1326                            if(currentSymbol == DL_SLOT || currentSymbol == FLEXI_SLOT)
1327                            {
1328                               dlSymbolPresent = true;
1329                               break;
1330                            }
1331                         }
1332                      }
1333                      /* Store all the values if all condition satisfies. */
1334                      if(dlSymbolPresent != true || slotCfg == UL_SLOT)
1335                      {
1336                         numK2 = msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2;
1337                         msg3K2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[numK2] = k2Index;
1338                         msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1339                      }
1340                   }
1341                }
1342             }
1343          }
1344       }
1345 #endif
1346    }
1347 }
1348
1349 /**********************************************************************
1350   End of file
1351  **********************************************************************/
1352