The simulators have been changed: due to linker errors that would arise otherwise, a lot of functions are defined in them to avoid such errors. Some functions are also defined in header files; in this commit, we define most functoins in nr_dummy_functions.c, which is compiled in, not by including the C file, but by adding it to the target in CMakeLists.txt - nr_dlsim+nr_ulsim need NR_IF_Module_init(), so it cannot be in nr_dummy_functions, but the others need it - Link correcr NR_IF_Module_init() into these simulators, and reduce overall link list - Correctly link remaining simulators
195 lines
6.6 KiB
C
195 lines
6.6 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 nr_prach_procedures.c
|
|
* \brief Implementation of gNB prach procedures from 38.213 LTE specifications
|
|
* \author R. Knopp,
|
|
* \date 2019
|
|
* \version 0.1
|
|
* \company Eurecom
|
|
* \email: knopp@eurecom.fr
|
|
* \note
|
|
* \warning
|
|
*/
|
|
|
|
#include "PHY/defs_gNB.h"
|
|
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
|
#include "nfapi_nr_interface_scf.h"
|
|
#include "fapi_nr_l1.h"
|
|
#include "nfapi_pnf.h"
|
|
#include "common/utils/LOG/log.h"
|
|
#include "common/utils/LOG/vcd_signal_dumper.h"
|
|
|
|
|
|
#include "assertions.h"
|
|
|
|
#include <time.h>
|
|
|
|
extern uint8_t nfapi_mode;
|
|
|
|
uint8_t get_nr_prach_duration(uint8_t prach_format){
|
|
|
|
switch(prach_format){
|
|
|
|
case 0: // format 0
|
|
return 0;
|
|
|
|
case 1: // format 1
|
|
return 0;
|
|
|
|
case 2: // format 2
|
|
return 0;
|
|
|
|
case 3: // format 3
|
|
return 0;
|
|
|
|
case 4: // format A1
|
|
return 2;
|
|
|
|
case 5: // format A2
|
|
return 4;
|
|
|
|
case 6: // format A3
|
|
return 6;
|
|
|
|
case 7: // format B1
|
|
return 2;
|
|
|
|
case 8: // format B4
|
|
return 12;
|
|
|
|
case 9: // format C0
|
|
return 2;
|
|
|
|
case 10: // format C2
|
|
return 6;
|
|
|
|
case 11: // format A1/B1
|
|
return 2;
|
|
|
|
case 12: // format A2/B2
|
|
return 4;
|
|
|
|
case 13: // format A3/B3
|
|
return 6;
|
|
|
|
default :
|
|
AssertFatal(1==0,"Invalid Prach format\n");
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot) {
|
|
|
|
uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0};
|
|
|
|
|
|
uint8_t pdu_index = 0;
|
|
RU_t *ru;
|
|
int aa=0;
|
|
int ru_aa;
|
|
|
|
|
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
|
|
gNB->UL_INFO.rach_ind.sfn = frame;
|
|
gNB->UL_INFO.rach_ind.slot = slot;
|
|
gNB->UL_INFO.rach_ind.pdu_list = gNB->prach_pdu_indication_list;
|
|
gNB->UL_INFO.rach_ind.number_of_pdus = 0;
|
|
|
|
ru=gNB->RU_list[0];
|
|
|
|
int prach_id=find_nr_prach(gNB,frame,slot,SEARCH_EXIST);
|
|
|
|
if (prach_id>=0) {
|
|
nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu;
|
|
uint8_t prachStartSymbol;
|
|
uint8_t N_dur = get_nr_prach_duration(prach_pdu->prach_format);
|
|
|
|
for(int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) {
|
|
for (ru_aa=0,aa=0;ru_aa<ru->nb_rx;ru_aa++,aa++) {
|
|
gNB->prach_vars.rxsigF[aa] = ru->prach_rxsigF[prach_oc][ru_aa];
|
|
}
|
|
|
|
prachStartSymbol = prach_pdu->prach_start_symbol+prach_oc*N_dur;
|
|
//comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
|
|
|
|
rx_nr_prach(gNB,
|
|
prach_pdu,
|
|
prach_oc,
|
|
frame,
|
|
slot,
|
|
&max_preamble[0],
|
|
&max_preamble_energy[0],
|
|
&max_preamble_delay[0]);
|
|
|
|
free_nr_prach_entry(gNB,prach_id);
|
|
LOG_D(PHY,"[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d (prach_energy counter %d)\n",
|
|
frame,slot,prach_oc,prachStartSymbol,
|
|
max_preamble[0],
|
|
max_preamble_energy[0]/10,
|
|
max_preamble_energy[0]%10,
|
|
max_preamble_delay[0],
|
|
gNB->prach_energy_counter);
|
|
|
|
if ((gNB->prach_energy_counter == 100) && (max_preamble_energy[0] > gNB->measurements.prach_I0+gNB->prach_thres)) {
|
|
|
|
LOG_I(NR_PHY,"[gNB %d][RAPROC] Frame %d, slot %d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol %u freq index %u\n",
|
|
gNB->Mod_id,
|
|
frame,
|
|
slot,
|
|
max_preamble[0],
|
|
max_preamble_energy[0]/10,
|
|
max_preamble_energy[0]%10,
|
|
gNB->measurements.prach_I0,gNB->prach_thres,
|
|
max_preamble_delay[0],
|
|
prachStartSymbol,
|
|
prach_pdu->num_ra);
|
|
|
|
T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(gNB->Mod_id), T_INT(frame), T_INT(slot),
|
|
T_INT(max_preamble[0]), T_INT(max_preamble_energy[0]), T_INT(max_preamble_delay[0]));
|
|
|
|
|
|
gNB->UL_INFO.rach_ind.number_of_pdus += 1;
|
|
|
|
gNB->prach_pdu_indication_list[pdu_index].phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value;
|
|
gNB->prach_pdu_indication_list[pdu_index].symbol_index = prachStartSymbol;
|
|
gNB->prach_pdu_indication_list[pdu_index].slot_index = slot;
|
|
gNB->prach_pdu_indication_list[pdu_index].freq_index = prach_pdu->num_ra;
|
|
gNB->prach_pdu_indication_list[pdu_index].avg_rssi = (max_preamble_energy[0]<631) ? (128+(max_preamble_energy[0]/5)) : 254;
|
|
gNB->prach_pdu_indication_list[pdu_index].avg_snr = 0xff; // invalid for now
|
|
|
|
gNB->prach_pdu_indication_list[pdu_index].num_preamble = 1;
|
|
gNB->prach_pdu_indication_list[pdu_index].preamble_list = gNB->preamble_list;
|
|
gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].preamble_index = max_preamble[0];
|
|
gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].timing_advance = max_preamble_delay[0];
|
|
gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].preamble_pwr = 0xffffffff;
|
|
pdu_index++;
|
|
}
|
|
gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0*900)>>10) + ((max_preamble_energy[0]*124)>>10);
|
|
if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10);
|
|
if (gNB->prach_energy_counter < 100) gNB->prach_energy_counter++;
|
|
} //if prach_id>0
|
|
} //for NUMBER_OF_NR_PRACH_OCCASION_MAX
|
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
|
|
}
|
|
|