/******************************************************************************/
// @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-15 12:03:23 +0200 (Wed, 15 Sep 2010) $
// $Rev: 3890 $
/******************************************************************************/

module GERAN_CommonFunctions
{
  import from GERAN_TypeDefs all;
  import from GERAN_Component all;
  import from GERAN_Parameters all;
  import from UTRAN_Parameters all;
  import from CommonDefs all;
  import from NAS_CommonTypeDefs all;
  import from NAS_CommonTemplates all;
  import from NAS_24008TypeDefs all;
  import from GERAN_Templates all;
  import from NAS_24008Templates all;
  import from GERAN_CellInfo all;
  import from CommonIratDefs all;
  import from UpperTesterFunctions all;
  import from NAS_AuxiliaryDefsAndFunctions all;
  import from UTRANGERAN_CommonFunctions all;
  import from Parameters all;
  
  //----------------------------------------------------------------------------
  function f_GERAN_Send_IR_SysInfoToEUTRA ( GERAN_CellId_Type p_CellId ) runs on GERAN_PTC
  {
    var template (value) CoOrd_GERANSysInfo_Type v_CoOrdCellInfo;

    var GERAN_CellInfo_Type v_CellInfo := f_GERAN_CellInfo_Get ( p_CellId );

    var integer v_Arfcn := bit2int ( v_CellInfo.freq.bCCH_Freq );
    var CoOrd_GERANNeighCell_Type v_NeighCells := v_CellInfo.freq.arfcnList;
    var B3_Type v_Ncc := v_CellInfo.info.ncc;
    var B3_Type v_Bcc := v_CellInfo.info.bcc;
    var O2_Type v_Cell_Identity := f_GERAN_CellInfo_GetCellIdentity ( p_CellId );
    var B1_Type v_BandIndicator := v_CellInfo.freq.bandIndicator;

    v_CoOrdCellInfo := cs_CoOrdGERANSysInfo ( v_Arfcn, v_NeighCells, v_Ncc, v_Bcc, v_Cell_Identity, v_BandIndicator );

    f_SendIRATCoOrd ( EUTRA, cms_IRAT_SysInfo ( cs_CoOrdGERAN_SysInfoSingleCell ( v_CoOrdCellInfo ) ) );
  }
  //----------------------------------------------------------------------------

  function f_GERAN_CreateCell (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var B10_Type v_GPRSFreq := f_GERAN_GPRSFreq_Get(p_CellId);
    
    f_CreateCell_GSM_Comb (p_CellId);
    
    f_GERAN_CreatePhyGPRSCh (p_CellId,
                             cs_FreqInfoBCCH(v_GPRSFreq), cs_PacketChDescr(v_GPRSFreq));
    f_CreateRLC_MAC_Entity(p_CellId);
    f_Create_LLE_Entity(p_CellId);
    
    f_GERAN_SendGSMSysInfo(p_CellId);
    
  } // end of f_GERAN_CreateCell
  
  function f_GERAN_CreateCell_MinUL (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  { // This cell doesn't include GPRS so should only be used for Measurement/Idle Mode tests
    f_CreateCell_GSM_Comb (p_CellId);
    f_GERAN_SendGSMSysInfo(p_CellId);
    
  } // end of f_GERAN_CreateCell_MinUL
  
  group M_RAT_SysInfo {

  function f_GERAN_SendGSMSysInfo(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var GERAN_SystemInformation_Type v_SysInfo := f_GERAN_SysInfo_Get(p_CellId);
    
    G_L2.send(cas_SysInfo1(p_CellId, tsc_PhyCh0, v_SysInfo.si1));
    G_L2.send(cas_SysInfo2(p_CellId, tsc_PhyCh0, v_SysInfo.si2));
    G_L2.send(cas_SysInfo3(p_CellId, tsc_PhyCh0, v_SysInfo.si3));
    G_L2.send(cas_SysInfo4(p_CellId, tsc_PhyCh0, v_SysInfo.si4));
    G_L2.send(cas_SysInfo13(p_CellId, tsc_PhyCh0, '0'B, v_SysInfo.si13));
    
    G_L2.send(cas_SysInfo2quater(p_CellId, tsc_PhyCh0, 0, '0'B, v_SysInfo.si2quater_1));
    if (isvalue(v_SysInfo.si2quater_2)) {
      G_L2.send(cas_SysInfo2quater(p_CellId, tsc_PhyCh0, 1, '0'B, v_SysInfo.si2quater_2));
    }
    if (px_GERAN_BandUnderTest ==  GSM_P900 or  px_GERAN_BandUnderTest == GSM_E900 )
      {
      G_L2.send(cas_SysInfo2bis(p_CellId, tsc_PhyCh0, 0, v_SysInfo.si2bis));
      }
    else if ( px_GERAN_BandUnderTest == GSM710)
      {
        G_L2.send(cas_SysInfo15(p_CellId, tsc_PhyCh0, '0'B, v_SysInfo.si15));
      }
    else if ( px_GERAN_BandUnderTest == T_GSM810)
      {
        v_SysInfo.si15 := valueof(cs_SysInfoType15(cs_SI15_RO('0111'B)));
        G_L2.send(cas_SysInfo15(p_CellId, tsc_PhyCh0,  '0'B, v_SysInfo.si15));
      }
    
    f_GERAN_SysInfo_Set(p_CellId, v_SysInfo);
    
  }// end of f_SendGSMSysInfo
  
  function f_SendGSMSACCHSysInfo (GERAN_CellId_Type p_CellId, PhysicalChId p_PhyCh, G_LogicChType p_LogicChType) runs on GERAN_PTC
  {
    var GERAN_SystemInformation_Type v_SysInfo := f_GERAN_SysInfo_Get(p_CellId);
    
    G_L2.send(cas_SysInfo5(p_CellId, p_PhyCh, p_LogicChType, v_SysInfo.si5));
    G_L2.send(cas_SysInfo6(p_CellId, p_PhyCh, p_LogicChType, v_SysInfo.si6));
    if ((px_GERAN_BandUnderTest == GSM_P900 ) or ( px_GERAN_BandUnderTest == GSM_E900 ))
      {
        G_L2.send(cas_SysInfo5bis(p_CellId, p_PhyCh, p_LogicChType, v_SysInfo.si5bis));
      }
  }
  } //end of group M_RAT_SysInfo
  

  function f_Create_LLE_Entity(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    G_CLLC.send (cas_G_CLLC_CreateLLE_REQ (p_CellId));
    G_CLLC.receive (car_G_CLLC_Config_CNF);
  }// end of f_Create_LLE_Entity
  
  function f_CreateRLC_MAC_Entity(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    G_CRLC.send (cas_G_CRLC_CreateRLC_MAC_REQ(p_CellId ));
    G_CRLC.receive (car_G_RLC_Config_CNF);
  }// end of f_CreateRLC_MAC_Entity
  
  function f_CreateCell_GSM_Comb(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    // @desc Combined Cell Control Channel created with power level set to OFF
    var B3_Type v_NCC := f_GERAN_NCC_Get(p_CellId);
    var B3_Type v_BCC := f_GERAN_BCC_Get(p_CellId);
    var O1_Type v_TA := f_GERAN_TA_Get(p_CellId);
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get();
    
    f_SetBS_IdCode (p_CellId, v_NCC, v_BCC, v_TA);
    
    v_SecurityInfo.cipherMode.startingCiph := '0'B;
    f_GERAN_SecurityInfo_Set(v_SecurityInfo);
    
    f_GERAN_CreatePhyCombinedCellControlCh (p_CellId);
    f_SendGSMSACCHSysInfo (p_CellId, tsc_PhyCh0, SDCCH_4);
  }// end of f_CreateCell_GSM_Comb
  
  function f_SetBS_IdCode (GERAN_CellId_Type p_CellId, B3_Type p_NCC, B3_Type p_BCC, O1_Type p_TA) runs on GERAN_PTC
  {
    G_CL1.send (cas_G_CL1_CreateCell_REQ(p_CellId, p_NCC, p_BCC, p_TA));
    G_CL1.receive (car_G_CPHY_Config_CNF);
  } // end of f_SetBS_IdCode
  
  function f_GERAN_CreatePhyCombinedCellControlCh(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    // @desc Combined Cell Control Channel created with power level set to OFF
    var B10_Type v_BCCH := f_GERAN_BCCHFreq_Get(p_CellId);
    var B3_Type v_TSC := f_GERAN_TSC_Get (p_CellId);
    var O1_Type v_TA := f_GERAN_TA_Get(p_CellId);
    var B1_Type v_BandInd := f_GERAN_BandInd_Get(p_CellId);
    var B5_Type v_L1Pwr := '01111'B; // arbitrary value
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get();
    var ControlChDescr v_CtrlChDesc := f_GERAN_ControlChDesc_Get (p_CellId);
    var integer v_I;
    var template (value) ChannelSpecificInfo v_ChSpecific;
    
    v_ChSpecific := cs_ChSpecificPara(cs_SDCCH4_Ch(v_SecurityInfo.cipherMode, v_SecurityInfo.authCS.KcGSM, v_L1Pwr, oct2bit(v_TA)),
                                      cs_CCCH_Info(v_CtrlChDesc.bS_PA_MFRMS, v_CtrlChDesc.bS_AG_BLKS_RES));
    
    // FCCH + SCH + BCCH + CCCH + SDCCH/4(0..3) + SACCH/C4(0..3)
    G_CL1.send (cas_CombinedCellControlCh(p_CellId, tsc_PhyCh0, v_BCCH, v_TSC, v_ChSpecific, tsc_GERAN_ChPwrLvl_Off, v_BandInd));
    G_CL1.receive (car_G_CPHY_Config_CNF);
    // Now turn off Measurement Reports on SACCH/4
    for ( v_I := 0; v_I <4; v_I := v_I + 1)
      {
        G_CL1.send (cas_G_CL2_MeasRptControl_REQ(p_CellId, tsc_PhyCh0, SDCCH_4, v_I, false));
      }
    alt {
      []    G_CL1.receive (car_G_CPHY_Config_CNF)
        {
          if (v_I > 1)
            {
              v_I := v_I - 1;
              repeat;
            }
        }
    }
    
  } // end of f_GERAN_CreatePhyCombinedCellControlCh
  
  function f_GERAN_CreatePhyGPRSCh(GERAN_CellId_Type p_CellId, template (value) FreqInfo p_FreqInfo, template (value) PacketChDescr p_PktCh)  runs on GERAN_PTC
  {
    // @desc GPRS Channel created with power level set to OFF
    var B1_Type v_BandInd := f_GERAN_BandInd_Get(p_CellId);
    
    // PDTCH/F + PACCH/F + PTCCH/F
    G_CL1.send (cas_CreateGPRSCh(p_CellId, tsc_PhyCh1, p_FreqInfo, p_PktCh.tN, p_PktCh.tSC, tsc_GERAN_ChPwrLvl_Off, v_BandInd));
    G_CL1.receive (car_G_CPHY_Config_CNF);
  } // end of f_SS_CreatePhyGPRSCh
  
  //----------------------------------------------------------------------------
   /* @desc      To be called after GERAN_Init, before the test case body for every test that doesn't start in GERAN.
   *             This will wait until Preamble is finished on EUTRA and it has received the AuthParams
   *             These are then stored in SecurityInfo
   */
  function f_GERAN_InterRAT_InitialiseAuthParams () runs on GERAN_PTC
{
    var IRAT_Coordination_MSG v_RxdMsg;
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get();

    EUTRA.receive (cmr_IRAT_AuthInfo) -> value v_RxdMsg;
    
    v_SecurityInfo.authPS := v_RxdMsg.Authentication.AuthPS;
    v_SecurityInfo.authCS := v_RxdMsg.Authentication.AuthCS;
    
    f_GERAN_SecurityInfo_Set (v_SecurityInfo);
}
  //----------------------------------------------------------------------------
  //  @desc Procedure to be used as the pre-Preamble to set the PTMSI, PTMSI Sig and TMSI in the USIM
  function f_GERAN_Pre_Preamble (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    f_GERAN_SetCellPowerLevel (p_CellId, tsc_GERAN_ServingCell);
    f_UT_SwitchOnUE(UT, false);
    f_GERAN_IdleUpdated (p_CellId);
    f_GERAN_SwitchPowerOff (p_CellId);
    f_GERAN_SetCellPowerLevel (p_CellId, tsc_GERAN_ChPwrLvl_Off);

    // then tell EUTRA it can do it's preamble
    f_SendIRATCoOrd (EUTRA, cms_IRAT_Trigger);
    }
  //----------------------------------------------------------------------------
  //  @desc Procedure to be used in the test case preamble when UE should be brought to state
  //  Registered, Idle Mode (state 2) on an GERAN cell.
  function f_GERAN_Preamble (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    f_GERAN_SetCellPowerLevel (p_CellId, tsc_GERAN_ServingCell);
    f_UT_SwitchOnUE(UT, false);
    f_GERAN_IdleUpdated (p_CellId);
    
    // Now get the security parameters that have been updated and send to EUTRA
    f_GERAN_SendAuthParameters ();
    
  } // end of f_GERAN_Preamble
  
  //----------------------------------------------------------------------------
  function f_GERAN_SendAuthParameters () runs on GERAN_PTC {
    
    // Now get the security parameters that have been updated
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get ();
    var Common_AuthenticationParams_Type v_AuthCS := v_SecurityInfo.authCS;
    
    EUTRA.send (cms_IRAT_AuthInfo(v_SecurityInfo.authPS,
                                  v_AuthCS,
                                   omit));
                                   
  }
  //----------------------------------------------------------------------------
  function f_GERAN_IdleUpdated (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var SubChannelNumber v_SubChannel;
    var float v_Wait1S := f_UG_SetTimerToleranceMax(1.0);
    
    if (not pc_AutomaticAttachSwitchON)
      {
        if (not pc_G_operation_mode_C)
          {
            v_SubChannel := f_GERAN_LocationUpdate (p_CellId);
            // wait for the UE to relax
            f_Delay(v_Wait1S);
            
            f_GERAN_DisableCiphering(p_CellId, tsc_PhyCh0, SDCCH_4, v_SubChannel);
          }
        f_UT_TriggerAttach(UT);
      }
    f_GERAN_GPRSAttach(p_CellId);
  }//end of f_GERAN_IdleUpdated
  
  function f_GERAN_GPRSAttach(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var G_LLC_DATAMESSAGE_IND v_LLCDataInd;
    var B3_Type v_AttachType;
    var octetstring v_PLMN := f_GERAN_PLMN_Get(p_CellId);
    var O1_Type v_RAC := f_GERAN_RAC_Get(p_CellId);
    var O2_Type v_LAC := f_GERAN_LAC_Get(p_CellId);
    
    f_UplinkTBFOnePhase (p_CellId);
    alt { // Receive GPRS Attach Request Message
      []    G_LLC.receive(car_G_LLC_UnitData_IND ( cr_G_AttachReq (cr_AttachTypeAny,  cr_MobileIdAny (omit), cr_RAI_Any (omit), ?)))
        -> value v_LLCDataInd
        {
          v_AttachType := v_LLCDataInd.unit.msg.attReq.attachType.attachType;
          f_GERAN_SplitPGCycle_Set(p_CellId, v_LLCDataInd.unit.msg.attReq.drxParameter);
        }
    }
    f_GERAN_GPRS_Authentication (p_CellId);
    
    // Send GPRS Attach Accept
    f_DownlinkTBFEstablishment(p_CellId, 1);
    G_LLC.send(cas_G_LLC_UnitData_Req (f_GERAN_TLLI_Get(p_CellId), tsc_LLCSapi_GMM, tsc_LLC_PM, px_GSM_CipheringOnOff,
                                       cs_G_AttachAccept (cs_GMM_AttachResult(v_AttachType), cs_RAI(omit, cs_LAI(omit, v_PLMN, v_LAC), v_RAC),
                                                          cs_PTMSI_Signature (px_PTMSI_SigDef), cs_MobileIdTMSIorPTMSI ('18'O, px_PTMSI_Def))));
    
    //Receive GPRS Attach Complete Message
    f_UplinkTBFOnePhase (p_CellId);
    G_LLC.receive(car_G_LLC_UnitData_IND (cr_G_AttachComplete));
    
  }// end of GPRSAttach
  
  function f_GERAN_SendAuthCoOrdParameters (IRAT_CO_ORD_PORT p_Port, template (omit) CoOrd_GUTIParam_Type p_GUTI) runs on GERAN_PTC
  {
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get();
    p_Port.send (cms_IRAT_AuthInfo(v_SecurityInfo.authPS, v_SecurityInfo.authCS, p_GUTI));
  }
  
  function f_GERAN_GPRS_Authentication (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var G_LLC_DATAMESSAGE_IND v_LLCDataInd;
    var TLLI v_TLLI;
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get();
    var B32_Type    v_AuthRES_High;
    var bitstring   v_AuthRES;
    
    v_SecurityInfo.authPS := f_AuthenticationInit (v_SecurityInfo.authPS);
    
    // Send AUTHENTICATION AND CIPHERING REQUEST using relevant PS keys computed before.
    f_DownlinkTBFEstablishment(p_CellId, 1);
    G_LLC.send(cas_G_LLC_UnitData_Req ( f_GERAN_TLLI_Get(p_CellId),
                                        tsc_LLCSapi_GMM,
                                        tsc_LLC_PM,
                                        tsc_LLC_NoCiph,
                                        cs_G_AuthAndCiphReq (cs_GMM_AuthRAND(v_SecurityInfo.authPS.RandValue),
                                                             cs_GMM_KeySeq(v_SecurityInfo.authPS.KeySeq),
                                                             v_SecurityInfo.cipherMode.algId,
                                                             cs_GMM_AUTN(v_SecurityInfo.authPS.AUTN))));
    
    f_UplinkTBFOnePhase (p_CellId);
    alt {
      [] G_LLC.receive (car_G_LLC_UnitData_IND ( cr_G_AuthAndCiphRsp (cr_AuthRspAny, cr_AuthCiphRspExtAny)))
        -> value v_LLCDataInd
        {// AUTHENTICATION AND CIPHERING RESPONSE including both Authentication Response parameters (RES and RES ext)
          v_AuthRES_High := v_LLCDataInd.unit.msg.authCipherResp.authRsp.rES;
          v_AuthRES := v_LLCDataInd.unit.msg.authCipherResp.authRspExt.rES;
          
          // don't change the TLLI, only the ciphering algorithm
          v_TLLI := f_GERAN_TLLI_Get(p_CellId); // careful, because this might have changed in ULTBF
          f_LLC_TLLI_Assign(p_CellId, v_TLLI, v_TLLI);
          
          // Verify that the received Authentication Response parameters match expected response:
          if (v_AuthRES != substr(v_SecurityInfo.authPS.XRES, 0, lengthof(v_AuthRES))) {
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Authentication Failed");
            }
        }
      [] G_LLC.receive (car_G_LLC_UnitData_IND (cr_G_AuthAndCiphRsp (cr_AuthRspAny, omit)))
        -> value v_LLCDataInd
        {// AUTHENTICATION AND CIPHERING RESPONSE including only one Authentication Response parameter (RES)
          v_AuthRES_High := v_LLCDataInd.unit.msg.authCipherResp.authRsp.rES;
          
          // don't change the TLLI, only the ciphering algorithm
          v_TLLI := f_GERAN_TLLI_Get(p_CellId); // careful, because this might have changed in ULTBF
          f_LLC_TLLI_Assign(p_CellId, v_TLLI, v_TLLI);
          
          // Verify that the received Authentication Response parameters match expected response.
          if (v_AuthRES_High != substr(v_SecurityInfo.authPS.XRES, 0, lengthof(v_AuthRES_High))) {
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Authentication Failed");
            }
        }
      [] G_LLC.receive (car_G_LLC_UnitData_IND ( cr_G_AuthAndCiphFailureAny))
        { //AUTHENTICATION AND CIPHERING Failure, so stop execution
          f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Received Authentication and Ciphering Failure");
        }
    } // end of alt
  }//end of f_GPRS_Authentication
  
  function f_UplinkTBFOnePhase (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var G_L2_DATAMESSAGE_IND v_ChanReq;
    var integer v_RR_RA;
    var RFN v_RFN;
    
    alt {
      [] G_L2.receive (car_G_L2_ACCESS_IND ( p_CellId , tsc_PhyCh0 , RACH , ? , ? , cr_ChanReqOnePhase ))
        -> value v_ChanReq
        {
          v_RFN := v_ChanReq.access.rfn;
          v_RR_RA := bit2int(v_ChanReq.access.burst.chReq.estCauRandomRef);
          if ((119 < v_RR_RA) or (v_RR_RA > 127)) {// establishment cause should be one phase access
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "wrong establishment cause");
          }
          f_ULTBFOnePhase (p_CellId, v_RFN, v_RR_RA);
        }
    }
    
  } // end of f_UplinkTBFOnePhase
  
  function f_ULTBFOnePhase (GERAN_CellId_Type p_CellId,
                            RFN p_RFN, integer p_RR_RA) runs on GERAN_PTC
  {
    var G_CPHY_CONFIG_CNF v_G_CL1_ComingFN_CNF;
    var G_RLC_DATAMESSAGE_IND v_G_RLC_ControlMsg_IND;
    var RFN v_StartingTime;
    var TLLI v_NewTLLI, v_TLLI;
    var B5_Type v_Gamma := f_GERAN_GAMMA_Get(p_CellId);
    var B10_Type v_GPRSFreq := f_GERAN_GPRSFreq_Get(p_CellId);
    
    G_CL1.send (cas_G_CL1_ComingFN_REQ( p_CellId, tsc_PhyCh1, PACCH_F));
    alt {
      [] G_CL1.receive (car_G_CL1_ComingFN_CNF) -> value v_G_CL1_ComingFN_CNF
        {
          v_StartingTime := v_G_CL1_ComingFN_CNF.comingFN;
        }
    }
    // Send IA with Poll Bit set so that a PCA is received
    G_L2.send (cas_G_L2_UNITDATA_REQ (p_CellId,
                                      tsc_PhyCh0,
                                      AGCH, 15,
                                      cs_G_RFN_Omit,
                                      cs_P_ImmediateAssignment ('0'B,
                                                                v_GPRSFreq,
                                                                p_RR_RA,
                                                                p_RFN,
                                                                cs_IARO_PUA( v_Gamma,
                                                                             (v_StartingTime.t1_ & v_StartingTime.t3 & v_StartingTime.t2)))));
    
    // Configure the Uplink TBF for Dynamic Allocation, USF 0 on timeslot 4
    G_CRLC.send (cas_ActivateTBF_UplinkDyn ( p_CellId, 1 ));
    G_CRLC.receive (car_G_RLC_Config_CNF);
    
    // Now wait for PCA
    alt {
      [] G_RLC.receive (car_G_RLC_ControlMsg_IND(p_CellId, tsc_PhyCh1, cr_PacketControlAcknowledgement))
        -> value v_G_RLC_ControlMsg_IND
        {
          v_NewTLLI := v_G_RLC_ControlMsg_IND.ctrl.msg.pktCtrlAck.tLLI;
          v_TLLI := f_GERAN_TLLI_Get(p_CellId);
          if (v_NewTLLI != v_TLLI)  //if the TLLI hasn't changed, don't bother calling LLCAssignReq
            {//Assign the value received from the MS
              f_LLC_TLLI_Assign (p_CellId, v_TLLI, v_NewTLLI);
              f_GERAN_OldTLLI_Set(p_CellId, v_TLLI);
              f_GERAN_TLLI_Set(p_CellId, v_NewTLLI);
            }
        }
    }
  } // end of f_ULTBFOnePhase
  
  function f_DownlinkTBFEstablishment (GERAN_CellId_Type p_CellId,
                                       integer p_USFRate) runs on GERAN_PTC
  {
    // The parameter p_USFRate controls the speed of the DL TBF transferring data blocks by controlling the USF rate:
    // 1 (normal value) ---> implementation dependent. TTCN does not specify the USF generating rate;
    // 2---> 10 data blocks per second;
    // 3---> 5 data blocks per second;
    // 4---> 1 data block per second;
    // 5---> 1 data block 2 seconds;
    // 6---> 1 data block 3 seconds;
    // 7---> 1 data block 4 seconds
    
    var B5_Type v_Gamma := f_GERAN_GAMMA_Get(p_CellId);
    var B10_Type v_GPRSFreq := f_GERAN_GPRSFreq_Get(p_CellId);
    var DRXparameter v_SplitPGCycle  := f_GERAN_SplitPGCycle_Get(p_CellId);
    var ControlChDescr v_CtrlCh := f_GERAN_ControlChDesc_Get(p_CellId);
    var TLLI v_TLLI := f_GERAN_TLLI_Get(p_CellId);
    var integer v_K, v_M;
    
    timer t_Dly := 0.250;
    
    t_Dly.start;
    alt {
      [] G_RLC.receive (car_G_RLC_ControlMsg_IND(p_CellId, tsc_PhyCh1, cr_PacketControlAcknowledgement))
        {
          t_Dly.stop;
        }
      [] t_Dly.timeout {}
    }
    
    G_CRLC.send (cas_ActivateTBF_Downlink(p_CellId, tsc_PhyCh1, p_USFRate));
    G_CRLC.receive (car_G_RLC_Config_CNF);
    
    if ((v_SplitPGCycle.splitPGcycleCode == '00000000'B) or (v_SplitPGCycle.splitOnCCCH == '0'B))
      {
        v_K := fl_PagingGroupCalculate (px_IMSI_Def, v_CtrlCh.cCCH_CONF, 6);
        
        G_L2.send (cas_G_Paging_REQ ( p_CellId , v_K, cs_P_ImmediateAssignment ('1'B, v_GPRSFreq, 0, cs_RFN_0, cs_IARO_PDA(v_TLLI, v_Gamma))));
      }
    else
      {
        v_M := (3 - bit2int(v_CtrlCh.bS_AG_BLKS_RES)) * 64;
        v_K := fl_PacketPagingGroupCalculate(px_IMSI_Def, bit2int(v_CtrlCh.cCCH_CONF), v_M,
                                             (3 - bit2int(v_CtrlCh.bS_AG_BLKS_RES))* bit2int(v_CtrlCh.bS_PA_MFRMS), v_SplitPGCycle.splitPGcycleCode);
        
        G_L2.send (cas_G_PagingGPRS_REQ ( p_CellId , v_K, bit2int(v_SplitPGCycle.splitPGcycleCode), cs_P_ImmediateAssignment ('1'B,v_GPRSFreq, 0, cs_RFN_0, cs_IARO_PDA(v_TLLI, v_Gamma))));
      }
    
  } // end of f_DownlinkTBFEstablishment
  
  function f_LLC_TLLI_Assign(GERAN_CellId_Type p_CellId,
                             TLLI p_Old,
                             TLLI p_New) runs on GERAN_PTC
  {
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get();
    
    G_CLLC.send (cas_G_CLLC_Assign_Req(p_CellId, p_Old, p_New, v_SecurityInfo.gprsCipherAlg, v_SecurityInfo.authPS.KcGSM));
    G_CLLC.receive (car_G_CLLC_Config_CNF);
  } // end of f_LLC_TLLI_Assign
  
  function f_Delete_GPRS_Entities (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    G_CRLC.send (cas_G_CRLC_DeleteRLC_MAC_REQ (p_CellId));
    G_CRLC.receive (car_G_RLC_Config_CNF);
    G_CLLC.send (cas_G_CLLC_DeleteLLE_REQ);
    G_CLLC.receive (car_G_CLLC_Config_CNF);
    
  } //end of f_Delete_GPRS_Entities

  function f_GERAN_SS_CellRelease (GERAN_CellId_Type p_CellId, boolean p_MinUL := false) runs on GERAN_PTC
  {
    G_CL1.send (cas_G_CL1_DeleteChannel_REQ ( p_CellId , tsc_PhyCh0));
    G_CL1.receive (car_G_CPHY_Config_CNF);
    if (not p_MinUL) {
      G_CL1.send (cas_G_CL1_DeleteChannel_REQ ( p_CellId , tsc_PhyCh1));
      G_CL1.receive (car_G_CPHY_Config_CNF);
    }
    G_CL1.send (cas_G_CL1_DeleteCell_REQ ( p_CellId ));
    G_CL1.receive (car_G_CPHY_Config_CNF);
    
  } //end of f_GPRS_SS_CellRelease
  
  function f_GERAN_DisableCiphering (GERAN_CellId_Type p_CellId,
                                     PhysicalChId p_PhyCh,
                                     G_LogicChType p_ChannelType,
                                     SubChannelNumber p_SubChannel) runs on GERAN_PTC
  {
    var G_LogicChType v_AssociatedCh;
    
    select (p_ChannelType) {
      case (SDCCH_4) {
        v_AssociatedCh := SACCH_C4;
      }
      case (SDCCH_8) {
        v_AssociatedCh := SACCH_C8;
      }
      case (TCH_F) {
        v_AssociatedCh := FACCH_F;
      }
    }
    if (px_GSM_CipheringOnOff == '1'B)
      {
        G_CL1.send (cas_G_CL1_CipherModeModify_REQ(p_CellId, p_PhyCh, p_ChannelType, p_SubChannel, (cs_CipherModeSetting('0'B))));
        G_CL1.send (cas_G_CL1_CipherModeModify_REQ(p_CellId, p_PhyCh, v_AssociatedCh, p_SubChannel, (cs_CipherModeSetting('0'B))));
        G_CL1.receive (car_G_CPHY_Config_CNF);
        G_CL1.receive (car_G_CPHY_Config_CNF);
      } // end of if - don't do anything if ciphering turned off
  } // end of f_G_DisableCiphering
  
  function f_GERAN_LocationUpdate (GERAN_CellId_Type p_CellId) runs on GERAN_PTC return SubChannelNumber
  {
    var G_L2_DATAMESSAGE_IND v_ChanReq, v_LocUpd, v_AuthResponse;
    var B10_Type v_BCCH := f_GERAN_BCCHFreq_Get(p_CellId);
    var B3_Type v_BCC := f_GERAN_BCC_Get(p_CellId);
    var octetstring v_PLMN := f_GERAN_PLMN_Get(p_CellId);
    var O2_Type v_LAC := f_GERAN_LAC_Get(p_CellId);
    var GERAN_SecurityInfo_Type v_SecurityInfo := f_GERAN_SecurityInfo_Get();
    var RFN v_RFN;
    var integer v_RR_RA;
    var B32_Type    v_AuthRES_High;
    var bitstring   v_AuthRES;
    var G_LogicChType v_ChannelType;
    var SubChannelNumber v_SubChannel;
    
    alt {
      []    G_L2.receive (car_G_L2_ACCESS_IND ( p_CellId , tsc_PhyCh0 , RACH , ? , ? , cr_G_ChannelReq_Any ))
        -> value v_ChanReq
        {
          v_RFN := v_ChanReq.access.rfn;
          v_RR_RA := bit2int(v_ChanReq.access.burst.chReq.estCauRandomRef);
          G_L2.send (cas_G_L2_UNITDATA_REQ (p_CellId, tsc_PhyCh0, AGCH, 15, cs_G_RFN_Omit, cs_ImmediateAssignment (v_BCCH , v_BCC, v_RR_RA , v_RFN)));
        }
    }
    alt {
      []    G_L2.receive (car_G_L2_Estab_IND (p_CellId, ?, ?, ?, cr_G_LocationUpdatingRequest))
        -> value v_LocUpd
        {
          v_ChannelType := v_LocUpd.sabm.g_LogicChType;
          v_SubChannel := v_LocUpd.sabm.subChannel;
        }
    }
    v_SecurityInfo.authCS := f_AuthenticationInit (v_SecurityInfo.authCS);
    
    G_L2.send (cas_G_L2_DATA_REQ ( p_CellId , 0, tsc_PhyCh0, v_ChannelType, v_SubChannel, cs_G_RFN_Omit,
                                   cs_G_AuthReq(v_SecurityInfo.authCS.KeySeq, v_SecurityInfo.authCS.RandValue, cs_GSM_AUTN(v_SecurityInfo.authCS.AUTN))));
    alt {
      []    G_L2.receive (car_G_L2_DATA_IND ( p_CellId,  ?, tsc_PhyCh0, ?, ?, ?,  cr_G_AuthRspAnyExt))
        -> value v_AuthResponse
        {//Receive Authentication Response with extension
          v_AuthRES_High := v_AuthResponse.l3.msg.authResponse.authRsp.rES;
          v_AuthRES := v_AuthResponse.l3.msg.authResponse.authRspExt.rES;
          // Verify that the received Authentication Response parameters match expected response:
          if (v_AuthRES != substr(v_SecurityInfo.authCS.XRES, 0, lengthof(v_AuthRES))) {
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Authentication Failed");
            }
        }
      []    G_L2.receive (car_G_L2_DATA_IND ( p_CellId,  ?, tsc_PhyCh0, ?, ?, ?,  cr_G_AuthRspAnyNoExt))
        -> value v_AuthResponse
        {//Receive Authentication Response without extension
          v_AuthRES_High := v_AuthResponse.l3.msg.authResponse.authRsp.rES;
          // Verify that the received Authentication Response parameters match expected response.
          if (v_AuthRES_High != substr(v_SecurityInfo.authCS.XRES, 0, lengthof(v_AuthRES_High))) {
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Authentication Failed");
            }
        }
      []    G_L2.receive (car_G_L2_DATA_IND ( p_CellId,  ?, tsc_PhyCh0, ?, ?, ?, cr_G_AuthFailAny))
        {
          f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Received Authentication Failure");
        }
    } //end of alt
    
    f_GERAN_Ciphering_Mode_Setting (p_CellId, tsc_PhyCh0, v_ChannelType, v_SubChannel);
    
    // Send Location Updating Accept
    G_L2.send (cas_G_L2_DATA_REQ (p_CellId, 0, tsc_PhyCh0, v_ChannelType, v_SubChannel, cs_G_RFN_Omit, cs_G_LocationUpdatingAccept ( v_PLMN, v_LAC, cs_MobileIdTMSIorPTMSI(omit, px_TMSI_Def) )));
    // Receive TMSI Reallocation Complete
    G_L2.receive (car_G_L2_DATA_IND ( p_CellId, ?, ? ,?, ?, ?,  cr_G_TMSI_ReallocCmpl));
    
    // release channel
    f_G_ChannelRelease (p_CellId, tsc_PhyCh0, v_ChannelType, v_SubChannel);
    
    return (v_SubChannel);
  } // end of f_G_LocationUpdate
  
  function f_GERAN_Ciphering_Mode_Setting (GERAN_CellId_Type p_CellId,
                                           PhysicalChId p_PhyCh,
                                           G_LogicChType p_ChannelType,
                                           SubChannelNumber p_SubChannel) runs on GERAN_PTC
  {
    if (px_GSM_CipheringOnOff == '1'B)
      {
        // Turn Ciphering On in SS
        G_CL1.send (cas_G_CL1_CipheringControl_REQ(p_CellId, p_PhyCh, '1'B));
        G_CL1.receive (car_G_CPHY_Config_CNF);
        
        //Turn Ciphering ON in UE - algorithm set to px_CiphAlg
        G_L2.send (cas_G_L2_DATA_REQ ( p_CellId, 0, p_PhyCh, p_ChannelType, p_SubChannel, cs_G_RFN_Omit, cs_G_CipheringModeCommand('1'B)));
        alt {
          []    G_L2.receive (car_G_L2_DATA_IND ( p_CellId, ? , p_PhyCh, ?, ?, ?, cr_G_CipheringModeComplete)) {};
          [] G_L2.receive {
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Ciphering Failed"); // if receive anything other than Complete, fail
          }
        }
      } // don't do anything if ciphering not turned on
  } // end of f_G_Ciphering_Mode_Setting
  
  function f_G_ChannelRelease (GERAN_CellId_Type p_CellId,
                               PhysicalChId p_PhyCh,
                               G_LogicChType p_ChannelType,
                               SubChannelNumber p_SubChannel) runs on GERAN_PTC
  {
    G_L2.send (cas_G_L2_DATA_REQ ( p_CellId, 0, p_PhyCh, p_ChannelType, p_SubChannel, cs_G_RFN_Omit, cs_G_ChReleaseNormal));
  } // end of f_G_ChannelRelease
  
  function f_GERAN_SetCellPowerLevel (GERAN_CellId_Type p_CellId,
                                      TX_Power p_Pwr) runs on GERAN_PTC
  {
    f_GERAN_SetChPwrLevel (p_CellId, tsc_PhyCh0, p_Pwr);  // GSM Combined Ctrl Ch
    f_GERAN_SetChPwrLevel (p_CellId, tsc_PhyCh1, p_Pwr);  //GPRS Ch
  }
  
  function f_GERAN_SetChPwrLevel (GERAN_CellId_Type p_CellId,
                                  PhysicalChId p_PhyCh,
                                  TX_Power p_Pwr) runs on GERAN_PTC
  {
    var integer v_PwruVemf := 113 - p_Pwr;
    
    G_CL1.send (cas_G_CL1_ChangePowerLevel_REQ ( p_CellId , p_PhyCh , v_PwruVemf));
    G_CL1.receive (car_G_CPHY_Config_CNF);
  }
  
  function fl_PagingGroupCalculate (hexstring p_IMSI,
                                    B3_Type p_CCCH_Conf,
                                    integer p_N) return integer
  {
    var integer v_IMSIShort := hex2int(p_IMSI[lengthof(p_IMSI)-3]); // IMSI mod 1000 is last 3 digits
    var integer v_BC_CC_Chans := 0;
    
    // 05.02, cl 3.3.2.3: LSB indicates whether combined or not, the next 2 bit indicate num of channels, at least 1
    select (p_CCCH_Conf) {
      case ('000'B,'001'B) {
        v_BC_CC_Chans := 1;
      }
      case ('010'B) {
        v_BC_CC_Chans := 2;
      }
      case ('100'B) {
        v_BC_CC_Chans := 3;
      }
      case ('110'B) {
        v_BC_CC_Chans := 4;
      }
    }
    return ((v_IMSIShort mod (p_N * v_BC_CC_Chans)) mod p_N);
  }
  
  function fl_PacketPagingGroupCalculate (hexstring p_IMSI,
                                          integer p_KC_Conf,
                                          integer p_M,
                                          integer p_N,
                                          B8_Type p_SplitPGCycleBits) return integer
  {
    var integer v_IMSIShort := hex2int(p_IMSI[lengthof(p_IMSI)-3]); // IMSI mod 1000 is last 3 digits
    var integer v_SplitPGCycle := bit2int(p_SplitPGCycleBits);
    var integer v_I := 0;
    var integer v_Val := 0;
    var integer v_LoopCount := 0;
    
    if (p_M < v_SplitPGCycle)
      {
        v_LoopCount := p_M;
      }
    else
      {
        v_LoopCount := v_SplitPGCycle;
      }
    // for I = (0,...,Min(M, SplitPGCycle)-1
    for (v_I := 0; v_I < v_LoopCount; v_I := v_I +1)
      {
        // MAX(I*M) div SPLITPGCycle, I)
        if (((v_I*p_M)/v_SplitPGCycle) > v_I)
          {
            v_Val := v_Val + ((v_I * p_M)/v_SplitPGCycle);
          }
        else
          {
            v_Val := v_Val + v_I;
          }
      }
    return ((((v_IMSIShort/(p_KC_Conf*p_N))*p_N) + (v_IMSIShort mod p_N) + v_Val) mod p_M);
  }

  function f_LLC_XID (GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var B10_Type v_BCCHARFCN := f_GERAN_BCCHFreq_Get (p_CellId);
    var G_L2_DATAMESSAGE_IND v_ChanReq;
    var G_LLC_DATAMESSAGE_IND v_XID;
    var integer v_RR_RA;
    var RFN v_RFN;
    
    timer t_Wait10S := f_UG_SetTimerToleranceMax(10.0);
    
    t_Wait10S.start;
    alt {
      [] G_L2.receive (car_G_L2_ACCESS_IND ( p_CellId , tsc_PhyCh0 , RACH , ? , ? , cr_ChanReqOnePhase ))
        -> value v_ChanReq
        {
          t_Wait10S.stop;
          v_RFN := v_ChanReq.access.rfn;
          v_RR_RA := bit2int(v_ChanReq.access.burst.chReq.estCauRandomRef);
          if ((119 < v_RR_RA) or (v_RR_RA > 127)) {// establishment cause should be one phase access
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "wrong establishment cause");
          }
          f_ULTBFOnePhase (p_CellId, v_RFN, v_RR_RA);
          alt {
            []  G_LLC.receive (car_G_LLC_XID_IndAny)
              -> value v_XID
              {
                fl_SendXIDRes (p_CellId, v_XID.xid.sAPI);
              }
          }
        }
      []  G_LLC.receive (car_G_LLC_XID_IndAny)
        -> value v_XID
        {
          t_Wait10S.stop;
          fl_SendXIDRes (p_CellId, v_XID.xid.sAPI);
        }
      []  G_RLC.receive (car_G_RLC_ControlMsg_IND(p_CellId, tsc_PhyCh1, cr_PacketResourceRequestAny))
        {
          t_Wait10S.stop;
          G_RLC.send (cas_G_RLC_ControlMsg_REQ_PACCH( p_CellId, tsc_PhyCh1, 1, tsc_UplinkTFI, cs_PacketUplinkAssignment(v_BCCHARFCN)));
          alt {
            [] G_L2.receive (car_G_L2_ACCESS_IND ( p_CellId , tsc_PhyCh0 , RACH , ? , ? , cr_ChanReqOnePhase ))
              -> value v_ChanReq
              {
                v_RFN := v_ChanReq.access.rfn;
                v_RR_RA := bit2int(v_ChanReq.access.burst.chReq.estCauRandomRef);
                if ((119 < v_RR_RA) or (v_RR_RA > 127)) {// establishment cause should be one phase access
                  f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "wrong establishment cause");
                }
                f_ULTBFOnePhase (p_CellId, v_RFN, v_RR_RA);
                  G_LLC.receive (car_G_LLC_XID_IndAny)
                    -> value v_XID;
                    fl_SendXIDRes (p_CellId, v_XID.xid.sAPI);
              }
            []  G_LLC.receive (car_G_LLC_XID_IndAny)
              -> value v_XID
              {
                fl_SendXIDRes (p_CellId, v_XID.xid.sAPI);
              }
          }
        }
      []  t_Wait10S.timeout {} // No XID coming
    }
    
  } //end of f_LLC_XID
  
  function fl_SendXIDRes (GERAN_CellId_Type p_CellId,
                          SAPI p_SAPI) runs on GERAN_PTC
  {
    var G_L2_DATAMESSAGE_IND v_ChanReq;
    var integer v_RR_RA;
    var RFN v_RFN;
    timer t_Wait5S := f_UG_SetTimerToleranceMax(5.0);
    
    f_DownlinkTBFEstablishment(p_CellId, 1);
    G_LLC.send (cas_G_LLC_XID_Res(f_GERAN_TLLI_Get(p_CellId), p_SAPI, omit));
    
    t_Wait5S.start;
    alt {
      []  t_Wait5S.timeout {}
      []  G_LLC.receive (car_G_LLC_XID_IndAny)
        { // already send response, so ignore this
          repeat;
        }
      [] G_L2.receive (car_G_L2_ACCESS_IND ( p_CellId , tsc_PhyCh0 , RACH , ? , ? , cr_ChanReqOnePhase ))
        -> value v_ChanReq
        {
          v_RFN := v_ChanReq.access.rfn;
          v_RR_RA := bit2int(v_ChanReq.access.burst.chReq.estCauRandomRef);
          if ((119 < v_RR_RA) or (v_RR_RA > 127)) {// establishment cause should be one phase access
            f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "wrong establishment cause");
          }
          t_Wait5S.stop;
          f_ULTBFOnePhase (p_CellId, v_RFN, v_RR_RA);
          
          G_LLC.receive (car_G_LLC_XID_IndAny);
          f_Delay (3.0);
        }
    } // end of 1st alt
  } // end of fl_SendXIDRes
  
  function f_GERAN_RAU(GERAN_CellId_Type p_CellId,
                       B1_Type p_FOR,
                       B3_Type p_Type) runs on GERAN_PTC
  {
    var G_LLC_DATAMESSAGE_IND v_LLCDataInd;
    var B3_Type v_UpdateType;
    var octetstring v_PLMN := f_GERAN_PLMN_Get(p_CellId);
    var O1_Type v_RAC := f_GERAN_RAC_Get(p_CellId);
    var O2_Type v_LAC := f_GERAN_LAC_Get(p_CellId);
    
    f_UplinkTBFOnePhase (p_CellId);
    alt { // Receive RAU Request Message
      []    G_LLC.receive(car_G_LLC_UnitData_IND ( cr_G_RA_UpdReqAny (cr_GMM_UpdateType( p_FOR, p_Type), cr_RAI_Any (omit), cr_PTMSI_SignatureAny ifpresent, ?)))
        -> value v_LLCDataInd
        {
          v_UpdateType := v_LLCDataInd.unit.msg.rauReq.updateType.updateValue;
        }
    }
    if (v_UpdateType != '000'B){
      v_UpdateType := '001'B;
    }
    // Do Authentication
    f_GERAN_GPRS_Authentication (p_CellId);
    
    // Send RAU Accept
    f_DownlinkTBFEstablishment(p_CellId, 1);
    G_LLC.send(cas_G_LLC_UnitData_Req (f_GERAN_TLLI_Get(p_CellId),
                                       tsc_LLCSapi_GMM,
                                       tsc_LLC_PM,
                                       px_GSM_CipheringOnOff,
                                       cs_G_RA_UpdAcc3 (cs_GMM_UpdateResult( v_UpdateType ),
                                                        cs_RAI(omit,
                                                               cs_LAI(omit, v_PLMN, v_LAC),
                                                               v_RAC),
                                                        cs_PTMSI_Signature (px_PTMSI_SigDef),
                                                        cs_MobileIdTMSIorPTMSI ('18'O, px_PTMSI_Def),
                                                        omit )));
    //Receive RAU Complete Message
    f_UplinkTBFOnePhase (p_CellId);
    G_LLC.receive(car_G_LLC_UnitData_IND (cr_G_RA_UpdComplete));
    
  }// end of f_GERAN_RAU
  
  function f_GERAN_508CheckCampOnNewGeranCell ( GERAN_CellId_Type p_CellId ) runs on GERAN_PTC
  {
    //  @desc Procedure which aims at checking whether the UE is camping on a new GERAN cell
    //  of a test case or not. The procedure is defined in 36.508 table 6.4.2.9-1.
    
    f_GERAN_RAU (p_CellId, '0'B, '001'B);
    f_GERAN_PreliminaryPass(__FILE__, __LINE__, "");
  }
  

  // @desc Function used in Idle Mode test cases to perform Routing Area Update on the new GERAN cell.
  // @param p_CellId The GERAN cell on which the random access request and the RAU will happen
  function f_GERAN_IdleMode_RAU ( GERAN_CellId_Type p_CellId ) runs on GERAN_PTC
  {
    const float const_IdleMode_GenericTimer_GERAN := 360.0;   /* Idle mode generic timer according to 36.523-3 cl. 7.8 */
    timer t_IdleMode_GenericTimer := f_UG_SetTimerToleranceMax(const_IdleMode_GenericTimer_GERAN);

    t_IdleMode_GenericTimer.start;
    f_GERAN_508CheckCampOnNewGeranCell ( p_CellId );
    t_IdleMode_GenericTimer.stop;
  }

  function f_GERAN_ActivatePDPContext(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var G_LLC_DATAMESSAGE_IND v_LLCDataInd;
    var TI v_TI;
    var O1_Type v_Len;
    var template (omit) PktDataProtoAddr v_PDPAddr;
    // UT function doesn't exist yet!
    //    f_UT_GERANActivateMOBearer(UT);
    
    f_UplinkTBFOnePhase (p_CellId);
    alt { // Receive Request Message
      []    G_LLC.receive(car_G_LLC_UnitData_IND ( cr_G_ActPDP_ContextReqMO_Any))
        -> value v_LLCDataInd
        {
          v_TI := v_LLCDataInd.unit.msg.actPDPContextReq.ti;
          v_Len := v_LLCDataInd.unit.msg.actPDPContextReq.pDP_Address.iel;
        }
    }
    if (v_Len == '02'O){
      v_PDPAddr := f_UG_GetPktDataProtoAddr(true);
    } else {
      v_PDPAddr := omit;
    }
    
    // Send Accept
    v_TI.tiFlag := '1'B;
    f_DownlinkTBFEstablishment(p_CellId, 1);
    G_LLC.send(cas_G_LLC_UnitData_Req (f_GERAN_TLLI_Get(p_CellId),
                                       tsc_LLCSapi_GMM,
                                       tsc_LLC_PM,
                                       px_GSM_CipheringOnOff,
                                       cs_G_PDPContextAccept (v_TI,
                                                              cs_LLC_SAPI_11,
                                                              cs_QoS_PDP3,
                                                              v_PDPAddr,
                                                              cs_ProtocolConfigOptions_PPP)));
  }// end of f_GERAN_ActivatePDPContext

  // was f_GERAN_DetachOnSwitchOff
  function f_GERAN_SwitchPowerOff(GERAN_CellId_Type p_CellId) runs on GERAN_PTC
  {
    var B2_Type v_Nmo := f_GERAN_NMO_Get ( p_CellId );
    var GERAN_POSTAMBLE_CONDITIONS v_Geran_Postamble_Condition := fl_GERAN_SetPostambleCondition ( );
    
    if (pc_SwitchOnOff) // The UE can actually be switched off
      {
        f_UT_SwitchOffUE (UT, false);
        
        if ((v_Geran_Postamble_Condition == GERAN_C3) or ((v_Geran_Postamble_Condition == GERAN_C2 and v_Nmo == '01'B))) {
             // Then expect an IMSI Detach
             G_L2.receive (car_G_L2_Estab_IND (p_CellId, ?, ?, ?, cr_G_Imsi_DetachInd));
        }
        
        if (v_Geran_Postamble_Condition != GERAN_C3) { // as long as GPRS is supported
            f_UplinkTBFOnePhase (p_CellId);
            G_LLC.receive(car_G_LLC_UnitData_IND ( cr_G_DetachRequest( cr_DetachTypeOnSwitchOff, cdr_MobileIdTMSI_tlv(?), cr_PTMSI_Signature2Any)));
        }
      }
    else
      {// The power must be removed from the UE
        f_UT_PowerOffUE (UT);
      }
    
  }// end of f_GERAN_DetachOnSwitchOff

  /*
   * @desc      Function to bring UE to switched/powered off state after test case execution in GERAN PTC
                This procedure is according to 36.523-3 cl. 10.2
   * @param     p_CellId
   * @param     p_GERAN_POSTAMBLE_STATE; as defined in 36.508 cl. 6.4.3.2
   * @param     p_DoUpdate - only set to true if UE is not registered to the LAC of this cell, so an RAU is required
   * @status
   */
  function f_GERAN_Postamble ( GERAN_CellId_Type         p_CellId,
                              GERAN_POSTAMBLE_STATE_TYPE p_GERAN_POSTAMBLE_STATE,
                              boolean p_DoUpdate := false) runs on GERAN_PTC
  {
    var boolean v_IsCombined := fl_GERAN_AttachTypeCheck();
    var B2_Type v_Nmo := f_GERAN_NMO_Get ( p_CellId );
    var B3_Type v_UpdateType := '000'B;
    if (v_IsCombined and v_Nmo == '00'B) {
      v_UpdateType := '001'B;
    }
    select ( p_GERAN_POSTAMBLE_STATE) {
      case ( G1_IDLE ) {
        //Switch/Power off UE
        f_GERAN_SwitchPowerOff ( p_CellId);
      }
      case ( G2_PSHANDOVER ) {
        if (p_DoUpdate) {
          f_GERAN_RAU ( p_CellId, '0'B, v_UpdateType);
          if (v_IsCombined and v_Nmo == '01'B) { // If NMO II and C2, then have to do LAU too
            f_GERAN_LocationUpdate (p_CellId);
          }
        }
        //Switch/Power off UE
        f_GERAN_SwitchPowerOff ( p_CellId );
      }
      case ( G3_CSFALLBACK ) {
        //Perform CS Fallback procedure
    //    f_GERAN_CS_Fallback ( p_CellId );  TBD

        //Switch/Power off UE
        f_GERAN_SwitchPowerOff ( p_CellId );
      }
      case ( G4_CSCALL ) {
        //Disconnect the active CC call
    //    f_GERAN_CC_Disconnect ( p_CellId ); TBD
        
        //SwitchPower off UE
        f_GERAN_SwitchPowerOff ( p_CellId );
      }
      case ( G5_DEREGISTERED ) {
        if ( pc_SwitchOnOff == true ) {
          //Simply switch the UE off
          f_UT_SwitchOffUE(UT, false);
        } else {//just remove power from UE
        f_UT_PowerOffUE ( UT );
        }
      }
      case else {//No state defined - just remove power from UE
        f_UT_PowerOffUE ( UT );
      }
    }
    //Release the GERAN cell
    f_GERAN_SS_CellRelease ( p_CellId );
  }

    /*
   * @desc      Function to set the postamble conditions based on the GERAN CS/PS domain support
   *            and the LTE UE Attach type. According to 36.523-3 Table 10.1-1
   * @return    GERAN_POSTAMBLE_CONDITIONS
   * @status
   */
  function fl_GERAN_SetPostambleCondition ( ) runs on GERAN_PTC return GERAN_POSTAMBLE_CONDITIONS
  {
    
    var boolean v_IsCombined := fl_GERAN_AttachTypeCheck();
    var GERAN_POSTAMBLE_CONDITIONS v_GERAN_POSTAMBLE_CONDITION := GERAN_C1;

    if ( v_IsCombined ) {//combined attach case
      if ( pc_GPRS ) {
          v_GERAN_POSTAMBLE_CONDITION := GERAN_C2
        }
      else {
        v_GERAN_POSTAMBLE_CONDITION := GERAN_C3
      }
    }
    return v_GERAN_POSTAMBLE_CONDITION;
  }

  /*
   * @desc      Copy of fl_AttachTypeCheck. Checks the set parameters pc_Combined_Attach, pc_Attach & px_AttachTypeTested
   *            and returns a boolean (TRUE is attach is combined, false if attach is EPS only)
   * @return    boolean
   * @status
   */
  function fl_GERAN_AttachTypeCheck () runs on GERAN_PTC return boolean
  {
    var boolean v_IsCombined := false;
    if( pc_Combined_Attach) {
      if (pc_Attach) { // So both set to true
        if (px_AttachTypeTested == COMBINED_ATTACH) { // only now check the PIXIT value
          v_IsCombined := true;
        }
      } else { // only combined set to true
          v_IsCombined := true;
      }
    } else if (not pc_Attach) { // so neither set to true
          f_GERAN_SetVerdictFailOrInconc(__FILE__, __LINE__, "Neither pc_Attach nor pc_Combined_Attach set to true");
    }
    return v_IsCombined;
  }

  function f_GERAN_CheckNoAttachOnCell ( GERAN_CellId_Type p_CellId, float p_Wait, charstring p_StepNo ) runs on GERAN_PTC
  {
   timer t_Wait := f_UG_SetTimerToleranceMin(p_Wait );
   t_Wait.start;
   alt {
   [] G_L2.receive (car_G_L2_ACCESS_IND ( p_CellId , tsc_PhyCh0 , RACH , ? , ? , ? ))
      {
        t_Wait.stop;
        f_GERAN_SetVerdictFailOrInconc (__FILE__, __LINE__, p_StepNo);
      }
   []   t_Wait.timeout
      {
        f_GERAN_PreliminaryPass (__FILE__, __LINE__, p_StepNo);
      }
   }
  } // end of f_GERAN_CheckNoAttachOnCell


  
  
} // End of module

