diff --git a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf index 4a3d2852c4..afe40c733c 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf @@ -196,6 +196,7 @@ RUs = ( att_tx = 0 att_rx = 0; bands = [78]; + sl_ahead=3; max_pdschReferenceSignalPower = -27; max_rxgain = 114; sf_extension = 0; diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c index cfe05042ce..f5dfe6137f 100644 --- a/common/config/config_load_configmodule.c +++ b/common/config/config_load_configmodule.c @@ -240,6 +240,7 @@ configmodule_interface_t *load_configmodule(int argc, for (int i=0; i handle_nr_nfapi_xxx_pdu --> sendTxFilled((L1_tx_filled)) --> nr_fill_ul_xxx - --> nr_fill_prach + --> nr_schedule_rx_prach() end gNB_dlsch_ulsch_scheduler --> NR_Schedule_response end diff --git a/doc/rach_processing_in_gNB.md b/doc/rach_processing_in_gNB.md new file mode 100644 index 0000000000..5c15cf0812 --- /dev/null +++ b/doc/rach_processing_in_gNB.md @@ -0,0 +1,24 @@ +The gNB RACH processing + +1. Collect I/Q samples +The gNB/ru main loop, in ru_thread() +If there is rach occasions in this slot +this main loop calls rx_nr_prach_ru() that stores the I/Q samples in the prach_item_t context + +2.process the samples +L1_rx_thread() has received slot indication by msg on queue resp_L1, it calls rx_func() => L1_nr_prach_procedures() +L1_nr_prach_procedures() fills nfapi_nr_rach_indication_t structure from result of rx_nr_prach() that process the content of rxsigF[prachOccasion][aa] +rx_func() sends the decoded rach to upper processing by call to NR_UL_indication() that calls handle_nr_rach() => nr_initiate_ra_proc() + +nr_initiate_ra_proc() creates a UE context if it needs, then sets UE.ra.ra_state to what it should do + +3. send the RACH DL +tx_func() that is launched by L1_tx_thread() as it gets L1_tx_out msg (from main loop in 1.) +tx_func()=>run_scheduler_monolithic()=>gNB_dlsch_ulsch_scheduler()=>nr_scheduler_RA() +nr_scheduler_RA() process all existing UE contexts, to see it it has to schedule a RACH DL + +4. global synchronisation +resp_L1 msg for (2.) is created in tx_func() that is launched by L1_tx_thread() (see3.) when it receives slot indication as it gets L1_tx_out msg +this msg is sent by the main loop (see 1.) +tx_func()=>run_scheduler_monolithic()=>nr_schedule_response ()=>nr_schedule_ul_tti_req ()=> nr_schedule_rx_prach() +writes in the triggering structure to (1.) that it will have to run rx_nr_prach_ru() in a given future slot diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 16ad366a0e..b0509f158d 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -387,10 +387,8 @@ void init_eNB_afterRU(void) int aa = 0; for (int ru_id = 0; ru_id < gNB->num_RU; ru_id++) { AssertFatal(gNB->RU_list[ru_id]->common.rxdataF != NULL, "RU %d : common.rxdataF is NULL\n", gNB->RU_list[ru_id]->idx); - AssertFatal(gNB->RU_list[ru_id]->prach_rxsigF != NULL, "RU %d : prach_rxsigF is NULL\n", gNB->RU_list[ru_id]->idx); for (int i = 0; i < gNB->RU_list[ru_id]->nb_rx; aa++, i++) { - LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa); - gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[0][i]; + LOG_I(PHY, "Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa); for (int b = 0; b < gNB->RU_list[ru_id]->num_beams_period; b++) { int idx = i + b * gNB->RU_list[ru_id]->nb_rx; gNB->common_vars.rxdataF[b][aa] = (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[idx]; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 20deff5725..ea43ecdff1 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1034,7 +1034,7 @@ void *ru_thread(void *param) RU_t *ru = (RU_t *)param; RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - PHY_VARS_gNB *gNB = RC.gNB[0]; + PHY_VARS_gNB *gNB = RC.gNB[0]; // this RU main loop handes only one RU int ret; int slot = fp->slots_per_frame-1; int frame = 1023; @@ -1047,7 +1047,7 @@ void *ru_thread(void *param) // set default return value sprintf(threadname,"ru_thread %u",ru->idx); LOG_I(PHY,"Starting RU %d (%s,%s) on cpu %d\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing],sched_getcpu()); - ru->config = RC.gNB[0]->gNB_config; + ru->config = gNB->gNB_config; nr_init_frame_parms(&ru->config, fp); nr_dump_frame_parms(fp); @@ -1179,12 +1179,17 @@ void *ru_thread(void *param) proc->timestamp_tx += fp->get_samples_per_slot(i % fp->slots_per_frame, fp); proc->tti_tx = (proc->tti_rx + ru->sl_ahead) % fp->slots_per_frame; proc->frame_tx = proc->tti_rx > proc->tti_tx ? (proc->frame_rx + 1) & 1023 : proc->frame_rx; - LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", - frame,slot, - proc->frame_rx,proc->tti_rx, - proc->frame_tx,proc->tti_tx, - RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); + LOG_D(PHY, + "AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", + frame, + slot, + proc->frame_rx, + proc->tti_rx, + proc->frame_tx, + proc->tti_tx, + gNB->proc.frame_rx, + gNB->proc.slot_rx, + gNB->proc.frame_tx); if (ru->idx != 0) proc->frame_tx = (proc->frame_tx + proc->frame_offset) & 1023; @@ -1199,7 +1204,7 @@ void *ru_thread(void *param) LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH); //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); - gNBscopeCopy(RC.gNB[0], + gNBscopeCopy(gNB, gNBRxdataF, ru->common.rxdataF[0], sizeof(c16_t), @@ -1208,34 +1213,11 @@ void *ru_thread(void *param) proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP); // Do PRACH RU processing - int prach_id = find_nr_prach_ru(ru, proc->frame_rx, proc->tti_rx, SEARCH_EXIST); - if (prach_id >= 0) { + prach_item_t *p = find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, SEARCH_EXIST); + if (p) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - - T(T_GNB_PHY_PRACH_INPUT_SIGNAL, - T_INT(proc->frame_rx), - T_INT(proc->tti_rx), - T_INT(0), - T_BUFFER(&ru->common.rxdata[0][fp->get_samples_slot_timestamp(proc->tti_rx - 1, fp, 0) /*-ru->N_TA_offset*/], - (fp->get_samples_per_slot(proc->tti_rx - 1, fp) + fp->get_samples_per_slot(proc->tti_rx, fp)) * 4)); - RU_PRACH_list_t *p = ru->prach_list + prach_id; - int N_dur = get_nr_prach_duration(p->fmt); - - for (int prach_oc = 0; prach_oc < p->num_prach_ocas; prach_oc++) { - int prachStartSymbol = p->prachStartSymbol + prach_oc * N_dur; - int beam_id = ru->prach_list[prach_id].beam ? ru->prach_list[prach_id].beam[prach_oc] : 0; - //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_ru(ru, - p->fmt, // could also use format - p->numRA, - beam_id, - prachStartSymbol, - p->slot, - prach_oc, - proc->frame_rx, - proc->tti_rx); - } - free_nr_ru_prach_entry(ru,prach_id); + // need to extract RACH data for lqter processing by rx_nr_prach() + rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0); } // end if (prach_id >= 0) } // end if (ru->feprx) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index e7132e15cf..5721b45f8d 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -1091,7 +1091,7 @@ void *UE_thread(void *arg) stream_status = STREAM_STATUS_SYNCED; tx_wait_for_dlsch[slot] = 0; } - + LOG_W(NR_PHY, "UE main thread is ending\n"); return NULL; } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index fbac6402f5..ca6c48dbef 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -139,10 +139,7 @@ int create_tasks_nrue(uint32_t ue_nb) { void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { int CC_id; - - if (s != NULL) { - printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); - } + LOG_W(NR_PHY, "called by: %s:%d %s() Exiting OAI softmodem: %s\n", file, line, function, s ? s : "no msg"); oai_exit = 1; @@ -496,9 +493,8 @@ int main(int argc, char **argv) printf("Entering ITTI signals handler\n"); printf("TYPE TO TERMINATE\n"); itti_wait_tasks_end(trigger_deregistration); - printf("Returned from ITTI signal handler\n"); - oai_exit=1; - printf("oai_exit=%d\n",oai_exit); + LOG_W(NR_PHY, "Returned from ITTI signal handler\n"); + oai_exit = 1; if (ouput_vcd) vcd_signal_dumper_close(); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 754ef60e55..12cf081fdc 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1481,7 +1481,10 @@ typedef enum { NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE, NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE, } nfapi_nr_ul_config_pdu_type_e; - +static const char* const txt_nfapi_nr_ul_config_pdu_type[] = {"NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE", + "NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE", + "NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE", + "NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE"}; typedef struct { uint16_t pdu_type;//0: PRACH PDU, 1: PUSCH PDU, 2: PUCCH PDU, 3: SRS PDU diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 778903be91..7a360e30ff 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -104,9 +104,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) // shortcuts NR_DL_FRAME_PARMS *const fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - NR_gNB_COMMON *const common_vars = &gNB->common_vars; - NR_gNB_PRACH *const prach_vars = &gNB->prach_vars; - + NR_gNB_COMMON *const common_vars = &gNB->common_vars; common_vars->analog_bf = cfg->analog_beamforming_ve.analog_bf_vendor_ext.value; LOG_I(PHY, "L1 configured with%s analog beamforming\n", common_vars->analog_bf ? "" : "out"); if (common_vars->analog_bf) { @@ -190,10 +188,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) common_vars->debugBuff_sample_offset = 0; // PRACH - prach_vars->rxsigF = (int16_t **)malloc16_clear(Prx*sizeof(int16_t*)); - prach_vars->prach_ifft = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t)); - - init_prach_list(gNB); + init_prach_list(&gNB->prach_list); int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; int n_buf = Prx*max_ul_mimo_layers; @@ -266,10 +261,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(common_vars->debugBuff); - NR_gNB_PRACH* prach_vars = &gNB->prach_vars; - free_and_zero(prach_vars->rxsigF); - free_and_zero(prach_vars->prach_ifft); - for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; for (int i = 0; i < n_buf; i++) { diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index ca753938a6..71418bb1e3 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -27,8 +27,6 @@ #include #include "openair1/PHY/defs_RU.h" -void init_prach_ru_list(RU_t *ru); - void nr_phy_init_RU(RU_t *ru) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; @@ -114,25 +112,10 @@ void nr_phy_init_RU(RU_t *ru) LOG_D(PHY, "rxdataF[%d] %p for RU %d\n", i, ru->common.rxdataF[i], ru->idx); } - /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ - // AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]), - // "nb_antennas_rx too large"); - for (int j = 0; j < NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX; j++) { - ru->prach_rxsigF[j] = (int16_t**)malloc(nb_rx_streams * sizeof(int16_t*)); - - for (int i = 0; i < nb_rx_streams; i++) { - // largest size for PRACH FFT is 4x98304 (16*24576) - ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear(4 * 98304 * 2 * sizeof(int16_t)); - LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n", i, ru->prach_rxsigF[j][i]); - } - } - AssertFatal(ru->num_gNB <= NUMBER_OF_gNB_MAX, "gNB instances %d > %d\n", ru->num_gNB,NUMBER_OF_gNB_MAX); LOG_D(PHY, "[INIT] %s() ru->num_gNB:%d \n", __FUNCTION__, ru->num_gNB); } // !=IF5 - - init_prach_ru_list(ru); } void nr_phy_free_RU(RU_t *ru) @@ -174,11 +157,6 @@ void nr_phy_free_RU(RU_t *ru) free_and_zero(ru->common.rxdataF[i]); free_and_zero(ru->common.rxdataF); - for (int j = 0; j < NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX; j++) { - for (int i = 0; i < nb_rx_streams; i++) - free_and_zero(ru->prach_rxsigF[j][i]); - free_and_zero(ru->prach_rxsigF[j]); - } for(int i = 0; i < ru->num_beams_period; ++i) free_and_zero(ru->common.beam_id[i]); free_and_zero(ru->common.beam_id); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 76d9b1185f..823af815d3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -36,286 +36,230 @@ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "openair1/PHY/NR_TRANSPORT/nr_prach.h" -void init_prach_list(PHY_VARS_gNB *gNB) +void init_prach_list(prach_list_t *l) { - AssertFatal(gNB != NULL, "gNB is null\n"); - for (int i = 0; i < NUMBER_OF_NR_PRACH_MAX; i++){ - gNB->prach_vars.list[i].frame = -1; - gNB->prach_vars.list[i].slot = -1; - gNB->prach_vars.list[i].num_slots = -1; - } + pthread_mutex_init(&l->prach_list_mutex, NULL); + for (prach_item_t *p = l->list; p < l->list + NUMBER_OF_NR_PRACH_MAX; p++) + *p = (prach_item_t){.frame = -1, .slot = -1}; } -void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id) +void free_nr_prach_entry(prach_list_t *l, prach_item_t *p) { - gNB->prach_vars.list[prach_id].frame = -1; - gNB->prach_vars.list[prach_id].slot = -1; - gNB->prach_vars.list[prach_id].num_slots = -1; - free_and_zero(gNB->prach_vars.list[prach_id].beam_nb); + pthread_mutex_lock(&l->prach_list_mutex); + if (p->frame == -1) + LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n"); + *p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1}; + pthread_mutex_unlock(&l->prach_list_mutex); } -int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) { - - AssertFatal(gNB!=NULL,"gNB is null\n"); - for (uint16_t i=0; iprach_vars.list + i; - LOG_D(PHY, "searching for PRACH in %d.%d prach_index %d=> %d.%d\n", frame, slot, i, p->frame, p->slot); - if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) { - return i; - } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) { - return i; +prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t type) +{ + pthread_mutex_lock(&l->prach_list_mutex); + prach_item_t *p = l->list; + prach_item_t *end = p + NUMBER_OF_NR_PRACH_MAX; + for (; p < end; p++) + if (p->frame == frame && (p->slot + p->num_slots - 1) == slot) + break; + if (p == end) { + if (type == SEARCH_EXIST) { + pthread_mutex_unlock(&l->prach_list_mutex); + return NULL; } + for (p = l->list; p < end; p++) + if (p->frame == -1 && p->slot == -1) + break; } - return -1; + if (p == end) { + pthread_mutex_unlock(&l->prach_list_mutex); + return NULL; + } + // mark it used, it will be filled later + p->frame = frame; + pthread_mutex_unlock(&l->prach_list_mutex); + return p; } -int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) +prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) { - int prach_id = find_nr_prach(gNB, SFN, Slot, SEARCH_EXIST_OR_FREE); - AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)), "illegal or no prach_id found!!! prach_id %d\n", prach_id); - gNB_PRACH_list_t *prach = &gNB->prach_vars.list[prach_id]; + prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, SEARCH_EXIST_OR_FREE); + if (!prach) { + LOG_W(PHY, "no free space for a new detected rach, discarding\n"); + return NULL; + } + const int fmt = prach_pdu->prach_format; + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + // we set only elements as the whole structure has been cleaned when we release it prach->frame = SFN; prach->slot = Slot; - const int format = prach_pdu->prach_format; - prach->num_slots = (format < 4) ? get_long_prach_dur(format, gNB->frame_parms.numerology_index) : 1; + prach->num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1; if (gNB->common_vars.beam_id) { int n_symb = get_nr_prach_duration(prach_pdu->prach_format); - prach->beam_nb = calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach->beam_nb)); + AssertFatal(prach_pdu->beamforming.dig_bf_interface < NFAPI_MAX_NUM_BG_IF, + "impossible beams size %d\n", + prach_pdu->beamforming.dig_bf_interface); for (int i = 0; i < prach_pdu->beamforming.dig_bf_interface; i++) { int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx; int start_symb = prach_pdu->prach_start_symbol + i * n_symb; int bitmap = SL_to_bitmap(start_symb, n_symb); - prach->beam_nb[i] = beam_index_allocation(gNB->enable_analog_das, - fapi_beam_idx, - &gNB->gNB_config.analog_beamforming_ve, - &gNB->common_vars, - Slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, - bitmap); + prach->beams[i] = beam_index_allocation(gNB->enable_analog_das, + fapi_beam_idx, + &gNB->gNB_config.analog_beamforming_ve, + &gNB->common_vars, + Slot, + NR_NUMBER_OF_SYMBOLS_PER_SLOT, + bitmap); } } - LOG_D(NR_PHY,"Copying prach pdu %d bytes to index %d\n", (int)sizeof(*prach_pdu), prach_id); - memcpy(&prach->pdu, prach_pdu, sizeof(*prach_pdu)); - return prach_id; + prach->pdu = *prach_pdu; + nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; + nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; + prach->rootSequenceIndex = occ->prach_root_sequence_index.value; + prach->numrootSequenceIndex = occ->num_root_sequences.value; + prach->msg1_frequencystart = occ->k1.value; + prach->mu = cfg->prach_sub_c_spacing.value; + prach->prach_sequence_length = cfg->prach_sequence_length.value; + prach->restricted_set = cfg->restricted_set_config.value; + prach->numerology_index = fp->numerology_index; + prach->nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value; + prach->Xu = gNB->X_u; + prach->rx_prach = &gNB->rx_prach; + return prach; } -void init_prach_ru_list(RU_t *ru) +static void rx_nr_prach_ru_internal(prach_item_t *p, + int beam_id, + int prachStartSymbol, + int prachOccasion, + int32_t **rxdata, + NR_DL_FRAME_PARMS *fp, + int N_TA_offset) { - AssertFatal(ru != NULL, "ru is null\n"); - for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { - ru->prach_list[i].frame = -1; - ru->prach_list[i].slot = -1; - ru->prach_list[i].num_slots = -1; - } - pthread_mutex_init(&ru->prach_list_mutex, NULL); -} - -int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type) -{ - AssertFatal(ru != NULL, "ru is null\n"); - pthread_mutex_lock(&ru->prach_list_mutex); - for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { - RU_PRACH_list_t *p = ru->prach_list + i; - LOG_D(PHY, "searching for PRACH in %d.%d : prach_index %d=> %d.%d\n", frame, slot, i, p->frame, p->slot); - if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) { - pthread_mutex_unlock(&ru->prach_list_mutex); - return i; - } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) { - pthread_mutex_unlock(&ru->prach_list_mutex); - return i; - } - } - pthread_mutex_unlock(&ru->prach_list_mutex); - return -1; -} - -void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_id) -{ - int prach_id = find_nr_prach_ru(ru, SFN, Slot, SEARCH_EXIST_OR_FREE); - AssertFatal((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX), - "illegal or no prach_id found!!! prach_id %d\n", - prach_id); - - pthread_mutex_lock(&ru->prach_list_mutex); - ru->prach_list[prach_id].frame = SFN; - ru->prach_list[prach_id].slot = Slot; - const int fmt = prach_pdu->prach_format; - ru->prach_list[prach_id].num_slots = (fmt < 4) ? get_long_prach_dur(fmt, ru->nr_frame_parms->numerology_index) : 1; - ru->prach_list[prach_id].fmt = fmt; - ru->prach_list[prach_id].numRA = prach_pdu->num_ra; - ru->prach_list[prach_id].beam = beam_id; - ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol; - ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas; - pthread_mutex_unlock(&ru->prach_list_mutex); -} - -void free_nr_ru_prach_entry(RU_t *ru, int prach_id) -{ - pthread_mutex_lock(&ru->prach_list_mutex); - ru->prach_list[prach_id].frame = -1; - ru->prach_list[prach_id].slot = -1; - pthread_mutex_unlock(&ru->prach_list_mutex); -} - -void rx_nr_prach_ru(RU_t *ru, - int prachFormat, - int numRA, - int beam, - int prachStartSymbol, - int prachStartSlot, - int prachOccasion, - int frame, - int slot) -{ - AssertFatal(ru != NULL,"ru is null\n"); - - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - int slot2 = slot; - int16_t *prach[ru->nb_rx]; - int prach_sequence_length = ru->config.prach_config.prach_sequence_length.value; - int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[numRA].k1.value; - const uint8_t prach_mu = ru->config.prach_config.prach_sub_c_spacing.value; - int sample_offset_slot; + const int sum = fp->ofdm_symbol_size + fp->nb_prefix_samples; + const int sum0 = fp->ofdm_symbol_size + fp->nb_prefix_samples0; if (prachStartSymbol == 0) { sample_offset_slot = 0; } else if (fp->slots_per_subframe == 1) { if (prachStartSymbol <= 7) - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * (prachStartSymbol - 1) + (fp->ofdm_symbol_size + fp->nb_prefix_samples0); + sample_offset_slot = sum * (prachStartSymbol - 1) + sum0; else - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * (prachStartSymbol - 2) + (fp->ofdm_symbol_size + fp->nb_prefix_samples0) * 2; + sample_offset_slot = sum * (prachStartSymbol - 2) + sum0 * 2; } else { - if (!(slot%(fp->slots_per_subframe/2))) - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * (prachStartSymbol - 1) + (fp->ofdm_symbol_size + fp->nb_prefix_samples0); + if (!(p->slot % (fp->slots_per_subframe / 2))) + sample_offset_slot = sum * (prachStartSymbol - 1) + sum0; else - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * prachStartSymbol; + sample_offset_slot = sum * prachStartSymbol; } LOG_D(PHY, "frame %d, slot %d: doing rx_nr_prach_ru for format %d, numRA %d, prachStartSymbol %d, prachOccasion %d\n", - frame, - slot, - prachFormat, - numRA, + p->frame, + p->slot, + p->pdu.prach_format, + p->pdu.num_ra, prachStartSymbol, prachOccasion); - - int16_t **rxsigF = ru->prach_rxsigF[prachOccasion]; - - AssertFatal(ru->if_south == LOCAL_RF || ru->if_south == REMOTE_IF5, - "we shouldn't call this if if_south != LOCAL_RF or REMOTE_IF5\n"); - - for (int aa = 0; aa < ru->nb_rx; aa++) { - if (prach_sequence_length == 0) - slot2 = prachStartSlot; - int idx = aa + beam * ru->nb_rx; - prach[aa] = (int16_t*)&ru->common.rxdata[idx][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - ru->N_TA_offset]; - } - int reps; int Ncp; int dftlen; - int mu = fp->numerology_index; + int mu = p->numerology_index; - if (prach_sequence_length == 0) { + if (p->prach_sequence_length == 0) { LOG_D(PHY, - "PRACH (ru %d) in %d.%d, format %d, msg1_frequencyStart %d\n", - ru->idx, - frame, - slot2, - prachFormat, - msg1_frequencystart); - switch (prachFormat) { - case 0: - reps = 1; - Ncp = 3168; - dftlen = 24576; - break; + "PRACH in %d.%d, format %d, msg1_frequencyStart %d\n", + p->frame, + p->slot, + p->pdu.prach_format, + p->msg1_frequencystart); + switch (p->pdu.prach_format) { + case 0: + reps = 1; + Ncp = 3168; + dftlen = 24576; + break; - case 1: - reps = 2; - Ncp = 21024; - dftlen = 24576; - break; + case 1: + reps = 2; + Ncp = 21024; + dftlen = 24576; + break; - case 2: - reps = 4; - Ncp = 4688; - dftlen = 24576; - break; + case 2: + reps = 4; + Ncp = 4688; + dftlen = 24576; + break; - case 3: - reps = 4; - Ncp = 3168; - dftlen = 6144; - break; + case 3: + reps = 4; + Ncp = 3168; + dftlen = 6144; + break; - default: - AssertFatal(1==0, "Illegal prach format %d for length 839\n", prachFormat); - break; + default: + AssertFatal(1 == 0, "Illegal prach format %d for length 839\n", p->pdu.prach_format); + break; } - } - else { + } else { LOG_D(PHY, - "PRACH (ru %d) in %d.%d, format %s, msg1_frequencyStart %d,startSymbol %d\n", - ru->idx, - frame, - slot, - prachfmt[prachFormat], - msg1_frequencystart, - prachStartSymbol); - switch (prachFormat) { - case 4: //A1 - reps = 2; - Ncp = 288 >> mu; - break; + "PRACH in %d.%d, format %s, msg1_frequencyStart %d,startSymbol %d\n", + p->frame, + p->slot, + prachfmt[p->pdu.prach_format], + p->msg1_frequencystart, + prachStartSymbol); + switch (p->pdu.prach_format) { + case 4: // A1 + reps = 2; + Ncp = 288 >> mu; + break; - case 5: //A2 - reps = 4; - Ncp = 576 >> mu; - break; + case 5: // A2 + reps = 4; + Ncp = 576 >> mu; + break; - case 6: //A3 - reps = 6; - Ncp = 864 >> mu; - break; + case 6: // A3 + reps = 6; + Ncp = 864 >> mu; + break; - case 7: //B1 - reps = 2; - Ncp = 216 >> mu; - break; + case 7: // B1 + reps = 2; + Ncp = 216 >> mu; + break; - /* - // B2 and B3 do not exist in FAPI - case 4: //B2 - reps = 4; - Ncp = 360 >> mu; - break; + /* + // B2 and B3 do not exist in FAPI + case 4: //B2 + reps = 4; + Ncp = 360 >> mu; + break; - case 5: //B3 - reps = 6; - Ncp = 504 >> mu; - break; - */ + case 5: //B3 + reps = 6; + Ncp = 504 >> mu; + break; + */ - case 8: //B4 - reps = 12; - Ncp = 936 >> mu; - break; + case 8: // B4 + reps = 12; + Ncp = 936 >> mu; + break; - case 9: //C0 - reps = 1; - Ncp = 1240 >> mu; - break; + case 9: // C0 + reps = 1; + Ncp = 1240 >> mu; + break; - case 10: //C2 - reps = 4; - Ncp = 2048 >> mu; - break; + case 10: // C2 + reps = 4; + Ncp = 2048 >> mu; + break; - default: - AssertFatal(1==0,"unknown prach format %x\n",prachFormat); - break; + default: + AssertFatal(1 == 0, "unknown prach format %x\n", p->pdu.prach_format); + break; } dftlen = 2048 >> mu; } @@ -323,12 +267,11 @@ void rx_nr_prach_ru(RU_t *ru, //actually what we should be checking here is how often the current prach crosses a 0.5ms boundary. //I am not quite sure for which paramter set this would be the case, //so I will ignore it for now and just check if the prach starts on a 0.5ms boundary - if(fp->numerology_index == 0) { + if (p->numerology_index == 0) { if (prachStartSymbol == 0 || prachStartSymbol == 7) Ncp += 16; - } - else { - if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + } else { + if (p->slot % (fp->slots_per_subframe / 2) == 0 && prachStartSymbol == 0) Ncp += 16; } @@ -399,183 +342,156 @@ void rx_nr_prach_ru(RU_t *ru, // Do forward transform if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - LOG_D(PHY, "rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d dftlen:%d\n", ru->nb_rx, Ncp, dftlen); + LOG_D(PHY, "rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d dftlen:%d\n", p->nb_rx, Ncp, dftlen); } - const unsigned int K = get_prach_K(prach_sequence_length, prachFormat, fp->numerology_index, prach_mu); - const uint8_t kbar = get_PRACH_k_bar(prach_mu, fp->numerology_index); + const unsigned int K = get_prach_K(p->prach_sequence_length, p->pdu.prach_format, p->numerology_index, p->mu); + const uint8_t kbar = get_PRACH_k_bar(p->mu, p->numerology_index); - int n_ra_prb = msg1_frequencystart; + int n_ra_prb = p->msg1_frequencystart; int k = (12*n_ra_prb) - 6*fp->N_RB_UL; - int N_ZC = (prach_sequence_length==0)?839:139; + int N_ZC = (p->prach_sequence_length == 0) ? 839 : 139; if (k<0) k+=(fp->ofdm_symbol_size); k*=K; k+=kbar; - for (int aa=0; aanb_rx; aa++) { - AssertFatal(prach[aa]!=NULL,"prach[%d] is null\n",aa); + for (int aa = 0; aa < p->nb_rx; aa++) { + // Fixme: slot or slot makes no sense ??? + int slot2 = p->prach_sequence_length ? p->slot : p->slot; + int idx = aa + beam_id * p->nb_rx; + c16_t *prach = (c16_t *)&rxdata[idx][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - N_TA_offset]; // do DFT - int16_t *prach2 = prach[aa] + (2*Ncp); // times 2 for complex samples - for (int i = 0; i < reps; i++) - dft(dftsize, prach2 + 2*dftlen*i, rxsigF[aa] + 2*dftlen*i, 1); - - //LOG_M("ru_rxsigF_tmp.m","rxsFtmp", rxsigF[aa], dftlen*2*reps, 1, 1); - - //Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH) - LOG_D(PHY,"Doing PRACH combining of %d reptitions N_ZC %d\n",reps,N_ZC); - int16_t rxsigF_tmp[N_ZC<<1]; - // if (k+N_ZC > dftlen) { // PRACH signal is split around DC - int16_t *rxsigF2=rxsigF[aa]; - int k2=k<<1; - - for (int j=0;j dftlen) { // PRACH signal is split around DC + int k2 = k; + for (int j = 0; j < N_ZC; j++, k2++) { + if (k2 == dftlen) + k2 = 0; + rxsigF_tmp[j] = c16add(rxsigF_tmp[j], tmp[k2]); + } } - memcpy((void*)rxsigF2,(void *)rxsigF_tmp,N_ZC<<2); + memcpy(p->rxsigF[prachOccasion][aa], rxsigF_tmp, sizeof(rxsigF_tmp)); } } -void rx_nr_prach(PHY_VARS_gNB *gNB, - nfapi_nr_prach_pdu_t *prach_pdu, - int prachOccasion, - int frame, - int slot, - uint16_t *max_preamble, - uint16_t *max_preamble_energy, - uint16_t *max_preamble_delay) +void rx_nr_prach_ru(prach_item_t *p, int32_t **rxdata, NR_DL_FRAME_PARMS *fp, int N_TA_offset) { - AssertFatal(gNB != NULL, "Can only be called from gNB\n"); - nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; - NR_DL_FRAME_PARMS *fp; + int N_dur = get_nr_prach_duration(p->pdu.prach_format); + LOG_D(NR_PHY_RACH, "%d.%d try to decode %d occasions \n", p->frame, p->slot, p->pdu.num_prach_ocas); + for (int prach_oc = 0; prach_oc < p->pdu.num_prach_ocas; prach_oc++) { + int prachStartSymbol = p->pdu.prach_start_symbol + prach_oc * N_dur; + int beam_id = p->beams[prach_oc]; + // 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_ru_internal(p, beam_id, prachStartSymbol, prach_oc, rxdata, fp, N_TA_offset); + } +} - uint16_t rootSequenceIndex; - int numrootSequenceIndex; - uint8_t restricted_set; - uint8_t n_ra_prb=0xFF; - int nb_rx; +rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion) +{ + rx_prach_out_t out = {}; + uint16_t preamble_index0 = 0; + uint16_t numshift = 0; + int first_nonzero_root_idx = 0; + bool new_dft = false; + int log2_ifft_size = 10; - int16_t **rxsigF = gNB->prach_vars.rxsigF; + const int nb_rx = in->nb_rx; + const int NCS = in->pdu.num_cs; + const int prach_fmt = in->pdu.prach_format; + const int N_ZC = in->prach_sequence_length == 0 ? 839 : 139; - uint8_t preamble_index; - uint16_t NCS=99,NCS2; - uint16_t preamble_offset=0,preamble_offset_old; - int16_t preamble_shift=0; - uint32_t preamble_shift2; - uint16_t preamble_index0=0,n_shift_ra=0,n_shift_ra_bar; - uint16_t d_start=0; - uint16_t numshift=0; - const uint16_t *prach_root_sequence_map; - uint8_t not_found; - uint16_t u; - int16_t *Xu=0; - uint16_t first_nonzero_root_idx=0; - uint8_t new_dft=0; - int32_t lev; - int16_t levdB; - int log2_ifft_size=10; - int16_t prach_ifft_tmp[2048*2] __attribute__((aligned(32))); - int32_t *prach_ifft=(int32_t*)NULL; - - fp = &gNB->frame_parms; + LOG_D(NR_PHY_RACH, + "L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d, format %d \n", + in->rootSequenceIndex, + in->numrootSequenceIndex, + NCS, + N_ZC, + prach_fmt); - nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value; - rootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].prach_root_sequence_index.value; - numrootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].num_root_sequences.value; - NCS = prach_pdu->num_cs;//cfg->num_prach_fd_occasions_list[0].prach_zero_corr_conf.value; - int prach_sequence_length = cfg->prach_sequence_length.value; - int msg1_frequencystart = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].k1.value; - // int num_unused_root_sequences = cfg->num_prach_fd_occasions_list[0].num_unused_root_sequences.value; - // cfg->num_prach_fd_occasions_list[0].unused_root_sequences_list - - restricted_set = cfg->restricted_set_config.value; - - uint8_t prach_fmt = prach_pdu->prach_format; - uint16_t N_ZC = (prach_sequence_length==0)?839:139; - - LOG_D(PHY,"L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d, format %d \n",rootSequenceIndex,numrootSequenceIndex,NCS,N_ZC,prach_fmt); - - prach_ifft = gNB->prach_vars.prach_ifft; if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - if ((frame&1023) < 20) LOG_D(PHY,"PRACH (gNB) : running rx_prach for slot %d, msg1_frequencystart %d, rootSequenceIndex %d\n", slot, msg1_frequencystart, rootSequenceIndex); + if ((in->frame & 1023) < 20) + LOG_D(PHY, "PRACH (gNB) : running rx_prach for slot %d, rootSequenceIndex %d\n", in->slot, in->rootSequenceIndex); } - start_meas(&gNB->rx_prach); + start_meas(in->rx_prach); - prach_root_sequence_map = (cfg->prach_sequence_length.value==0) ? prach_root_sequence_map_0_3 : prach_root_sequence_map_abc; + const uint16_t *prach_root_sequence_map = + in->prach_sequence_length == 0 ? prach_root_sequence_map_0_3 : prach_root_sequence_map_abc; // PDP is oversampled, e.g. 1024 sample instead of 839 // Adapt the NCS (zero-correlation zones) with oversampling factor e.g. 1024/839 - NCS2 = (N_ZC==839) ? ((NCS<<10)/839) : ((NCS<<8)/139); + int NCS2 = N_ZC == 839 ? (NCS << 10) / 839 : (NCS << 8) / 139; - if (NCS2==0) NCS2 = N_ZC; + if (NCS2 == 0) + NCS2 = N_ZC; + int preamble_offset = 0, preamble_offset_old = 99; - preamble_offset_old = 99; - - - *max_preamble_energy = 0; - *max_preamble_delay = 0; - *max_preamble = 0; - int16_t prachF[2 * 1024]; - for (preamble_index=0 ; preamble_index<64 ; preamble_index++) { + int16_t preamble_shift = 0; + const int dft_sz = N_ZC == 839 ? 1024 : 256; + int32_t prach_ifft[dft_sz] __attribute__((aligned(32))); + for (int preamble_index = 0; preamble_index < 64; preamble_index++) { if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],(N_ZC==839) ? 840: 140)); - if (en>60) LOG_D(PHY,"frame %d, slot %d : Trying preamble %d \n",frame,slot,preamble_index); + int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], N_ZC == 839 ? 840 : 140)); + if (en > 60) + LOG_D(PHY, "frame %d, slot %d : Trying preamble %d \n", in->frame, in->slot, preamble_index); } - if (restricted_set == 0) { + if (in->restricted_set == 0) { // This is the relative offset in the root sequence table (5.7.2-4 from 36.211) for the given preamble index preamble_offset = ((NCS==0)? preamble_index : (preamble_index/(N_ZC/NCS))); if (preamble_offset != preamble_offset_old) { preamble_offset_old = preamble_offset; - new_dft = 1; + new_dft = true; // This is the \nu corresponding to the preamble index preamble_shift = 0; - } - - else { - preamble_shift -= NCS; + } else { + preamble_shift -= NCS; if (preamble_shift < 0) - preamble_shift+=N_ZC; + preamble_shift += N_ZC; } } else { // This is the high-speed case - new_dft = 0; + new_dft = false; uint16_t nr_du[NR_PRACH_SEQ_LEN_L - 1]; nr_fill_du(N_ZC, prach_root_sequence_map, nr_du); // set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this // preamble index and find the corresponding cyclic shift // Check if all shifts for that root have been processed + int n_shift_ra = 0, n_shift_ra_bar, d_start = 0; if (preamble_index0 == numshift) { - not_found = 1; - new_dft = 1; + bool not_found = true; + new_dft = true; preamble_index0 -= numshift; - //(preamble_offset==0 && numshift==0) ? (preamble_offset) : (preamble_offset++); - - while (not_found == 1) { + while (not_found) { // current root depending on rootSequenceIndex - int index = (rootSequenceIndex + preamble_offset) % N_ZC; - - u = prach_root_sequence_map[index]; - + int index = (in->rootSequenceIndex + preamble_offset) % N_ZC; + int u = nr_du[prach_root_sequence_map[index]]; uint16_t n_group_ra = 0; - - if ((nr_du[u] < (N_ZC / 3)) && (nr_du[u] >= NCS) ) { - n_shift_ra = nr_du[u] / NCS; - d_start = (nr_du[u] << 1) + (n_shift_ra * NCS); + + if (u < (N_ZC / 3) && u >= NCS) { + n_shift_ra = u / NCS; + d_start = (u << 1) + (n_shift_ra * NCS); n_group_ra = N_ZC / d_start; - n_shift_ra_bar = max(0, (N_ZC-(nr_du[u] << 1) - (n_group_ra * d_start)) / N_ZC); - } else if ((nr_du[u] >= (N_ZC / 3)) && (nr_du[u] <= ((N_ZC - NCS) >> 1))) { - n_shift_ra = (N_ZC - (nr_du[u] << 1)) / NCS; - d_start = N_ZC - (nr_du[u] << 1) + (n_shift_ra * NCS); - n_group_ra = nr_du[u] / d_start; - n_shift_ra_bar = min(n_shift_ra, max(0, (nr_du[u]- (n_group_ra * d_start)) / NCS)); + n_shift_ra_bar = max(0, (N_ZC - (u << 1) - (n_group_ra * d_start)) / N_ZC); + } else if (u >= (N_ZC / 3) && u <= ((N_ZC - NCS) >> 1)) { + n_shift_ra = (N_ZC - (u << 1)) / NCS; + d_start = N_ZC - (u << 1) + (n_shift_ra * NCS); + n_group_ra = u / d_start; + n_shift_ra_bar = min(n_shift_ra, max(0, (u - (n_group_ra * d_start)) / NCS)); } else { n_shift_ra = 0; n_shift_ra_bar = 0; @@ -584,12 +500,13 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, // This is the number of cyclic shifts for the current root u numshift = (n_shift_ra * n_group_ra) + n_shift_ra_bar; // skip to next root and recompute parameters if numshift==0 - (numshift>0) ? (not_found = 0) : (preamble_offset++); + numshift > 0 ? not_found = false : preamble_offset++; } } if (n_shift_ra>0) - preamble_shift = -((d_start * (preamble_index0/n_shift_ra)) + ((preamble_index0%n_shift_ra)*NCS)); // minus because the channel is h(t -\tau + Cv) + preamble_shift = -(d_start * (preamble_index0 / n_shift_ra) + + (preamble_index0 % n_shift_ra) * NCS); // minus because the channel is h(t -\tau + Cv) else preamble_shift = 0; @@ -602,14 +519,14 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, first_nonzero_root_idx = preamble_offset; } - // Compute DFT of RX signal (conjugate input, results in conjugate output) for each new rootSequenceIndex + // Compute DFT of RX signal (conjugate in->rxsigF[occasion], results in conjugate output) for each new rootSequenceIndex if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840)); + int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], 840)); if (en>60) LOG_D(PHY, "frame %d, slot %d : preamble index %d, NCS %d, N_ZC/NCS %d: offset %d, preamble shift %d , en %d)\n", - frame, - slot, + in->frame, + in->slot, preamble_index, NCS, N_ZC / NCS, @@ -618,44 +535,37 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, en); } - LOG_D(PHY,"PRACH RX preamble_index %d, preamble_offset %d\n",preamble_index,preamble_offset); + LOG_D(NR_PHY_RACH, + "PRACH RX preamble_index %d, preamble_offset %d, preamb shift %d new dft %d\n", + preamble_index, + preamble_offset, + preamble_shift, + new_dft); + if (new_dft) { + new_dft = false; - if (new_dft == 1) { - new_dft = 0; - - Xu = (int16_t*)gNB->X_u[preamble_offset-first_nonzero_root_idx]; - + c16_t *Xu = in->Xu[preamble_offset - first_nonzero_root_idx]; LOG_D(PHY,"PRACH RX new dft preamble_offset-first_nonzero_root_idx %d\n",preamble_offset-first_nonzero_root_idx); - memset(prach_ifft,0,((N_ZC==839) ? 2048 : 256)*sizeof(int32_t)); - memset(prachF, 0, sizeof(int16_t) * 2 * 1024); + memset(prach_ifft, 0, sizeof(prach_ifft)); if (LOG_DUMPFLAG(DEBUG_PRACH)) { - LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],N_ZC,1,1); - LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1); + LOG_M("prach_rxF0.m", "prach_rxF0", in->rxsigF[occasion][0], N_ZC, 1, 1); + LOG_M("prach_rxF1.m", "prach_rxF1", in->rxsigF[occasion][1], 6144, 1, 1); } - + c16_t prachF[dft_sz] __attribute__((aligned(32))); for (int aa = 0; aa < nb_rx; aa++) { - // Do componentwise product with Xu* on each antenna - - for (int offset = 0; offset < (N_ZC << 1); offset += 2) { - prachF[offset] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset] + (int32_t)Xu[offset+1]*rxsigF[aa][offset+1])>>15); - prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset+1] - (int32_t)Xu[offset+1]*rxsigF[aa][offset])>>15); + // Do componentwise product with Xu* on each antenna + for (int offset = 0; offset < N_ZC; offset++) { + prachF[offset] = c16MulConjShift(Xu[offset], in->rxsigF[occasion][aa][offset], 15); } - + memset(prachF + N_ZC, 0, sizeof(*prachF) * (dft_sz - N_ZC)); // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) - if (N_ZC == 839) { - idft(IDFT_1024, prachF, prach_ifft_tmp, 1); - // compute energy and accumulate over receive antennas - for (int i = 0; i < 1024; i++) - prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[i<<1] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)]; - } else { - idft(IDFT_256, prachF, prach_ifft_tmp, 1); - log2_ifft_size = 8; - // compute energy and accumulate over receive antennas and repetitions for BR - for (int i = 0; i < 256; i++) - prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)]; - } + c16_t prach_ifft_tmp[dft_sz] __attribute__((aligned(32))); + idft(get_idft(dft_sz), (int16_t *)prachF, (int16_t *)prach_ifft_tmp, 1); + // compute energy and accumulate over receive antennas + for (int i = 0; i < dft_sz; i++) + prach_ifft[i] += squaredMod(prach_ifft_tmp[i]); if (LOG_DUMPFLAG(DEBUG_PRACH)) { if (aa == 0) @@ -678,23 +588,22 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, } } // new dft - - // check energy in nth time shift, for - preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<*max_preamble_energy) { - LOG_D(PHY,"preamble_index %d, delay %d en %d dB > %d dB\n",preamble_index,i,levdB,*max_preamble_energy); - *max_preamble_energy = levdB; - *max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate - *max_preamble = preamble_index; + int lev = prach_ifft[preamble_shift2 + i]; + int levdB = dB_fixed_times10(lev); + if (levdB > out.max_preamble_energy || (levdB == out.max_preamble_energy && out.max_preamble_delay > i)) { + LOG_D(NR_PHY_RACH, "preamble_index %d, delay %d en %d dB > %d dB\n", preamble_index, i, levdB, out.max_preamble_energy); + out.max_preamble_energy = levdB; + out.max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate + out.max_preamble = preamble_index; } } - }// preamble_index - + } // preamble_index // The conversion from *max_preamble_delay from TA value is done here. // It is normalized to the 30.72 Ms/s, considering the numerology, N_RB and the sampling rate @@ -711,34 +620,15 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, // Format >3: 2048/2^mu samples @ 30.72 Ms/s, 2048/2^mu * 4 samples @ 122.88 Ms/s // By solving: // max_preamble_delay * ( (2048/2^mu*(fs/30.72M)) / 256 ) / fs = TA * 16 * 64 / 2^mu * Tc - uint16_t *TA = max_preamble_delay; - int mu = fp->numerology_index; - if (cfg->prach_sequence_length.value == 0) { + int mu = in->numerology_index; + if (in->prach_sequence_length == 0) { if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2) - *TA = *TA * 3 * (1 << mu) / 2; + out.max_preamble_delay *= 3 * (1 << mu) / 2; else if (prach_fmt == 3) - *TA = *TA * 3 * (1 << mu) / 8; - } - else *TA = *TA/2; - - if (LOG_DUMPFLAG(DEBUG_PRACH)) { - //int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840)); - // if (en>60) { - int k = (12 * n_ra_prb) - 6 * fp->N_RB_UL; - if (k < 0) - k += fp->ofdm_symbol_size; - - k*=12; - k+=13; - k*=2; - - LOG_M("rxsigF.m","prach_rxF", &rxsigF[0][0], 12288, 1, 1); - LOG_M("prach_rxF_comp0.m","prach_rxF_comp0", prachF, 1024, 1, 1); - LOG_M("Xu.m","xu", Xu, N_ZC, 1, 1); - LOG_M("prach_ifft0.m","prach_t0", prach_ifft, 1024, 1, 1); - // } - } - stop_meas(&gNB->rx_prach); + out.max_preamble_delay *= 3 * (1 << mu) / 8; + } else + out.max_preamble_delay /= 2; + stop_meas(in->rx_prach); + return out; } - diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index a7769dc84d..0714f3dde3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -200,32 +200,18 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu); -int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); +prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); -void rx_nr_prach(PHY_VARS_gNB *gNB, - nfapi_nr_prach_pdu_t *prach_pdu, - int prachOccasion, - int frame, - int subframe, - uint16_t *max_preamble, - uint16_t *max_preamble_energy, - uint16_t *max_preamble_delay); +typedef struct rx_prach_out { + uint16_t max_preamble; + uint16_t max_preamble_energy; + uint16_t max_preamble_delay; +} rx_prach_out_t; +rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion); -void rx_nr_prach_ru(RU_t *ru, - int prach_fmt, - int numRA, - int beam, - int prachStartSymbol, - int prachStartSlot, - int prachOccasion, - int frame, - int subframe); - -void nr_fill_prach_ru(RU_t *ru,int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_nb); - -int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, find_type_t type); -int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type); +void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset); +prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, find_type_t type); void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -245,12 +231,9 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); -void init_prach_list(PHY_VARS_gNB *gNB); -void init_prach_ru_list(RU_t *ru); -void free_nr_ru_prach_entry(RU_t *ru, int prach_id); int get_nr_prach_duration(uint8_t prach_format); -void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id); +void free_nr_prach_entry(prach_list_t *, prach_item_t *); void nr_decode_pucch1(c16_t **rxdataF, pucch_GroupHopping_t pucch_GroupHopping, diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index e72465c4a9..0e21f37fde 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -190,19 +190,6 @@ typedef struct { task_ans_t *ans; } feptx_cmd_t; -typedef struct { - int frame; - int slot; - int fmt; - int numRA; - int prachStartSymbol; - int num_prach_ocas; - int num_slots; - int *beam; -} RU_PRACH_list_t; - -#define NUMBER_OF_NR_RU_PRACH_MAX 8 -#define NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX 12 #define RU_RX_SLOT_DEPTH 4 typedef struct RU_proc_t_s { /// Pointer to associated RU descriptor @@ -604,11 +591,7 @@ typedef struct RU_t_s { int32_t *bw_list[NUMBER_OF_eNB_MAX+1]; /// beamforming weight vectors int32_t **beam_weights[NUMBER_OF_eNB_MAX+1][15]; - /// prach commands - RU_PRACH_list_t prach_list[NUMBER_OF_NR_RU_PRACH_MAX]; - /// mutex for prach_list access - pthread_mutex_t prach_list_mutex; - /// received frequency-domain signal for PRACH (IF4p5 RRU) + /// received frequency-domain signal for PRACH (IF4p5 RRU) int16_t **prach_rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX]; /// received frequency-domain signal for PRACH BR (IF4p5 RRU) int16_t **prach_rxsigF_br[4]; diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index b6619efc6e..dbb07a9bbb 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -993,6 +993,9 @@ extern int sync_var; #define MBSFN_FDD_SF6 0x10 #define MBSFN_FDD_SF7 0x08 #define MBSFN_FDD_SF8 0x04 + +#define NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX 12 + typedef struct { pthread_mutex_t mutex_failure; bool failed; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index ebf459402e..ad08cc1df1 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -134,28 +134,6 @@ typedef struct { nfapi_nr_dl_tti_ssb_pdu ssb_pdu; } NR_gNB_SSB_t; -typedef struct { - int frame; - int slot; - // identifier for concurrent beams - // prach duration in slots - int num_slots; - int *beam_nb; - nfapi_nr_prach_pdu_t pdu; -} gNB_PRACH_list_t; - -#define NUMBER_OF_NR_PRACH_MAX 8 - -typedef struct { - /// \brief ?. - /// second index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx. - /// third index: frequency-domain sample [0..ofdm_symbol_size*12[ - int16_t **rxsigF; - /// \brief local buffer to compute prach_ifft - int32_t *prach_ifft; - gNB_PRACH_list_t list[NUMBER_OF_NR_PRACH_MAX]; -} NR_gNB_PRACH; - typedef struct { uint8_t NumPRSResources; prs_config_t prs_cfg[NR_MAX_PRS_RESOURCES_PER_SET]; @@ -430,7 +408,7 @@ typedef struct PHY_VARS_gNB_s { int max_nb_pusch; NR_gNB_COMMON common_vars; - NR_gNB_PRACH prach_vars; + prach_list_t prach_list; NR_gNB_PRS prs_vars; NR_gNB_PUSCH *pusch_vars; NR_gNB_PUCCH_t *pucch; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 0d1cab4045..f4681020eb 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -133,6 +133,34 @@ typedef struct { int resource_type; } nr_srs_info_t; +#define NUMBER_OF_NR_PRACH_MAX 8 +typedef struct { + int frame; + int slot; + int num_slots; // prach duration in slots + int beams[NFAPI_MAX_NUM_BG_IF]; + nfapi_nr_prach_pdu_t pdu; + int rootSequenceIndex; + int numrootSequenceIndex; + int msg1_frequencystart; + int mu; + int prach_sequence_length; + int restricted_set; + int numerology_index; + int nb_rx; + c16_t rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L]; + c16_t (*Xu)[839]; + time_stats_t *rx_prach; +} prach_item_t; + +typedef struct { + /// prach commands + prach_item_t list[NUMBER_OF_NR_PRACH_MAX]; + /// mutex for prach_list access + pthread_mutex_t prach_list_mutex; +} prach_list_t; +void init_prach_list(prach_list_t *); + typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS; typedef uint32_t (*get_samples_per_slot_t)(int slot, const NR_DL_FRAME_PARMS *fp); diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index d61f0d0548..be532a0c54 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -41,15 +41,10 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu){} -void nr_fill_prach(PHY_VARS_gNB *gNB, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} -void nr_fill_prach_ru(RU_t *ru, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} - +void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) +{ +} + void nr_phy_config_request(NR_PHY_Config_t *gNB){} void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c index 9c9ecea443..7377a455dd 100644 --- a/openair1/SCHED/nfapi_nr_dummy.c +++ b/openair1/SCHED/nfapi_nr_dummy.c @@ -37,15 +37,10 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu){} -void nr_fill_prach(PHY_VARS_gNB *gNB, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} -void nr_fill_prach_ru(RU_t *ru, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} - +void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) +{ +} + void nr_phy_config_request(NR_PHY_Config_t *gNB){} void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 74a2178982..9e4ab67efc 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -127,44 +127,28 @@ void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti int slot = UL_tti_req->Slot; for (int i = 0; i < UL_tti_req->n_pdus; i++) { - switch (UL_tti_req->pdus_list[i].pdu_type) { + int type = UL_tti_req->pdus_list[i].pdu_type; + LOG_D(NR_PHY, + "frame %d, slot %d got %s for %d.%d\n", + frame, + slot, + txt_nfapi_nr_ul_config_pdu_type[type], + UL_tti_req->SFN, + UL_tti_req->Slot); + switch (type) { case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); break; case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); break; - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; - int id = nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - if (gNB->RU_list[0]->if_south == LOCAL_RF || gNB->RU_list[0]->if_south == REMOTE_IF5) - nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu, gNB->prach_vars.list[id].beam_nb); - break; + prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + if (!prach) + LOG_W(NR_PHY_RACH, "Error in scheduling rach\n"); + } break; case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu); break; } diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index c56a37ca1d..e6cd15b4a9 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -49,99 +49,86 @@ int get_nr_prach_duration(uint8_t prach_format) 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]; + prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, SEARCH_EXIST); + if (!prach_id) { + return; + } - 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; - int N_dur = get_nr_prach_duration(prach_pdu->prach_format); + nfapi_nr_prach_pdu_t *prach_pdu = &prach_id->pdu; + LOG_D(NR_PHY_RACH, "%d.%d, prachstart slot %d prach entry occas %d\n", frame, slot, prach_id->slot, prach_pdu->num_prach_ocas); + const int prach_start_slot = prach_id->slot; + int 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_aanb_rx;ru_aa++,aa++) { - gNB->prach_vars.rxsigF[aa] = ru->prach_rxsigF[prach_oc][ru_aa]; - } + for (int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) { + uint 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_prach_out_t res = rx_nr_prach(prach_id, prach_oc); + 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, + res.max_preamble, + res.max_preamble_energy / 10, + res.max_preamble_energy % 10, + res.max_preamble_delay, + gNB->prach_energy_counter); - 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}. + if ((gNB->prach_energy_counter == NUM_PRACH_RX_FOR_NOISE_ESTIMATE) + && (res.max_preamble_energy > 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, + res.max_preamble, + res.max_preamble_energy / 10, + res.max_preamble_energy % 10, + gNB->measurements.prach_I0, + gNB->prach_thres, + res.max_preamble_delay, + prachStartSymbol, + prach_pdu->num_ra); - 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); + T(T_ENB_PHY_INITIATE_RA_PROCEDURE, + T_INT(gNB->Mod_id), + T_INT(frame), + T_INT(slot), + T_INT(res.max_preamble), + T_INT(res.max_preamble_energy), + T_INT(res.max_preamble_delay)); - if ((gNB->prach_energy_counter == NUM_PRACH_RX_FOR_NOISE_ESTIMATE) - && (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 < NUM_PRACH_RX_FOR_NOISE_ESTIMATE) - gNB->prach_energy_counter++; - } //if prach_id>0 - rach_ind->slot = prach_start_slot; - } // for NUMBER_OF_NR_PRACH_OCCASION_MAX + nfapi_nr_prach_indication_pdu_t *ind = rach_ind->pdu_list + rach_ind->number_of_pdus; + *ind = (nfapi_nr_prach_indication_pdu_t){ + .phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value, + .symbol_index = prachStartSymbol, + .slot_index = slot, + .freq_index = prach_pdu->num_ra, + .avg_rssi = (res.max_preamble_energy < 631) ? (128 + (res.max_preamble_energy / 5)) : 254, + .avg_snr = 0xff, // invalid for now + .num_preamble = 1, + .preamble_list = { + {.preamble_index = res.max_preamble, .timing_advance = res.max_preamble_delay, .preamble_pwr = 0xffffffff}}}; + rach_ind->number_of_pdus++; + } + gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0 * 900) >> 10) + ((res.max_preamble_energy * 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 < NUM_PRACH_RX_FOR_NOISE_ESTIMATE) + gNB->prach_energy_counter++; + } // if prach_id>0 + rach_ind->slot = prach_start_slot; + LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n"); + free_nr_prach_entry(&gNB->prach_list, prach_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 35e242cad3..aba532a80d 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -135,10 +135,11 @@ int main(int argc, char **argv){ double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs=-1, bw; int i, l, aa, aarx, trial, n_frames = 1, rx_prach_start; //, ntrials=1; c16_t **txdata; - int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0; + int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, + loglvl = OAILOG_INFO; uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0; uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0; - uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format0, format1; + uint16_t Nid_cell = 0, preamble_tx = 0, format0, format1; uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB; uint64_t SSB_positions = 0x01; uint16_t RA_sfn_index; @@ -151,9 +152,7 @@ int main(int argc, char **argv){ NR_DL_FRAME_PARMS *frame_parms; nfapi_nr_prach_config_t *prach_config; - nfapi_nr_prach_pdu_t *prach_pdu; fapi_nr_prach_config_t *ue_prach_config; - fapi_nr_ul_config_prach_pdu *ue_prach_pdu; channel_desc_t *UE2gNB; SCM_t channel_model = Rayleigh1; @@ -417,7 +416,6 @@ int main(int argc, char **argv){ ru = RC.ru[0]; frame_parms = &gNB->frame_parms; prach_config = &gNB->gNB_config.prach_config; - prach_pdu = &gNB->prach_vars.list[0].pdu; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) s_re = malloc(2*sizeof(double*)); @@ -561,9 +559,6 @@ int main(int argc, char **argv){ prach_config->restricted_set_config.value = restrictedSetConfig; prach_config->prach_sequence_length.value = prach_sequence_length; prach_config->prach_sub_c_spacing.value = mu; - prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); - prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); - prach_pdu->prach_format = prach_format; memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); RC.nb_nr_L1_inst=1; @@ -573,6 +568,10 @@ int main(int argc, char **argv){ phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); + nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_list.list[0].pdu; + prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); + prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); + prach_pdu->prach_format = prach_format; // Configure UE UE = malloc(sizeof(PHY_VARS_NR_UE)); @@ -588,7 +587,7 @@ int main(int argc, char **argv){ exit(-1); } - ue_prach_pdu = &UE->prach_vars[0]->prach_pdu; + fapi_nr_ul_config_prach_pdu *ue_prach_pdu = &UE->prach_vars[0]->prach_pdu; ue_prach_config = &UE->nrUE_config.prach_config; txdata = UE->common_vars.txData; @@ -716,9 +715,8 @@ int main(int argc, char **argv){ } rx_prach_start = subframe*frame_parms->samples_per_subframe; - if (n_frames==1) printf("slot %d, rx_prach_start %d\n",slot,rx_prach_start); - uint16_t preamble_rx, preamble_energy; - + if (n_frames == 1) + printf("slot %d, rx_prach_start %d\n", slot, rx_prach_start); for (SNR = snr0; SNR < snr1 && !stop; SNR += .1) { for (ue_speed = ue_speed0; ue_speed < ue_speed1 && !stop; ue_speed += 10) { @@ -729,8 +727,7 @@ int main(int argc, char **argv){ prach_errors=0; for (trial = 0; trial < n_frames && !stop; trial++) { - - if (input_fd==NULL) { + if (input_fd == NULL) { sigma2_dB = 10*log10((double)tx_lev) - SNR - 10*log10(N_RB_UL*12/N_ZC); if (n_frames==1) @@ -757,45 +754,67 @@ int main(int argc, char **argv){ tmp->i = (short)(.167 * (r_im[aa][i] + (iqim * r_re[aa][i]) + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0))); } } - } else { - n_bytes = fread(&ru->common.rxdata[0][rx_prach_start],sizeof(int32_t),frame_parms->samples_per_subframe,input_fd); - printf("fread %d bytes from file %s\n",n_bytes,input_file); - if (n_bytes!=frame_parms->samples_per_subframe) { - printf("expected %d bytes\n",frame_parms->samples_per_subframe); - exit(-1); - } - } + } else { + n_bytes = fread(&ru->common.rxdata[0][rx_prach_start], sizeof(int32_t), frame_parms->samples_per_subframe, input_fd); + printf("fread %d bytes from file %s\n", n_bytes, input_file); + if (n_bytes != frame_parms->samples_per_subframe) { + printf("expected %d bytes\n", frame_parms->samples_per_subframe); + exit(-1); + } + } - for (l = 0; l < frame_parms->symbols_per_slot; l++) { - for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - nr_slot_fep_ul(frame_parms, ru->common.rxdata[aa], ru->common.rxdataF[aa], l, slot, ru->N_TA_offset); - } - } + for (l = 0; l < frame_parms->symbols_per_slot; l++) { + for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + nr_slot_fep_ul(frame_parms, ru->common.rxdata[aa], ru->common.rxdataF[aa], l, slot, ru->N_TA_offset); + } + } - rx_nr_prach_ru(ru, prach_format, numRA, 0, prachStartSymbol, slot, prachOccasion, frame, slot); + nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; + nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; + prach_pdu->num_prach_ocas=1; + prach_item_t in = {.frame = frame, + .slot = slot, + .pdu = *prach_pdu, + .rootSequenceIndex = occ->prach_root_sequence_index.value, + .numrootSequenceIndex = occ->num_root_sequences.value, + .msg1_frequencystart = occ->k1.value, + .mu = cfg->prach_sub_c_spacing.value, + .prach_sequence_length = cfg->prach_sequence_length.value, + .restricted_set = cfg->restricted_set_config.value, + .numerology_index = gNB->frame_parms.numerology_index, + .nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value, + .Xu = gNB->X_u, + .rx_prach = &gNB->rx_prach}; + rx_nr_prach_ru(&in, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); + if (n_frames == 1) + LOG_I(PHY, + "ncs %d,num_seq %d\n", + prach_pdu->num_cs, + prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); + rx_prach_out_t out = rx_nr_prach(&in, prachOccasion); - for (int i = 0; i < ru->nb_rx; ++i) - gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i]; - if (n_frames == 1) printf("ncs %d,num_seq %d\n",prach_pdu->num_cs, prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); - rx_nr_prach(gNB, prach_pdu, prachOccasion, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay); + // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", out.max_preamble_energy, out.max_preamble, + // preamble_tx); - // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx); - - if (preamble_rx != preamble_tx) + if (out.max_preamble != preamble_tx) prach_errors++; else - delay_avg += (double)preamble_delay; + delay_avg += (double)out.max_preamble_delay; N_ZC = (prach_sequence_length) ? 139 : 839; - if (n_frames==1) { - printf("preamble %d (tx %d) : energy %d, delay %d\n",preamble_rx,preamble_tx,preamble_energy,preamble_delay); + if (n_frames == 1) { + printf("preamble %d (tx %d) : energy %d, delay %d\n", + out.max_preamble, + preamble_tx, + out.max_preamble_energy, + out.max_preamble_delay); #ifdef NR_PRACH_DEBUG LOG_M("prach0.m","prach0", &txdata[0][prach_start], frame_parms->samples_per_subframe, 1, 1); LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1); - LOG_M("ru_prach_rxsigF0.m","rxsF0", ru->prach_rxsigF[0][0], N_ZC, 1, 1); + LOG_M("ru_prach_rxsigF0.m", "rxsF0", in.rxsigF[0][0], N_ZC, 1, 1); LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1); LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1); #endif @@ -815,8 +834,7 @@ int main(int argc, char **argv){ } if (input_fd) break; - } //SNR loop - + } // SNR loop free_channel_desc_scm(UE2gNB); nr_phy_free_RU(ru); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5e9cd47a79..198975f1ae 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -60,7 +60,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &gNB->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; + nfapi_nr_config_request_scf_t *cfg = &gNB->config[0]; NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; uint8_t config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; @@ -351,10 +351,10 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; int slots_frame = gNB->frame_structure.numb_slots_frame; int index = ul_buffer_index(frameP, slotP, slots_frame, gNB->UL_tti_req_ahead_size); - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index]; - nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; + nfapi_nr_ul_tti_request_t *UL_tti_req = &gNB->UL_tti_req_ahead[0][index]; + nfapi_nr_config_request_scf_t *cfg = &gNB->config[0]; - if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) { + if (is_ul_slot(slotP, &gNB->frame_structure)) { const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric; uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex; int slot_index = 0; @@ -390,16 +390,15 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) uint32_t N_t_slot = cc->prach_info.N_t_slot; uint32_t start_symb = cc->prach_info.start_symbol; for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion - AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]), - "Invalid UL_tti_req->n_pdus %d\n", - UL_tti_req->n_pdus); - - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t); - nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu; - memset(prach_pdu, 0, sizeof(nfapi_nr_prach_pdu_t)); + AssertFatal(UL_tti_req->n_pdus < sizeofArray(UL_tti_req->pdus_list), "Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus); + nfapi_nr_ul_tti_request_number_of_pdus_t *newpdu = UL_tti_req->pdus_list + UL_tti_req->n_pdus; + *newpdu = (nfapi_nr_ul_tti_request_number_of_pdus_t){ + .pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE, + .pdu_size = sizeof(nfapi_nr_prach_pdu_t), + }; UL_tti_req->n_pdus += 1; int num_td_occ = 0; + nfapi_nr_prach_pdu_t *prach_pdu = &newpdu->prach_pdu; for (int td_index = 0; td_index < N_t_slot; td_index++) { uint32_t config_period = cc->prach_info.x; prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + @@ -1123,7 +1122,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ const uint16_t mask = SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nbSymb); int slots_frame = mac->frame_structure.numb_slots_frame; int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, slots_frame, mac->vrb_map_UL_size); - uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_beam.idx][buffer_index * MAX_BWP_SIZE]; + uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[ra->Msg3_beam.idx][buffer_index * MAX_BWP_SIZE]; for (int i = 0; i < ra->msg3_nb_rb; ++i) { AssertFatal(!(vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] & mask), "RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n", @@ -1135,7 +1134,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ LOG_D(NR_MAC, "UE %04x: %d.%d RA is active, Msg3 in (%d,%d)\n", UE->rnti, frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, slots_frame, mac->UL_tti_req_ahead_size); - nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][buffer_index]; + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &mac->UL_tti_req_ahead[CC_id][buffer_index]; AssertFatal(future_ul_tti_req->SFN == ra->Msg3_frame && future_ul_tti_req->Slot == ra->Msg3_slot, "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", @@ -1431,7 +1430,12 @@ static void nr_generate_Msg2(module_id_t module_idP, scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; if (!msg2_in_response_window(ra->preamble_frame, ra->preamble_slot, n_slots_frame, rrc_ra_ResponseWindow, frameP, slotP)) { - LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", ra->RA_rnti, UE->rnti); + LOG_E(NR_MAC, + "sfn: %d.%d UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", + frameP, + slotP, + ra->RA_rnti, + UE->rnti); nr_release_ra_UE(nr_mac, UE->rnti); return; } diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 37661d7ad1..493221d6a9 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -184,12 +184,17 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; /* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */ if (is_prach_slot) { + if (!ru->prach_buf) { + LOG_W(HW, "we get rach data from ru, but it is not scheduled %d.%d\n", frame, slot); + return -1; + } for (sym_idx = 0; sym_idx < prach_sym; sym_idx++) { for (int aa = 0; aa < ru->nb_rx; aa++) { int16_t *dst, *src; int idx = 0; oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru); - dst = ru->prach_buf[aa]; // + (sym_idx*576)); + // hardcoded to use only first prach occasion + dst = (int16_t *)ru->prach_buf[0][aa]; src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData; /* convert Network order to host order */ if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 48e95e7344..9158e468d4 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -31,6 +31,7 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "openair1/PHY/defs_gNB.h" +#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h" #include "oaioran.h" #include "oran-config.h" @@ -212,13 +213,15 @@ int trx_oran_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) { - ru_info_t ru_info; - ru_info.nb_rx = ru->nb_rx * ru->num_beams_period; - ru_info.nb_tx = ru->nb_tx * ru->num_beams_period; - ru_info.rxdataF = ru->common.rxdataF; - ru_info.beam_id = ru->common.beam_id; - ru_info.num_beams_period = ru->num_beams_period; - ru_info.prach_buf = ru->prach_rxsigF[0]; // index: [prach_oca][ant_id] + prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, SEARCH_EXIST); + ru_info_t ru_info = { + .nb_rx = ru->nb_rx * ru->num_beams_period, + .nb_tx = ru->nb_tx * ru->num_beams_period, + .rxdataF = ru->common.rxdataF, + .beam_id = ru->common.beam_id, + .num_beams_period = ru->num_beams_period, + .prach_buf = prach_id ? prach_id->rxsigF : NULL, + }; RU_proc_t *proc = &ru->proc; int f, sl; @@ -269,12 +272,13 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { start_meas(&ru->tx_fhaul); - ru_info_t ru_info; - ru_info.nb_rx = ru->nb_rx * ru->num_beams_period; - ru_info.nb_tx = ru->nb_tx * ru->num_beams_period; - ru_info.txdataF_BF = ru->common.txdataF_BF; - ru_info.beam_id = ru->common.beam_id; - ru_info.num_beams_period = ru->num_beams_period; + ru_info_t ru_info = { + .nb_rx = ru->nb_rx * ru->num_beams_period, + .nb_tx = ru->nb_tx * ru->num_beams_period, + .txdataF_BF = ru->common.txdataF_BF, + .beam_id = ru->common.beam_id, + .num_beams_period = ru->num_beams_period, + }; // printf("south_out:\tframe=%d\tslot=%d\ttimestamp=%ld\n",frame,slot,timestamp); diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index 7dd61ad739..6ec011a24b 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -28,7 +28,8 @@ #include #include "xran_fh_o_du.h" - +#include "openair1/PHY/impl_defs_nr.h" +#include "openair1/PHY/TOOLS/tools_defs.h" /* * Structure added to bear the information needed from OAI RU */ @@ -50,7 +51,7 @@ typedef struct ru_info_s { int num_beams_period; // Needed for Prach - int16_t **prach_buf; + c16_t (*prach_buf)[NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L]; } ru_info_t; /** @brief Reads RX data (PRACH/PUSCH) of next slot. diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 13a414fed6..94234a755f 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -688,6 +688,8 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, if (b->conn_sock >= 0) { samplesBlockHeader_t header = {nsamps, nbAnt, timestamp}; + if (!nbAnt) + LOG_E(HW, "rfsimulator sending 0 tx antennas\n"); fullwrite(b->conn_sock, &header, sizeof(header), t); if (nbAnt == 1) { fullwrite(b->conn_sock, samplesVoid[0], sampleToByte(nsamps, nbAnt), t); @@ -796,6 +798,8 @@ static void process_recv_header(rfsimulator_state_t *t, buffer_t *b, bool first_ // We have a transmission hole to fill, like TDD // we create no signal samples up to the beginning of this reception int nbAnt = b->th.nbAnt; + if (!nbAnt) + LOG_E(HW, "rfsimulator receive 0 rx antennas\n"); if (b->th.timestamp - b->lastReceivedTS < CirSize) { // case we wrap at circular buffer end for (uint64_t index = b->lastReceivedTS; index < b->th.timestamp; index++) { @@ -822,6 +826,8 @@ static void process_recv_header(rfsimulator_state_t *t, buffer_t *b, bool first_ b->transferPtr = (char *)&b->circularBuf[(b->lastReceivedTS * b->th.nbAnt) % CirSize]; // we now need to read the samples b->remainToTransfer = sampleToByte(b->th.size, b->th.nbAnt); + if (!b->remainToTransfer) + b->headerMode = true; // We got a header with 0 antennas, no I/Q to read return; }