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