Long PRACH extends beyond a slot. Changes necessary to mark future slots that may contain prach in ru, phy and mac functions. In RU, the PRACH IDFT is done only after receiving last slot and marks for L1 to start processing. The L1 processes at the last prach slot and reports to MAC with the first slot index. In MAC scheduler, the VRB for future slots are also marked as used. PRACH scheduler is called in advance one frame minus num prach slots.
194 lines
6.5 KiB
C
194 lines
6.5 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>
|
|
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, nfapi_nr_rach_indication_t *rach_ind)
|
|
{
|
|
uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={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);
|
|
rach_ind->sfn = frame;
|
|
rach_ind->slot = slot;
|
|
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) {
|
|
LOG_D(NR_PHY,"%d.%d Got prach entry id %d\n",frame,slot,prach_id);
|
|
nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu;
|
|
const int prach_start_slot = gNB->prach_vars.list[prach_id].slot;
|
|
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]);
|
|
LOG_D(NR_PHY,"Freeing PRACH entry %d\n",prach_id);
|
|
free_nr_prach_entry(gNB,prach_id);
|
|
LOG_D(NR_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)
|
|
&& (rach_ind->number_of_pdus < MAX_NUM_NR_RX_RACH_PDUS)) {
|
|
LOG_A(NR_PHY,
|
|
"[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol "
|
|
"%u freq index %u\n",
|
|
frame,
|
|
prach_start_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]));
|
|
|
|
nfapi_nr_prach_indication_pdu_t *ind = rach_ind->pdu_list + rach_ind->number_of_pdus;
|
|
ind->phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value;
|
|
ind->symbol_index = prachStartSymbol;
|
|
ind->slot_index = slot;
|
|
ind->freq_index = prach_pdu->num_ra;
|
|
ind->avg_rssi = (max_preamble_energy[0] < 631) ? (128 + (max_preamble_energy[0] / 5)) : 254;
|
|
ind->avg_snr = 0xff; // invalid for now
|
|
|
|
ind->num_preamble = 1;
|
|
ind->preamble_list[0].preamble_index = max_preamble[0];
|
|
ind->preamble_list[0].timing_advance = max_preamble_delay[0];
|
|
ind->preamble_list[0].preamble_pwr = 0xffffffff;
|
|
rach_ind->number_of_pdus++;
|
|
}
|
|
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
|
|
rach_ind->slot = prach_start_slot;
|
|
} // for NUMBER_OF_NR_PRACH_OCCASION_MAX
|
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
|
|
}
|