/******************************************************************************/
// @copyright   Copyright Notification
//   No part may be reproduced except as authorized by written permission.
//   The copyright and the foregoing restriction extend to reproduction in all media.
//   Trademark 2010, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC).
//   All rights reserved.
// @version: IWD_10wk37
// $Date: 2010-09-06 18:31:12 +0200 (Mon, 06 Sep 2010) $
// $Rev: 3822 $
/******************************************************************************/

module EUTRA_ConfigurationSteps {

  //=========================================================================
  // Import Part
  //=========================================================================

  import from EUTRA_RRC_ASN1_Definitions language "ASN.1:1997" all;
  import from CommonDefs all;
  import from EUTRA_ASP_TypeDefs all;
  import from EUTRA_DRB_Templates all;
  import from EUTRA_Component all;
  import from EUTRA_CommonDefs all;
  import from EUTRA_CellInfo all;
  import from EUTRA_SRB_Templates all;
  import from EUTRA_CellCfg_Templates all;
  import from EUTRA_AspCommon_Templates all;

  //------------------------------------------------------------------------------------------
  // basic functions:

  /*
   * @desc      Readio Bearer configuration
   * @param     p_CellId
   * @param     p_RadioBearerList
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @status    APPROVED
   */
  function f_EUTRA_SS_CommonRadioBearerConfig(CellId_Type p_CellId,
                                              template (value) RadioBearerList_Type p_RadioBearerList,
                                              template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now) runs on EUTRA_PTC
  { /* @sic R5s100135 sic@ */
    var boolean v_CnfFlag;
    if (match(valueof(p_TimingInfo), cs_TimingInfo_Now)) {
      v_CnfFlag := tsc_CnfReq;
    } else {
      v_CnfFlag := tsc_NoCnfReq;
    }
    SYS.send(cas_CommonRadioBearerConfig_REQ(p_CellId, p_TimingInfo, p_RadioBearerList, v_CnfFlag));
    if (v_CnfFlag == tsc_CnfReq) {
      SYS.receive(car_CommonRadioBearerConfig_CNF(p_CellId));
    }
  }

  /*
   * @desc      Readio Bearer configuration for one DRB
   * @param     p_CellId
   * @param     p_RadioBearer
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @status    APPROVED
   */
  function f_EUTRA_SS_CommonRadioBearerConfig_SingleDRB(CellId_Type p_CellId,
                                                        template (value) RadioBearer_Type p_RadioBearer,
                                                        template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now) runs on EUTRA_PTC
  { /* @sic R5s100072 sic@ */
    var template (value) RadioBearerList_Type v_RadioBearerList := { p_RadioBearer };
    f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_RadioBearerList, p_TimingInfo);
  }

  /*
   * @desc      Cell Configuration
   * @param     p_CellId
   * @param     p_SYSTEM_CTRL_REQ
   * @status    APPROVED
   */
  function f_EUTRA_SS_CommonCellConfig(CellId_Type p_CellId,
                                       template (value) SYSTEM_CTRL_REQ p_SYSTEM_CTRL_REQ) runs on EUTRA_PTC
  {
    SYS.send( p_SYSTEM_CTRL_REQ );
    if (valueof(p_SYSTEM_CTRL_REQ.Common.ControlInfo.CnfFlag) == true) {  /* @sic R5s100135 sic@ */
      SYS.receive ( car_CellConfig_CNF ( p_CellId ) );
    }
  }

  /*
   * @desc      Cell Configuration: enable/disable L1 and MAC indications
   * @param     p_CellId
   * @param     p_SYSTEM_CTRL_REQ
   * @status    APPROVED
   */
  function f_EUTRA_SS_CommonL1MacIndCtrlConfig(CellId_Type p_CellId,
                                               template (value) SYSTEM_CTRL_REQ p_SYSTEM_CTRL_REQ) runs on EUTRA_PTC
  {
    SYS.send( p_SYSTEM_CTRL_REQ );
    if (valueof(p_SYSTEM_CTRL_REQ.Common.ControlInfo.CnfFlag) == true) {
      SYS.receive ( car_SYSTEM_CTRL_L1MACInd_CNF( p_CellId ) );
    }
  }

  //----------------------------------------------------------------------------
  // SRB Configuration

  /*
   * @desc      SRB Configuration
   * @param     p_CellId
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @status    APPROVED
   */
  function f_EUTRA_SS_ConfigureSRBs(CellId_Type p_CellId,
                                    template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now) runs on EUTRA_PTC
  { /* @sic R5s100072 sic@ */
    var template (value) RadioBearerList_Type v_SrbList := {
      cs_SRB0_ConfigDef,
      cs_SRB1_ConfigDef,
      cs_SRB2_ConfigDef
    };
    f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_SrbList, p_TimingInfo);
  };

  /*
   * @desc      SRB Configuration
   * @param     p_CellId
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @status    (APPROVED)
   */
  function f_EUTRA_SS_ReleaseSRBs(CellId_Type p_CellId,
                                  template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now) runs on EUTRA_PTC
  { /* @sic R5s100072 sic@ */
    var template (value) RadioBearerList_Type v_SrbList := {
      cs_SRB_Release(tsc_SRB0),
      cs_SRB_Release(tsc_SRB1),
      cs_SRB_Release(tsc_SRB2)
    };
    f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_SrbList, p_TimingInfo);
  };

  //----------------------------------------------------------------------------
  // DRB Configuration

  /*
   * @desc      DRB Configuration
   * @param     p_CellId
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @status    APPROVED
   */
  function f_EUTRA_SS_DRB1_DefConfig ( CellId_Type  p_CellId,
                                       template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now) runs on EUTRA_PTC
  { /* @sic R5s100072 sic@ */
    var template (value) RadioBearerList_Type v_DrbList := {
      cs_OneDRB_ConfigAM(tsc_DRB1)
    };

    f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_DrbList, p_TimingInfo);
  }

  /*
   * @desc      DRB Configuration
   * @param     p_CellId
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @status    (APPROVED)
   */
  function f_EUTRA_SS_DRB1_Release ( CellId_Type  p_CellId,
                                     template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now) runs on EUTRA_PTC
  { /* @sic R5s100072 sic@ */
    var template (value) RadioBearerList_Type v_DrbList := {
      cs_DRB_Release(tsc_DRB1)
    };

    f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_DrbList, p_TimingInfo);
  }

  /*
   * @desc      generic configuration for multiple DRBs;
   *            configures additional DRBs; it is assumed that DRB1 is reverved for the default bearer which is already configured
   * @param     p_CellId
   * @param     p_NoOfAddDRBs_AM
   * @param     p_NoOfAddDRBs_UM
   * @status    APPROVED
   */
  function f_EUTRA_SS_DRB_AddConfig ( CellId_Type  p_CellId,
                                      integer p_NoOfAddDRBs_AM,
                                      integer p_NoOfAddDRBs_UM) runs on EUTRA_PTC
  {
    var template (value) RadioBearerList_Type v_DRB_ToAddModList;
    var integer v_DRB_Id;
    var integer n, m;

    if (p_NoOfAddDRBs_AM + p_NoOfAddDRBs_UM > 0) {          // @sic R5s100100 sic@
      v_DRB_Id := tsc_DRB1 + 1;                             // DRB1 is the default bearer
      for (n := 0; n < p_NoOfAddDRBs_AM; n := n + 1) {
        v_DRB_ToAddModList[n] := cs_OneDRB_ConfigAM(v_DRB_Id);
        v_DRB_Id := v_DRB_Id + 1;
      }
      for (m := 0; m < p_NoOfAddDRBs_UM; m := m + 1) {
        v_DRB_ToAddModList[n+m] := cs_OneDRB_ConfigUM(v_DRB_Id);
        v_DRB_Id := v_DRB_Id + 1;
      }
      
      f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_DRB_ToAddModList);
    }
  };

  //----------------------------------------------------------------------------
  /*
   * @desc      Release SRB[0..2] and all given DRBs
   * @param     p_CellId
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @param     p_DrbList            (default value: tsc_DrbList_Def)
   * @status    APPROVED
   */
  function f_EUTRA_SS_SRBs_DRBs_Release ( CellId_Type  p_CellId,
                                          template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now,
                                          DRB_IdentityList_Type p_DrbList := tsc_DrbList_Def ) runs on EUTRA_PTC
  {
    var template (value) RadioBearerList_Type v_SrbDrbList := {
      cs_SRB_Release(tsc_SRB0),
      cs_SRB_Release(tsc_SRB1),
      cs_SRB_Release(tsc_SRB2)
    };
    var integer i := lengthof(v_SrbDrbList);
    var integer k;
    
    for (k:=0; k < lengthof(p_DrbList); k:= k+1) {
      v_SrbDrbList[i+k] := cs_DRB_Release(p_DrbList[k]);    /* @sic R5s100279 change 1 sic@ */
    }

    f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_SrbDrbList, p_TimingInfo);
  }
 
  /*
   * @desc      Configure SRB[0..2] and given DRBs
   * @param     p_CellId
   * @param     p_TimingInfo         (default value: cs_TimingInfo_Now)
   * @param     p_DrbConfigList      (default value: cs_DrbConfigList_Def)
   * @status    APPROVED
   */
  function f_EUTRA_SS_SRBs_DRBs_Config ( CellId_Type  p_CellId,
                                         template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now,
                                         template (value) RadioBearerList_Type p_DrbConfigList := cs_DrbConfigList_Def ) runs on EUTRA_PTC
  {
    var template (value) RadioBearerList_Type v_SrbDrbList := {
      cs_SRB0_ConfigDef,
      cs_SRB1_ConfigDef,
      cs_SRB2_ConfigDef
    };
    var integer i := lengthof(v_SrbDrbList);
    var integer k;
    
    for (k:=0; k < lengthof(p_DrbConfigList); k:= k+1) {
      v_SrbDrbList[i+k] := p_DrbConfigList[k];          /* @sic R5s100279 change 2 sic@ */
    }

    f_EUTRA_SS_CommonRadioBearerConfig(p_CellId, v_SrbDrbList, p_TimingInfo);
  }
  
  /*
   * @desc      Reset SRB[0..2] and default DRB
   * @param     p_CellId
   * @status    APPROVED
   */
  function f_EUTRA_SS_SRBs_DRB1_ResetNow ( CellId_Type  p_CellId ) runs on EUTRA_PTC
  { /* Note: this function shall use timing info "Now" only otherwise between release and config there have to be at least 5ms */
    f_EUTRA_SS_SRBs_DRBs_Release ( p_CellId );
    f_EUTRA_SS_SRBs_DRBs_Config ( p_CellId );
  }
  
  //----------------------------------------------------------------------------
  // Cell configurations:

  /*
   * @desc      create cell and send out system information
   * @param     p_CellId
   * @status    APPROVED
   */
  function f_EUTRA_CellConfig_Def (CellId_Type p_CellId) runs on EUTRA_PTC
  {
    f_EUTRA_SS_ConfigureActiveCell(  p_CellId );
    f_EUTRA_SS_ConfigureSRBs ( p_CellId );
    f_EUTRA_SS_DRB1_DefConfig ( p_CellId );
  };

  /*
   * @desc      create cell and send out system information: default configuration (SRBs + default DRB) + additional DRBs
   * @param     p_CellId
   * @param     p_NoOfAddDRBs_AM
   * @param     p_NoOfAddDRBs_UM
   * @status    APPROVED
   */
  function f_EUTRA_CellConfig_DRB_Common (CellId_Type p_CellId,
                                          integer p_NoOfAddDRBs_AM,
                                          integer p_NoOfAddDRBs_UM) runs on EUTRA_PTC
  {
    f_EUTRA_CellConfig_Def(p_CellId);
    f_EUTRA_SS_DRB_AddConfig(p_CellId, p_NoOfAddDRBs_AM, p_NoOfAddDRBs_UM);
  };

  /*
   * @desc      create cell and send out system information
   * @param     p_CellId
   * @status    APPROVED
   */
  function f_EUTRA_CellConfig_DefPlusUM (CellId_Type p_CellId) runs on EUTRA_PTC
  {
    f_EUTRA_CellConfig_Def ( p_CellId );
    f_EUTRA_SS_CommonRadioBearerConfig_SingleDRB(p_CellId, cs_OneDRB_ConfigUM(tsc_DRB2));
  };

  /*
   * @desc      create cell with SRBs being preconfigured
   * @param     p_CellId
   * @status    APPROVED
   */
  function f_EUTRA_CellConfig_SRBs_Only (CellId_Type p_CellId) runs on EUTRA_PTC
  {
    // create cell and send out system information
    f_EUTRA_SS_ConfigureActiveCell ( p_CellId );
    f_EUTRA_SS_ConfigureSRBs ( p_CellId );
  };

  //----------------------------------------------------------------------------
  /*
   * @desc      extract scheduling info from SIB1; => whenever SIB scheduling is setup or changed
   *            this function returns required SS configuration
   * @param     p_SIB1
   * @param     p_FDD_TDD
   * @return    template (value) AllSiSchedul_Type
   * @status    APPROVED
   */
  function f_EUTRA_SS_SetupSchedulingInfo(  SystemInformationBlockType1 p_SIB1,
                                            EUTRA_FDD_TDD_Mode_Type  p_FDD_TDD )
    return template (value) AllSiSchedul_Type
  {
    var template (value) SiSchedulList_Type v_SiSchedulList;
    var integer v_NoOfSIs := lengthof(p_SIB1.schedulingInfoList);     // TTCN-3 3.4.1: sizeof replaced by lengthof
    var integer v_SubframeOffset;                          /* offset within the SI-window */
    var integer v_RV := 2;                                 /* @sic R5s100302 change 9 sic@ */
    var integer I;
    
    for (I := 0; I < v_NoOfSIs; I:= I + 1) {
      /* Assigne the subframe offset according to 36.523-3 Table 7.7.2.2;
         mapping of the SIBs to the SIs is specified in 36.508 cl. 4.4.3.1.2 "Scheduling of system information blocks"
         => there is a maximum of 4 SIs */
     select (p_FDD_TDD) {
        case (FDD) {
          select (I) {
            case (0) {   // Subframe offset for SI1
              v_SubframeOffset := 1;
            }
            case (1) { // Subframe offset for SI2
              v_SubframeOffset := 1;
            }
            // R5-096691: 3 -> 1
            case (2) { // Subframe offset for SI3
              v_SubframeOffset := 3;
              v_RV := 1;                /* @sic R5s100302 change 9 sic@ */
            }
            case (3) {   // Subframe offset for SI4
              v_SubframeOffset := 7;
              v_RV := 3;                /* @sic R5s100302 change 9 sic@ */
            }
            case else {  FatalError (__FILE__, __LINE__, "No subframe offset defined for that SI"); }
          }
        }
       case (TDD) {  // R5-096691
         select (I) {
           case (0) { // Subframe offset for SI1
             v_SubframeOffset := 4;
           }
           case (1) { // Subframe offset for SI2
             v_SubframeOffset := 4;
           }
           case (2) { // Subframe offset for SI3
             v_SubframeOffset := 9;
           }
           case (3) {
             v_SubframeOffset := 9;
           }  // Subframe offset for SI4
           case else {  FatalError (__FILE__, __LINE__, "No subframe offset defined for that SI"); }
         }
       }
    }
     v_SiSchedulList[I] := cs_SiSchedul_Def(p_SIB1.schedulingInfoList[I].si_Periodicity, v_SubframeOffset);
     /* @sic R5s100302 change 9 sic@ */
     if (match ( dci_1C, v_SiSchedulList[I].Window[0].DciInfo.Format) ) {
       v_SiSchedulList[I].Window[0].DciInfo.RedundancyVersionList[0] := v_RV;
     }
    }
    return cs_SiSchedulList_Def(p_SIB1.si_WindowLength, v_SiSchedulList);
  }
  
  //----------------------------------------------------------------------------
  /*
   * @desc      basic cell configuration (active cell)
   * @param     p_CellId
   * @status    APPROVED
   */
  function f_EUTRA_SS_ConfigureActiveCell(CellId_Type p_CellId) runs on EUTRA_PTC
  {
    var EUTRA_CellInfo_Type v_CellInfo:= f_EUTRA_CellInfo_Get (p_CellId);
    var template (value) AllSiSchedul_Type    v_SiSchedul;
    //Get FDD or TDD mode from Cell-configuration
    var EUTRA_FDD_TDD_Mode_Type  v_EUTRA_FDD_TDD_Mode:=f_EUTRA_CellInfo_GetFDD_TDD (p_CellId);

    var template (value) StaticCellInfo_Type v_StaticCellInfo;

    v_SiSchedul := f_EUTRA_SS_SetupSchedulingInfo(v_CellInfo.Sysinfo.BCCH_Info.SIB1.message_.c1.systemInformationBlockType1, v_EUTRA_FDD_TDD_Mode);      /* derive SS's scheduling information from SIB1 */
    select (v_EUTRA_FDD_TDD_Mode) {
      case (FDD) {
        v_StaticCellInfo := cs_StaticCellInfo_FDD(v_CellInfo.CellIds.PhysicalCellId,
                                                  v_CellInfo.Frequency.FrequencyBandIndicator,
                                                  v_CellInfo.Frequency.UL_DL_Earfcn.dl_CarrierFreq,
                                                  v_CellInfo.Frequency.UL_DL_Earfcn.ul_CarrierFreq,
                                                  v_CellInfo.Frequency.DL_ChBandwidth,
                                                  v_CellInfo.Frequency.UL_ChBandwidth,
                                                  v_CellInfo.CellTimingInfo.Tcell,       /* @sic R5s100029 change 3 sic@ */
                                                  v_CellInfo.CellTimingInfo.SfnOffset);  /* @sic R5s100029 change 3 sic@ */
      }

      case (TDD) {
        v_StaticCellInfo := cs_StaticCellInfo_TDD (v_CellInfo.CellIds.PhysicalCellId,
                                                   v_CellInfo.Frequency.FrequencyBandIndicator,
                                                   v_CellInfo.Frequency.UL_DL_Earfcn.dl_CarrierFreq,
                                                   v_CellInfo.Frequency.DL_ChBandwidth, // @sic R5s100190 sic@
                                                   v_CellInfo.CellTimingInfo.Tcell,   // @sic R5s100513 sic@
                                                   v_CellInfo.CellTimingInfo.SfnOffset,   // @sic R5s100513 sic@
                                                   v_CellInfo.Sysinfo.BCCH_Info.SIB1.message_.c1.systemInformationBlockType1.tdd_Config);
      }
    }

    f_EUTRA_SS_CommonCellConfig(p_CellId, cas_CellConfig_Def_REQ(p_CellId,
                                                                 cs_TimingInfo_Now,
                                                                 v_StaticCellInfo,
                                                                 v_SiSchedul,
                                                                 v_CellInfo));
    if (f_TestcaseIsL2Testcase()) {     /* @sic R5s100135 sic@ */
      f_EUTRA_SS_CommonL1MacIndCtrlConfig(p_CellId, cas_HarqErrorIndication_REQ(p_CellId));
    }
  };

  /*
   * @desc      Function to Config/Reconfig Active cell info of a cell
   *            For example new C-RNTI
   * @param     p_CellId
   * @param     p_TimingInfo
   * @param     p_ActiveCellConfig
   * @status    APPROVED
   */
  function f_SS_ConfigActiveCellInfo (CellId_Type p_CellId,
                                      template (value) TimingInfo_Type p_TimingInfo,
                                      template (value) ActiveCellConfig_Type p_ActiveCellConfig) runs on EUTRA_PTC
  {
    f_EUTRA_SS_CommonCellConfig(p_CellId, cas_ActiveCellConfig_REQ ( p_CellId, p_TimingInfo, p_ActiveCellConfig ));
  };

  //============================================================================
  // Function to Config SS for reporting Preamble Reception
  //----------------------------------------------------------------------------

  /*
   * @desc      To configure SS to start or stop reporting indication of Rach preamble
   * @param     p_CellId
   * @param     p_RachPreambleMode
   * @status    APPROVED
   */
  function f_EUTRA_SS_ConfigRachPreambleIndMode (CellId_Type p_CellId,
                                                 L1Mac_IndicationMode_Type p_RachPreambleMode) runs on EUTRA_PTC
  {
    f_EUTRA_SS_CommonL1MacIndCtrlConfig(p_CellId, cas_RachPreambleIndConfig_REQ (p_CellId, p_RachPreambleMode));
  };

  //============================================================================
  // Function to config special RACH Response
  //----------------------------------------------------------------------------
  /*
   * @desc      Function to config special RACH Response
   * @param     p_CellId
   * @param     p_CRNTI
   * @param     p_RachProcedureConfig
   * @param     p_TimingInfo        (default value: cs_TimingInfo_Now)
   * @status    APPROVED
   */
  function f_EUTRA_SS_ConfigRachProcedure(CellId_Type p_CellId,
                                          template (omit) C_RNTI p_CRNTI,
                                          template (value) RachProcedureConfig_Type p_RachProcedureConfig,
                                          template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now  // @sic R5s100178 sic@
                                          ) runs on EUTRA_PTC
  {
    f_EUTRA_SS_CommonCellConfig(p_CellId, cas_RachProcedureConfig_REQ(p_CellId, p_CRNTI, p_RachProcedureConfig, p_TimingInfo));
  };

  //============================================================================
  // Function to set cell power level
  //----------------------------------------------------------------------------
  /*
   * @desc      calculate new attenuation for a cell based on the previous attenuation and the given absolute cell power;
   *            the attenuation is written back to the global TTCN-3 EUTRA_CellInfo but no configuration is performed at SS
   * @param     p_CellId
   * @param     p_NewPowerLevel   absolute (negative) value as specified in the test prose
   * @return    Attenuation_Type
   * @status    APPROVED
   */
  function fl_EUTRA_ChangeCellAttenuation(CellId_Type p_CellId,
                                          AbsoluteCellPower_Type p_NewPowerLevel) runs on EUTRA_PTC return Attenuation_Type
  {
    var ReferenceCellPower_Type v_CurrentCellPower := f_EUTRA_CellInfo_GetCellPower( p_CellId );
    var AbsoluteCellPower_Type v_CurrentRefPowerLevel := v_CurrentCellPower.MaxReferencePower;
    var Attenuation_Type v_Attenuation;
    var integer v_AttenuationValue;

    if ( p_NewPowerLevel == tsc_NonSuitableOffCellRS_EPRE ) {
      v_Attenuation.Off := true;
    } else {
      v_AttenuationValue := v_CurrentRefPowerLevel - p_NewPowerLevel;  // v_CurrentRefPowerLevel and p_NewPowerLevel both are negative values

      if (v_AttenuationValue < 0) {  // i.e. |p_NewPowerLevel| < |v_CurrentRefPowerLevel|
        FatalError (__FILE__, __LINE__, "Initial reference power has invalid value");
      } else {
        v_Attenuation.Value := v_AttenuationValue;
      }
    }

    v_CurrentCellPower.Attenuation := v_Attenuation;
    f_EUTRA_CellInfo_SetCellPower ( p_CellId, v_CurrentCellPower );

    return v_Attenuation;
  }

  type record CellPower_Type {                  /* @status    APPROVED */
    CellId_Type CellId,
    AbsoluteCellPower_Type NewPowerLevel
  };
  type record length(1..tsc_EUTRA_MaxNumberOfCells) of CellPower_Type CellPowerList_Type;       /* used together with f_EUTRA_SetCellPowerList
                                                                                                   @status    APPROVED */

  template (value) CellPower_Type cs_CellPower(CellId_Type p_CellId,
                                               AbsoluteCellPower_Type p_NewPowerLevel) :=
  { /* @status    APPROVED */
    CellId := p_CellId,
    NewPowerLevel := p_NewPowerLevel
  };

  /*
   * @desc      to configure power of several cells in one go
   * @param     p_CellPowerList
   * @param     p_TimingInfo
   * @status    APPROVED
   */
  function f_EUTRA_SetCellPowerList ( template (value) CellPowerList_Type p_CellPowerList,
                                      template (value) TimingInfo_Type p_TimingInfo ) runs on EUTRA_PTC
  {
    var integer i;
    var CellPower_Type v_CellPower;
    var CellAttenuationList_Type v_CellAttenuationList;

    for (i:=0; i<lengthof(p_CellPowerList); i:=i+1) {
      v_CellPower := valueof(p_CellPowerList[i]);   // valueof cannot be avoided here
      v_CellAttenuationList[i].CellId := v_CellPower.CellId;
      v_CellAttenuationList[i].Attenuation := fl_EUTRA_ChangeCellAttenuation(v_CellPower.CellId, v_CellPower.NewPowerLevel);
    }

    SYS.send( cas_CellConfig_Power_REQ ( v_CellAttenuationList, p_TimingInfo ) );
    SYS.receive ( car_CellConfig_Power_CNF );

  }

  /*
   * @desc      Sets the cell power attenuation and stores the value in the EUTRA_CellInfo
   * @param     p_CellId
   * @param     p_NewPowerLevel   absolute (negative) value as specified in the test prose
   * @param     p_TimingInfo
   * @status    APPROVED
   */
  function f_EUTRA_SetCellPower ( CellId_Type p_CellId,
                                  AbsoluteCellPower_Type p_NewPowerLevel,
                                  template (value) TimingInfo_Type p_TimingInfo ) runs on EUTRA_PTC
  {
    var template (value) CellPowerList_Type v_CellPowerList := { cs_CellPower(p_CellId, p_NewPowerLevel) };
    f_EUTRA_SetCellPowerList ( v_CellPowerList, p_TimingInfo );
  }


  //============================================================================
  // Functions to deal with different modes for Timing Alignment Period
  // (PUCCH synchronisation)
  //----------------------------------------------------------------------------

  /*
   * @desc      returns template acc. to the global TimingAdvancePeriod
   * @return    template (value) PUCCH_Synch_Type
   * @status    APPROVED
   */
  function f_EUTRA_PUCCH_Synch_Auto() runs on EUTRA_PTC return template (value) PUCCH_Synch_Type
  {
    var TimingAdvance_Period_Type v_TimingAdvance_Period;
    if (f_EUTRA_TimingAdvancePeriodMode_Get() == normal) {
      v_TimingAdvance_Period := tsc_TA_Period_Def;
    } else {
      v_TimingAdvance_Period := tsc_TA_Period_L2UM;
    }
    return cs_PUCCH_Synch_Auto_Def(v_TimingAdvance_Period);
  }

  //----------------------------------------------------------------------------
  /*
   * @desc      sets global variable in EUTRA_Component and configures SS accordingly
   * @param     p_CellId
   * @param     p_TimingAdvancePeriodMode
   * @param     p_TimingInfo        (default value: cs_TimingInfo_Now)
   * @status    APPROVED
   */
  function f_EUTRA_PUCCH_AutoSync_SetAndConfigure(CellId_Type p_CellId,
                                                  EUTRA_TimingAdvancePeriodMode_Type p_TimingAdvancePeriodMode,
                                                  template (value) TimingInfo_Type p_TimingInfo := cs_TimingInfo_Now) runs on EUTRA_PTC
  {
    var template (value) PUCCH_Synch_Type v_PUCCH_Synch;

    f_EUTRA_TimingAdvancePeriodMode_Set(p_TimingAdvancePeriodMode);  // global variable has to be set before calling f_EUTRA_PUCCH_Synch_Auto
    v_PUCCH_Synch := f_EUTRA_PUCCH_Synch_Auto();
    f_EUTRA_SS_CommonCellConfig(p_CellId, cas_PUCCH_Synch_Config_REQ(p_CellId, p_TimingInfo, v_PUCCH_Synch) );
  }
  
  //============================================================================
  // Function to start UL grant allocation and PUCCH synchronisation
  //----------------------------------------------------------------------------

  /*
   * @desc      starts UL grant transmission on SI reception
   *            configures SS to maintain UE in PUCCH synchronised state
   *            needs to be called when UE enters connected mode in a cell (after reception of RRCConnectionReq or HandoverComplete)
   * @param     p_CellId
   * @param     p_TimingInfo
   * @status    APPROVED
   */
  function f_EUTRA_StartDefULGrantTransmission ( CellId_Type p_CellId,
                                                 template (value) TimingInfo_Type p_TimingInfo ) runs on EUTRA_PTC
  {
    var template (value) PUCCH_Synch_Type v_PUCCH_Synch := f_EUTRA_PUCCH_Synch_Auto(); // @sic R5-101177, R5-101178, R5-101050 sic@
    f_EUTRA_SS_CommonCellConfig(p_CellId, cas_ULGrantAllocation_Def_REQ (p_CellId, p_TimingInfo, v_PUCCH_Synch) );
  };

  /*
   * @desc      stops UL grant transmission
   *            configures SS to not maintain UE in PUCCH synchronised state
   *            needs to be called when UE enters idle mode in a cell (after RRCConnectionRelease)
   * @param     p_CellId
   * @param     p_TimingInfo
   * @status    APPROVED
   */
  function f_EUTRA_StopULGrantTransmission ( CellId_Type p_CellId,
                                             template (value) TimingInfo_Type p_TimingInfo ) runs on EUTRA_PTC
  {
    f_EUTRA_SS_CommonCellConfig(p_CellId, cas_ULGrantAllocation_Stop_REQ (p_CellId,p_TimingInfo) );
  };

  //============================================================================
  /*
   * @desc      Common function to release all cells
   * @status    APPROVED
   */
  function f_EUTRA_ReleaseAllCells() runs on EUTRA_PTC
  { /* @sic R5-103847: new function to release all cells in one go (replacing f_EUTRA_ReleaseCells and f_EUTRA_ReleaseCell) sic@  */
    var CellId_Type v_CellId := eutra_Cell_NonSpecific;
    SYS.send ( cas_ReleaseCell_REQ(v_CellId, cs_TimingInfo_Now));
    // cas_ReleaseCell_REQ requires no confirmation
  }
}
