To minimize migration effort, we follow the logic of legacy macro Rel10 and Rel14 used for conditional compilation of current code. In the future, they might be changed to accommodate finer software configuration, e.g. MAKE_VERSION(12,2,0) or MAKE_VERSION(13,1,0) .... etc.
624 lines
20 KiB
C
624 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 "UTIL/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 "UTIL/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,
|
|
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;
|
|
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(0, NULL, 0, module_idP, 0,
|
|
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(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0],
|
|
UE_mac_inst[module_idP].RA_Msg3_size, module_idP, 3,
|
|
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;
|
|
// Panos: Modification for phy_stub_ue operation
|
|
if(nfapi_mode == 3) { // Panos: 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 RACH_ConfigCommon *rach_ConfigCommon =
|
|
(struct RACH_ConfigCommon *) NULL;
|
|
int32_t frame_diff = 0;
|
|
mac_rlc_status_resp_t rlc_status;
|
|
uint8_t dcch_header_len = 0;
|
|
uint16_t sdu_lengths[8];
|
|
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
|
|
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 (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[0] = 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 (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
|
|
,0,
|
|
0
|
|
#endif
|
|
);
|
|
|
|
|
|
LOG_D(MAC, "[UE %d] TX Got %d bytes for DCCH\n",
|
|
module_idP, sdu_lengths[0]);
|
|
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 PreambleTransMax_n3:
|
|
preambleTransMax = 3;
|
|
break;
|
|
case PreambleTransMax_n4:
|
|
preambleTransMax = 4;
|
|
break;
|
|
case PreambleTransMax_n5:
|
|
preambleTransMax = 5;
|
|
break;
|
|
case PreambleTransMax_n6:
|
|
preambleTransMax = 6;
|
|
break;
|
|
case PreambleTransMax_n7:
|
|
preambleTransMax = 7;
|
|
break;
|
|
case PreambleTransMax_n8:
|
|
preambleTransMax = 8;
|
|
break;
|
|
case PreambleTransMax_n10:
|
|
preambleTransMax = 10;
|
|
break;
|
|
case PreambleTransMax_n20:
|
|
preambleTransMax = 20;
|
|
break;
|
|
case PreambleTransMax_n50:
|
|
preambleTransMax = 50;
|
|
break;
|
|
case PreambleTransMax_n100:
|
|
preambleTransMax = 100;
|
|
break;
|
|
case 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);
|
|
}
|