/******************************************************************************/
// @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-17 11:13:38 +0200 (Fri, 17 Sep 2010) $
// $Rev: 3954 $
/******************************************************************************/

module CommonIratDefs {
  import from CommonDefs all;
  import from NAS_AuxiliaryDefsAndFunctions all;

  //----------------------------------------------------------------------------

  type union IRAT_Coordination_MSG { /* @status    APPROVED */
    IRAT_CoOrd_SysInfo_Type  SysInfo,
    IRAT_CoOrd_Auth_Type     Authentication,
    Null_Type                TriggerEvent,
    Null_Type                Confirmation
  };

  type union IRAT_CoOrd_SysInfo_Type { /* @status    APPROVED */
    CoOrd_GERANSysInfo_List_Type Geran,
    CoOrd_UTRANSysInfo_List_Type Utran,
    CoOrd_EUTRASysInfo_List_Type Eutra,
    CoOrd_CDMA2000SysInfo_List_Type   Cdma2000,
    Null_Type noParams 
  };

  type record IRAT_CoOrd_Auth_Type {            /* @status    APPROVED */
    Common_AuthenticationParams_Type AuthPS,
    Common_AuthenticationParams_Type AuthCS,
    CoOrd_GUTIParam_Type GutiParams  optional
  };

  type record CoOrd_GUTIParam_Type {            /* @status    APPROVED */
    B16_Type  MME_GroupId,
    B8_Type   MME_Code,
    B32_Type  M_TMSI
  };

  type record of CoOrd_GERANSysInfo_Type  CoOrd_GERANSysInfo_List_Type;         /* @status    APPROVED */

  type record CoOrd_GERANSysInfo_Type {         /* @status    APPROVED */
    integer Arfcn,
    CoOrd_GERANNeighCell_Type NeighCells,
    B3_Type Ncc,
    B3_Type Bcc,
    O2_Type Cell_Identity,
    B1_Type BandIndicator // This can't be an ASN.1 type because it's sent to EUTRA too
  };
  type record of integer CoOrd_GERANNeighCell_Type;  /* the ARFCN of the cells, defined as an integer;
                                                        @status    APPROVED */

  type record of CoOrd_UTRANSysInfo_Type  CoOrd_UTRANSysInfo_List_Type;         /* @status    APPROVED */

  type union CoOrd_UTRANSysInfo_Type {          /* @status    APPROVED */
    CoOrd_UTRANSysInfoFDD_Type FDD,
    CoOrd_UTRANSysInfoTDD_Type TDD
  }

  type record CoOrd_UTRANSysInfoTDD_Type {      /* @status    APPROVED */
    integer Freq, // the ARFCN of a cell
    integer CellParametersID,
    B1_Type Tstd,
    B1_Type Diversity,
    O3_Type PLMN,          // the PLMN of the cell, defined in octets
    B28_Type CellIdentity   // the identity of the cell (as transmitted in SIB3) use fl_UTRAN_GetCellIndentity
  }

  type record CoOrd_UTRANSysInfoFDD_Type {      /* @status    APPROVED */
    integer  Freq,           // the ARFCN of a cell, defined as an integer
    integer  ScramblingCode,  // the primary scrambling code of a cell, defined as an integer
    O3_Type  PLMN,          // the PLMN of the cell, defined in octets
    B28_Type CellIdentity   // the identity of the cell (as transmitted in SIB3)
  };

  type record of CoOrd_CDMA2000SysInfo_Type CoOrd_CDMA2000SysInfo_List_Type;      /* @status    APPROVED */
  
  type record CoOrd_CDMA2000SysInfo_Type {           /* @status    APPROVED */
      boolean          IsHRPD,
      integer          Arfcn,
      integer          BandClass,
      integer          PNOffset,
      integer          SearchWindowSize,
      B128_Type        SectorID_HRPD,
      B16_Type         BaseId,
      B16_Type         NID,
      B15_Type         SID
  };
  
  type record of CoOrd_EUTRASysInfo_Type  CoOrd_EUTRASysInfo_List_Type;         /* @status    APPROVED */


  type record CoOrd_EUTRASysInfo_Type {         /* @status    APPROVED */
    integer Arfcn
  };

  type record of IRAT_CoOrd_SysInfo_Type IRAT_CoOrd_SysInfo_List_Type;    /* used as return type for f_IRAT_InitialCoOrd_2Ports
                                                                             @status    APPROVED */

  // All Messages can go in both directions:
  type port IRAT_CO_ORD_PORT message {          /* @status    APPROVED */
    out IRAT_Coordination_MSG;
    in  IRAT_Coordination_MSG;
  };

  // To indicate which PTCs are configured (EUTRA alone is included for completeness)
  type enumerated IRAT_ConfiguredPTCs_Type { EUTRA_Only, EUTRA_UTRAN, EUTRA_GERAN, EUTRA_UTRAN_GERAN, EUTRA_CDMA2000 }


  //----------------------------------------------------------------------------

  group IRAT_Templates {

  //------------------------------------
  // Coordination messages:
  template (value) IRAT_Coordination_MSG cms_IRAT_SysInfo(template (value) IRAT_CoOrd_SysInfo_Type p_SysInfo) :=
  { /* @status    APPROVED */
    SysInfo := p_SysInfo
  };

  template IRAT_Coordination_MSG cmr_IRAT_SysInfo :=
  { /* @status    APPROVED */
    SysInfo := ?
  };

  template (value) IRAT_Coordination_MSG cms_IRAT_Trigger :=
  {
    TriggerEvent := true
  };

  template IRAT_Coordination_MSG cmr_IRAT_Trigger :=
  {
    TriggerEvent := true
  };

  template (value) IRAT_Coordination_MSG cms_IRAT_AuthInfo (template (value) Common_AuthenticationParams_Type p_PS, template (value) Common_AuthenticationParams_Type p_CS, template (omit) CoOrd_GUTIParam_Type p_GUTIParams) :=
  {
    Authentication := {
      AuthPS  := p_PS,
      AuthCS  := p_CS,
      GutiParams := p_GUTIParams
    }
  };

  template IRAT_Coordination_MSG cmr_IRAT_AuthInfo :=
  {
    Authentication := ?
  };

  template (value) CoOrd_GUTIParam_Type cs_IRAT_GUTIStuff (B16_Type p_MME_GroupId, B8_Type p_MME_Code, B32_Type p_M_TMSI) :=
  {
    MME_GroupId := p_MME_GroupId,
    MME_Code    := p_MME_Code,
    M_TMSI      := p_M_TMSI
  };
  //------------------------------------
  // UTRAN Sys info used in coordination:

  template (value) CoOrd_UTRANSysInfoFDD_Type cs_CoOrdUTRANSysInfo_FDD (integer p_Freq,
                                                                        integer p_Code,
                                                                        O3_Type p_PLMN,
                                                                        B28_Type p_CellIdentity) :=
  {
    Freq := p_Freq,
    ScramblingCode := p_Code,
    PLMN := p_PLMN,          // the PLMN of the cell, defined in octets
    CellIdentity := p_CellIdentity
  };

  template (value) CoOrd_UTRANSysInfoTDD_Type cs_CoOrdUTRANSysInfo_TDD (integer p_Freq,
                                                                        integer p_CellParametersID,
                                                                        B1_Type p_Tstd,
                                                                        B1_Type p_Diversity,
                                                                        O3_Type p_PLMN,
                                                                        B28_Type p_CellIdentity) :=
  {
    Freq         := p_Freq,
    CellParametersID := p_CellParametersID,
    Tstd         := p_Tstd,
    Diversity    := p_Diversity,
    PLMN         := p_PLMN,          // the PLMN of the cell, defined in octets
    CellIdentity := p_CellIdentity
  };


  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdUTRAN_SysInfo(template (value) CoOrd_UTRANSysInfo_Type p_Cell5,
                                                                 template (value) CoOrd_UTRANSysInfo_Type p_Cell7,
                                                                 template (value) CoOrd_UTRANSysInfo_Type p_Cell8,
                                                                 template (value) CoOrd_UTRANSysInfo_Type p_Cell9) :=
  { // UTRAN sys info to be sent from UTRAN-PTC to EUTRA-PTC
    Utran := {
      p_Cell5,
      p_Cell7,
      p_Cell8,
      p_Cell9
    }
  };

    template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdC2K_NoParams :=
  { // no parameters to be sent from EUTRAN-PTC to C2K-PTC
    noParams := true 
  };
  //------------------------------------
  // GERAN Sys info used in coordination:

  template (value) CoOrd_GERANSysInfo_Type cs_CoOrdGERANSysInfo(integer p_Arfcn,
                                                                CoOrd_GERANNeighCell_Type p_Neigh,
                                                                B3_Type p_Ncc,
                                                                B3_Type p_Bcc,
                                                                O2_Type p_CellId,
                                                                B1_Type p_BandInd) :=
  {
    Arfcn :=  p_Arfcn,
    NeighCells := p_Neigh,
    Ncc := p_Ncc,
    Bcc := p_Bcc,
    Cell_Identity := p_CellId,
    BandIndicator := p_BandInd
  };

  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdGERAN_SysInfo (template (value) CoOrd_GERANSysInfo_Type p_Cell24,
                                                                  template (value) CoOrd_GERANSysInfo_Type p_Cell25,
                                                                  template (value) CoOrd_GERANSysInfo_Type p_Cell26) :=
  {
    Geran := {
      p_Cell24,
      p_Cell25,
      p_Cell26
    }
  };

  //------------------------------------
  // CDMA2000 Sys info used in coordination:

  template (value) CoOrd_CDMA2000SysInfo_Type cs_CoOrdCDMA2000_SysInfoSingleCell (boolean p_IsHRPD,
                                                                                  integer p_ARFCN,
                                                                                  integer p_BandClass,
                                                                                  integer p_PNOffset,
                                                                                  integer p_SearchWindowSize,
                                                                                  B128_Type p_SectorID_HRPD,
                                                                                  B16_Type  p_BaseId,
                                                                                  B16_Type  p_NID,
                                                                                  B15_Type  p_SID) :=
  {
    IsHRPD    := p_IsHRPD,
    Arfcn     := p_ARFCN,
    BandClass := p_BandClass,
    PNOffset  := p_PNOffset,
    SearchWindowSize := p_SearchWindowSize,
    SectorID_HRPD := p_SectorID_HRPD,
    BaseId := p_BaseId,
    NID := p_NID,
    SID := p_SID
  };
  
  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdCDMA2000_SysInfoOneCell (template (value) CoOrd_CDMA2000SysInfo_Type p_Cell) :=
  {
    Cdma2000 := {p_Cell}
  };
  
  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdCDMA2000_SysInfoTwoCell (template (value) CoOrd_CDMA2000SysInfo_Type p_Cell1,
                                                                            template (value) CoOrd_CDMA2000SysInfo_Type p_Cell2) :=
  {
    Cdma2000 := {p_Cell1, p_Cell2}
  };
  
  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdCDMA2000_SysInfo (template (value) CoOrd_CDMA2000SysInfo_Type p_Cell15,
                                                                     template (value) CoOrd_CDMA2000SysInfo_Type p_Cell16,
                                                                     template (value) CoOrd_CDMA2000SysInfo_Type p_Cell17,
                                                                     template (value) CoOrd_CDMA2000SysInfo_Type p_Cell18) :=
  {
    Cdma2000 := {
      p_Cell15,
      p_Cell16,
      p_Cell17,
      p_Cell18
    }
  };

  //------------------------------------
  // EUTRA Sys info used in coordination:

  template (value) CoOrd_EUTRASysInfo_Type cs_CoOrdEUTRASysInfo(integer p_Arfcn) :=
  { /* @status    APPROVED */
    Arfcn :=  p_Arfcn
  };

  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdEUTRA_SysInfo (template (value) CoOrd_EUTRASysInfo_List_Type p_CoOrd_EUTRASysInfo_List ) :=
  { /* @status    APPROVED */
    Eutra :=  p_CoOrd_EUTRASysInfo_List
  };

  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdEUTRA_SysInfoSingleCell ( template (value) CoOrd_EUTRASysInfo_Type p_Cell) :=
  { /* EUTRA sys info to be sent from EUTRA-PTC to other PTCs */
    Eutra := { p_Cell }
  };

  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdUTRAN_SysInfoSingleCell ( template (value) CoOrd_UTRANSysInfo_Type p_Cell ) :=
  { // UTRAN sys info to be sent from UTRAN-PTC to EUTRA-PTC
    Utran := { p_Cell }
  };

  template (value) IRAT_CoOrd_SysInfo_Type cs_CoOrdGERAN_SysInfoSingleCell ( template (value) CoOrd_GERANSysInfo_Type p_Cell ) :=
  { // GERAN sys info to be sent from GERAN-PTC to EUTRA-PTC
    Geran := { p_Cell }
  };

  } // end of group

  //----------------------------------------------------------------------------
  function f_SendIRATCoOrd (IRAT_CO_ORD_PORT p_Port, template (value) IRAT_Coordination_MSG p_Msg)
  {
    p_Port.send (p_Msg);
  }

  //----------------------------------------------
  /*
   * @desc      Wait for a coordination meessage from other PTC at the given port
   * @param     p_Port
   * @return    IRAT_CoOrd_SysInfo_Type
   * @status    APPROVED
   */
  function f_WaitForIRATCoOrd_SysInfo (IRAT_CO_ORD_PORT p_Port) return IRAT_CoOrd_SysInfo_Type
  {
    var IRAT_Coordination_MSG v_ReceivedMsg;
    var IRAT_CoOrd_SysInfo_Type v_SysInfoRx;

    alt {
      [] p_Port.receive(cmr_IRAT_SysInfo) -> value v_ReceivedMsg {
        v_SysInfoRx := v_ReceivedMsg.SysInfo;
      }
      [] p_Port.receive {  // to immediately detect programming errors (shall normally not happen)
        FatalError(__FILE__, __LINE__, "unexpected coordination message");
      }
    }
    return v_SysInfoRx;
  }

  function f_WaitForIRATCoOrd_Trigger (IRAT_CO_ORD_PORT p_Port) return boolean
  {
    var boolean v_Received := false;

    alt {
      [] p_Port.receive(cmr_IRAT_Trigger) {
        v_Received := true;
      }
      [] p_Port.receive {  // to immediately detect programming errors (shall normally not happen)
        FatalError(__FILE__, __LINE__, "unexpected coordination message");
      }
    }
    return v_Received;
  }

  function f_ReceiveAuthCoOrdParameters (IRAT_CO_ORD_PORT p_Port) return IRAT_CoOrd_Auth_Type
{
    var IRAT_Coordination_MSG v_RxdMsg;

    p_Port.receive (cmr_IRAT_AuthInfo) -> value v_RxdMsg;
    return (v_RxdMsg.Authentication);
}

  //----------------------------------------------
  /*
   * @desc      send system information of this PTC to the other PTC and wait for the system information from the other side
   * @param     p_Port
   * @param     p_SysInfoTx
   * @return    IRAT_CoOrd_SysInfo_Type
   * @status    APPROVED
   */
  function f_IRAT_InitialCoOrd(IRAT_CO_ORD_PORT p_Port,
                               template (value) IRAT_CoOrd_SysInfo_Type p_SysInfoTx) return IRAT_CoOrd_SysInfo_Type
  {
    var IRAT_CoOrd_SysInfo_Type v_SysInfoRx;

    p_Port.send(cms_IRAT_SysInfo(p_SysInfoTx));
    v_SysInfoRx := f_WaitForIRATCoOrd_SysInfo (p_Port);

    return v_SysInfoRx;
  }

  //----------------------------------------------------------------------------
  /*
   * @desc      send system information of this PTC to the other PTCs and wait for the system information from the other sides
   * @param     p_Port1
   * @param     p_Port2
   * @param     p_SysInfoTx
   * @return    IRAT_CoOrd_SysInfo_List_Type
   * @status    APPROVED
   */
  function f_IRAT_InitialCoOrd_2Ports(IRAT_CO_ORD_PORT p_Port1,
                                      IRAT_CO_ORD_PORT p_Port2,
                                      template (value) IRAT_CoOrd_SysInfo_Type p_SysInfoTx) return IRAT_CoOrd_SysInfo_List_Type
  {
    var IRAT_CoOrd_SysInfo_List_Type v_SysInfoRxList;

    p_Port1.send(cms_IRAT_SysInfo(p_SysInfoTx));
    p_Port2.send(cms_IRAT_SysInfo(p_SysInfoTx));
    v_SysInfoRxList[0] := f_WaitForIRATCoOrd_SysInfo (p_Port1);
    v_SysInfoRxList[1] := f_WaitForIRATCoOrd_SysInfo (p_Port2);  /* Note: that works since the coordination ports are not handled by the default behaviour
                                                                  *       i.e. there is a blocking receive for port1 and if the response for port2
                                                                  *       is faster it remains in port2's input queue */
    return v_SysInfoRxList;
  }

  //----------------------------------------------------------------------------
  function f_IRAT_Send_EUTRA_SysInfoToOtherPort(IRAT_CO_ORD_PORT p_Irat_Coord_Port,
                                                integer p_Arfcn)
  {
    var template (value) CoOrd_EUTRASysInfo_Type v_Cell := cs_CoOrdEUTRASysInfo(p_Arfcn);
    f_SendIRATCoOrd ( p_Irat_Coord_Port, cms_IRAT_SysInfo ( cs_CoOrdEUTRA_SysInfoSingleCell ( v_Cell ) ) );
  }

} // end of module
