1. Modify all expressions using original LTE-RRC data types for new generated ones 2. Does not change any program logic
625 lines
20 KiB
C
625 lines
20 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
/*! \file ra_procedures.c
|
|
* \brief Routines for UE MAC-layer Random-access procedures (36.321) V8.6 2009-03
|
|
* \author R. Knopp and Navid Nikaein
|
|
* \date 2011
|
|
* \version 0.1
|
|
* \company Eurecom
|
|
* \email: knopp@eurecom.fr navid.nikaein@eurecom.fr
|
|
* \note
|
|
* \warning
|
|
*/
|
|
|
|
#include "mac_extern.h"
|
|
#include "mac.h"
|
|
#include "mac_proto.h"
|
|
#include "common/utils/LOG/vcd_signal_dumper.h"
|
|
#include "PHY_INTERFACE/phy_interface_extern.h"
|
|
#include "SCHED_UE/sched_UE.h"
|
|
#include "COMMON/mac_rrc_primitives.h"
|
|
#include "RRC/LTE/rrc_extern.h"
|
|
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
|
|
#include "common/utils/LOG/log.h"
|
|
#include "UTIL/OPT/opt.h"
|
|
#include "OCG.h"
|
|
#include "OCG_extern.h"
|
|
#include "SIMULATION/TOOLS/sim.h" // for taus
|
|
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
|
|
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
|
|
|
|
extern uint8_t nfapi_mode;
|
|
extern UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
|
|
|
|
/// This routine implements Section 5.1.2 (UE Random Access Resource Selection) from 36.321
|
|
void
|
|
get_prach_resources(module_id_t module_idP,
|
|
int CC_id,
|
|
uint8_t eNB_index,
|
|
uint8_t t_id,
|
|
uint8_t first_Msg3,
|
|
LTE_RACH_ConfigDedicated_t * rach_ConfigDedicated)
|
|
{
|
|
uint8_t Msg3_size = UE_mac_inst[module_idP].RA_Msg3_size;
|
|
PRACH_RESOURCES_t *prach_resources =
|
|
&UE_mac_inst[module_idP].RA_prach_resources;
|
|
LTE_RACH_ConfigCommon_t *rach_ConfigCommon = NULL;
|
|
uint8_t noGroupB = 0;
|
|
uint8_t f_id = 0, num_prach = 0;
|
|
int numberOfRA_Preambles;
|
|
int messageSizeGroupA;
|
|
int sizeOfRA_PreamblesGroupA;
|
|
int messagePowerOffsetGroupB;
|
|
int PLThreshold;
|
|
|
|
AssertFatal(CC_id == 0,
|
|
"Transmission on secondary CCs is not supported yet\n");
|
|
AssertFatal(UE_mac_inst[module_idP].radioResourceConfigCommon != NULL,
|
|
"[UE %d] FATAL radioResourceConfigCommon is NULL !!!\n",
|
|
module_idP);
|
|
|
|
rach_ConfigCommon =
|
|
&UE_mac_inst[module_idP].radioResourceConfigCommon->
|
|
rach_ConfigCommon;
|
|
numberOfRA_Preambles =
|
|
(1 + rach_ConfigCommon->preambleInfo.numberOfRA_Preambles) << 2;
|
|
|
|
if (rach_ConfigDedicated) { // This is for network controlled Mobility, later
|
|
if (rach_ConfigDedicated->ra_PRACH_MaskIndex != 0) {
|
|
prach_resources->ra_PreambleIndex =
|
|
rach_ConfigDedicated->ra_PreambleIndex;
|
|
prach_resources->ra_RACH_MaskIndex =
|
|
rach_ConfigDedicated->ra_PRACH_MaskIndex;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* TODO: gcc warns if this variable is not always set, let's put -1 for no more warning */
|
|
messageSizeGroupA = -1;
|
|
|
|
if (!rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) {
|
|
noGroupB = 1;
|
|
} else {
|
|
sizeOfRA_PreamblesGroupA =
|
|
(rach_ConfigCommon->preambleInfo.
|
|
preamblesGroupAConfig->sizeOfRA_PreamblesGroupA + 1) << 2;
|
|
switch (rach_ConfigCommon->preambleInfo.
|
|
preamblesGroupAConfig->messageSizeGroupA) {
|
|
case 0:
|
|
messageSizeGroupA = 56;
|
|
break;
|
|
case 1:
|
|
messageSizeGroupA = 144;
|
|
break;
|
|
case 2:
|
|
messageSizeGroupA = 208;
|
|
break;
|
|
case 3:
|
|
messageSizeGroupA = 256;
|
|
break;
|
|
}
|
|
|
|
/* TODO: what value to use as default? */
|
|
messagePowerOffsetGroupB = -9999;
|
|
switch (rach_ConfigCommon->preambleInfo.
|
|
preamblesGroupAConfig->messagePowerOffsetGroupB) {
|
|
case 0:
|
|
messagePowerOffsetGroupB = -9999;
|
|
break;
|
|
case 1:
|
|
messagePowerOffsetGroupB = 0;
|
|
break;
|
|
case 2:
|
|
messagePowerOffsetGroupB = 5;
|
|
break;
|
|
case 3:
|
|
messagePowerOffsetGroupB = 8;
|
|
break;
|
|
case 4:
|
|
messagePowerOffsetGroupB = 10;
|
|
break;
|
|
case 5:
|
|
messagePowerOffsetGroupB = 12;
|
|
break;
|
|
case 6:
|
|
messagePowerOffsetGroupB = 15;
|
|
break;
|
|
case 7:
|
|
messagePowerOffsetGroupB = 18;
|
|
break;
|
|
}
|
|
|
|
PLThreshold =
|
|
0 - get_DELTA_PREAMBLE(module_idP,
|
|
CC_id) -
|
|
get_Po_NOMINAL_PUSCH(module_idP,
|
|
CC_id) - messagePowerOffsetGroupB;
|
|
// Note Pcmax is set to 0 here, we have to fix this
|
|
|
|
if (sizeOfRA_PreamblesGroupA == numberOfRA_Preambles) {
|
|
noGroupB = 1;
|
|
}
|
|
}
|
|
|
|
if (first_Msg3 == 1) {
|
|
if (noGroupB == 1) {
|
|
// use Group A procedure
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex =
|
|
(taus()) % numberOfRA_Preambles;
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex =
|
|
0;
|
|
UE_mac_inst[module_idP].RA_usedGroupA = 1;
|
|
} else if ((Msg3_size < messageSizeGroupA) ||
|
|
(get_PL(module_idP, 0, eNB_index) > PLThreshold)) {
|
|
// use Group A procedure
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex =
|
|
(taus()) % sizeOfRA_PreamblesGroupA;
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex =
|
|
0;
|
|
UE_mac_inst[module_idP].RA_usedGroupA = 1;
|
|
} else { // use Group B
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex =
|
|
sizeOfRA_PreamblesGroupA +
|
|
(taus()) % (numberOfRA_Preambles -
|
|
sizeOfRA_PreamblesGroupA);
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex =
|
|
0;
|
|
UE_mac_inst[module_idP].RA_usedGroupA = 0;
|
|
}
|
|
|
|
UE_mac_inst[module_idP].
|
|
RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER =
|
|
get_Po_NOMINAL_PUSCH(module_idP, CC_id);
|
|
} else { // Msg3 is being retransmitted
|
|
if (UE_mac_inst[module_idP].RA_usedGroupA == 1) {
|
|
if (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) {
|
|
UE_mac_inst[module_idP].RA_prach_resources.
|
|
ra_PreambleIndex =
|
|
(taus()) %
|
|
rach_ConfigCommon->preambleInfo.
|
|
preamblesGroupAConfig->sizeOfRA_PreamblesGroupA;
|
|
} else {
|
|
UE_mac_inst[module_idP].RA_prach_resources.
|
|
ra_PreambleIndex = (taus()) & 0x3f;
|
|
}
|
|
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex =
|
|
0;
|
|
} else {
|
|
// FIXME rach_ConfigCommon->preambleInfo.preamblesGroupAConfig may be zero
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex =
|
|
rach_ConfigCommon->preambleInfo.
|
|
preamblesGroupAConfig->sizeOfRA_PreamblesGroupA +
|
|
(taus()) %
|
|
(rach_ConfigCommon->preambleInfo.numberOfRA_Preambles -
|
|
rach_ConfigCommon->preambleInfo.
|
|
preamblesGroupAConfig->sizeOfRA_PreamblesGroupA);
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex =
|
|
0;
|
|
}
|
|
}
|
|
|
|
// choose random PRACH resource in TDD
|
|
if (UE_mac_inst[module_idP].tdd_Config) {
|
|
num_prach = get_num_prach_tdd(module_idP);
|
|
|
|
if ((num_prach > 0) && (num_prach < 6)) {
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index =
|
|
(taus() % num_prach);
|
|
}
|
|
|
|
f_id = get_fid_prach_tdd(module_idP,
|
|
UE_mac_inst
|
|
[module_idP].RA_prach_resources.
|
|
ra_TDD_map_index);
|
|
}
|
|
// choose RA-RNTI
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_RNTI =
|
|
1 + t_id + 10 * f_id;
|
|
}
|
|
|
|
void
|
|
Msg1_transmitted(module_id_t module_idP, uint8_t CC_id,
|
|
frame_t frameP, uint8_t eNB_id)
|
|
{
|
|
|
|
AssertFatal(CC_id == 0,
|
|
"Transmission on secondary CCs is not supported yet\n");
|
|
// start contention resolution timer
|
|
UE_mac_inst[module_idP].RA_attempt_number++;
|
|
|
|
if (opt_enabled) {
|
|
trace_pdu(DIRECTION_UPLINK, NULL, 0, module_idP, WS_NO_RNTI,
|
|
UE_mac_inst[module_idP].RA_prach_resources.
|
|
ra_PreambleIndex, UE_mac_inst[module_idP].txFrame,
|
|
UE_mac_inst[module_idP].txSubframe, 0,
|
|
UE_mac_inst[module_idP].RA_attempt_number);
|
|
LOG_D(OPT,
|
|
"[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x with size %d\n",
|
|
module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
Msg3_transmitted(module_id_t module_idP, uint8_t CC_id,
|
|
frame_t frameP, uint8_t eNB_id)
|
|
{
|
|
|
|
AssertFatal(CC_id == 0,
|
|
"Transmission on secondary CCs is not supported yet\n");
|
|
|
|
// start contention resolution timer
|
|
LOG_D(MAC,
|
|
"[UE %d][RAPROC] Frame %d : Msg3_tx: Setting contention resolution timer\n",
|
|
module_idP, frameP);
|
|
UE_mac_inst[module_idP].RA_contention_resolution_cnt = 0;
|
|
UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1;
|
|
|
|
if (opt_enabled) { // msg3
|
|
trace_pdu(DIRECTION_UPLINK , &UE_mac_inst[module_idP].CCCH_pdu.payload[0],
|
|
UE_mac_inst[module_idP].RA_Msg3_size, module_idP, WS_C_RNTI,
|
|
UE_mac_inst[module_idP].crnti,
|
|
UE_mac_inst[module_idP].txFrame,
|
|
UE_mac_inst[module_idP].txSubframe, 0, 0);
|
|
LOG_D(OPT,
|
|
"[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d with size %d\n",
|
|
module_idP, frameP, UE_mac_inst[module_idP].crnti
|
|
/*UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex */
|
|
, UE_mac_inst[module_idP].RA_Msg3_size);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id,
|
|
frame_t frameP, uint8_t eNB_indexP,
|
|
sub_frame_t subframeP)
|
|
{
|
|
|
|
uint8_t Size = 0;
|
|
UE_MODE_t UE_mode;
|
|
// Modification for phy_stub_ue operation
|
|
if(nfapi_mode == 3) { // phy_stub_ue mode
|
|
UE_mode = UE_mac_inst[module_idP].UE_mode[0];
|
|
LOG_D(MAC, "ue_get_rach , UE_mode: %d", UE_mode);
|
|
}
|
|
else { // Full stack mode
|
|
UE_mode = get_ue_mode(module_idP,0,eNB_indexP);
|
|
}
|
|
|
|
|
|
uint8_t lcid = CCCH;
|
|
uint16_t Size16;
|
|
struct LTE_RACH_ConfigCommon *rach_ConfigCommon =
|
|
(struct LTE_RACH_ConfigCommon *) NULL;
|
|
int32_t frame_diff = 0;
|
|
uint8_t dcch_header_len = 0;
|
|
uint16_t sdu_lengths;
|
|
uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];
|
|
|
|
AssertFatal(CC_id == 0,
|
|
"Transmission on secondary CCs is not supported yet\n");
|
|
|
|
if (UE_mode == PRACH) {
|
|
LOG_D(MAC, "ue_get_rach 3, RA_active value: %d", UE_mac_inst[module_idP].RA_active);
|
|
if (UE_mac_inst[module_idP].radioResourceConfigCommon) {
|
|
rach_ConfigCommon =
|
|
&UE_mac_inst[module_idP].
|
|
radioResourceConfigCommon->rach_ConfigCommon;
|
|
} else {
|
|
return (NULL);
|
|
}
|
|
|
|
if (UE_mac_inst[module_idP].RA_active == 0) {
|
|
LOG_I(MAC, "RA not active\n");
|
|
// check if RRC is ready to initiate the RA procedure
|
|
Size = mac_rrc_data_req_ue(module_idP,
|
|
CC_id,
|
|
frameP,
|
|
CCCH, 1,
|
|
&UE_mac_inst[module_idP].
|
|
CCCH_pdu.payload[sizeof
|
|
(SCH_SUBHEADER_SHORT)
|
|
+ 1], eNB_indexP,
|
|
0);
|
|
Size16 = (uint16_t) Size;
|
|
|
|
// LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",module_idP,frameP,Size);
|
|
LOG_I(RRC,
|
|
"[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_DATA_REQ (RRCConnectionRequest eNB %d) --->][MAC_UE][MOD %02d][]\n",
|
|
frameP, module_idP, eNB_indexP, module_idP);
|
|
LOG_I(MAC,
|
|
"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",
|
|
module_idP, frameP, Size);
|
|
|
|
if (Size > 0) {
|
|
UE_mac_inst[module_idP].RA_active = 1;
|
|
UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER =
|
|
1;
|
|
UE_mac_inst[module_idP].RA_Msg3_size =
|
|
Size + sizeof(SCH_SUBHEADER_SHORT) +
|
|
sizeof(SCH_SUBHEADER_SHORT);
|
|
UE_mac_inst[module_idP].RA_prachMaskIndex = 0;
|
|
UE_mac_inst[module_idP].RA_prach_resources.Msg3 =
|
|
UE_mac_inst[module_idP].CCCH_pdu.payload;
|
|
UE_mac_inst[module_idP].RA_backoff_cnt = 0; // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)
|
|
|
|
AssertFatal(rach_ConfigCommon != NULL,
|
|
"[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",
|
|
module_idP, frameP);
|
|
UE_mac_inst[module_idP].RA_window_cnt =
|
|
2 +
|
|
rach_ConfigCommon->ra_SupervisionInfo.
|
|
ra_ResponseWindowSize;
|
|
|
|
if (UE_mac_inst[module_idP].RA_window_cnt == 9) {
|
|
UE_mac_inst[module_idP].RA_window_cnt = 10; // Note: 9 subframe window doesn't exist, after 8 is 10!
|
|
}
|
|
|
|
UE_mac_inst[module_idP].RA_tx_frame = frameP;
|
|
UE_mac_inst[module_idP].RA_tx_subframe = subframeP;
|
|
UE_mac_inst[module_idP].RA_backoff_frame = frameP;
|
|
UE_mac_inst[module_idP].RA_backoff_subframe = subframeP;
|
|
// Fill in preamble and PRACH resource
|
|
get_prach_resources(module_idP, CC_id, eNB_indexP,
|
|
subframeP, 1, NULL);
|
|
|
|
generate_ulsch_header((uint8_t *) & UE_mac_inst[module_idP].CCCH_pdu.payload[0], // mac header
|
|
1, // num sdus
|
|
0, // short pading
|
|
&Size16, // sdu length
|
|
&lcid, // sdu lcid
|
|
NULL, // power headroom
|
|
NULL, // crnti
|
|
NULL, // truncated bsr
|
|
NULL, // short bsr
|
|
NULL, // long_bsr
|
|
1); //post_padding
|
|
return (&UE_mac_inst[module_idP].RA_prach_resources);
|
|
|
|
} else if (UE_mac_inst[module_idP].
|
|
scheduling_info.BSR_bytes[UE_mac_inst[module_idP].
|
|
scheduling_info.LCGID
|
|
[DCCH]] > 0) {
|
|
// This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example)
|
|
dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element
|
|
LOG_USEDINLOG_VAR(mac_rlc_status_resp_t,rlc_status)=mac_rlc_status_ind(module_idP,
|
|
UE_mac_inst[module_idP].crnti,
|
|
eNB_indexP, frameP, subframeP,
|
|
ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6
|
|
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
|
,0, 0
|
|
#endif
|
|
);
|
|
|
|
if (UE_mac_inst[module_idP].crnti_before_ho)
|
|
LOG_D(MAC,
|
|
"[UE %d] Frame %d : UL-DCCH -> ULSCH, HO RRCConnectionReconfigurationComplete (%x, %x), RRC message has %d bytes to send throug PRACH (mac header len %d)\n",
|
|
module_idP, frameP,
|
|
UE_mac_inst[module_idP].crnti,
|
|
UE_mac_inst[module_idP].crnti_before_ho,
|
|
rlc_status.bytes_in_buffer, dcch_header_len);
|
|
else
|
|
LOG_D(MAC,
|
|
"[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to send through PRACH(mac header len %d)\n",
|
|
module_idP, frameP, rlc_status.bytes_in_buffer,
|
|
dcch_header_len);
|
|
|
|
sdu_lengths = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6, //not used
|
|
(char *) &ulsch_buff[0]
|
|
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
|
,0,
|
|
0
|
|
#endif
|
|
);
|
|
|
|
if(sdu_lengths > 0)
|
|
LOG_D(MAC, "[UE %d] TX Got %d bytes for DCCH\n",
|
|
module_idP, sdu_lengths);
|
|
else
|
|
LOG_E(MAC, "[UE %d] TX DCCH error\n",
|
|
module_idP );
|
|
|
|
update_bsr(module_idP, frameP, subframeP, eNB_indexP);
|
|
UE_mac_inst[module_idP].
|
|
scheduling_info.BSR[UE_mac_inst[module_idP].
|
|
scheduling_info.LCGID[DCCH]] =
|
|
locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE,
|
|
UE_mac_inst
|
|
[module_idP].scheduling_info.BSR_bytes
|
|
[UE_mac_inst
|
|
[module_idP].scheduling_info.LCGID
|
|
[DCCH]]);
|
|
|
|
//TO DO: fill BSR infos in UL TBS
|
|
|
|
//header_len +=2;
|
|
UE_mac_inst[module_idP].RA_active = 1;
|
|
UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER =
|
|
1;
|
|
UE_mac_inst[module_idP].RA_Msg3_size =
|
|
Size + dcch_header_len;
|
|
UE_mac_inst[module_idP].RA_prachMaskIndex = 0;
|
|
UE_mac_inst[module_idP].RA_prach_resources.Msg3 =
|
|
ulsch_buff;
|
|
UE_mac_inst[module_idP].RA_backoff_cnt = 0; // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)
|
|
|
|
AssertFatal(rach_ConfigCommon != NULL,
|
|
"[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",
|
|
module_idP, frameP);
|
|
UE_mac_inst[module_idP].RA_window_cnt =
|
|
2 +
|
|
rach_ConfigCommon->ra_SupervisionInfo.
|
|
ra_ResponseWindowSize;
|
|
|
|
if (UE_mac_inst[module_idP].RA_window_cnt == 9) {
|
|
UE_mac_inst[module_idP].RA_window_cnt = 10; // Note: 9 subframe window doesn't exist, after 8 is 10!
|
|
}
|
|
|
|
|
|
UE_mac_inst[module_idP].RA_tx_frame = frameP;
|
|
UE_mac_inst[module_idP].RA_tx_subframe = subframeP;
|
|
UE_mac_inst[module_idP].RA_backoff_frame = frameP;
|
|
UE_mac_inst[module_idP].RA_backoff_subframe = subframeP;
|
|
// Fill in preamble and PRACH resource
|
|
get_prach_resources(module_idP, CC_id, eNB_indexP,
|
|
subframeP, 1, NULL);
|
|
generate_ulsch_header((uint8_t *) ulsch_buff, // mac header
|
|
1, // num sdus
|
|
0, // short pading
|
|
&Size16, // sdu length
|
|
&lcid, // sdu lcid
|
|
NULL, // power headroom
|
|
&UE_mac_inst[module_idP].crnti, // crnti
|
|
NULL, // truncated bsr
|
|
NULL, // short bsr
|
|
NULL, // long_bsr
|
|
0); //post_padding
|
|
|
|
return (&UE_mac_inst[module_idP].RA_prach_resources);
|
|
}
|
|
} else { // RACH is active
|
|
LOG_D(MAC,
|
|
"[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n",
|
|
module_idP, frameP, subframeP,
|
|
UE_mac_inst[module_idP].RA_window_cnt,
|
|
UE_mac_inst[module_idP].RA_tx_frame,
|
|
UE_mac_inst[module_idP].RA_tx_subframe);
|
|
|
|
// compute backoff parameters
|
|
if (UE_mac_inst[module_idP].RA_backoff_cnt > 0) {
|
|
frame_diff =
|
|
(sframe_t) frameP -
|
|
UE_mac_inst[module_idP].RA_backoff_frame;
|
|
|
|
if (frame_diff < 0) {
|
|
frame_diff = -frame_diff;
|
|
}
|
|
|
|
UE_mac_inst[module_idP].RA_backoff_cnt -=
|
|
((10 * frame_diff) +
|
|
(subframeP -
|
|
UE_mac_inst[module_idP].RA_backoff_subframe));
|
|
|
|
UE_mac_inst[module_idP].RA_backoff_frame = frameP;
|
|
UE_mac_inst[module_idP].RA_backoff_subframe = subframeP;
|
|
}
|
|
// compute RA window parameters
|
|
if (UE_mac_inst[module_idP].RA_window_cnt > 0) {
|
|
frame_diff =
|
|
(frame_t) frameP - UE_mac_inst[module_idP].RA_tx_frame;
|
|
|
|
if (frame_diff < 0) {
|
|
frame_diff = -frame_diff;
|
|
}
|
|
|
|
UE_mac_inst[module_idP].RA_window_cnt -=
|
|
((10 * frame_diff) +
|
|
(subframeP - UE_mac_inst[module_idP].RA_tx_subframe));
|
|
LOG_D(MAC,
|
|
"[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, adjusted window cnt %d\n",
|
|
module_idP, frameP, subframeP,
|
|
UE_mac_inst[module_idP].RA_window_cnt);
|
|
}
|
|
|
|
if ((UE_mac_inst[module_idP].RA_window_cnt <= 0) &&
|
|
(UE_mac_inst[module_idP].RA_backoff_cnt <= 0)) {
|
|
|
|
UE_mac_inst[module_idP].RA_tx_frame = frameP;
|
|
UE_mac_inst[module_idP].RA_tx_subframe = subframeP;
|
|
UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER++;
|
|
UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER += (rach_ConfigCommon->powerRampingParameters.powerRampingStep << 1); // 2dB increments in ASN.1 definition
|
|
int preambleTransMax = -1;
|
|
switch (rach_ConfigCommon->ra_SupervisionInfo.
|
|
preambleTransMax) {
|
|
case LTE_PreambleTransMax_n3:
|
|
preambleTransMax = 3;
|
|
break;
|
|
case LTE_PreambleTransMax_n4:
|
|
preambleTransMax = 4;
|
|
break;
|
|
case LTE_PreambleTransMax_n5:
|
|
preambleTransMax = 5;
|
|
break;
|
|
case LTE_PreambleTransMax_n6:
|
|
preambleTransMax = 6;
|
|
break;
|
|
case LTE_PreambleTransMax_n7:
|
|
preambleTransMax = 7;
|
|
break;
|
|
case LTE_PreambleTransMax_n8:
|
|
preambleTransMax = 8;
|
|
break;
|
|
case LTE_PreambleTransMax_n10:
|
|
preambleTransMax = 10;
|
|
break;
|
|
case LTE_PreambleTransMax_n20:
|
|
preambleTransMax = 20;
|
|
break;
|
|
case LTE_PreambleTransMax_n50:
|
|
preambleTransMax = 50;
|
|
break;
|
|
case LTE_PreambleTransMax_n100:
|
|
preambleTransMax = 100;
|
|
break;
|
|
case LTE_PreambleTransMax_n200:
|
|
preambleTransMax = 200;
|
|
break;
|
|
}
|
|
|
|
if (UE_mac_inst[module_idP].
|
|
RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax) {
|
|
LOG_D(MAC,
|
|
"[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n",
|
|
module_idP, frameP, preambleTransMax);
|
|
// send message to RRC
|
|
UE_mac_inst[module_idP].
|
|
RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
|
|
UE_mac_inst[module_idP].
|
|
RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER
|
|
= get_Po_NOMINAL_PUSCH(module_idP, CC_id);
|
|
}
|
|
|
|
UE_mac_inst[module_idP].RA_window_cnt =
|
|
2 +
|
|
rach_ConfigCommon->ra_SupervisionInfo.
|
|
ra_ResponseWindowSize;
|
|
UE_mac_inst[module_idP].RA_backoff_cnt = 0;
|
|
|
|
// Fill in preamble and PRACH resource
|
|
get_prach_resources(module_idP, CC_id, eNB_indexP,
|
|
subframeP, 0, NULL);
|
|
return (&UE_mac_inst[module_idP].RA_prach_resources);
|
|
}
|
|
}
|
|
} else if (UE_mode == PUSCH) {
|
|
LOG_D(MAC,
|
|
"[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...",
|
|
module_idP);
|
|
AssertFatal(1 == 0, "");
|
|
}
|
|
|
|
return (NULL);
|
|
}
|