93948f1ac07cdf7395a82c6492746118d4d6401e
[o-du/l2.git] / src / 5gnrsch / rg_sch_hdfdd.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:     LTE-MAC layer
22  
23      Type:     C source file
24  
25      Desc:     C source code for HD-FDD functions
26  
27      File:     rg_sch_hdfdd.c
28  
29 **********************************************************************/
30
31 /** @file rg_sch_hdfdd.c
32 @brief This module handles the  Periodic CQI/PMI/RI, SRS, SR and Half Duplex 
33        functionality 
34 */
35
36 /* header include files -- defines (.h) */
37 #include "common_def.h"
38 #include "lrg.h"
39 #include "rgr.h"
40 #include "tfu.h"
41 #include "rg_env.h"
42 #include "rg_sch_inf.h"
43 #include "rg_sch_err.h"
44 #include  "rgr.h"
45 #include  "rgm.h"
46 #include "rg_sch.h"
47 #include "rg_sch_cmn.h"
48 #include "rl_interface.h"
49 #include "rl_common.h"
50
51 /* header/extern include files (.x) */
52 #include "tfu.x"           /* RGU types */
53 #include "lrg.x"           /* layer management typedefs for MAC */
54 #include "rgr.x"           /* layer management typedefs for MAC */
55 #include "rgm.x"           /* layer management typedefs for MAC */
56 #include "rg_sch_inf.x"    /* typedefs for Scheduler */
57 #include "rg_sch.x"        /* typedefs for Scheduler */
58 #include "rg_sch_cmn.x"
59
60
61 #ifdef LTEMAC_HDFDD
62 #ifdef __cplusplus
63 extern "C" {
64 #endif /* __cplusplus */
65
66
67 /* @details
68  *
69  *     Function : rgSCHHdFddUeCfg 
70  *
71  *     Invoking Module Processing:
72  *      - This shall be invoked by SCH_GOM at UE Re/configuration. 
73  *        
74  *     Processing Steps:
75  *     - For UE-specific Half Duplex  
76  *      - Allocate the memory and place the UE in cellCb->hdUeLstCp 
77  *        - Update subframes information state to defualt
78  *        - Update subframes information sfn to defualt
79  *     - Return ROK
80  *
81  *  @param[in]  RgSchCellCb  *cell
82  *  @param[in]  RgSchUeCb    *ue
83  *  @param[in]  Bool         *hdFddEnbl
84  *
85  *  @return  S16
86  *      -# ROK
87  *      -# RFAILED
88 */ 
89
90 S16 rgSCHHdFddUeCfg(RgSchCellCb  *cellCb,RgSchUeCb *ueCb,Bool hdFddEnbl)
91 {
92    uint8_t sfi;
93
94    DU_LOG("\nDEBUG  -->  SCH : rgSCHHdFddUeCfg(): UeId =%d hdFddEnbl=%d",
95                ueCb->ueId, hdFddEnbl);
96    if(ueCb->hdFddEnbld == TRUE)
97    {
98       if (hdFddEnbl == FALSE)
99       {
100          /* Do not allow switch from HD-FDD to FD-FDD configuration */
101          DU_LOG("\nERROR  -->  SCH : rgSCHHdFddUeCfg(): HD-FDD  to FD-FDD Configuration is not allowed"
102                "CRNTI:%d",ueCb->ueId);
103       }
104       else
105       {
106          /* If already enabled then it can be second reconfiguration */
107          DU_LOG("\nERROR  -->  SCH : rgSCHHdFddUeCfg(): HD-FDD already enabled for this UE"
108                   "CRNTI:%d",ueCb->ueId);
109       }
110       return RFAILED;
111    }
112
113 #ifdef LTEMAC_SPS
114    /* Check is SPS enabled for this UE */
115    if(hdFddEnbl == TRUE &&
116        (ueCb->ul.ulSpsCfg.isUlSpsEnabled == TRUE ||
117         ueCb->dl.dlSpsCfg.isDlSpsEnabled == TRUE))
118    {
119       DU_LOG("\nERROR  -->  SCH : rgSCHHdFddUeCfg(): Could'nt do HDFDD cfg, SPS already configured"
120                "CRNTI:%d",ueCb->ueId);
121       return RFAILED;
122    }
123 #endif
124
125    ueCb->hdFddEnbld = hdFddEnbl;
126    if( hdFddEnbl == TRUE)
127    {
128       rgSCHUtlAllocSBuf(cellCb->instIdx,(Data **) &ueCb->hdFddCb,
129              sizeof(RgSchUeHdFddCb));
130       if (ueCb->hdFddCb != NULLP)
131       {
132          for (sfi = 0; sfi < RG_SCH_HDFDD_NUMSFINFO; sfi++)
133          {
134             ueCb->hdFddCb->subfrm[sfi].subFrmDir = RG_SCH_HDFDD_NOSCHD;
135             ueCb->hdFddCb->subfrm[sfi].sfn      = RG_SCH_HDFDD_INVSFN;
136          }
137          /* Add this UE to list maintained in CellCb */
138          /* cmLListAdd2Tail(&cellCb->hdFddLst,&ueCb->hdFddCb->hdFddLstEnt); */
139       }
140       else
141       {
142          DU_LOG("\nERROR  -->  SCH : rgSCHHdFddUeCfg(): Could not allocate memory for hd-fdd ueCb"
143                "CRNTI:%d",ueCb->ueId);
144          return RFAILED;
145       }
146    }
147    return ROK;
148 }/*rgSCHHdFddUeCfg*/
149
150
151 /* @brief Frees Half Duplex  related data structures
152  *
153  * @details
154  *
155  *     Function : rgSCHHdFddUeDel
156  *
157  *     Invoking Module Processing:
158  *      - This shall be invoked by SCH_GOM at Ue deletion.
159  *
160  *     Processing Steps:
161  *       - if Half Duplex is enabled
162  *       - if (ueCb->hdFddCb != NULL)
163  *        - Remove ue from  cellCb->hdUeLstCp;
164  *        - Dellocate memory 
165  *       - else
166  *        - Nothing to do
167  *      - Return ROK
168  *  @param[in]  RgSchCellCb  *cell
169  *  @param[in]  RgSchUeCb    *ue
170  *
171  *  @return ( S16
172  *      -# ROK
173 *
174 */
175 S16 rgSCHHdFddUeDel(RgSchCellCb *cellCb,RgSchUeCb   *ueCb)
176 {
177
178     DU_LOG("\nDEBUG  -->  SCH : rgSCHHdFddUeDel(): UeId =%d hdFdd=%x",
179              ueCb->ueId, ueCb->hdFddEnbld);
180
181
182     if (ueCb->hdFddCb)
183     {
184        /* ccpu00117052 - MOD - Passing double pointer
185        for proper NULLP assignment*/
186        rgSCHUtlFreeSBuf(cellCb->instIdx, (Data **)(&(ueCb->hdFddCb)),
187              sizeof(RgSchUeHdFddCb));   
188        ueCb->hdFddEnbld = FALSE;
189     }
190
191     return ROK;
192 } /* rgSCHHdFddUeDel */
193
194
195
196 #ifdef TFU_UPGRADE
197 /* @brief Mark the subframes as uplink for HD FDD if CQI/RI or SRS or RI is
198  * expecting .
199  *
200  * @details
201  *
202  *     Function: rgSCHCmnHdFddPtUlMrk 
203  *     Purpose:  Updation of Periodic CQI/PMI, SRS and SR tranmission
204  *               instance updates
205  *               for HD FDD UEs
206  *  @param[in]  RgSchCellCb *cell
207  *  @return    None
208  */
209
210 Void rgSCHCmnHdFddPtUlMrk(RgSchCellCb *cellCb)
211 {
212    uint16_t           sfn; /* System Frame Number */
213    uint32_t           pti; /* Index into Periodic table */
214    uint16_t           sfi; /* Index into HDFDD state table */
215    CmLListCp          *cqiLst;
216    CmLListCp          *srsLst;
217    CmLListCp          *srLst;
218    CmLListCp          *riLst;
219    CmLList            *cqiNode;
220    CmLList            *srsNode;
221    CmLList            *srNode;
222    CmLList            *riNode;
223    CmLteTimingInfo    timeInfo;
224    RgSchUePCqiCb      *cqiCb = NULLP;
225    RgSchUePCqiCb      *riCb = NULLP;
226
227
228    timeInfo = cellCb->crntTime;
229
230    /* Determine indexes */
231    pti = RG_SCH_HDFDD_GETPTI(timeInfo);
232    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_HDFDD_DELTA);
233    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_HDFDD_DELTA);
234
235    /* Get PT entries for */
236    cqiLst = &cellCb->pCqiSrsSrLst[pti].cqiLst;
237    srsLst = &cellCb->pCqiSrsSrLst[pti].srsLst;
238    srLst  = &cellCb->pCqiSrsSrLst[pti].srLst;
239    riLst  = &cellCb->pCqiSrsSrLst[pti].riLst;
240
241    /* Get first node in each list */
242    CM_LLIST_FIRST_NODE(cqiLst, cqiNode);
243    CM_LLIST_FIRST_NODE(srsLst, srsNode);
244    CM_LLIST_FIRST_NODE(riLst,  riNode);
245    CM_LLIST_FIRST_NODE(srLst,  srNode);
246
247    /* Mark corresponding the subframe as uplink control */
248    while ((NULLP != cqiNode ) &&
249          (NULLP != srsNode  ) &&
250          (NULLP != srNode   )  &&
251          (NULLP != riNode   ))
252    {
253      cqiCb = (RgSchUePCqiCb *)(cqiNode->node);
254      RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)(cqiCb->servCellInfo->ue),
255                      RG_SCH_HDFDD_UL, sfn, sfi);
256       /* SRS Transmission instances */
257       RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)srsNode->node,
258                      RG_SCH_HDFDD_UL, sfn, sfi);
259       /* SR Transmission instances */
260       RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)srNode->node,
261                      RG_SCH_HDFDD_UL, sfn, sfi);
262       /* RI Transmission instances */
263      riCb = (RgSchUePCqiCb *)(riNode->node);
264      RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)riCb->servCellInfo->ue,
265                      RG_SCH_HDFDD_UL, sfn, sfi);
266
267       /* Get next UeCb for all lists */
268       CM_LLIST_NEXT_NODE(cqiLst, cqiNode);
269       CM_LLIST_NEXT_NODE(srsLst, srsNode);
270       CM_LLIST_NEXT_NODE(srLst, srNode);
271       CM_LLIST_NEXT_NODE(riLst, riNode);
272    }
273
274    while ( NULLP != cqiNode)
275    {
276       /* CQI/PMI Transmission instances */
277       cqiCb = (RgSchUePCqiCb *)(cqiNode->node);
278       RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)(cqiCb->servCellInfo->ue),
279                      RG_SCH_HDFDD_UL, sfn, sfi);
280       CM_LLIST_NEXT_NODE(cqiLst, cqiNode);
281    }
282    while( NULLP != srsNode)
283    {
284       /* SRS Transmission instances */
285       RG_SCH_HDFDD_VLDTANDMARK(((RgSchUeCb*)srsNode->node),
286                      RG_SCH_HDFDD_UL, sfn, sfi);
287       CM_LLIST_NEXT_NODE(srsLst, srsNode);
288    }
289    while( NULLP != srNode)
290    {
291       /* SR Transmission instances */
292       RG_SCH_HDFDD_VLDTANDMARK(((RgSchUeCb*)srNode->node),
293                      RG_SCH_HDFDD_UL, sfn, sfi);
294       CM_LLIST_NEXT_NODE(srLst, srNode);
295    }
296    while( NULLP != riNode)
297    {
298       /* RI Transmission instances */
299      riCb = (RgSchUePCqiCb *)(riNode->node);
300      RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)riCb->servCellInfo->ue,
301                      RG_SCH_HDFDD_UL, sfn, sfi);
302      CM_LLIST_NEXT_NODE(riLst, riNode);
303    }
304
305    return;
306 } /* rgSCHCmnHdFddPtUlMrk */
307 #endif /* ifdef TFU_UPGRADE */
308
309
310
311 /* @brief Decides whether UE can be allowed for DL in given subframe
312  *
313  * @details
314  *
315  *     Function : rgSCHCmnHdFddChkUlAllow 
316  *
317  *     Invoking Module Processing:
318  *      - This shall be invoked by schedulars before allocating  UL grants .
319  *
320  *     Processing Steps:
321  *       - if Half Duplex is enabled
322  *       - If ue->sf[reqsf].state is "DONWLINK"
323  *            set alloweUlSch=FALSE
324  *       - else
325  *            set alloweUlSch=TRUE
326  *        This function Marking for BCCH/PCCH occasions is also done
327  *      - Return ROK
328  *  @param[in]  RgSchCellCb  *cell
329  *  @param[in]  RgSchUeCb    *ue
330  *
331  *  @return    None
332  *
333  */
334 Void rgSCHCmnHdFddChkUlAllow(RgSchCellCb *cellCb,RgSchUeCb *ueCb,uint8_t *allow)
335 {
336    uint16_t         sfn;
337    uint16_t         sfi;
338    CmLteTimingInfo  timeInfo;
339    RgSchDlSf        *sf = NULLP; /* Dl subframe info */
340    uint8_t          ulOffset
341
342    DU_LOG("\nDEBUG  -->  SCH :  rgSCHCmnHdFddChkUlAllow: ueId=%d ", ueCb->ueId);
343
344    *allow = FALSE;
345
346    timeInfo = cellCb->crntTime;
347
348    ulOffset = RGSCH_PDCCH_PUSCH_DELTA - 
349           TFU_CRCIND_ULDELTA + RGSCH_PDCCH_PUSCH_DELTA;
350    RG_SCH_ADD_TO_CRNT_TIME(cellCb->crntTime, timeInfo, ulOffset);
351
352    /* Set default value */
353    *allow = FALSE;
354
355    /* Validate condition 1 */
356    /* For (curretn time + DL_DELTA)th sf */
357
358    /* Also get subframe pointer to fetch Common Ch allocation */
359    sf = rgSCHUtlSubFrmGet(cellCb, timeInfo);
360
361    sfn = timeInfo.sfn;
362    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
363
364    /* Validate condition 2 */
365    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
366    {
367          /* Common channel scheduled */
368          /* Mark the BCCH/PCCH occasion */
369          RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, sfn, sfi);
370          DU_LOG("\nDEBUG  -->  SCH : rgSCHCmnHdFddChkUlAllow: Already marked for Cmn DL, ueId = %d ",
371             ueCb->ueId);
372    }
373    if ((ueCb->hdFddCb->subfrm[sfi].sfn == sfn) &&
374          (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLDATA ||
375           ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLCNTRL))
376    {
377       /* Downlink scheduled */
378       *allow = FALSE;
379       DU_LOG("\nERROR  -->  SCH : rgSCHCmnHdFddChkUlAllow: Already marked for DL, ueId = %d ",
380                ueCb->ueId);
381       return;
382    }
383
384    /* Validate condition 3 */
385    /* For (curretn time + DL_DELTA + HRQ_DELTA)th sf
386       - i.e. next HARQ Feedback occasion */
387    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
388    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
389    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
390        ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL)
391    {
392       /* No place for HARQ feedback */
393       *allow = FALSE;
394       DU_LOG("\nERROR  -->  SCH : rgSCHCmnHdFddChkUlAllow: No Place for HARQ, ueId = %d ",
395          ueCb->ueId);
396       return;
397
398    }
399    /* Validate condition 4 */
400    /* For (curretn time + DL_DELTA - HRQ_DELTA)th sf
401       - i.e. previous HARQ Feedback occasion */
402    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (-RG_SCH_CMN_HARQ_INTERVAL));
403    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (-RG_SCH_CMN_HARQ_INTERVAL));
404    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
405        ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL)
406    {
407       *allow = FALSE;
408       DU_LOG("\nERROR  -->  SCH :  rgSCHCmnHdFddChkUlAllow: No Place for UL grant, ueId = %d ",
409                ueCb->ueId);
410       return;
411
412    }
413    /* Validate condition 5 */
414    /* For (curretn time + DL_DELTA - 1)th sf -i.e. Guard time */
415    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (-RG_SCH_HDFDD_GRDTIM_DUR));
416    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (-RG_SCH_HDFDD_GRDTIM_DUR));
417    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
418        (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLDATA))
419    {
420       /* This subframe may be a switching gaurd time */
421       *allow = FALSE;
422       DU_LOG("\nERROR  -->  SCH :  rgSCHCmnHdFddChkUlAllow: No Place for Guard time, ueId = %d ",
423              ueCb->ueId);
424       return;
425
426    }
427    /* Adition guard time rule check: Above check is only for PDSCH, lets check
428       is there is any BCCH/PCCH data scheduled */
429    RG_SCH_ADD_TO_CRNT_TIME(cellCb->crntTime, timeInfo, 
430                       (ulOffset - RG_SCH_HDFDD_GRDTIM_DUR));
431    /* Also get subframe pointer to fetch Common Ch allocation */
432    sf = rgSCHUtlSubFrmGet(cellCb, timeInfo);
433    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
434    {
435       /* Common channel scheduled */
436       /* Mark the BCCH/PCCH occasion */
437       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, timeInfo.sfn, sfi);
438       *allow = FALSE;
439       DU_LOG("\nERROR  -->  SCH : rgSCHCmnHdFddChkUlAllow: Already marked for Cmn DL, ueId = %d ",
440          ueCb->ueId);
441       return;
442
443    }
444
445    /* All validation done. Safe to for UL */
446    *allow = TRUE;
447    return;
448 } /* rgSCHCmnHdFddChkUlAllow */
449
450
451  /* @brief Decides whether UE can be allowed for UL in given subframe
452  *
453  * @details
454  *
455  *     Function : rgSCHCmnHdFddChkDlAllow
456  *
457  *     Invoking Module Processing:
458  *      - This shall be invoked by schedulars before allocating for DL.
459  *
460  *     Processing Steps:
461  *          Condition 1:  subframe n + DL_DELTA should not be uplink
462  *          Condition 2:  subframe n+ DL_DELTA + 1 should meet guard time
463  *                        creation rule. For more
464  *                        information refer to section "2.25.7.1 Guard time
465  *                        creation rule"
466  *          Condition 3:  subframe n + DL_DELTA + HRQ_DELTA should not be
467  *                        downlink so that downlink data (HARQ Feedback)
468  *                        can be received in next 4 subframe. {n + 7} Above
469  *                        conditions have to
470  *                        be validated by taking SFN number into consideration.
471  *          if all conditions are met then *allow is set to TRUE or lese to
472  *          FALSE.
473  *          if hd-fdd is not anabled for this UE, then *allow is always TRUE.
474  *   
475  *   Returns None
476  *  @param[in]  RgSchCellCb  *cellCb
477  *  @param[in]  RgSchUeCb    *ueCb
478  *  @param[in]  CmLteTimingInfo    *timeInfo
479  *  @param[out] uint8_t *allow -- TRUE is allowed or FALSE if no allowedi.
480  *                   Valdity of this pointer is not done in this function
481  *
482  */
483 Void rgSCHCmnHdFddChkDlAllow 
484 (
485 RgSchCellCb *cellCb,
486 RgSchUeCb *ueCb,
487 Bool *allow /* Valdity of this pointer is not done in this function */
488 )
489 {
490    uint16_t     sfn;
491    uint16_t     sfi;
492    RgSchDlSf *sf = NULLP; /* Dl subframe info */
493    CmLteTimingInfo timeInfo;
494    CmLteTimingInfo tempTimeInfo;
495
496    *allow = FALSE;
497
498    timeInfo = cellCb->crntTime;
499    RGSCH_INCR_SUB_FRAME(timeInfo, RG_SCH_CMN_DL_DELTA);
500
501    DU_LOG("\nDEBUG  -->  SCH : rgSCHCmnHdFddDlSchAll (): ueId=%d ", ueCb->ueId);
502
503    /* Also get subframe pointer to fetch Common Ch allocation */
504    sf = rgSCHUtlSubFrmGet(cellCb, timeInfo);
505
506    /* Validate condition 1 */
507    /* For (curretn time + DL_DELTA)th sf */
508    sfn = timeInfo.sfn;
509    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
510
511    if ((ueCb->hdFddCb->subfrm[sfi].sfn == sfn) &&
512         (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL))
513    {
514       /* Uplink scheduled */
515       DU_LOG("\nERROR  -->  SCH : rgSCHCmnHdFddChkDlAllow: sf is UL, ueId=%d ", ueCb->ueId);
516       *allow = FALSE;
517       return;
518    }
519
520    /* It is not validation, but BCCH/PCCH marking is done here */
521    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
522    {
523       /* Common channel scheduled */
524       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, sfn, sfi); /* NOT_HIT */
525    }
526
527    /* Validate condition 2 */
528    /* For (curretn time + DL_DELTA + 1)th sf -i.e. Guard time */
529    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
530    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
531    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
532           (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL))
533    {
534       /* This subframe may be a switching guard time */
535       DU_LOG("\nERROR  -->  SCH :  rgSCHCmnHdFddChkDlAllow: Guard time rule not met, ueId=%d ",
536               ueCb->ueId);
537       *allow = FALSE;
538       return;
539    }
540
541    /* Validate condition 3 */
542    /* For (curretn time + DL_DELTA + HRQ_DELTA)th sf - i.e. next HARQ
543       Feedback occasion */
544
545    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
546    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
547
548    /* First check for any Common channel info is scheduled */
549    RG_SCH_ADD_TO_CRNT_TIME(timeInfo, tempTimeInfo, RG_SCH_CMN_HARQ_INTERVAL)
550    /* Also get subframe pointer to fetch Common Ch allocation */
551    sf = rgSCHUtlSubFrmGet(cellCb, tempTimeInfo);
552    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
553    {
554          /* Common channel scheduled */
555       /* Do the marking for this subframe */
556       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, tempTimeInfo.sfn, sfi);
557       DU_LOG("\nDEBUG  -->  SCH : rgSCHCmnHdFddChkDlAllow: Possible systemInfo, ueId=%d ",
558               ueCb->ueId);
559    }
560
561    /* Check for actual validation condition 3 */
562    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
563        ueCb->hdFddCb->subfrm[sfi].subFrmDir != RG_SCH_HDFDD_UL)
564    {
565       /* No place for HARQ feedback */
566       DU_LOG("\nERROR  -->  SCH : rgSCHCmnHdFddChkDlAllow: No place for HARQ feedback, ueId=%d ",
567             ueCb->ueId);
568       *allow = FALSE;
569
570       /* Mark this sf as DLCNTRL */
571       ueCb->hdFddCb->subfrm[sfi].subFrmDir =RG_SCH_HDFDD_DLCNTRL;
572       return;
573    }
574
575
576    /* If we are here then, subframe at HARQth location can be UL.
577       But check if Guard violation is done */
578    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL-1);
579    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL-1);
580    /* check for any Common channel info is scheduled */
581    RG_SCH_ADD_TO_CRNT_TIME(timeInfo, tempTimeInfo, (RG_SCH_CMN_HARQ_INTERVAL-1))
582    /* Also get subframe pointer to fetch Common Ch allocation */
583    sf = rgSCHUtlSubFrmGet(cellCb, tempTimeInfo);
584    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
585    {
586          /* Common channel scheduled */
587       /* Do the marking for this subframe */
588       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, tempTimeInfo.sfn, sfi);
589       DU_LOG("\nDEBUG  -->  SCH : rgSCHCmnHdFddChkDlAllow: (GT) Possible systemInfo, ueId=%d ",
590               ueCb->ueId);
591    }
592
593    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
594        ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLDATA)
595    {
596       /* No place for HARQ feedback */
597       DU_LOG("\nERROR  -->  SCH : rgSCHCmnHdFddChkDlAllow: (GT) No place for HARQ feedback,"
598              "ueId=%d ",ueCb->ueId);
599
600       *allow = FALSE;
601       return;
602    }
603    /* First check for any Common channel info is scheduled */
604
605    *allow = TRUE;
606    /* All validation done. Safe to for DL */
607    return;
608 } /* rgSCHCmnHdFddChkDlAllow */
609
610
611
612 /* @brief Decides whether NACK can be sent in a given subrame
613  *
614  * @details
615  *
616  *     Function : rgSCHCmnHdFddChkNackAllow
617  *
618  *     Invoking Module Processing:
619  *      - This shall be invoked by schedulars.
620  *
621  *  @param[in]  RgSchUeCb    *ue
622  *
623  *  @return  None
624  *
625  */
626
627 Void rgSCHCmnHdFddChkNackAllow(RgSchCellCb *cellCb,RgSchUeCb *ueCb,CmLteTimingInfo  timeInfo,Bool *sndNACK)
628 {
629    RgSchDlSf *sf;
630    CmLteTimingInfo  tempTimeInfo;
631
632    /* Information in timeInfo contains (n+DL_DELTA) th subframe info*/
633
634    *sndNACK = FALSE;
635
636    /* Determine SFN and sf index for current subframe.
637       Note: Round function used as example */
638    tempTimeInfo = timeInfo;
639    RGSCH_INCR_SUB_FRAME(tempTimeInfo, RG_SCH_CMN_HARQ_INTERVAL);
640
641    /* Also get subframe pointer to fetch Common Ch allocation */
642    sf = rgSCHUtlSubFrmGet(cellCb, tempTimeInfo);
643
644    /* Check is this subframe has any Common Channel info scheduled */
645    if(RG_SCH_HDFDD_ISCMN_SCHED(sf))
646    {
647       /* Yes, Cannot send NACK */
648       DU_LOG("\nERROR  -->  SCH : rgSCHCmnHdFddChkNackAllow: Cannot send NACK, ueId = %d ",
649                ueCb->ueId);
650       *sndNACK = FALSE;
651    }
652    else
653    {
654       /* safe, Send NACK */
655       DU_LOG("\nDEBUG  -->  SCH : rgSCHCmnHdFddChkNackAllow: NACk can be sent, ueId = %d ",
656                ueCb->ueId);
657       *sndNACK = TRUE;
658    }
659
660    return;
661 } /* rgSCHCmnHdFddChkNackAllow */
662
663
664
665
666  /* @brief makes final marking for HD-FDD UL allocations
667  *
668  * @details
669  *
670  *     Function : rgSCHCmnHdFddUpdULMark
671  *
672  *     Invoking Module Processing:
673  *      - This shall be invoked by schedulars at the time of UL allocation
674  *        finalization.
675  *
676  *     Processing Steps:
677  *   
678  *  @param[in]  RgSchCellCb  *cellCb
679  *  @param[in]  RgSchUeCb    *ueCb
680  *  @param[in]  CmLteTimingInfo    *timeInfo
681  *  @param[out] uint8_t *allow -- TRUE is allowed or FALSE if no allowedi.
682  *             Valdity of this pointer is not done in this function.
683  *
684  *  @return  None
685  */
686 Void rgSCHCmnHdFddUpdULMark(RgSchCellCb *cellCb,RgSchUeCb   *ueCb)
687 {
688
689    uint16_t sfn;
690    uint16_t sfi;
691    CmLteTimingInfo  timeInfo;
692    uint8_t   ulOffset;
693
694    ulOffset = RGSCH_PDCCH_PUSCH_DELTA - 
695               TFU_CRCIND_ULDELTA + RGSCH_PDCCH_PUSCH_DELTA;
696    RG_SCH_ADD_TO_CRNT_TIME(cellCb->crntTime, timeInfo, ulOffset)
697
698
699    /* Mark (n + UL_DELTA)th subframe as UL */
700    sfn = timeInfo.sfn;
701    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
702
703    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_UL, sfn, sfi);
704
705    /* Mark (n + UL_DELTA + HARQ_DELTA)th subframe as DL */
706    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
707    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
708    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
709
710    /* Mark (n + UL_DELTA - HARQ_DELTA)th subframe as DL */
711    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (0-RG_SCH_CMN_HARQ_INTERVAL));
712    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (0-RG_SCH_CMN_HARQ_INTERVAL));
713    if (ueCb->hdFddCb->subfrm[sfi].subFrmDir != RG_SCH_HDFDD_DLDATA)
714    {
715       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
716    }
717
718    /* Mark (n + UL_DELTA - 1)th subframe as DL_CNTRL */
719    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, -RG_SCH_HDFDD_GRDTIM_DUR);
720    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, -RG_SCH_HDFDD_GRDTIM_DUR);
721    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
722
723    /* Remove marking for older subframes */
724
725    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (S16)(ulOffset * -1));
726    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (ulOffset * -1));
727    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_NOSCHD, RG_SCH_HDFDD_INVSFN, sfi);
728
729    return;
730 } /* rgSCHCmnHdFddUpdULMark */
731
732
733
734
735  /* @brief makes final marking for HD-FDD DL allocations
736  *
737  * @details
738  *
739  *     Function : rgSCHCmnHdFddUpdDLMark
740  *
741  *     Invoking Module Processing:
742  *      - This shall be invoked by schedulars at the time of DL allocation
743  *          finalization.
744  *
745  *     Processing Steps:
746  *   
747  *  @param[in]  RgSchCellCb  *cellCb
748  *  @param[in]  RgSchUeCb    *ueCb
749  *  @param[in]  CmLteTimingInfo    *timeInfo
750  *  @param[out] uint8_t *allow -- TRUE is allowed or FALSE if no allowed.
751  *                Valdity of this pointer is not done in this function
752  *
753  *  @return  None
754  */
755
756 Void rgSCHCmnHdFddUpdDLMark(RgSchCellCb *cellCb,RgSchUeCb *ueCb)
757 {
758
759    uint16_t sfn;
760    uint16_t sfi;
761    CmLteTimingInfo  timeInfo;
762
763    timeInfo = cellCb->crntTime;
764    RGSCH_INCR_SUB_FRAME(timeInfo, RG_SCH_CMN_DL_DELTA);
765
766    /* Mark (n + DL_DELTA)th subframe as DL */
767    sfn = timeInfo.sfn;
768    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
769
770    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, sfn, sfi);
771
772    /* Mark (n + 1)th subframe as DL_CNTRL */
773    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
774    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
775    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
776
777    /* Mark (n + DL_DELTA + HARQ_DELTA )th subframe as UL */
778    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
779    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
780    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_UL, sfn, sfi);
781
782    /* Mark (n + DL_DELTA + HARQ_DELTA - 1)th subframe
783       as DL control for Guard period */
784    RG_SCH_HDFDD_GETSFN(sfn, timeInfo,
785           (RG_SCH_CMN_HARQ_INTERVAL - RG_SCH_HDFDD_GRDTIM_DUR));
786    RG_SCH_HDFDD_GETSFI(sfi, timeInfo,
787          (RG_SCH_CMN_HARQ_INTERVAL - RG_SCH_HDFDD_GRDTIM_DUR));
788    if (ueCb->hdFddCb->subfrm[sfi].subFrmDir != RG_SCH_HDFDD_UL)
789    {
790       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
791    }
792
793    return;
794 } /* rgSCHCmnHdFddUpdDLMark */
795
796
797  /* @brief determines effective SFN
798  *
799  * @details
800  *
801  *     Function : rgSCHHdFddGetSfn
802  *
803  *     Invoking Module Processing:
804  *       Any HD-FDD module can invoke this function.
805  *
806  *     Processing Steps:
807  *   
808  *  @param[out]  *sfn uint32_t
809  *  @param[in]  timeInfo timing information subframe of interest 
810  *  @param[in]  offsest  Offest with w.r.t which SFN has to be determined
811  *
812  *  @return  None
813  */
814
815 Void rgSCHHdFddGetSfn(uint16_t *sfn,CmLteTimingInfo  timeInfo,S16 offset)
816 {
817    uint16_t tempSfn;
818    S16 tempSfCount;
819
820    if(((S16)(timeInfo.subframe) + offset) >= RGSCH_NUM_SUB_FRAMES)
821    {
822       /* Increament to number of times of SFNs that can be possible
823          with this offset */
824       tempSfn = (timeInfo.sfn +
825                 ((timeInfo.subframe + offset) / RGSCH_NUM_SUB_FRAMES))
826                 & (RGSCH_MAX_SFN -1); /* Mod with MAX SFN supported */
827    }
828    else
829    {
830       if(((S16)(timeInfo.subframe) + offset) < 0)
831       {
832          /* If negative, then definitely at least previous SFN */
833          tempSfn = (timeInfo.sfn - 1) & (RGSCH_MAX_SFN -1);
834
835          /* Now find how many more times we need to decreament */
836          tempSfCount = timeInfo.subframe + offset;
837          RG_SCH_HDFDD_ROLLSFN(tempSfCount, tempSfn);
838       }
839       else
840       {
841          /* No change in sfn */
842          tempSfn = timeInfo.sfn;
843       }
844    }
845    *sfn = tempSfn;
846
847    return;
848 } /* End of rgSCHHdFddGetSfn */
849
850
851 #ifdef __cplusplus
852 }
853  /* extern C */
854 #endif /* __cplusplus */
855
856 #endif /* LTEMAC_HDFDD */
857
858
859
860
861 /**********************************************************************
862  
863          End of file
864 **********************************************************************/