1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for Entry point fucntions
29 **********************************************************************/
31 /** @file sch_common.c
32 @brief This module performs common scheduling
34 #include "common_def.h"
41 #include "du_app_mac_inf.h"
42 #include "mac_sch_interface.h"
44 #include "sch_utils.h"
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];
52 SchMacUlSchInfoFunc schMacUlSchInfoOpts[] =
60 * @brief common resource allocation for SSB
64 * Function : schBroadcastSsbAlloc
66 * This function handles common scheduling for SSB
68 * @param[in] SchCellCb *cell, cell cb
69 * @param[in] DlBrdcstAlloc *dlBrdcstAlloc, DL brdcst allocation
72 uint8_t schBroadcastSsbAlloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstAlloc *dlBrdcstAlloc)
75 uint8_t ssbStartSymb, idx;
77 SchDlSlotInfo *schDlSlotInfo;
82 DU_LOG("\nERROR --> SCH: schBroadcastSsbAlloc() : Cell is NULL");
86 if(dlBrdcstAlloc == NULL)
88 DU_LOG("\nERROR --> SCH: schBroadcastSsbAlloc() : dlBrdcstAlloc is NULL");
92 schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
93 ssbStartPrb = cell->cellCfg.ssbSchCfg.ssbOffsetPointA; //+Kssb
94 ssbStartSymb = cell->ssbStartSymbArr[dlBrdcstAlloc->ssbIdxSupported-1]; /*since we are supporting only 1 ssb beam */
96 /* Assign interface structure */
97 for(idx=0; idx<dlBrdcstAlloc->ssbIdxSupported; idx++)
100 ssbInfo.fdAlloc.startPrb = ssbStartPrb;
101 ssbInfo.fdAlloc.numPrb = SCH_SSB_NUM_PRB;
102 ssbInfo.tdAlloc.startSymb = ssbStartSymb;
103 ssbInfo.tdAlloc.numSymb = SCH_SSB_NUM_SYMB;
104 dlBrdcstAlloc->ssbInfo[idx] = ssbInfo;
105 schDlSlotInfo->ssbInfo[idx] = ssbInfo;
108 if((allocatePrbDl(cell, slotTime, ssbStartSymb, SCH_SSB_NUM_SYMB, &ssbInfo.fdAlloc.startPrb, ssbInfo.fdAlloc.numPrb)) != ROK)
110 DU_LOG("\nERROR --> SCH: PRB allocation failed for SSB in SFN:SLOT [%d : %d]", slotTime.sfn, slotTime.slot);
115 schDlSlotInfo->ssbPres = true;
116 schDlSlotInfo->ssbIdxSupported = dlBrdcstAlloc->ssbIdxSupported;
121 * @brief common resource allocation for SIB1
125 * Function : schBroadcastSib1Alloc
127 * This function handles common scheduling for SIB1
129 * @param[in] SchCellCb *cell, cell cb
130 * @param[in] DlBrdcstAlloc *dlBrdcstAlloc, DL brdcst allocation
133 uint8_t schBroadcastSib1Alloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstAlloc *dlBrdcstAlloc)
135 uint8_t dmrsStartSymbol, startSymbol, numSymbol ;
137 FreqDomainAlloc freqAlloc;
138 TimeDomainAlloc timeAlloc;
139 SchDlSlotInfo *schDlSlotInfo = NULLP;
143 DU_LOG("\nERROR --> SCH: schBroadcastSsbAlloc() : Cell is NULL");
147 if(dlBrdcstAlloc == NULL)
149 DU_LOG("\nERROR --> SCH: schBroadcastSsbAlloc() : dlBrdcstAlloc is NULL");
153 dmrs = cell->cellCfg.sib1SchCfg.sib1PdschCfg.dmrs;
154 freqAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc;
155 timeAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschTimeAlloc.timeAlloc;
156 schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
158 /* Find total symbols used including DMRS */
159 /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
160 * in that case only PDSCH symbols are marked as occupied */
161 dmrsStartSymbol = findDmrsStartSymbol(dmrs.dlDmrsSymbPos);
162 if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
164 startSymbol = timeAlloc.startSymb;
165 numSymbol = timeAlloc.numSymb;
167 /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
170 startSymbol = dmrsStartSymbol;
171 numSymbol = dmrs.nrOfDmrsSymbols + timeAlloc.numSymb;
175 if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol, &freqAlloc.startPrb, freqAlloc.numPrb)) != ROK)
177 DU_LOG("\nERROR --> SCH: PRB allocation failed for SIB1 in SFN:Slot [%d : %d]", slotTime.sfn, slotTime.slot);
181 memcpy(&dlBrdcstAlloc->sib1Alloc.bwp, &cell->cellCfg.sib1SchCfg.bwp, sizeof(BwpCfg));
182 memcpy(&dlBrdcstAlloc->sib1Alloc.sib1PdcchCfg, &cell->cellCfg.sib1SchCfg.sib1PdcchCfg, sizeof(PdcchCfg));
183 memcpy(&dlBrdcstAlloc->sib1Alloc.sib1PdschCfg, &cell->cellCfg.sib1SchCfg.sib1PdschCfg, sizeof(PdschCfg));
184 dlBrdcstAlloc->sib1Alloc.sib1PdcchCfg.dci.pdschCfg = &dlBrdcstAlloc->sib1Alloc.sib1PdschCfg;
185 schDlSlotInfo->sib1Pres = true;
189 /*******************************************************************
191 * @brief Handles sending UL scheduler info to MAC
195 * Function : sendUlSchInfoToMac
198 * Sends UL Sch info to MAC from SCH
201 * @return ROK - success
204 * ****************************************************************/
205 int sendUlSchInfoToMac(UlSchedInfo *ulSchedInfo, Inst inst)
209 memset(&pst, 0, sizeof(Pst));
210 FILL_PST_SCH_TO_MAC(pst, inst);
211 pst.event = EVENT_UL_SCH_INFO;
213 return(*schMacUlSchInfoOpts[pst.selector])(&pst, ulSchedInfo);
216 * @brief resource allocation for PRACH
220 * Function : schPrachResAlloc
222 * This function handles PRACH allocation
224 * @param[in] SchCellCb *cell, cell cb
225 * @param[in] UlSchedInfo *ulSchedInfo, UL scheduling info
228 void schPrachResAlloc(SchCellCb *cell, UlSchedInfo *ulSchedInfo, SlotTimingInfo prachOccasionTimingInfo)
231 uint8_t numPrachRb = 0;
233 uint8_t freqStart = 0;
234 uint8_t prachCfgIdx = 0;
235 uint8_t prachFormat = 0;
238 uint16_t prachSubframe = 0;
239 uint8_t prachStartSymbol = 0;
240 uint8_t prachOcas = 0;
241 uint8_t dataType = 0;
243 uint8_t subFrame = 0;
244 SchUlSlotInfo *schUlSlotInfo = NULLP;
246 puschScs = cell->cellCfg.schInitialUlBwp.bwp.scs;
247 schUlSlotInfo = cell->schUlSlotInfo[prachOccasionTimingInfo.slot];
248 prachCfgIdx = cell->cellCfg.schRachCfg.prachCfgIdx;
250 /* derive the prachCfgIdx table paramters */
251 x = prachCfgIdxTable[prachCfgIdx][1];
252 y = prachCfgIdxTable[prachCfgIdx][2];
253 prachSubframe = prachCfgIdxTable[prachCfgIdx][3];
255 if((prachOccasionTimingInfo.sfn%x) == y)
258 subFrame = prachOccasionTimingInfo.slot/2;
260 subFrame = prachOccasionTimingInfo.slot;
262 /* check for subFrame number */
263 if ((1 << subFrame) & prachSubframe)
265 /* prach ocassion present in this subframe */
267 if(UL_SLOT != schGetSlotSymbFrmt(prachOccasionTimingInfo.slot%cell->numSlotsInPeriodicity,\
268 cell->slotFrmtBitMap))
270 DU_LOG("\nERROR --> SCH : PrachCfgIdx %d doesn't support UL slot", prachCfgIdx);
275 prachFormat = prachCfgIdxTable[prachCfgIdx][0];
276 prachStartSymbol = prachCfgIdxTable[prachCfgIdx][4];
277 prachOcas = prachCfgIdxTable[prachCfgIdx][6];
279 /* freq domain resource determination for RACH*/
280 freqStart = cell->cellCfg.schRachCfg.msg1FreqStart;
281 /* numRa determined as 𝑛 belonging {0,1,.., M − 1},
282 * where M is given by msg1Fdm */
283 numRa = (cell->cellCfg.schRachCfg.msg1Fdm - 1);
284 for(idx=0; idx<MAX_RACH_NUM_RB_IDX; idx++)
286 if(numRbForPrachTable[idx][0] == cell->cellCfg.schRachCfg.rootSeqLen)
288 if(numRbForPrachTable[idx][1] == cell->cellCfg.schRachCfg.prachSubcSpacing)
290 if(numRbForPrachTable[idx][2] == puschScs)
297 numPrachRb = numRbForPrachTable[idx][3];
298 dataType |= SCH_DATATYPE_PRACH;
299 /* Considering first slot in the frame for PRACH */
301 //schUlSlotInfo->assignedPrb[idx] = freqStart+numPrachRb;
303 ulSchedInfo->dataType = dataType;
305 ulSchedInfo->prachSchInfo.numPrachOcas = prachOcas;
306 ulSchedInfo->prachSchInfo.prachFormat = prachFormat;
307 ulSchedInfo->prachSchInfo.numRa = numRa;
308 ulSchedInfo->prachSchInfo.prachStartSymb = prachStartSymbol;
309 DU_LOG("\nINFO --> SCH : RACH occassion set for slot %d", prachOccasionTimingInfo.slot);
316 * @brief Function to fill Pucch Format 0
320 * Function : fillPucchFormat0
322 * Function to fill Pucch format 0
324 * @param[in] SchPucchInfo pointer, SchPucchResrcInfo pointer
328 void fillPucchFormat0(SchPucchInfo *ulSchedPucch, SchPucchResrcInfo *resrcInfo)
330 if(resrcInfo->SchPucchFormat.format0)
332 ulSchedPucch->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
333 ulSchedPucch->pucchFormat = PUCCH_FORMAT_0;
334 ulSchedPucch->initialCyclicShift = resrcInfo->SchPucchFormat.format0->initialCyclicShift;
335 ulSchedPucch->tdAlloc.numSymb = resrcInfo->SchPucchFormat.format0->numSymbols;
336 ulSchedPucch->tdAlloc.startSymb = resrcInfo->SchPucchFormat.format0->startSymbolIdx;
341 * @brief Function to fill Pucch Format 1
345 * Function : fillPucchFormat1
347 * Function to fill Pucch format 1
349 * @param[in] SchPucchInfo pointer, SchPucchResrcInfo pointer
353 void fillPucchFormat1(SchPucchInfo *ulSchedPucch, SchPucchResrcInfo *resrcInfo)
355 if(resrcInfo->SchPucchFormat.format1)
357 ulSchedPucch->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
358 ulSchedPucch->pucchFormat = PUCCH_FORMAT_1;
359 ulSchedPucch->initialCyclicShift = resrcInfo->SchPucchFormat.format1->initialCyclicShift;
360 ulSchedPucch->tdAlloc.numSymb = resrcInfo->SchPucchFormat.format1->numSymbols;
361 ulSchedPucch->tdAlloc.startSymb = resrcInfo->SchPucchFormat.format1->startSymbolIdx;
362 ulSchedPucch->timeDomOCC = resrcInfo->SchPucchFormat.format1->timeDomOCC;
367 * @brief Function to fill Pucch format for UL Sched Info
371 * Function : fillUlSchedPucchFormat
373 * Function to fill Pucch format for UL Sched Info
375 * @param[in] pucchFormat , SchPucchInfo pointer,
376 * @param[in] SchPucchFormatCfg pointer, SchPucchResrcInfo pointer
380 uint8_t fillUlSchedPucchFormat(uint8_t pucchFormat, SchPucchInfo *ulSchedPucch,\
381 SchPucchResrcInfo *resrcInfo, SchPucchFormatCfg *formatCfg)
390 fillPucchFormat0(ulSchedPucch, resrcInfo);
397 fillPucchFormat1(ulSchedPucch, resrcInfo);
401 memcpy(&ulSchedPucch->cmnFormatCfg, formatCfg, sizeof(SchPucchFormatCfg));
404 }/* To Add support for more Pucch Format */
407 DU_LOG("\nERROR --> SCH : Invalid PUCCH format[%d] in fillUlSchedPucchFormatCfg()", pucchFormat);
415 * @brief Function to fill Pucch Dedicated Cfg for UL Sched Info
419 * Function : fillUlSchedPucchDedicatedCfg
421 * Function to fill Pucch Dedicated Cfg for UL Sched Info
423 * @param[in] pucchFormat to be filled
424 * @param[in] SchPucchFormatCfg pointer, SchPucchCfg pointer
428 uint8_t fillUlSchedPucchDedicatedCfg(uint16_t numSlots, SchPucchCfg *pucchDedCfg,\
429 SlotTimingInfo *slotInfo, SchPucchInfo *ulSchedPucch)
431 uint8_t ret, resrcSetIdx, resrcIdx, schedReqIdx, srPeriodicity = 0;
432 uint16_t srOffset = 0;
435 if(pucchDedCfg->resrcSet && pucchDedCfg->resrc)
437 //Assuming one entry in the list
438 for(resrcSetIdx = 0; resrcSetIdx < pucchDedCfg->resrcSet->resrcSetToAddModListCount; resrcSetIdx++)
440 for(resrcIdx = 0; resrcIdx < pucchDedCfg->resrc->resrcToAddModListCount; resrcIdx++)
442 if(pucchDedCfg->resrcSet->resrcSetToAddModList[resrcSetIdx].resrcList[resrcSetIdx] ==\
443 pucchDedCfg->resrc->resrcToAddModList[resrcIdx].resrcId)
445 ulSchedPucch->intraFreqHop = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].intraFreqHop;
446 ulSchedPucch->secondPrbHop = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].secondPrbHop;
447 ulSchedPucch->fdAlloc.startPrb = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].startPrb;
448 ulSchedPucch->pucchFormat = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].pucchFormat;
449 ret = fillUlSchedPucchFormat(ulSchedPucch->pucchFormat, ulSchedPucch,\
450 &pucchDedCfg->resrc->resrcToAddModList[resrcIdx], NULLP);
457 if(pucchDedCfg->format1)
459 memset(&ulSchedPucch->cmnFormatCfg, 0, sizeof(SchPucchFormatCfg));
460 ret = fillUlSchedPucchFormat(ulSchedPucch->pucchFormat, ulSchedPucch, NULLP, pucchDedCfg->format1);
465 /* setting SR and UCI flag */
466 if(pucchDedCfg->schedReq)
468 for(schedReqIdx = 0; schedReqIdx < pucchDedCfg->schedReq->schedAddModListCount; schedReqIdx++)
470 srPeriodicity = pucchDedCfg->schedReq->schedAddModList[schedReqIdx].periodicity;
471 srOffset = pucchDedCfg->schedReq->schedAddModList[schedReqIdx].offset;
474 if(((numSlots * slotInfo->sfn + slotInfo->slot - srOffset) % srPeriodicity) == 0)
476 ulSchedPucch->srFlag = true;
477 ulSchedPucch->uciFlag = true;
484 * @brief Function to fill Pucch Resource Info
488 * Function : fillPucchResourceInfo
490 * Function to fill Pucch Resource Info
492 * @param[in] SchPucchInfo *schPucchInfo, Inst inst
493 * @return ROK/RFAILED
496 uint16_t fillPucchResourceInfo(SchPucchInfo *schPucchInfo, Inst inst)
498 uint8_t ret = ROK, ueIdx = 0, pucchIdx = 0;
499 SchCellCb *cell = schCb[inst].cells[inst];
500 SchPucchCfgCmn *pucchCfg = NULLP;
501 SchBwpParams *ulBwp = NULLP;
503 GET_UE_IDX(schPucchInfo->rnti, ueIdx);
504 if(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfgPres)
506 /* fill pucch dedicated cfg */
507 ret = fillUlSchedPucchDedicatedCfg(cell->numSlots,\
508 &cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg, &cell->slotInfo, schPucchInfo);
511 memset(schPucchInfo, 0, sizeof(SchPucchInfo));
512 DU_LOG("\nERROR --> SCH : Filling PUCCH dedicated cfg failed at fillPucchResourceInfo()");
518 /* fill pucch common cfg */
519 /* derive pucchResourceSet from schCellCfg */
520 pucchCfg = &cell->cellCfg.schInitialUlBwp.pucchCommon;
521 pucchIdx = pucchCfg->pucchResourceCommon;
522 ulBwp = &cell->cellCfg.schInitialUlBwp.bwp;
523 schPucchInfo->fdAlloc.startPrb = ulBwp->freqAlloc.startPrb + pucchResourceSet[pucchIdx][3];
524 schPucchInfo->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
525 schPucchInfo->tdAlloc.startSymb = pucchResourceSet[pucchIdx][1];
526 schPucchInfo->tdAlloc.numSymb = pucchResourceSet[pucchIdx][2];
527 schPucchInfo->pucchFormat = pucchResourceSet[pucchIdx][0];
529 /* set SR and UCI flag to false */
530 schPucchInfo->srFlag = true;
531 schPucchInfo->uciFlag = true;
533 /* set HARQ flag to true */
534 schPucchInfo->harqFlag = true;
535 schPucchInfo->numHarqBits = 1; /* 1 bit for HARQ */
541 * @brief resource allocation for UL
545 * Function : schUlResAlloc
547 * This function handles UL Resource allocation
549 * @param[in] SchCellCb *cell, cellCb
552 uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst)
555 UlSchedInfo ulSchedInfo;
556 SchUlSlotInfo *schUlSlotInfo = NULLP;
557 SlotTimingInfo ulTimingInfo;
558 memset(&ulSchedInfo, 0, sizeof(UlSchedInfo));
561 ADD_DELTA_TO_TIME(cell->slotInfo,ulTimingInfo,PHY_DELTA_UL+SCHED_DELTA);
563 ulSchedInfo.cellId = cell->cellId;
564 ulSchedInfo.slotIndInfo.cellId = ulSchedInfo.cellId;
565 ulSchedInfo.slotIndInfo.sfn = ulTimingInfo.sfn;
566 ulSchedInfo.slotIndInfo.slot = ulTimingInfo.slot;
568 /* Schedule resources for PRACH */
569 if(cell->firstSib1Transmitted)
570 schPrachResAlloc(cell, &ulSchedInfo, ulTimingInfo);
572 schUlSlotInfo = cell->schUlSlotInfo[ulTimingInfo.slot];
573 if(schUlSlotInfo->schPuschInfo)
575 ulSchedInfo.crnti = schUlSlotInfo->schPuschInfo->crnti;
576 ulSchedInfo.dataType |= SCH_DATATYPE_PUSCH;
577 memcpy(&ulSchedInfo.schPuschInfo, schUlSlotInfo->schPuschInfo,
578 sizeof(SchPuschInfo));
579 SCH_FREE(schUlSlotInfo->schPuschInfo, sizeof(SchPuschInfo));
580 schUlSlotInfo->schPuschInfo = NULL;
583 if(schUlSlotInfo->pucchPres)
585 ulSchedInfo.dataType |= SCH_DATATYPE_UCI;
586 fillPucchResourceInfo(&schUlSlotInfo->schPucchInfo, schInst);
587 memcpy(&ulSchedInfo.schPucchInfo, &schUlSlotInfo->schPucchInfo,
588 sizeof(SchPucchInfo));
589 memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
593 ret = sendUlSchInfoToMac(&ulSchedInfo, schInst);
596 DU_LOG("\nERROR --> SCH : Sending UL Sch info from SCH to MAC failed");
599 schInitUlSlot(schUlSlotInfo);
603 /*******************************************************************
605 * @brief Fills pdcch and pdsch info for msg4
609 * Function : schDlRsrcAllocMsg4
612 * Fills pdcch and pdsch info for msg4
615 * @return ROK - success
618 * ****************************************************************/
619 uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo slotTime, DlMsgAlloc *msg4Alloc)
621 uint8_t coreset0Idx = 0;
622 uint8_t firstSymbol = 0;
623 uint8_t numSymbols = 0;
624 uint8_t mcs = 4; /* MCS fixed to 4 */
625 uint8_t dmrsStartSymbol = 0, startSymbol = 0, numSymbol = 0;
628 SchBwpDlCfg *initialBwp = NULLP;
629 PdcchCfg *pdcch = NULLP;
630 PdschCfg *pdsch = NULLP;
635 DU_LOG("\nERROR --> SCH: schDlRsrcAllocMsg4() : Cell is NULL");
639 if(msg4Alloc == NULL)
641 DU_LOG("\nERROR --> SCH: schDlRsrcAllocMsg4() : msg4Alloc is NULL");
645 pdcch = &msg4Alloc->dlMsgPdcchCfg;
646 pdsch = &msg4Alloc->dlMsgPdschCfg;
647 bwp = &msg4Alloc->bwp;
648 initialBwp = &cell->cellCfg.schInitialDlBwp;
649 coreset0Idx = initialBwp->pdcchCommon.commonSearchSpace.coresetId;
651 /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
652 numRbs = coresetIdxTable[coreset0Idx][1];
653 numSymbols = coresetIdxTable[coreset0Idx][2];
655 /* calculate time domain parameters */
656 uint16_t mask = 0x2000;
657 for(firstSymbol=0; firstSymbol<MAX_SYMB_PER_SLOT; firstSymbol++)
659 if(initialBwp->pdcchCommon.commonSearchSpace.monitoringSymbol & mask)
666 bwp->freqAlloc.numPrb = initialBwp->bwp.freqAlloc.numPrb;
667 bwp->freqAlloc.startPrb = initialBwp->bwp.freqAlloc.startPrb;
668 bwp->subcarrierSpacing = initialBwp->bwp.scs;
669 bwp->cyclicPrefix = initialBwp->bwp.cyclicPrefix;
671 /* fill the PDCCH PDU */
672 pdcch->coresetCfg.startSymbolIndex = firstSymbol;
673 pdcch->coresetCfg.durationSymbols = numSymbols;
674 memcpy(pdcch->coresetCfg.freqDomainResource, \
675 cell->cellCfg.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
677 pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
678 pdcch->coresetCfg.regBundleSize = 6; /* spec-38.211 sec 7.3.2.2 */
679 pdcch->coresetCfg.interleaverSize = 2; /* spec-38.211 sec 7.3.2.2 */
680 pdcch->coresetCfg.coreSetType = 0;
681 pdcch->coresetCfg.coreSetSize = numRbs;
682 pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
683 pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
685 pdcch->dci.rnti = cell->schDlSlotInfo[slotTime.slot]->dlMsgInfo->crnti;
686 pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
687 pdcch->dci.scramblingRnti = 0;
688 pdcch->dci.cceIndex = 4; /* considering SIB1 is sent at cce 0-1-2-3 */
689 pdcch->dci.aggregLevel = 4;
690 pdcch->dci.beamPdcchInfo.numPrgs = 1;
691 pdcch->dci.beamPdcchInfo.prgSize = 1;
692 pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
693 pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
694 pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
695 pdcch->dci.txPdcchPower.powerValue = 0;
696 pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
698 /* fill the PDSCH PDU */
700 pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
701 pdsch->rnti = cell->schDlSlotInfo[slotTime.slot]->dlMsgInfo->crnti;
703 pdsch->numCodewords = 1;
704 for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
706 pdsch->codeword[cwCount].targetCodeRate = 308;
707 pdsch->codeword[cwCount].qamModOrder = 2;
708 pdsch->codeword[cwCount].mcsIndex = mcs; /* mcs configured to 4 */
709 pdsch->codeword[cwCount].mcsTable = 0; /* notqam256 */
710 pdsch->codeword[cwCount].rvIndex = 0;
711 tbSize = schCalcTbSize(msg4Alloc->dlMsgInfo.dlMsgPduLen + TX_PAYLOAD_HDR_LEN); /* MSG4 size + FAPI header size*/
712 pdsch->codeword[cwCount].tbSize = tbSize;
714 pdsch->dataScramblingId = cell->cellCfg.phyCellId;
715 pdsch->numLayers = 1;
716 pdsch->transmissionScheme = 0;
718 pdsch->dmrs.dlDmrsSymbPos = 4; /* Bitmap value 00000000000100 i.e. using 3rd symbol for PDSCH DMRS */
719 pdsch->dmrs.dmrsConfigType = 0; /* type-1 */
720 pdsch->dmrs.dlDmrsScramblingId = cell->cellCfg.phyCellId;
721 pdsch->dmrs.scid = 0;
722 pdsch->dmrs.numDmrsCdmGrpsNoData = 1;
723 pdsch->dmrs.dmrsPorts = 0;
724 pdsch->dmrs.mappingType = DMRS_MAP_TYPE_A; /* Setting to Type-A */
725 pdsch->dmrs.nrOfDmrsSymbols = NUM_DMRS_SYMBOLS;
726 pdsch->dmrs.dmrsAddPos = DMRS_ADDITIONAL_POS;
728 pdsch->pdschTimeAlloc.timeAlloc.startSymb = 3; /* spec-38.214, Table 5.1.2.1-1 */
729 pdsch->pdschTimeAlloc.timeAlloc.numSymb = NUM_PDSCH_SYMBOL;
731 pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
732 pdsch->pdschFreqAlloc.freqAlloc.startPrb = MAX_NUM_RB;
733 pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, mcs, NUM_PDSCH_SYMBOL);
734 pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
736 /* Find total symbols occupied including DMRS */
737 dmrsStartSymbol = findDmrsStartSymbol(pdsch->dmrs.dlDmrsSymbPos);
738 /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
739 * in that case only PDSCH symbols are marked as occupied */
740 if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
742 startSymbol = pdsch->pdschTimeAlloc.timeAlloc.startSymb;
743 numSymbol = pdsch->pdschTimeAlloc.timeAlloc.numSymb;
745 /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
748 startSymbol = dmrsStartSymbol;
749 numSymbol = pdsch->dmrs.nrOfDmrsSymbols + pdsch->pdschTimeAlloc.timeAlloc.numSymb;
752 /* Allocate the number of PRBs required for RAR PDSCH */
753 if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol,\
754 &pdsch->pdschFreqAlloc.freqAlloc.startPrb, pdsch->pdschFreqAlloc.freqAlloc.numPrb)) != ROK)
756 DU_LOG("\nERROR --> SCH : Resource allocation failed for MSG4");
760 pdsch->beamPdschInfo.numPrgs = 1;
761 pdsch->beamPdschInfo.prgSize = 1;
762 pdsch->beamPdschInfo.digBfInterfaces = 0;
763 pdsch->beamPdschInfo.prg[0].pmIdx = 0;
764 pdsch->beamPdschInfo.prg[0].beamIdx[0] = 0;
765 pdsch->txPdschPower.powerControlOffset = 0;
766 pdsch->txPdschPower.powerControlOffsetSS = 0;
768 pdcch->dci.pdschCfg = pdsch;
773 uint16_t schAllocPucchResource(SchCellCb *cell, uint16_t crnti, uint16_t slot)
775 uint8_t k1 = SCH_DEFAULT_K1, ueIdx = 0, dlToUlAckIdx;
776 uint16_t pucchSlot = 0;
777 SchUlSlotInfo *schUlSlotInfo = NULLP;
778 SchPucchCfg *schPucchCfg = NULLP;
780 GET_UE_IDX(crnti, ueIdx);
781 if(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfgPres)
783 schPucchCfg = &(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg);
784 if(schPucchCfg->dlDataToUlAck)
786 for(dlToUlAckIdx = 0; dlToUlAckIdx < schPucchCfg->dlDataToUlAck->dlDataToUlAckListCount; dlToUlAckIdx++)
788 //For now considering only the first value in the list
789 k1 = schPucchCfg->dlDataToUlAck->dlDataToUlAckList[dlToUlAckIdx];
795 pucchSlot = (slot + k1) % cell->numSlots;
796 schUlSlotInfo = cell->schUlSlotInfo[pucchSlot];
797 memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
799 schUlSlotInfo->pucchPres = true;
800 schUlSlotInfo->schPucchInfo.rnti = crnti;
805 /*******************************************************************
807 * @brief Fills pdcch and pdsch info for dedicated DL msg
811 * Function : schDlRsrcAllocDlMsg
814 * Fills pdcch and pdsch info for dl msg
817 * @return ROK - success
820 * ****************************************************************/
821 uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,
822 uint32_t *accumalatedSize, DlMsgAlloc *dlMsgAlloc)
826 PdcchCfg *pdcch = NULLP;
827 PdschCfg *pdsch = NULLP;
830 SchControlRsrcSet coreset1;
831 SchPdschConfig pdschCfg;
832 uint8_t dmrsStartSymbol, startSymbol, numSymbol;
834 pdcch = &dlMsgAlloc->dlMsgPdcchCfg;
835 pdsch = &dlMsgAlloc->dlMsgPdschCfg;
836 bwp = &dlMsgAlloc->bwp;
838 GET_UE_IDX(crnti, ueIdx);
839 ueCb = cell->ueCb[ueIdx-1];
840 coreset1 = ueCb.ueCfg.spCellCfg.servCellCfg.initDlBwp.pdcchCfg.cRSetToAddModList[0];
841 pdschCfg = ueCb.ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg;
844 bwp->freqAlloc.numPrb = MAX_NUM_RB;
845 bwp->freqAlloc.startPrb = 0;
846 bwp->subcarrierSpacing = cell->cellCfg.sib1SchCfg.bwp.subcarrierSpacing;
847 bwp->cyclicPrefix = cell->cellCfg.sib1SchCfg.bwp.cyclicPrefix;
849 /* fill the PDCCH PDU */
850 //Considering coreset1 also starts from same symbol as coreset0
851 pdcch->coresetCfg.startSymbolIndex = coresetIdxTable[0][3];
852 pdcch->coresetCfg.durationSymbols = coreset1.duration;
853 memcpy(pdcch->coresetCfg.freqDomainResource, coreset1.freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
854 pdcch->coresetCfg.cceRegMappingType = coreset1.cceRegMappingType; /* non-interleaved */
855 pdcch->coresetCfg.regBundleSize = 6; /* must be 6 for non-interleaved */
856 pdcch->coresetCfg.interleaverSize = 0; /* NA for non-interleaved */
857 pdcch->coresetCfg.coreSetType = 1; /* non PBCH coreset */
858 //Considering number of RBs in coreset1 is same as coreset0
859 pdcch->coresetCfg.coreSetSize = coresetIdxTable[0][1];
860 pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
861 pdcch->coresetCfg.precoderGranularity = coreset1.precoderGranularity;
863 pdcch->dci.rnti = ueCb.crnti;
864 pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
865 pdcch->dci.scramblingRnti = 0;
866 pdcch->dci.cceIndex = 0; /* 0-3 for UL and 4-7 for DL */
867 pdcch->dci.aggregLevel = 4;
868 pdcch->dci.beamPdcchInfo.numPrgs = 1;
869 pdcch->dci.beamPdcchInfo.prgSize = 1;
870 pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
871 pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
872 pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
873 pdcch->dci.txPdcchPower.powerValue = 0;
874 pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
876 /* fill the PDSCH PDU */
878 pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
879 pdsch->rnti = ueCb.crnti;
881 pdsch->numCodewords = 1;
882 for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
884 pdsch->codeword[cwCount].targetCodeRate = 308;
885 pdsch->codeword[cwCount].qamModOrder = ueCb.ueCfg.dlModInfo.modOrder;
886 pdsch->codeword[cwCount].mcsIndex = ueCb.ueCfg.dlModInfo.mcsIndex;
887 pdsch->codeword[cwCount].mcsTable = ueCb.ueCfg.dlModInfo.mcsTable;
888 pdsch->codeword[cwCount].rvIndex = 0;
889 tbSize = schCalcTbSize(*accumalatedSize + TX_PAYLOAD_HDR_LEN);
890 if(tbSize < *accumalatedSize)
891 *accumalatedSize = tbSize - TX_PAYLOAD_HDR_LEN;
892 pdsch->codeword[cwCount].tbSize = tbSize;
894 pdsch->dataScramblingId = cell->cellCfg.phyCellId;
895 pdsch->numLayers = 1;
896 pdsch->transmissionScheme = 0;
898 pdsch->dmrs.dlDmrsSymbPos = 4; /* Bitmap value 00000000000100 i.e. using 3rd symbol for PDSCH DMRS */
899 pdsch->dmrs.dmrsConfigType = 0; /* type-1 */
900 pdsch->dmrs.dlDmrsScramblingId = cell->cellCfg.phyCellId;
901 pdsch->dmrs.scid = 0;
902 pdsch->dmrs.numDmrsCdmGrpsNoData = 1;
903 pdsch->dmrs.dmrsPorts = 0;
904 pdsch->dmrs.mappingType = DMRS_MAP_TYPE_A; /* Setting to Type-A */
905 pdsch->dmrs.nrOfDmrsSymbols = NUM_DMRS_SYMBOLS;
906 pdsch->dmrs.dmrsAddPos = pdschCfg.dmrsDlCfgForPdschMapTypeA.addPos;
908 pdsch->pdschTimeAlloc.timeAlloc.startSymb = pdschCfg.timeDomRsrcAllociList[0].startSymbol;
909 pdsch->pdschTimeAlloc.timeAlloc.numSymb = pdschCfg.timeDomRsrcAllociList[0].symbolLength;
911 pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
912 pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
913 pdsch->pdschFreqAlloc.freqAlloc.startPrb = MAX_NUM_RB;
914 pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, ueCb.ueCfg.dlModInfo.mcsIndex, \
915 pdschCfg.timeDomRsrcAllociList[0].symbolLength);
917 /* Find total symbols occupied including DMRS */
918 dmrsStartSymbol = findDmrsStartSymbol(pdsch->dmrs.dlDmrsSymbPos);
919 /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
920 * in that case only PDSCH symbols are marked as occupied */
921 if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
923 startSymbol = pdsch->pdschTimeAlloc.timeAlloc.startSymb;
924 numSymbol = pdsch->pdschTimeAlloc.timeAlloc.numSymb;
926 /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
929 startSymbol = dmrsStartSymbol;
930 numSymbol = pdsch->dmrs.nrOfDmrsSymbols + pdsch->pdschTimeAlloc.timeAlloc.numSymb;
933 /* Allocate the number of PRBs required for DL PDSCH */
934 if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol,\
935 &pdsch->pdschFreqAlloc.freqAlloc.startPrb, pdsch->pdschFreqAlloc.freqAlloc.numPrb)) != ROK)
937 DU_LOG("\nERROR --> SCH : allocatePrbDl() failed for DL MSG");
941 pdsch->beamPdschInfo.numPrgs = 1;
942 pdsch->beamPdschInfo.prgSize = 1;
943 pdsch->beamPdschInfo.digBfInterfaces = 0;
944 pdsch->beamPdschInfo.prg[0].pmIdx = 0;
945 pdsch->beamPdschInfo.prg[0].beamIdx[0] = 0;
946 pdsch->txPdschPower.powerControlOffset = 0;
947 pdsch->txPdschPower.powerControlOffsetSS = 0;
949 pdcch->dci.pdschCfg = pdsch;
953 /*******************************************************************
955 * @brief Fills k0 and k1 information table for FDD
959 * Function : BuildK0K1TableForFdd
962 * Fills k0 and k1 information table for FDD
964 * @params[in] SchCellCb *cell,SchK0K1TimingInfoTbl *k0K1InfoTbl,bool
965 * pdschCfgCmnPres,uint8_t numTimeDomAlloc, SchPdschCfgCmnTimeDomRsrcAlloc
966 * cmnTimeDomRsrcAllocList[], SchPdschTimeDomRsrcAlloc
967 * dedTimeDomRsrcAllocList[], uint8_t ulAckListCount, uint8_t *UlAckTbl
968 * @return ROK - success
971 * ****************************************************************/
972 void BuildK0K1TableForFdd(SchCellCb *cell, SchK0K1TimingInfoTbl *k0K1InfoTbl, bool pdschCfgCmnPres,SchPdschCfgCmn pdschCmnCfg,\
973 SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
976 uint8_t k1TmpVal =0, cfgIdx=0;
977 uint8_t slotIdx=0, k0Index=0, k1Index=0, numK0=0, numK1=0, numTimeDomAlloc=0;
979 /* TODO Commented these below lines for resolving warnings. Presently these variable are not
980 * required but this will require for harq processing */
981 // uint8_t k0TmpVal = 0;
982 // SchPdschCfgCmnTimeDomRsrcAlloc cmnTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
983 // SchPdschTimeDomRsrcAlloc dedTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
985 /* Initialization the structure and storing the total slot values. */
986 memset(k0K1InfoTbl, 0, sizeof(SchK0K1TimingInfoTbl));
987 k0K1InfoTbl->tblSize = cell->numSlots;
989 /* Storing time domain resource allocation list based on common or dedicated configuration. */
990 if(pdschCfgCmnPres == true)
992 numTimeDomAlloc = pdschCmnCfg.numTimeDomAlloc;
993 for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
995 /*TODO uncomment this line during harq processing */
996 //cmnTimeDomRsrcAllocList[cfgIdx] = pdschCmnCfg.timeDomRsrcAllocList[cfgIdx];
1001 numTimeDomAlloc = pdschDedCfg.numTimeDomRsrcAlloc;
1002 for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1004 /*TODO uncomment this line during harq processing */
1005 //dedTimeDomRsrcAllocList[cfgIdx] = pdschDedCfg.timeDomRsrcAllociList[cfgIdx];
1009 /* Checking all the slots for K0 and K1 values. */
1010 for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1013 /* Storing the values of k0 based on time domain resource
1014 * allocation list. If the value is unavailable then fill default values,
1015 * As per 38.331 PDSCH-TimeDomainResourceAllocation field descriptions. */
1016 for(k0Index = 0; ((k0Index < numTimeDomAlloc) && (k0Index < MAX_NUM_K0_IDX)); k0Index++)
1018 /* TODO These if 0 we will remove during harq processing */
1020 if(pdschCfgCmnPres == true)
1022 k0TmpVal = cmnTimeDomRsrcAllocList[k0Index].k0;
1026 if(dedTimeDomRsrcAllocList[k0Index].k0 != NULLP)
1028 k0TmpVal = *(dedTimeDomRsrcAllocList[k0Index].k0);
1032 k0TmpVal = DEFAULT_K0_VALUE;
1036 /* Checking all the Ul Alloc values. If value is less than MIN_NUM_K1_IDX
1037 * then skip else continue storing the values. */
1039 for(k1Index = 0; k1Index < ulAckListCount; k1Index++)
1041 k1TmpVal = UlAckTbl[k1Index];
1042 if(k1TmpVal <= MIN_NUM_K1_IDX)
1047 k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.k1Indexes[numK1++] = k1Index;
1048 /* TODO Store K1 index where harq feedback will be received in harq table. */
1052 k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.numK1 = numK1;
1053 k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k0Index = k0Index;
1059 k0K1InfoTbl->k0k1TimingInfo[slotIdx].numK0 = numK0;
1064 /*******************************************************************
1066 * @brief Fills k0 and k1 information table
1070 * Function : BuildK0K1Table
1073 * Fills K0 and k1 information table
1075 * @params[in] SchCellCb *cell,SchK0K1TimingInfoTbl *k0K1InfoTbl,bool
1076 * pdschCfgCmnPres,uint8_t numTimeDomAlloc, SchPdschCfgCmnTimeDomRsrcAlloc
1077 * cmnTimeDomRsrcAllocList[], SchPdschTimeDomRsrcAlloc
1078 * dedTimeDomRsrcAllocList[], uint8_t ulAckListCount, uint8_t *UlAckTbl
1079 * @return ROK - success
1082 * ****************************************************************/
1083 void BuildK0K1Table(SchCellCb *cell, SchK0K1TimingInfoTbl *k0K1InfoTbl, bool pdschCfgCmnPres, SchPdschCfgCmn pdschCmnCfg,\
1084 SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
1089 bool ulSlotPresent = false;
1090 uint8_t k0TmpVal = 0, k1TmpVal =0, tmpSlot=0, startSymbol=0, endSymbol=0, checkSymbol=0;
1091 uint8_t slotIdx=0, k0Index=0, k1Index=0, numK0=0, numK1=0, cfgIdx=0, numTimeDomAlloc =0, totalCfgSlot =0;
1092 SchPdschCfgCmnTimeDomRsrcAlloc cmnTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
1093 SchPdschTimeDomRsrcAlloc dedTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
1096 if(cell->cellCfg.dupMode == DUPLEX_MODE_FDD)
1098 BuildK0K1TableForFdd(cell, k0K1InfoTbl, pdschCfgCmnPres, pdschCmnCfg, pdschDedCfg, ulAckListCount, UlAckTbl);
1104 /* Initialization the K0K1 structure, total num of slot and calculating the slot pattern length. */
1105 memset(k0K1InfoTbl, 0, sizeof(SchK0K1TimingInfoTbl));
1106 k0K1InfoTbl->tblSize = cell->numSlots;
1107 totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbSchCfg.scsCommon, cell->cellCfg.tddCfg.tddPeriod);
1109 /* Storing time domain resource allocation list based on common or
1110 * dedicated configuration availability. */
1111 if(pdschCfgCmnPres == true)
1113 numTimeDomAlloc = pdschCmnCfg.numTimeDomAlloc;
1114 for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1116 cmnTimeDomRsrcAllocList[cfgIdx] = pdschCmnCfg.timeDomRsrcAllocList[cfgIdx];
1121 numTimeDomAlloc = pdschDedCfg.numTimeDomRsrcAlloc;
1122 for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1124 dedTimeDomRsrcAllocList[cfgIdx] = pdschDedCfg.timeDomRsrcAllociList[cfgIdx];
1128 /* Checking all possible indexes for K0 and K1 values. */
1129 for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1131 /* If current slot is UL or FLEXI then Skip because PDCCH is sent only in DL slots. */
1132 slotCfg = schGetSlotSymbFrmt(slotIdx%totalCfgSlot, cell->slotFrmtBitMap);
1133 if(slotCfg == UL_SLOT || slotCfg == FLEXI_SLOT)
1138 /* Storing K0 , start symbol and length symbol for further processing.
1139 * If K0 value is not available then we can fill the default values
1140 * given in spec 38.331. */
1142 for(k0Index = 0; ((k0Index < numTimeDomAlloc) && (k0Index < MAX_NUM_K0_IDX)); k0Index++)
1144 if(pdschCfgCmnPres == true)
1146 k0TmpVal = cmnTimeDomRsrcAllocList[k0Index].k0;
1147 startSymbol = cmnTimeDomRsrcAllocList[k0Index].startSymbol;
1148 endSymbol = startSymbol + cmnTimeDomRsrcAllocList[k0Index].lengthSymbol;
1152 if(dedTimeDomRsrcAllocList[k0Index].k0 != NULLP)
1154 k0TmpVal = *(dedTimeDomRsrcAllocList[k0Index].k0);
1158 k0TmpVal = DEFAULT_K0_VALUE;
1160 startSymbol = dedTimeDomRsrcAllocList[k0Index].startSymbol;
1161 endSymbol = startSymbol + dedTimeDomRsrcAllocList[k0Index].symbolLength;
1164 /* If current slot + k0 is UL then skip the slot
1165 * else if it is DL slot then continue the next steps
1166 * else if it is a FLEXI slot then check symbols of slot, It should not
1167 * contain any UL slot. */
1168 tmpSlot = (slotIdx+k0TmpVal) % totalCfgSlot;
1169 slotCfg = schGetSlotSymbFrmt(tmpSlot, cell->slotFrmtBitMap);
1170 if(slotCfg == UL_SLOT)
1174 if(slotCfg == FLEXI_SLOT)
1176 for(checkSymbol = startSymbol; checkSymbol<endSymbol; checkSymbol ++)
1178 slotCfg = cell->cellCfg.tddCfg.slotCfg[tmpSlot][checkSymbol];
1179 if(slotCfg == UL_SLOT)
1186 /* If current slot + k0 + k1 is a DL slot then skip the slot
1187 * else if it is UL slot then store the information
1188 * else if it is FLEXI slot then check the symbols, it must have
1189 * at least one UL symbol. */
1191 for(k1Index = 0; k1Index < ulAckListCount; k1Index++)
1193 k1TmpVal = UlAckTbl[k1Index];
1194 if(k1TmpVal > MIN_NUM_K1_IDX)
1196 tmpSlot = (slotIdx+k0TmpVal+k1TmpVal) % totalCfgSlot;
1197 slotCfg = schGetSlotSymbFrmt(tmpSlot, cell->slotFrmtBitMap);
1198 if(slotCfg == DL_SLOT)
1202 if(slotCfg == FLEXI_SLOT)
1204 for(checkSymbol = 0; checkSymbol< MAX_SYMB_PER_SLOT;checkSymbol++)
1206 if(cell->cellCfg.tddCfg.slotCfg[tmpSlot][checkSymbol] == UL_SLOT)
1208 ulSlotPresent = true;
1213 if(ulSlotPresent == true || slotCfg == UL_SLOT)
1215 k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.k1Indexes[numK1++] = k1Index;
1216 /* TODO Store K1 index where harq feedback will be received
1222 /* Store all the values if all condition satisfies. */
1225 k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.numK1 = numK1;
1226 k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k0Index = k0Index;
1232 k0K1InfoTbl->k0k1TimingInfo[slotIdx].numK0 = numK0;
1239 /*******************************************************************
1241 * @brief Fills K2 information table for FDD
1245 * Function : BuildK2InfoTableForFdd
1248 * Fills K2 information table for FDD
1250 * @params[in] SchCellCb *cell,SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[],
1251 * uint16_t puschSymTblSize,SchK2TimingInfoTbl *k2InfoTbl
1252 * @return ROK - success
1255 * ****************************************************************/
1256 void BuildK2InfoTableForFdd(SchCellCb *cell, SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[], uint16_t puschSymTblSize,\
1257 SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
1259 uint16_t slotIdx=0, k2Index=0, k2TmpIdx=0, msg3K2TmpIdx=0;
1261 /* Initialization the structure and storing the total slot values. */
1262 memset(k2InfoTbl, 0, sizeof(SchK2TimingInfoTbl));
1263 k2InfoTbl->tblSize = cell->numSlots;
1265 msg3K2InfoTbl->tblSize = cell->numSlots;
1267 /* Checking all possible indexes for K2. */
1268 for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1270 /* Storing K2 values. */
1271 for(k2Index = 0; ((k2Index < puschSymTblSize) && (k2Index < MAX_NUM_K2_IDX)); k2Index++)
1273 k2TmpIdx= k2InfoTbl->k2TimingInfo[slotIdx].numK2;
1274 k2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[k2TmpIdx] = k2Index;
1275 k2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1277 /* Updating K2 values for MSG3 */
1280 msg3K2TmpIdx = msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2;
1281 msg3K2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[msg3K2TmpIdx] = k2Index;
1282 msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1288 /*******************************************************************
1290 * @brief Fills K2 information table
1294 * Function : BuildK2InfoTable
1297 * Fills K2 information table
1299 * @params[in] SchCellCb *cell,SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[],
1300 * uint16_t puschSymTblSize, SchK2TimingInfoTbl *k2InfoTbl
1301 * @return ROK - success
1304 * ****************************************************************/
1305 void BuildK2InfoTable(SchCellCb *cell, SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[], uint16_t puschSymTblSize,\
1306 SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
1310 bool dlSymbolPresent = false;
1311 uint8_t slotIdx=0, k2Index=0, k2Val=0, k2TmpVal=0, msg3K2TmpVal=0, msg3Delta=0, numK2 =0, currentSymbol =0;
1312 uint8_t startSymbol =0, endSymbol =0, checkSymbol=0, totalCfgSlot=0, slotCfg=0;
1313 SlotConfig currentSlot;
1316 if(cell->cellCfg.dupMode == DUPLEX_MODE_FDD)
1318 BuildK2InfoTableForFdd(cell, timeDomRsrcAllocList, puschSymTblSize, msg3K2InfoTbl, k2InfoTbl);
1324 /* Initialization the structure and storing the total slot values. */
1325 memset(k2InfoTbl, 0, sizeof(SchK2TimingInfoTbl));
1326 k2InfoTbl->tblSize = cell->numSlots;
1328 msg3K2InfoTbl->tblSize = cell->numSlots;
1329 totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbSchCfg.scsCommon, cell->cellCfg.tddCfg.tddPeriod);
1331 /* Checking all possible indexes for K2. */
1332 for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1334 currentSlot = schGetSlotSymbFrmt(slotIdx % totalCfgSlot, cell->slotFrmtBitMap);
1336 /* If current slot is UL then skip because PDCCH is sent only in DL slots */
1337 if(currentSlot != UL_SLOT)
1339 for(k2Index = 0; ((k2Index < puschSymTblSize) && (k2Index < MAX_NUM_K2_IDX)); k2Index++)
1341 /* Storing k2, startSymbol, endSymbol information for further processing.
1342 * If k2 is absent then fill the default values given in spec 38.331
1343 * PUSCH-TimeDomainResourceAllocationList field descriptions */
1344 k2Val = timeDomRsrcAllocList[k2Index].k2;
1347 switch(cell->cellCfg.ssbSchCfg.scsCommon)
1350 k2Val = DEFAULT_K2_VALUE_FOR_SCS15;
1353 k2Val = DEFAULT_K2_VALUE_FOR_SCS30;
1356 k2Val = DEFAULT_K2_VALUE_FOR_SCS60;
1359 k2Val = DEFAULT_K2_VALUE_FOR_SCS120;
1364 /* Current slot + k2 should be either UL or FLEXI slot.
1365 * If slot is FLEXI then check all the symbols of that slot,
1366 * it should not contain any DL or FLEXI slot */
1367 k2TmpVal = (slotIdx + k2Val) % totalCfgSlot;
1368 slotCfg = schGetSlotSymbFrmt(k2TmpVal, cell->slotFrmtBitMap);
1369 if(slotCfg != DL_SLOT)
1371 if(slotCfg == FLEXI_SLOT)
1373 startSymbol = timeDomRsrcAllocList[k2Index].startSymbol;
1374 endSymbol = startSymbol+ timeDomRsrcAllocList[k2Index].symbolLength;
1375 dlSymbolPresent = false;
1376 for(checkSymbol= startSymbol; checkSymbol<endSymbol; checkSymbol++)
1378 currentSymbol = cell->cellCfg.tddCfg.slotCfg[k2TmpVal][checkSymbol];
1379 if(currentSymbol == DL_SLOT || currentSymbol == FLEXI_SLOT)
1381 dlSymbolPresent = true;
1386 /* Store all the values if all condition satisfies. */
1387 if(dlSymbolPresent != true || slotCfg == UL_SLOT)
1389 numK2 = k2InfoTbl->k2TimingInfo[slotIdx].numK2;
1390 k2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[numK2] = k2Index;
1391 k2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1397 msg3Delta = puschDeltaTable[cell->cellCfg.numerology];
1399 /* Check for K2 for MSG3 */
1400 /* Current slot + k2 should be either UL or FLEXI slot.
1401 * If slot is FLEXI then check all the symbols of that slot,
1402 * it should not contain any DL or FLEXI slot */
1403 msg3K2TmpVal = (slotIdx + k2Val + msg3Delta) % totalCfgSlot;
1404 slotCfg = schGetSlotSymbFrmt(msg3K2TmpVal, cell->slotFrmtBitMap);
1405 if(slotCfg != DL_SLOT)
1407 if(slotCfg == FLEXI_SLOT)
1409 startSymbol = timeDomRsrcAllocList[k2Index].startSymbol;
1410 endSymbol = startSymbol+ timeDomRsrcAllocList[k2Index].symbolLength;
1411 dlSymbolPresent = false;
1412 for(checkSymbol= startSymbol; checkSymbol<endSymbol; checkSymbol++)
1414 currentSymbol = cell->cellCfg.tddCfg.slotCfg[msg3K2TmpVal][checkSymbol];
1415 if(currentSymbol == DL_SLOT || currentSymbol == FLEXI_SLOT)
1417 dlSymbolPresent = true;
1422 /* Store all the values if all condition satisfies. */
1423 if(dlSymbolPresent != true || slotCfg == UL_SLOT)
1425 numK2 = msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2;
1426 msg3K2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[numK2] = k2Index;
1427 msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1438 /**********************************************************************
1440 **********************************************************************/