[Epic-ID: ODUHIGH-406][Task-ID: ODUHIGH-415]: Paging Configuration 93/7593/4
authorbarveankit <anbarve@radisys.com>
Thu, 20 Jan 2022 11:32:27 +0000 (17:02 +0530)
committerbarveankit <anbarve@radisys.com>
Tue, 1 Feb 2022 11:28:26 +0000 (16:58 +0530)
Signed-off-by: barveankit <anbarve@radisys.com>
Change-Id: I5b8e25415abfb7fcafbcd6c6512d566f941847c9
Signed-off-by: barveankit <anbarve@radisys.com>
13 files changed:
src/5gnrmac/mac_cfg_hdl.c
src/5gnrsch/sch.c
src/5gnrsch/sch.h
src/5gnrsch/sch_common.c
src/5gnrsch/sch_utils.c
src/5gnrsch/sch_utils.h
src/cm/common_def.c
src/cm/common_def.h
src/cm/du_app_mac_inf.h
src/cm/mac_sch_interface.h
src/du_app/du_cfg.c
src/du_app/du_cfg.h
src/du_app/du_sys_info_hdl.c

index 6f193c0..6205e5b 100644 (file)
@@ -263,6 +263,7 @@ uint8_t MacSchCellCfgReq(Pst *pst, MacCellCfg *macCellCfg)
    {
       schCellCfg.ssbSchCfg.nSSBMask[ssbMaskIdx] = macCellCfg->ssbCfg.ssbMask[ssbMaskIdx];
    }
+   schCellCfg.ssbSchCfg.totNumSsb = countSetBits(schCellCfg.ssbSchCfg.nSSBMask[0]);
 
    /* fill SIB1 scheduler parameters */
    schCellCfg.sib1SchCfg.sib1PduLen = macCellCfg->sib1Cfg.sib1PduLen;
@@ -270,6 +271,13 @@ uint8_t MacSchCellCfgReq(Pst *pst, MacCellCfg *macCellCfg)
    schCellCfg.sib1SchCfg.coresetZeroIndex = macCellCfg->sib1Cfg.coresetZeroIndex;
    schCellCfg.sib1SchCfg.searchSpaceZeroIndex = macCellCfg->sib1Cfg.searchSpaceZeroIndex;
    schCellCfg.sib1SchCfg.sib1Mcs = macCellCfg->sib1Cfg.sib1Mcs;
+   schCellCfg.sib1SchCfg.pageCfg.numPO  =  macCellCfg->sib1Cfg.pagingCfg.numPO;
+   schCellCfg.sib1SchCfg.pageCfg.poPresent = macCellCfg->sib1Cfg.pagingCfg.poPresent;
+
+   if(schCellCfg.sib1SchCfg.pageCfg.poPresent)
+   {
+      memcpy(schCellCfg.sib1SchCfg.pageCfg.pagingOcc, macCellCfg->sib1Cfg.pagingCfg.pagingOcc, MAX_PO_PER_PF);
+   }
 
    /* fill RACH config params */
    schCellCfg.schRachCfg.prachCfgIdx = macCellCfg->prachCfg.prachCfgIdx;
index fc845eb..a0ff776 100644 (file)
@@ -887,7 +887,10 @@ uint8_t SchHdlCellCfgReq(Pst *pst, SchCellCfg *schCellCfg)
    fillSchSib1Cfg(schCellCfg->numerology, schCellCfg->bandwidth, cellCb->numSlots,
         &(schCellCfg->sib1SchCfg), schCellCfg->phyCellId,
         schCellCfg->ssbSchCfg.ssbOffsetPointA);
+   
+   
    memcpy(&cellCb->cellCfg, schCellCfg, sizeof(SchCellCfg));
+   schProcPagingCfg(cellCb);
 
    /* Fill coreset frequencyDomainResource bitmap */
    coreset0Idx = cellCb->cellCfg.schInitialDlBwp.pdcchCommon.commonSearchSpace.coresetId;
@@ -1972,6 +1975,118 @@ uint8_t MacSchSliceReCfgReq(Pst *pst, SchSliceCfgReq *schSliceReCfgReq)
    return ROK;
 }
 
+/****************************************************************************
+ *
+ * @brief Stores the Paging Configuration from DU APP in CellCb 
+ *
+ * @details
+ *
+ *    Function : schProcPagingParam
+ *
+ *    Functionality:
+ *          Process the Paging Configuration when FirstPDCCHMonitoring for
+ *          Paging Ocassion is not present.
+ *
+ *          As per 38.304 Sec 7.1,
+ *          "When firstPDCCH-MonitoringOccasionOfPO is present, the
+ *          starting PDCCH monitoring occasion number of (i_s + 1)th PO is the
+ *          (i_s + 1)th value of the firstPDCCHMonitoringOccasionOfPO
+ *          parameter; otherwise, it is equal to i_s * S."
+ *          "S = number of actual transmitted SSBs determined according 
+ *              to ssb-PositionsInBurst in SIB1"
+ *
+ * @params[in] SchCellCb *cell 
+ *       
+ * @return void 
+ *        
+ *************************************************************************/
+void schProcPagingCfg(SchCellCb *cell)
+{
+   PageCfg *pageCfgRcvd = NULL;
+   uint8_t i_sIdx = 0;
+
+   pageCfgRcvd = &(cell->cellCfg.sib1SchCfg.pageCfg);
+
+   if(pageCfgRcvd->poPresent == TRUE)
+   {
+      /*Fetching first Pdcch Monitoring Occasion for SFN (i_s + 1)th*/
+      for(i_sIdx = 0; i_sIdx < pageCfgRcvd->numPO; i_sIdx++)
+      {
+         cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pageCfgRcvd->pagingOcc[i_sIdx] / MAX_SYMB_PER_SLOT ;
+         if ((pageCfgRcvd->pagingOcc[i_sIdx] % MAX_SYMB_PER_SLOT) != 0 )
+         {
+            cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot++;
+         }
+
+         cell->pageCb.pagMonOcc[i_sIdx].frameOffset = 0;
+
+      }
+   }
+   else
+   {
+      schCfgPdcchMonOccOfPO(cell);                  
+   }
+}
+
+/****************************************************************************
+ *
+ * @brief Calculate PO if not present in Configuration 
+ *
+ * @details
+ *
+ *    Function : schCfgPdcchMonOccOfPO
+ *
+ *    Functionality: In this function, PO are calculated i_s * S because
+ *    FirstPDCCHMonitoring_ForPO is not present.
+ *
+ * @params[in] SchCellCb *cellCb
+ *       
+ * @return void 
+ *        
+ *************************************************************************/
+void schCfgPdcchMonOccOfPO(SchCellCb *cell)
+{
+   uint8_t         cnt = 0, incr = 1, i_sIdx = 0, frameOffSet = 0;
+   uint8_t         nsValue = cell->cellCfg.sib1SchCfg.pageCfg.numPO;
+   uint8_t         totalNumSsb = cell->cellCfg.ssbSchCfg.totNumSsb;
+   SlotTimingInfo  tmpTimingInfo, pdcchTime; 
+
+   /*Starting with First Sfn and slot*/
+   tmpTimingInfo.sfn = 0;
+   tmpTimingInfo.slot = 0;
+
+   pdcchTime = tmpTimingInfo;
+
+   while(i_sIdx < nsValue)
+   {
+      /*Increment frame Offset if PO falls on next SFN*/
+      if(pdcchTime.sfn != tmpTimingInfo.sfn)
+      {
+         frameOffSet++;
+      }
+      pdcchTime = tmpTimingInfo;
+      schIncrSlot(&(tmpTimingInfo), incr, cell->numSlots);
+
+      if (i_sIdx == 0)
+      {
+         cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pdcchTime.slot;
+         cell->pageCb.pagMonOcc[i_sIdx].frameOffset = frameOffSet;
+         i_sIdx++;
+      }
+      else
+      {
+         cnt++;
+         if((cnt == totalNumSsb) && (i_sIdx < MAX_PO_PER_PF)) 
+         {
+            cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pdcchTime.slot;
+            cell->pageCb.pagMonOcc[i_sIdx].frameOffset = frameOffSet;
+            cnt = 0;
+            i_sIdx++;
+         }
+      }
+   }
+}
+
 /**********************************************************************
   End of file
  **********************************************************************/
index 0c0b7ab..5c46b6e 100644 (file)
@@ -293,6 +293,31 @@ typedef struct schRaReq
    SlotTimingInfo  winEndTime;
 }SchRaReq;
 
+typedef struct schPageInfo
+{
+  uint8_t        pf;       /*Value of Paging Frame received from DUAPP*/
+  uint8_t        i_s;      /*Value of Paging Occ Index received from DUAPP*/
+  SlotTimingInfo TxTime;   /*Start Paging window*/
+  uint8_t        crntSsbIdx; /*Counts the slot till totalSSB is receached*/
+  uint8_t        mcs;
+  uint8_t        nPRB;
+  uint16_t       msgLen;
+  uint8_t        *pagePdu;   
+}SchPageInfo;
+
+typedef struct schPagingOcc
+{
+  uint8_t frameOffset;
+  uint8_t pagingOccSlot;
+}SchPagingOcc;
+
+typedef struct schPageCb
+{
+   CmLListCp    pageReqInfoRecord[MAX_SFN];   /*List of Page Records received which are stored per sfn*/
+   SchPagingOcc pagMonOcc[MAX_PO_PER_PF]; /*Paging Occasion Slot/FrameOffset are stored*/ 
+   SchPageInfo  currPageInfo;   /*Page Req which is being currently processed */
+}SchPageCb;
+
 /**
  * @brief
  * Cell Control block per cell.
@@ -317,6 +342,7 @@ typedef struct schCellCb
    uint32_t      boIndBitMap;                       /*!<Bit map to indicate UEs that have recevied BO */
    SchUeCb       ueCb[MAX_NUM_UE];                  /*!<Pointer to UE contexts of this cell */
    CmLListCp     ueToBeScheduled;                   /*!<Linked list to store UEs pending to be scheduled, */
+   SchPageCb     pageCb;        /*!<Page Record at Schedular*/
 #ifdef NR_TDD
    uint8_t       numSlotsInPeriodicity;             /*!< number of slots in configured periodicity and SCS */
    uint32_t      slotFrmtBitMap;                    /*!< 2 bits must be read together to determine D/U/S slots. 00-D, 01-U, 10-S */
@@ -407,6 +433,9 @@ void prbAllocUsingRRMPolicy(CmLListCp *lcLL, bool dedicatedPRB, uint16_t mcsIdx,
                       uint16_t *sharedPRB, uint16_t *reservedPRB, bool *isTxPayloadLenAdded, bool *srRcvd);
 void updateBsrAndLcList(CmLListCp *lcLL, BsrInfo *bsrInfo, uint8_t status);
 
+/*Paging Functions*/
+void schProcPagingCfg(SchCellCb *cell);
+void schCfgPdcchMonOccOfPO(SchCellCb *cell);
 /**********************************************************************
   End of file
  **********************************************************************/
index 4907c77..2d03702 100644 (file)
@@ -2098,7 +2098,41 @@ void updateBsrAndLcList(CmLListCp *lcLL, BsrInfo *bsrInfo, uint8_t status)
       }
       node = next;
    }
-}     
+}
+
+/********************************************************************************
+ *
+ * @brief Increment the Slot by a input factor
+ *
+ * @details
+ *
+ *    Function : schIncrSlot
+ *
+ *    Functionality:
+ *       Increment the slot by a input factor till num of Slots configured in a
+ *       Radio Frame. If it exceeds, move to next sfn.
+ *
+ * @params[in/out] SlotTimingInfo timingInfo
+ *        [in]     uint8_t incr [Increment factor]
+ *        [in]     numSlotsPerRF [Number of Slots configured per RF as per
+ *                                numerology]
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ *******************************************************************/
+void schIncrSlot(SlotTimingInfo *timingInfo, uint8_t incr, uint16_t numSlotsPerRF)
+{
+   timingInfo->slot += incr;
+   if(timingInfo->slot >= numSlotsPerRF)
+   {
+      timingInfo->sfn += timingInfo->slot/numSlotsPerRF;
+      timingInfo->slot %= numSlotsPerRF;
+      if(timingInfo->sfn >  MAX_SFN)
+      {
+         timingInfo->sfn %= MAX_SFN;
+      }
+   }
+}
 /**********************************************************************
   End of file
  **********************************************************************/
index 90b979d..b960586 100644 (file)
@@ -1757,7 +1757,6 @@ void covertFreqDomRsrcMapToIAPIFormat(uint8_t *sourceBitMap, uint8_t *destBitMap
       numBitsToShift += 8;
    }
 }
-
 /**********************************************************************
          End of file
 **********************************************************************/
index 78a0400..44a1472 100644 (file)
@@ -137,6 +137,7 @@ void deleteLcLL(CmLListCp *lcLL);
 /*Will be enabled for debugging*/
 void printLcLL(CmLListCp *lcLL);
 #endif
+
 /**********************************************************************
   End of file
  **********************************************************************/
index 897360d..cfe9cf7 100644 (file)
@@ -388,6 +388,34 @@ Region region, Pool pool, Data *ptr, Size size, uint8_t memType)
    else
       return RFAILED;
 }
+
+
+/*******************************************************************
+*
+* @brief  countSetBits in an integer
+*
+* @details
+*
+*    Function : countSetBits 
+*
+*    Functionality: countSetBits in unsigned integer
+*
+* @params[in] uint32_t number/Bitmask
+*
+* @return [out] uint8_t count of Set Bits
+*
+* ****************************************************************/
+uint8_t countSetBits(uint32_t num)
+{
+   uint8_t count = 0;
+
+   while(num)
+   {
+      count += num & 1;
+      num >>= 1;
+   }
+   return(count);
+}
 /**********************************************************************
          End of file
 **********************************************************************/
index c709204..fc51869 100644 (file)
 #define ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL      5     /* in milliseconds */
 #define ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL  60000 /* in milliseconds */
 
+/*Spec 38.331 Sec 6.4: Maximum number of paging occasion per paging frame*/
+#define MAX_PO_PER_PF 4
+
 /* Defining macros for common utility functions */
 #define ODU_GET_MSG_BUF SGetMsg
 #define ODU_PUT_MSG_BUF SPutMsg
    _isLcidValid = ((_lcId >= SRB0_LCID && _lcId <= MAX_DRB_LCID) ? 1 : 0);\
 }
 
+#define GET_PAGING_CYCLE(enmValue, T) {               \
+        if (enmValue == 0) T = 32;                           \
+       else if (enmValue == 1) T = 64;                       \
+       else if (enmValue == 2) T = 128;                      \
+       else if (enmValue == 3) T = 256;                      \
+       else T = 0;                                         \
+}
+
+#define GET_NUM_PAGING_OCC(enmValue, PO) {               \
+        if (enmValue == 0) PO = 4;                            \
+       else if (enmValue == 1) PO = 2;                       \
+       else if (enmValue == 2) PO = 1;                      \
+       else PO = 0;                                         \
+}
 typedef enum
 {
    UE_CFG_INACTIVE,
@@ -321,6 +338,7 @@ uint8_t SGetStaticBufNewForDebug(char *file, char *func, char *line, \
 Region region, Pool pool, Data **ptr, Size size, uint8_t memType);
 uint8_t SPutStaticBufNewForDebug(char *file, char *func, char *line, \
 Region region, Pool pool, Data *ptr, Size size, uint8_t memType);
+uint8_t countSetBits(uint32_t num);
 
 #endif
 
index a0d81ec..985f29e 100644 (file)
@@ -570,6 +570,13 @@ typedef struct prachCfg
    uint8_t       raRspWindow;         /* RA Response Window */
 }PrachCfg;
 
+typedef struct schPageCfg
+{
+  uint8_t  numPO;                    /*Derived from Ns*/
+  bool     poPresent;                /*Whether FirstPDCCH-MonitoringPO is present or not*/
+  uint16_t pagingOcc[MAX_PO_PER_PF]; /*FirstPDCCH-Monitoring Paging Occasion*/
+}SchPageCfg;
+
 typedef struct sib1CellCfg
 {
    uint8_t  *sib1Pdu;
@@ -578,6 +585,7 @@ typedef struct sib1CellCfg
    uint8_t coresetZeroIndex;     /* derived from 4 LSB of pdcchSib1 present in MIB */
    uint8_t searchSpaceZeroIndex; /* derived from 4 MSB of pdcchSib1 present in MIB */
    uint16_t sib1Mcs;
+   SchPageCfg  pagingCfg;
 } Sib1CellCfg; 
 
 typedef struct bwpParams
index 2f1e83d..3424bfd 100644 (file)
@@ -449,6 +449,10 @@ typedef struct
    SchSSBPeriod   ssbPeriod;        /* SSB Periodicity in msec */
    uint8_t     ssbSubcOffset;    /* Subcarrier Offset(Kssb) */
    uint32_t    nSSBMask[SCH_SSB_MASK_SIZE];      /* Bitmap for actually transmitted SSB. */
+   
+   /*Ref:Spec 38.331 "ssb-PositionsInBurst", Value 0 in Bitmap => corresponding SS/PBCH block is not transmitted
+    *value 1 => corresponding SS/PBCH block is transmitted*/
+   uint8_t     totNumSsb;       /*S = Total Number of Actual SSB transmitted*/
 }SchSsbCfg;
 
 typedef struct bwpCfg
@@ -582,6 +586,13 @@ typedef struct pdcchCfg
 } PdcchCfg;
 /* end of SIB1 PDCCH structures */
 
+typedef struct pageCfg
+{
+   uint8_t  numPO;                    /*Derived from Ns*/
+   bool     poPresent;                /*FirstPDCCH-MonitoringPO is present or not*/
+   uint16_t pagingOcc[MAX_PO_PER_PF]; /*FirstPDCCH-Monitoring Paging Occasion*/
+}PageCfg;
+
 typedef struct
 {
    /* parameters recieved from DU-APP */
@@ -592,10 +603,11 @@ typedef struct
    uint16_t sib1Mcs;
 
    /* parameters derived in scheduler */
-   uint8_t n0;
-   BwpCfg bwp;
-   PdcchCfg sib1PdcchCfg;
-   PdschCfg sib1PdschCfg;
+   uint8_t   n0;
+   BwpCfg    bwp;
+   PdcchCfg  sib1PdcchCfg;
+   PdschCfg  sib1PdschCfg;
+   PageCfg   pageCfg;         /*Config of Paging*/
 }SchSib1Cfg;
 
 typedef struct schRachCfg
@@ -760,7 +772,7 @@ typedef struct schCellCfg
    SchPlmnInfoList plmnInfoList;     /* Consits of PlmnId and Snssai list */
 #ifdef NR_TDD
    TDDCfg         tddCfg;           /* TDD Cfg */ 
-#endif   
+#endif  
 }SchCellCfg;
 
 typedef struct schCellCfgCfm
index 5576e95..9b5db13 100644 (file)
@@ -214,7 +214,6 @@ uint8_t readMacCfg()
    duCfgParam.macCellCfg.ssbCfg.ssbScOffset = SSB_SUBCARRIER_OFFSET;
 #endif
    duCfgParam.macCellCfg.ssbCfg.ssbMask[0] = 1; /* only one SSB is transmitted */
-   duCfgParam.macCellCfg.ssbCfg.ssbMask[1] = 0;
    if(BuildMibPdu() != ROK)
    {
       DU_LOG("\nERROR  -->  Failed to build MIB PDU");
@@ -278,7 +277,20 @@ uint8_t readMacCfg()
    duCfgParam.macCellCfg.sib1Cfg.coresetZeroIndex = CORESET_0_INDEX;
    duCfgParam.macCellCfg.sib1Cfg.searchSpaceZeroIndex = SEARCHSPACE_0_INDEX;
    duCfgParam.macCellCfg.sib1Cfg.sib1Mcs = DEFAULT_MCS;
-
+  
+   GET_NUM_PAGING_OCC(duCfgParam.sib1Params.srvCellCfgCommSib.dlCfg.pcchCfg.ns,
+                           duCfgParam.macCellCfg.sib1Cfg.pagingCfg.numPO);
+   if(duCfgParam.sib1Params.srvCellCfgCommSib.dlCfg.pcchCfg.firstPDCCHMontioringType != \
+             PCCH_Config__firstPDCCH_MonitoringOccasionOfPO_PR_NOTHING)
+   {
+      duCfgParam.macCellCfg.sib1Cfg.pagingCfg.poPresent = TRUE;
+      memcpy(duCfgParam.macCellCfg.sib1Cfg.pagingCfg.pagingOcc, 
+              duCfgParam.sib1Params.srvCellCfgCommSib.dlCfg.pcchCfg.firstPDCCHMontioringInfo,MAX_PO_PER_PF);
+   }
+   else
+   {
+      duCfgParam.macCellCfg.sib1Cfg.pagingCfg.poPresent = FALSE;
+   }
 
    /* fill Intial DL BWP */
    duCfgParam.macCellCfg.initialDlBwp.bwp.firstPrb = 0;
@@ -530,8 +542,13 @@ uint8_t fillServCellCfgCommSib(SrvCellCfgCommSib *srvCellCfgComm)
 
    /* Configuring PCCH Config for SIB1 */
    pcchCfg.dfltPagingCycle = PagingCycle_rf256;
-   pcchCfg.nAndPagingFrmOffPresent = PCCH_Config__nAndPagingFrameOffset_PR_oneT;
-   pcchCfg.numPagingOcc = PCCH_Config__ns_four;
+   pcchCfg.nAndPagingFrmOffsetType = PCCH_Config__nAndPagingFrameOffset_PR_oneT;
+   pcchCfg.pageFrameOffset = 0;
+   pcchCfg.ns = PCCH_Config__ns_one;
+   pcchCfg.firstPDCCHMontioringType = PCCH_Config__firstPDCCH_MonitoringOccasionOfPO_PR_sCS30KHZoneT_SCS15KHZhalfT;
+   memset(pcchCfg.firstPDCCHMontioringInfo, 0, sizeof(uint16_t));
+   pcchCfg.firstPDCCHMontioringInfo[0] = 44;
+   
    srvCellCfgComm->dlCfg.pcchCfg = pcchCfg;
 
 
index 80cd078..5fbbd32 100644 (file)
@@ -1107,10 +1107,12 @@ typedef struct bcchCfg
 
 typedef struct pcchCfg
 {
-   long   dfltPagingCycle;      /* Default paging cycle */
-   long   nAndPagingFrmOffPresent;
-   long   nAndPagingFrmOff;     /* n and Paging Frame offset */
-   long   numPagingOcc;         /* Number of paging occassions in paging frame */
+   uint8_t  dfltPagingCycle;                        /* Default paging cycle */
+   uint8_t  nAndPagingFrmOffsetType;                /*Number of PagingFrames in PagingCycle defined in terms of T.*/
+   uint8_t  pageFrameOffset;                        /* Paging Frame offset */
+   uint8_t  ns;                                     /* Number of paging occassions in paging frame */
+   uint8_t  firstPDCCHMontioringType;               /* First PDCCH Monitoring Paging Occasion Presence Type*/
+   uint16_t firstPDCCHMontioringInfo[MAX_PO_PER_PF];/*Indicates the first PDCCH monitoring occasion of each PO of the PF*/
 }PcchCfg;
 
 typedef struct scsSpecCarrier
index ecf04e7..edc240d 100644 (file)
@@ -1286,6 +1286,139 @@ uint8_t BuildBcchConfig(BCCH_Config_t *bcchCfg)
    return ROK;
 }/* BuildBcchConfig */
 
+/*******************************************************************
+ *
+ * @brief fills First PDCCH monitoring Paging occasions 
+ *
+ * @details
+ *
+ *    Function : fillFirstPdcchMonitoringOcc
+ *
+ *    Functionality:
+ *        Fills PDCCH Monitoring PO in PCCH configuration
+ *
+ * @params[in] 
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillFirstPdcchMonitoringOcc(struct PCCH_Config__firstPDCCH_MonitoringOccasionOfPO *firstPO,\
+                                      PcchCfg *srcPcchCfg)
+{
+   uint8_t numPO = 0, poIdx = 0;
+
+   firstPO->present = srcPcchCfg->firstPDCCHMontioringType;
+
+   GET_NUM_PAGING_OCC(srcPcchCfg->ns, numPO);
+   if(srcPcchCfg->ns == 0)
+   {
+      DU_LOG("\nINFO   -->  DU APP : Paging Occasions is ZERO, no need to fill further");
+      return ROK;
+   }
+
+   /*Note: Valid values for each number of PO is from Spec 36.331: PCCH-COnfig*/
+   switch(firstPO->present)
+   {
+      case PCCH_Config__firstPDCCH_MonitoringOccasionOfPO_PR_NOTHING:
+         {
+            break;
+         }
+      case PCCH_Config__firstPDCCH_MonitoringOccasionOfPO_PR_sCS15KHZoneT:
+         {
+            DU_ALLOC(firstPO->choice.sCS15KHZoneT, \
+                  sizeof(struct PCCH_Config__firstPDCCH_MonitoringOccasionOfPO__sCS15KHZoneT));
+
+            if(firstPO->choice.sCS15KHZoneT == NULLP)
+            {
+               DU_LOG("\nERROR  -->  DU APP : FirstPdcchMonitoringPO Memory allocation failure");
+               return RFAILED;
+            }
+            firstPO->choice.sCS15KHZoneT->list.count = numPO;
+            firstPO->choice.sCS15KHZoneT->list.size = numPO * sizeof(long *);
+
+            DU_ALLOC(firstPO->choice.sCS15KHZoneT->list.array, firstPO->choice.sCS15KHZoneT->list.size);
+            if(!firstPO->choice.sCS15KHZoneT->list.array)
+            {
+               DU_LOG("\nERROR  -->  DU APP : FirstPdcchMonitoringPO Memory allocation failure");
+               return RFAILED;
+            }
+
+            for(poIdx = 0; poIdx < numPO; poIdx++)
+            {
+               /* Spec 36.331: PCCH-Config: firstPDCCH-MonitoringOccasionOfPO [MAX of sCS15KHZoneT]
+                * Since FirstPDCCHMonitoring_PO is not valid thus no need to continue further*/
+               if(srcPcchCfg->firstPDCCHMontioringInfo[poIdx] > 139)
+               {
+                  DU_LOG("\nERROR  -->  DU APP : Invalid Paging Ocassion value for 15kHz");
+                  return RFAILED;
+               }
+               DU_ALLOC(firstPO->choice.sCS15KHZoneT->list.array[poIdx], sizeof(long));
+               if(!firstPO->choice.sCS15KHZoneT->list.array[poIdx])
+               {
+                  DU_LOG("\nERROR  -->  DU APP : FirstPdcchMonitoringPO Memory allocation failure");
+                  return RFAILED;
+               }
+            }
+
+            poIdx = 0;
+            *firstPO->choice.sCS15KHZoneT->list.array[poIdx] = srcPcchCfg->firstPDCCHMontioringInfo[poIdx];
+
+            break;
+         }
+      case PCCH_Config__firstPDCCH_MonitoringOccasionOfPO_PR_sCS30KHZoneT_SCS15KHZhalfT:
+         {
+            DU_ALLOC(firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT, \
+                  sizeof(struct PCCH_Config__firstPDCCH_MonitoringOccasionOfPO__sCS30KHZoneT_SCS15KHZhalfT));
+
+            if(firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT == NULLP)
+            {
+               DU_LOG("\nERROR  -->  DU APP : FirstPdcchMonitoringPO Memory allocation failure");
+               return RFAILED;
+            }
+            firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.count = numPO;
+            firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.size = numPO * sizeof(long *);
+
+            DU_ALLOC(firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.array, \
+                  firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.size);
+
+            if(!firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.array)
+            {
+               DU_LOG("\nERROR  -->  DU APP : FirstPdcchMonitoringPO Memory allocation failure");
+               return RFAILED;
+            }
+
+            for(poIdx = 0; poIdx < numPO; poIdx++)
+            {
+               /* Spec 36.331: PCCH-Config:firstPDCCH-MonitoringOccasionOfPO [MAX of sCS30KHZoneT-SCS15KHZhalfT]
+                * Since FirstPDCCHMonitoring_PO is not valid thus no need to continue further*/
+               if(srcPcchCfg->firstPDCCHMontioringInfo[poIdx] > 279)
+               {
+                  DU_LOG("\nERROR  -->  DU APP : Invalid Paging Ocassion value for 30kHz or 15kHz HAlFT");
+                  return RFAILED;
+               }
+               DU_ALLOC(firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.array[poIdx], sizeof(long));
+               if(!firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.array[poIdx])
+               {
+                  DU_LOG("\nERROR  -->  DU APP : FirstPdcchMonitoringPO Memory allocation failure");
+                  return RFAILED;
+               }
+            }
+
+            poIdx = 0;
+            *firstPO->choice.sCS30KHZoneT_SCS15KHZhalfT->list.array[poIdx] = srcPcchCfg->firstPDCCHMontioringInfo[poIdx];
+            break;
+         }
+         //TODO for other cases
+      default:
+         {
+            DU_LOG("\nERROR  -->  DU APP : Invalid firstPDCCH-MonitoringOccasionOfPO");
+            return RFAILED;
+
+            break;
+         }
+   }
+   return ROK;
+}
 /*******************************************************************
  *
  * @brief Builds PCCH configuration 
@@ -1309,47 +1442,86 @@ uint8_t BuildPcchConfig(PCCH_Config_t *pcchCfg)
    duPcchCfg = duCfgParam.sib1Params.srvCellCfgCommSib.dlCfg.pcchCfg;
 
    pcchCfg->defaultPagingCycle = duPcchCfg.dfltPagingCycle;
-   pcchCfg->nAndPagingFrameOffset.present =  duPcchCfg.nAndPagingFrmOffPresent;
+   pcchCfg->nAndPagingFrameOffset.present =  duPcchCfg.nAndPagingFrmOffsetType;
    switch(pcchCfg->nAndPagingFrameOffset.present)
    {
+      /**Note: PagingFrame Offset Value differs for each Paging Duration
+       *(oneT, halfT,...). The Range of Offset given in Spec 38.331,Pcch-Config*/
       case PCCH_Config__nAndPagingFrameOffset_PR_NOTHING:
-      {
-         //TODO
-         break;
-      }
+         {
+            //TODO          
+            break;
+         }
       case PCCH_Config__nAndPagingFrameOffset_PR_oneT:
-      {
-         //TODO
-        break;
-      }
+         {
+            pcchCfg->nAndPagingFrameOffset.choice.oneT = NULLD;
+            break;
+         }
       case PCCH_Config__nAndPagingFrameOffset_PR_halfT:
-      {
-        //TODO
-        break;
-      }
+         {
+            /*Spec 38.331: PCCH_Config: nAndPagingFrameOffset [MAX value of halfT] */
+            if(duPcchCfg.pageFrameOffset > 1)
+            {
+               DU_LOG("\nERROR  -->  DU APP : Invalid PagingFrameOffset for HALF_T");
+               return RFAILED;
+            }
+            pcchCfg->nAndPagingFrameOffset.choice.halfT = duPcchCfg.pageFrameOffset;
+            break;
+         }
       case PCCH_Config__nAndPagingFrameOffset_PR_quarterT:
-      {
-        //TODO
-        break;
-      }
+         {
+            /*Spec 38.331: PCCH_Config: nAndPagingFrameOffset [MAX value of quarterT] */
+            if(duPcchCfg.pageFrameOffset > 3)
+            {
+               DU_LOG("\nERROR  -->  DU APP : Invalid PagingFrameOffset for QUARTER_T");
+               return RFAILED;
+            }
+            pcchCfg->nAndPagingFrameOffset.choice.quarterT = duPcchCfg.pageFrameOffset;
+            break;
+         }
       case PCCH_Config__nAndPagingFrameOffset_PR_oneEighthT:
-      {
-        //TODO
-        break;
-      }
+         {
+            /*Spec 38.331: PCCH_Config: nAndPagingFrameOffset [MAX value of oneEighthT] */
+            if(duPcchCfg.pageFrameOffset > 7)
+            {
+               DU_LOG("\nERROR  -->  DU APP : Invalid PagingFrameOffset for ONE_EIGHTH_T");
+               return RFAILED;
+            }
+            pcchCfg->nAndPagingFrameOffset.choice.oneEighthT = duPcchCfg.pageFrameOffset;
+            break;
+         }
       case PCCH_Config__nAndPagingFrameOffset_PR_oneSixteenthT:
-      {
-        //TODO
-        break;
-      }
+         {
+            /*Spec 38.331: PCCH_Config: nAndPagingFrameOffset [MAX value of oneSixteenthT] */
+            if(duPcchCfg.pageFrameOffset > 15)
+            {
+               DU_LOG("\nERROR  -->  DU APP : Invalid PagingFrameOffset for ONE_SIXTEENTH_T");
+               return RFAILED;
+            }
+            pcchCfg->nAndPagingFrameOffset.choice.oneSixteenthT = duPcchCfg.pageFrameOffset;
+            break;
+         }
       default:
-      {
-        DU_LOG("\nERROR  -->  DU APP : Invalid nAndPagingFrameOffset configuration");
-        return RFAILED;
-      }
+         {
+            DU_LOG("\nERROR  -->  DU APP : Invalid nAndPagingFrameOffset configuration");
+            return RFAILED;
+         }
    }
-   pcchCfg->ns = duPcchCfg.numPagingOcc;
+   pcchCfg->ns = duPcchCfg.ns;
 
+   DU_ALLOC(pcchCfg->firstPDCCH_MonitoringOccasionOfPO, \
+         sizeof(struct PCCH_Config__firstPDCCH_MonitoringOccasionOfPO));
+   if(pcchCfg->firstPDCCH_MonitoringOccasionOfPO == NULLP)
+   {
+      DU_LOG("\nERROR  -->  DU APP : BuildPcchConfig >> Memory Allocation fails");
+      return RFAILED;
+   }
+
+   if(fillFirstPdcchMonitoringOcc(pcchCfg->firstPDCCH_MonitoringOccasionOfPO, &duPcchCfg) == RFAILED)
+   {
+      DU_LOG("\nERROR  -->  DU APP : BuildPcchConfig >> Filling of Paging Occ failed");
+      return RFAILED;
+   }
    return ROK;
 }/* BuildPcchConfig */