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