merge, compile ok, regular exe ok, ocp-gnb not
This commit is contained in:
@@ -53,7 +53,7 @@ volatile int oai_exit = 0;
|
||||
double cpuf;
|
||||
uint16_t sf_ahead=4;
|
||||
int otg_enabled;
|
||||
uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
int split73;
|
||||
char * split73_config;
|
||||
|
||||
+206
-204
@@ -101,8 +101,8 @@ extern openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
|
||||
extern int transmission_mode;
|
||||
|
||||
uint16_t sl_ahead=6;
|
||||
uint16_t sf_ahead=6;
|
||||
extern uint16_t sf_ahead;
|
||||
extern uint16_t sl_ahead;
|
||||
//pthread_t main_gNB_thread;
|
||||
|
||||
time_stats_t softmodem_stats_mt; // main thread
|
||||
@@ -144,10 +144,14 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
|
||||
|
||||
|
||||
static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) {
|
||||
|
||||
sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
|
||||
start_meas(&softmodem_stats_rxtx_sf);
|
||||
|
||||
// *******************************************************************
|
||||
|
||||
// NFAPI not yet supported for NR - this code has to be revised
|
||||
if (nfapi_mode == 1) {
|
||||
// I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
|
||||
//add_subframe(&frame, &subframe, 4);
|
||||
@@ -173,20 +177,18 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
frame_tx, slot_tx);
|
||||
}
|
||||
}
|
||||
|
||||
/// NR disabling
|
||||
// ****************************************
|
||||
// Common RX procedures subframe n
|
||||
|
||||
T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx));
|
||||
|
||||
/*
|
||||
// if this is IF5 or 3GPP_gNB
|
||||
if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
|
||||
wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx);
|
||||
}
|
||||
|
||||
// UE-specific RX processing for subframe n
|
||||
if (nfapi_mode == 0 || nfapi_mode == 1) */
|
||||
// if this is IF5 or 3GPP_gNB
|
||||
if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
|
||||
wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx);
|
||||
}
|
||||
*/
|
||||
|
||||
// Call the scheduler
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
gNB->UL_INFO.frame = frame_rx;
|
||||
gNB->UL_INFO.slot = slot_rx;
|
||||
@@ -194,22 +196,30 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
gNB->UL_INFO.CC_id = gNB->CC_id;
|
||||
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
|
||||
// RX processing
|
||||
int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx);
|
||||
int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx);
|
||||
|
||||
/// end
|
||||
// *****************************************
|
||||
// TX processing for subframe n+sl_ahead
|
||||
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
|
||||
// (may be relaxed in the future for performance reasons)
|
||||
// *****************************************
|
||||
//if (wait_CCs(proc)<0) return(-1);
|
||||
if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
|
||||
// UE-specific RX processing for subframe n
|
||||
// TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
}
|
||||
|
||||
if (oai_exit) return(-1);
|
||||
|
||||
//if (slot_rx == NR_UPLINK_SLOT || gNB->frame_parms.frame_type == FDD)
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
// *****************************************
|
||||
// TX processing for subframe n+sf_ahead
|
||||
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
|
||||
// (may be relaxed in the future for performance reasons)
|
||||
// *****************************************
|
||||
|
||||
if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
|
||||
|
||||
if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
stop_meas( &softmodem_stats_rxtx_sf );
|
||||
@@ -388,14 +398,15 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct
|
||||
RU_proc_t *ru_proc=&ru->proc;
|
||||
proc->frame_rx = frame_rx;
|
||||
proc->slot_rx = slot_rx;
|
||||
sl_ahead = sf_ahead*fp->slots_per_subframe;
|
||||
|
||||
if (!oai_exit) {
|
||||
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx));
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot);
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
|
||||
L1_proc->frame_rx = ru_proc->frame_rx;
|
||||
L1_proc->slot_rx = ru_proc->tti_rx;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
|
||||
|
||||
if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
|
||||
|
||||
@@ -558,7 +569,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
abstime.tv_sec += 1;
|
||||
}
|
||||
|
||||
// wake up TX for subframe n+sl_ahead
|
||||
// wake up TX for subframe n+sf_ahead
|
||||
// lock the TX mutex and make sure the thread is ready
|
||||
AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
|
||||
|
||||
@@ -572,17 +583,17 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
// We have just received and processed the common part of a subframe, say n.
|
||||
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
|
||||
// transmitted timestamp of the next TX slot (first).
|
||||
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
|
||||
// we want to generate subframe (n+sl_ahead), so TS_tx = TX_rx+sl_ahead*samples_per_tti,
|
||||
// and proc->slot_tx = proc->slot_rx+sl_ahead
|
||||
// and proc->slot_tx = proc->slot_rx+sl_ahead
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot);
|
||||
|
||||
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
|
||||
// we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
|
||||
// and proc->slot_tx = proc->slot_rx+sf_ahead
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
|
||||
L1_proc->frame_rx = ru_proc->frame_rx;
|
||||
L1_proc->slot_rx = ru_proc->tti_rx;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
|
||||
|
||||
LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sl_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sl_ahead);
|
||||
LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sf_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sf_ahead);
|
||||
|
||||
pthread_mutex_unlock( &L1_proc->mutex );
|
||||
|
||||
@@ -719,64 +730,62 @@ static void *process_stats_thread(void *param) {
|
||||
|
||||
void init_gNB_proc(int inst) {
|
||||
int i=0;
|
||||
int CC_id;
|
||||
int CC_id = 0;
|
||||
PHY_VARS_gNB *gNB;
|
||||
gNB_L1_proc_t *proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx;
|
||||
LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]);
|
||||
|
||||
for (CC_id=0; CC_id<RC.nb_nr_CC[inst]; CC_id++) {
|
||||
gNB = RC.gNB[inst][CC_id];
|
||||
// LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]);
|
||||
gNB = RC.gNB[inst];
|
||||
#ifndef OCP_FRAMEWORK
|
||||
LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id);
|
||||
LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id);
|
||||
#endif
|
||||
proc = &gNB->proc;
|
||||
L1_proc = &proc->L1_proc;
|
||||
L1_proc_tx = &proc->L1_proc_tx;
|
||||
L1_proc->instance_cnt = -1;
|
||||
L1_proc_tx->instance_cnt = -1;
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
L1_proc_tx->instance_cnt_RUs = 0;
|
||||
proc->instance_cnt_prach = -1;
|
||||
proc->instance_cnt_asynch_rxtx = -1;
|
||||
proc->CC_id = CC_id;
|
||||
proc->first_rx =1;
|
||||
proc->first_tx =1;
|
||||
proc->RU_mask =0;
|
||||
proc->RU_mask_tx = (1<<gNB->num_RU)-1;
|
||||
proc->RU_mask_prach =0;
|
||||
pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
|
||||
pthread_mutex_init( &L1_proc->mutex, NULL);
|
||||
pthread_mutex_init( &L1_proc_tx->mutex, NULL);
|
||||
pthread_cond_init( &L1_proc->cond, NULL);
|
||||
pthread_cond_init( &L1_proc_tx->cond, NULL);
|
||||
pthread_mutex_init( &proc->mutex_prach, NULL);
|
||||
pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU,NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU_tx,NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
|
||||
pthread_cond_init( &proc->cond_prach, NULL);
|
||||
pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
|
||||
LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag);
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT );
|
||||
threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT);
|
||||
}
|
||||
|
||||
if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
|
||||
//pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
|
||||
char name[16];
|
||||
|
||||
if (gNB->single_thread_flag==0) {
|
||||
snprintf( name, sizeof(name), "L1 %d", i );
|
||||
pthread_setname_np( L1_proc->pthread, name );
|
||||
snprintf( name, sizeof(name), "L1TX %d", i );
|
||||
pthread_setname_np( L1_proc_tx->pthread, name );
|
||||
}
|
||||
|
||||
AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
|
||||
|
||||
proc = &gNB->proc;
|
||||
L1_proc = &proc->L1_proc;
|
||||
L1_proc_tx = &proc->L1_proc_tx;
|
||||
L1_proc->instance_cnt = -1;
|
||||
L1_proc_tx->instance_cnt = -1;
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
L1_proc_tx->instance_cnt_RUs = 0;
|
||||
proc->instance_cnt_prach = -1;
|
||||
proc->instance_cnt_asynch_rxtx = -1;
|
||||
proc->CC_id = CC_id;
|
||||
proc->first_rx =1;
|
||||
proc->first_tx =1;
|
||||
proc->RU_mask =0;
|
||||
proc->RU_mask_tx = (1<<gNB->num_RU)-1;
|
||||
proc->RU_mask_prach =0;
|
||||
pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
|
||||
pthread_mutex_init( &L1_proc->mutex, NULL);
|
||||
pthread_mutex_init( &L1_proc_tx->mutex, NULL);
|
||||
pthread_cond_init( &L1_proc->cond, NULL);
|
||||
pthread_cond_init( &L1_proc_tx->cond, NULL);
|
||||
pthread_mutex_init( &proc->mutex_prach, NULL);
|
||||
pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU,NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU_tx,NULL);
|
||||
pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
|
||||
pthread_cond_init( &proc->cond_prach, NULL);
|
||||
pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
|
||||
LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag);
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT );
|
||||
threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT);
|
||||
}
|
||||
|
||||
if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
|
||||
//pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
|
||||
char name[16];
|
||||
|
||||
if (gNB->single_thread_flag==0) {
|
||||
snprintf( name, sizeof(name), "L1 %d", i );
|
||||
pthread_setname_np( L1_proc->pthread, name );
|
||||
snprintf( name, sizeof(name), "L1TX %d", i );
|
||||
pthread_setname_np( L1_proc_tx->pthread, name );
|
||||
}
|
||||
|
||||
AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
|
||||
|
||||
/* setup PHY proc TX sync mechanism */
|
||||
pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
|
||||
@@ -795,52 +804,51 @@ void kill_gNB_proc(int inst) {
|
||||
gNB_L1_proc_t *proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
|
||||
|
||||
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
gNB=RC.gNB[inst][CC_id];
|
||||
proc = &gNB->proc;
|
||||
L1_proc = &proc->L1_proc;
|
||||
L1_proc_tx = &proc->L1_proc_tx;
|
||||
LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
pthread_mutex_lock(&L1_proc->mutex);
|
||||
L1_proc->instance_cnt = 0;
|
||||
pthread_cond_signal(&L1_proc->cond);
|
||||
pthread_mutex_unlock(&L1_proc->mutex);
|
||||
pthread_mutex_lock(&L1_proc_tx->mutex);
|
||||
L1_proc_tx->instance_cnt = 0;
|
||||
pthread_cond_signal(&L1_proc_tx->cond);
|
||||
pthread_mutex_unlock(&L1_proc_tx->mutex);
|
||||
}
|
||||
|
||||
proc->instance_cnt_prach = 0;
|
||||
pthread_cond_signal( &proc->cond_prach );
|
||||
pthread_cond_signal( &proc->cond_asynch_rxtx );
|
||||
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
|
||||
// LOG_D(PHY, "joining pthread_prach\n");
|
||||
// pthread_join( proc->pthread_prach, (void**)&status );
|
||||
LOG_I(PHY, "Destroying prach mutex/cond\n");
|
||||
pthread_mutex_destroy( &proc->mutex_prach );
|
||||
pthread_cond_destroy( &proc->cond_prach );
|
||||
LOG_I(PHY, "Destroying UL_INFO mutex\n");
|
||||
pthread_mutex_destroy(&gNB->UL_INFO_mutex);
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
LOG_I(PHY, "Joining L1_proc mutex/cond\n");
|
||||
pthread_join( L1_proc->pthread, (void **)&status );
|
||||
LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
|
||||
pthread_join( L1_proc_tx->pthread, (void **)&status );
|
||||
}
|
||||
|
||||
LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
|
||||
pthread_mutex_destroy( &L1_proc->mutex );
|
||||
pthread_cond_destroy( &L1_proc->cond );
|
||||
LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
|
||||
pthread_mutex_destroy( &L1_proc_tx->mutex );
|
||||
pthread_cond_destroy( &L1_proc_tx->cond );
|
||||
pthread_mutex_destroy( &proc->mutex_RU );
|
||||
pthread_mutex_destroy( &proc->mutex_RU_tx );
|
||||
gNB=RC.gNB[inst];
|
||||
proc = &gNB->proc;
|
||||
L1_proc = &proc->L1_proc;
|
||||
L1_proc_tx = &proc->L1_proc_tx;
|
||||
LOG_I(PHY, "Killing TX inst %d\n",inst );
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
pthread_mutex_lock(&L1_proc->mutex);
|
||||
L1_proc->instance_cnt = 0;
|
||||
pthread_cond_signal(&L1_proc->cond);
|
||||
pthread_mutex_unlock(&L1_proc->mutex);
|
||||
pthread_mutex_lock(&L1_proc_tx->mutex);
|
||||
L1_proc_tx->instance_cnt = 0;
|
||||
pthread_cond_signal(&L1_proc_tx->cond);
|
||||
pthread_mutex_unlock(&L1_proc_tx->mutex);
|
||||
}
|
||||
|
||||
proc->instance_cnt_prach = 0;
|
||||
pthread_cond_signal( &proc->cond_prach );
|
||||
pthread_cond_signal( &proc->cond_asynch_rxtx );
|
||||
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
|
||||
// LOG_D(PHY, "joining pthread_prach\n");
|
||||
// pthread_join( proc->pthread_prach, (void**)&status );
|
||||
LOG_I(PHY, "Destroying prach mutex/cond\n");
|
||||
pthread_mutex_destroy( &proc->mutex_prach );
|
||||
pthread_cond_destroy( &proc->cond_prach );
|
||||
LOG_I(PHY, "Destroying UL_INFO mutex\n");
|
||||
pthread_mutex_destroy(&gNB->UL_INFO_mutex);
|
||||
|
||||
if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
|
||||
LOG_I(PHY, "Joining L1_proc mutex/cond\n");
|
||||
pthread_join( L1_proc->pthread, (void **)&status );
|
||||
LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
|
||||
pthread_join( L1_proc_tx->pthread, (void **)&status );
|
||||
}
|
||||
|
||||
LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
|
||||
pthread_mutex_destroy( &L1_proc->mutex );
|
||||
pthread_cond_destroy( &L1_proc->cond );
|
||||
LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
|
||||
pthread_mutex_destroy( &L1_proc_tx->mutex );
|
||||
pthread_cond_destroy( &L1_proc_tx->cond );
|
||||
pthread_mutex_destroy( &proc->mutex_RU );
|
||||
pthread_mutex_destroy( &proc->mutex_RU_tx );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -872,48 +880,41 @@ void print_opp_meas(void) {
|
||||
|
||||
/// eNB kept in function name for nffapi calls, TO FIX
|
||||
void init_eNB_afterRU(void) {
|
||||
int inst,CC_id,ru_id,i,aa;
|
||||
int inst,ru_id,i,aa;
|
||||
PHY_VARS_gNB *gNB;
|
||||
LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst);
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_inst; inst++) {
|
||||
LOG_I(PHY,"RC.nb_nr_CC[inst]:%d\n", RC.nb_nr_CC[inst]);
|
||||
LOG_I(PHY,"RC.nb_nr_CC[inst:%d]:%p\n", inst, RC.gNB[inst]);
|
||||
gNB = RC.gNB[inst];
|
||||
phy_init_nr_gNB(gNB,0,0);
|
||||
|
||||
for (CC_id=0; CC_id<RC.nb_nr_CC[inst]; CC_id++) {
|
||||
LOG_I(PHY,"RC.nb_nr_CC[inst:%d][CC_id:%d]:%p\n", inst, CC_id, RC.gNB[inst][CC_id]);
|
||||
gNB = RC.gNB[inst][CC_id];
|
||||
phy_init_nr_gNB(gNB,0,0);
|
||||
// map antennas and PRACH signals to gNB RX
|
||||
if (0) AssertFatal(gNB->num_RU>0,"Number of RU attached to gNB %d is zero\n",gNB->Mod_id);
|
||||
|
||||
// map antennas and PRACH signals to gNB RX
|
||||
if (0) AssertFatal(gNB->num_RU>0,"Number of RU attached to gNB %d is zero\n",gNB->Mod_id);
|
||||
LOG_I(PHY,"Mapping RX ports from %d RUs to gNB %d\n",gNB->num_RU,gNB->Mod_id);
|
||||
LOG_I(PHY,"gNB->num_RU:%d\n", gNB->num_RU);
|
||||
|
||||
LOG_I(PHY,"Mapping RX ports from %d RUs to gNB %d\n",gNB->num_RU,gNB->Mod_id);
|
||||
//LOG_I(PHY,"Overwriting gNB->prach_vars.rxsigF[0]:%p\n", gNB->prach_vars.rxsigF[0]);
|
||||
// gNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *));
|
||||
LOG_I(PHY,"gNB->num_RU:%d\n", gNB->num_RU);
|
||||
|
||||
for (ru_id=0,aa=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 (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[0][aa] = gNB->RU_list[ru_id]->prach_rxsigF[i];
|
||||
gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i];
|
||||
}
|
||||
for (ru_id=0,aa=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 (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[i];
|
||||
gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i];
|
||||
}
|
||||
|
||||
/* TODO: review this code, there is something wrong.
|
||||
* In monolithic mode, we come here with nb_antennas_rx == 0
|
||||
* (not tested in other modes).
|
||||
*/
|
||||
//init_precoding_weights(RC.gNB[inst][CC_id]);
|
||||
}
|
||||
|
||||
/* TODO: review this code, there is something wrong.
|
||||
* In monolithic mode, we come here with nb_antennas_rx == 0
|
||||
* (not tested in other modes).
|
||||
*/
|
||||
//init_precoding_weights(RC.gNB[inst]);
|
||||
init_gNB_proc(inst);
|
||||
}
|
||||
|
||||
@@ -926,51 +927,52 @@ void init_eNB_afterRU(void) {
|
||||
}
|
||||
|
||||
void init_gNB(int single_thread_flag,int wait_for_sync) {
|
||||
int CC_id;
|
||||
|
||||
int inst;
|
||||
PHY_VARS_gNB *gNB;
|
||||
LOG_I(PHY,"[nr-softmodem.c] gNB structure about to be allocated RC.nb_nr_L1_inst:%d RC.nb_nr_L1_CC[0]:%d\n",RC.nb_nr_L1_inst,RC.nb_nr_L1_CC[0]);
|
||||
|
||||
if (RC.gNB == NULL) RC.gNB = (PHY_VARS_gNB ***) malloc(RC.nb_nr_L1_inst*sizeof(PHY_VARS_gNB **));
|
||||
|
||||
LOG_I(PHY,"[lte-softmodem.c] gNB structure RC.gNB allocated\n");
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
if (RC.gNB[inst] == NULL) RC.gNB[inst] = (PHY_VARS_gNB **) malloc(RC.nb_nr_CC[inst]*sizeof(PHY_VARS_gNB *));
|
||||
|
||||
for (CC_id=0; CC_id<RC.nb_nr_L1_CC[inst]; CC_id++) {
|
||||
if (RC.gNB[inst][CC_id] == NULL) RC.gNB[inst][CC_id] = (PHY_VARS_gNB *) malloc(sizeof(PHY_VARS_gNB));
|
||||
|
||||
gNB = RC.gNB[inst][CC_id];
|
||||
gNB->abstraction_flag = 0;
|
||||
gNB->single_thread_flag = single_thread_flag;
|
||||
/*nr_polar_init(&gNB->nrPolar_params,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);*/
|
||||
LOG_I(PHY,"Initializing gNB %d CC_id %d single_thread_flag:%d\n",inst,CC_id,single_thread_flag);
|
||||
#ifndef OCP_FRAMEWORK
|
||||
LOG_I(PHY,"Initializing gNB %d CC_id %d\n",inst,CC_id);
|
||||
#endif
|
||||
LOG_I(PHY,"Registering with MAC interface module\n");
|
||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(inst))!=NULL,"Cannot register interface");
|
||||
gNB->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
|
||||
memset((void *)&gNB->UL_tti_req,0,sizeof(nfapi_nr_ul_tti_request_t));
|
||||
//memset((void *)&gNB->Sched_INFO,0,sizeof(gNB->Sched_INFO));
|
||||
LOG_I(PHY,"Setting indication lists\n");
|
||||
gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = gNB->rx_pdu_list;
|
||||
gNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = gNB->crc_pdu_list;
|
||||
gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
|
||||
gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;
|
||||
|
||||
gNB->prach_energy_counter = 0;
|
||||
if (RC.gNB == NULL) {
|
||||
RC.gNB = (PHY_VARS_gNB **) malloc((1+RC.nb_nr_L1_inst)*sizeof(PHY_VARS_gNB *));
|
||||
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
RC.gNB[inst] = (PHY_VARS_gNB *) malloc(sizeof(PHY_VARS_gNB));
|
||||
memset((void*)RC.gNB[inst],0,sizeof(PHY_VARS_gNB));
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB);
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
|
||||
LOG_I(PHY,"[lte-softmodem.c] gNB structure RC.gNB[%d] allocated @ %p\n",inst,RC.gNB[inst]);
|
||||
gNB = RC.gNB[inst];
|
||||
gNB->abstraction_flag = 0;
|
||||
gNB->single_thread_flag = single_thread_flag;
|
||||
/*nr_polar_init(&gNB->nrPolar_params,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);*/
|
||||
LOG_I(PHY,"Initializing gNB %d single_thread_flag:%d\n",inst,gNB->single_thread_flag);
|
||||
#ifndef OCP_FRAMEWORK
|
||||
LOG_I(PHY,"Initializing gNB %d\n",inst);
|
||||
#endif
|
||||
|
||||
LOG_I(PHY,"Registering with MAC interface module (before %p)\n",gNB->if_inst);
|
||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(inst))!=NULL,"Cannot register interface");
|
||||
LOG_I(PHY,"Registering with MAC interface module (after %p)\n",gNB->if_inst);
|
||||
gNB->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
|
||||
LOG_I(PHY,"Setting indication lists\n");
|
||||
gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = gNB->rx_pdu_list;
|
||||
gNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = gNB->crc_pdu_list;
|
||||
gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
|
||||
gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;
|
||||
gNB->prach_energy_counter = 0;
|
||||
}
|
||||
|
||||
|
||||
LOG_I(PHY,"[nr-softmodem.c] gNB structure allocated\n");
|
||||
}
|
||||
|
||||
|
||||
+192
-160
@@ -50,6 +50,7 @@
|
||||
#include <execinfo.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <math.h>
|
||||
|
||||
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
|
||||
@@ -130,7 +131,8 @@ void configure_rru(int idx, void *arg);
|
||||
int attach_rru(RU_t *ru);
|
||||
int connect_rau(RU_t *ru);
|
||||
|
||||
extern uint16_t sl_ahead;
|
||||
uint16_t sf_ahead;
|
||||
uint16_t sl_ahead;
|
||||
|
||||
extern int emulate_rf;
|
||||
extern int numerology;
|
||||
@@ -296,29 +298,24 @@ int connect_rau(RU_t *ru)
|
||||
/* Southbound Fronthaul functions, RCC/RAU */
|
||||
|
||||
// southbound IF5 fronthaul for 16-bit OAI format
|
||||
static inline void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL);
|
||||
}
|
||||
|
||||
// southbound IF5 fronthaul for Mobipass packet format
|
||||
static inline void fh_if5_mobipass_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
send_IF5(ru, timestamp, slot, &ru->seqno, IF5_MOBIPASS);
|
||||
}
|
||||
|
||||
// southbound IF4p5 fronthaul
|
||||
static inline void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx);
|
||||
|
||||
if (nr_slot_select(&ru->gNB_list[0]->gNB_config,ru->proc.tti_tx,frame)!=SF_UL) send_IF4p5(ru,frame, slot, IF4p5_PDLFFT);
|
||||
|
||||
if ((nr_slot_select(cfg,ru->proc.frame_tx,ru->proc.tti_tx)&NR_DOWNLINK_SLOT) > 0)
|
||||
send_IF4p5(ru,frame, slot, IF4p5_PDLFFT);
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
@@ -332,8 +329,9 @@ void fh_if5_south_in(RU_t *ru,
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL);
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_slot*20))&1023;
|
||||
proc->tti_rx = (proc->timestamp_rx / fp->samples_per_slot)%20;
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
|
||||
uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe;
|
||||
proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame);
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *tti) {
|
||||
@@ -391,12 +389,12 @@ void fh_if4p5_south_in(RU_t *ru,
|
||||
} while(proc->symbol_mask[sl] != symbol_mask_full);
|
||||
|
||||
//caculate timestamp_rx, timestamp_tx based on frame and subframe
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
proc->timestamp_rx = ((proc->frame_rx * fp->slots_per_frame) + proc->tti_rx ) * fp->samples_per_slot ;
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(proc->tti_rx, fp, 0);
|
||||
// proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe);
|
||||
proc->tti_tx = (sl+sl_ahead)%fp->slots_per_frame;
|
||||
proc->frame_tx = (sl>(fp->slots_per_frame-sl_ahead)) ? (f+1)&1023 : f;
|
||||
proc->tti_tx = (sl+(fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
|
||||
proc->frame_tx = (sl>(fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (f+1)&1023 : f;
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *slot) {
|
||||
@@ -503,8 +501,9 @@ void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
openair0_timestamp timestamp_tx;
|
||||
recv_IF5(ru, ×tamp_tx, *slot, IF5_RRH_GW_DL);
|
||||
// printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx);
|
||||
tti_tx = (timestamp_tx/fp->samples_per_slot)%fp->slots_per_frame;
|
||||
frame_tx = (timestamp_tx/(fp->samples_per_slot*fp->slots_per_frame))&1023;
|
||||
frame_tx = (timestamp_tx / (fp->samples_per_subframe*10))&1023;
|
||||
uint32_t idx_sf = timestamp_tx / fp->samples_per_subframe;
|
||||
tti_tx = (idx_sf * fp->slots_per_subframe + (int)round((float)(timestamp_tx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame);
|
||||
|
||||
if (proc->first_tx != 0) {
|
||||
*slot = tti_tx;
|
||||
@@ -520,7 +519,7 @@ void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
|
||||
void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
uint16_t packet_type;
|
||||
uint32_t symbol_number,symbol_mask,symbol_mask_full=0;
|
||||
@@ -533,10 +532,10 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
do {
|
||||
recv_IF4p5(ru, &frame_tx, &slot_tx, &packet_type, &symbol_number);
|
||||
|
||||
if ((nr_slot_select(cfg,slot_tx,frame_tx) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
|
||||
if (((nr_slot_select(cfg,frame_tx,slot_tx) & NR_DOWNLINK_SLOT) > 0) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
|
||||
|
||||
LOG_D(PHY,"subframe %d (%d): frame %d, subframe %d, symbol %d\n",
|
||||
*slot,nr_slot_select(cfg,*slot,*frame),frame_tx,slot_tx,symbol_number);
|
||||
LOG_D(PHY,"slot %d (%d): frame %d, slot %d, symbol %d\n",
|
||||
*slot,nr_slot_select(cfg,frame_tx,*slot),frame_tx,slot_tx,symbol_number);
|
||||
|
||||
if (proc->first_tx != 0) {
|
||||
*frame = frame_tx;
|
||||
@@ -555,14 +554,14 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
|
||||
} else AssertFatal(1==0,"Illegal IF4p5 packet type (should only be IF4p5_PDLFFT%d\n",packet_type);
|
||||
} while (symbol_mask != symbol_mask_full);
|
||||
|
||||
if (nr_slot_select(cfg,slot_tx,frame_tx) == SF_DL) stop_meas(&ru->rx_fhaul);
|
||||
if ((nr_slot_select(cfg,frame_tx,slot_tx) & NR_DOWNLINK_SLOT)>0) stop_meas(&ru->rx_fhaul);
|
||||
|
||||
proc->tti_tx = slot_tx;
|
||||
proc->frame_tx = frame_tx;
|
||||
proc->tti_tx = slot_tx;
|
||||
proc->frame_tx = frame_tx;
|
||||
|
||||
if ((frame_tx == 0)&&(slot_tx == 0)) proc->frame_tx_unwrap += 1024;
|
||||
|
||||
proc->timestamp_tx = ((((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * fp->slots_per_frame) + (uint64_t)slot_tx) * (uint64_t)fp->samples_per_slot;
|
||||
proc->timestamp_tx = (((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(slot_tx, fp, 0);
|
||||
LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,slot_tx);
|
||||
|
||||
// dump VCD output for first RU in list
|
||||
@@ -604,7 +603,7 @@ void fh_if4p5_north_out(RU_t *ru) {
|
||||
stop_meas(&ru->tx_fhaul);
|
||||
}
|
||||
|
||||
static void *emulatedRF_thread(void *param) {
|
||||
void *emulatedRF_thread(void *param) {
|
||||
RU_proc_t *proc = (RU_proc_t *) param;
|
||||
int microsec = 500; // length of time to sleep, in miliseconds
|
||||
struct timespec req = {0};
|
||||
@@ -629,26 +628,27 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
void *rxp[ru->nb_rx];
|
||||
unsigned int rxs;
|
||||
int i;
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp);
|
||||
openair0_timestamp ts,old_ts;
|
||||
AssertFatal(*slot<fp->slots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame);
|
||||
|
||||
for (i=0; i<ru->nb_rx; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][*slot*fp->samples_per_slot];
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
|
||||
old_ts = proc->timestamp_rx;
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",fp->samples_per_slot,*slot,rxp[0]);
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]);
|
||||
|
||||
if(emulate_rf) {
|
||||
wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
|
||||
release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
|
||||
rxs = fp->samples_per_slot;
|
||||
rxs = samples_per_slot;
|
||||
ts = old_ts + rxs;
|
||||
} else {
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
|
||||
&ts,
|
||||
rxp,
|
||||
fp->samples_per_slot,
|
||||
samples_per_slot,
|
||||
ru->nb_rx);
|
||||
}
|
||||
|
||||
@@ -658,21 +658,22 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
|
||||
//AssertFatal(rxs == fp->samples_per_subframe,
|
||||
//"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs);
|
||||
if (rxs != fp->samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_slot,rxs);
|
||||
if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs);
|
||||
|
||||
if (proc->first_rx == 1) {
|
||||
ru->ts_offset = proc->timestamp_rx;
|
||||
proc->timestamp_rx = 0;
|
||||
} else {
|
||||
if (proc->timestamp_rx - old_ts != fp->samples_per_slot) {
|
||||
LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_slot,ru->ts_offset);
|
||||
ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_slot);
|
||||
if (proc->timestamp_rx - old_ts != fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp)) {
|
||||
LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot,ru->ts_offset);
|
||||
ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot);
|
||||
proc->timestamp_rx = ts-ru->ts_offset;
|
||||
}
|
||||
}
|
||||
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_slot*fp->slots_per_frame))&1023;
|
||||
proc->tti_rx = (proc->timestamp_rx / fp->samples_per_slot)%fp->slots_per_frame;
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
|
||||
uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe;
|
||||
proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame);
|
||||
// synchronize first reception to frame 0 subframe 0
|
||||
LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
|
||||
ru->idx,
|
||||
@@ -688,7 +689,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *slot) {
|
||||
LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot);
|
||||
LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot);
|
||||
exit_fun("Exiting");
|
||||
}
|
||||
|
||||
@@ -705,7 +706,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
//printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
|
||||
|
||||
if (rxs != fp->samples_per_slot) {
|
||||
if (rxs != samples_per_slot) {
|
||||
//exit_fun( "problem receiving samples" );
|
||||
LOG_E(PHY, "problem receiving samples\n");
|
||||
}
|
||||
@@ -715,69 +716,83 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
//nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
void *txp[ru->nb_tx];
|
||||
unsigned int txs;
|
||||
int i;
|
||||
int i,txsymb;
|
||||
T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot),
|
||||
T_INT(0), T_BUFFER(&ru->common.txdata[0][slot * fp->samples_per_slot], fp->samples_per_slot * 4));
|
||||
int sf_extension = 0;
|
||||
//nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame,frame);
|
||||
T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4));
|
||||
|
||||
if ((slot == 0) ||
|
||||
(slot == 1) || IS_SOFTMODEM_RFSIM ) {
|
||||
int siglen=fp->samples_per_slot;
|
||||
int flags;
|
||||
if (slot==0)
|
||||
flags = 2;
|
||||
else if (slot==1)
|
||||
flags=3;
|
||||
else
|
||||
flags=4;
|
||||
int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame);
|
||||
int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame);
|
||||
int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame);
|
||||
int sf_extension = 0; //sf_extension = ru->sf_extension;
|
||||
int siglen=fp->get_samples_per_slot(slot,fp);
|
||||
int flags=1;
|
||||
|
||||
/*
|
||||
if (SF_type == SF_S) {
|
||||
siglen = fp->dl_symbols_in_S_subframe*(fp->ofdm_symbol_size+fp->nb_prefix_samples0);
|
||||
flags=3; // end of burst
|
||||
}
|
||||
if ((fp->frame_type == TDD) &&
|
||||
(SF_type == SF_DL)&&
|
||||
(prevSF_type == SF_UL) &&
|
||||
(nextSF_type == SF_DL)) {
|
||||
flags = 2; // start of burst
|
||||
sf_extension = ru->N_TA_offset<<1;
|
||||
}
|
||||
//nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame);
|
||||
if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) {
|
||||
|
||||
if ((cfg->subframe_config.duplex_mode == TDD) &&
|
||||
(SF_type == SF_DL)&&
|
||||
(prevSF_type == SF_UL) &&
|
||||
(nextSF_type == SF_UL)) {
|
||||
flags = 4; // start of burst and end of burst (only one DL SF between two UL)
|
||||
sf_extension = ru->N_TA_offset<<1;
|
||||
} */
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot );
|
||||
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
txp[i] = (void *)&ru->common.txdata[i][(slot*fp->samples_per_slot)-sf_extension];
|
||||
if(slot_type == NR_MIXED_SLOT) {
|
||||
txsymb = 0;
|
||||
for(int symbol_count =0;symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT;symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0)
|
||||
txsymb++;
|
||||
}
|
||||
AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb);
|
||||
if(slot%(fp->slots_per_subframe/2))
|
||||
siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
else
|
||||
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
//+ ru->end_of_burst_delay;
|
||||
flags=3; // end of burst
|
||||
}
|
||||
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD &&
|
||||
slot_type == NR_DOWNLINK_SLOT &&
|
||||
prevslot_type == NR_UPLINK_SLOT) {
|
||||
flags = 2; // start of burst
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
|
||||
// prepare tx buffer pointers
|
||||
start_meas(&ru->tx_fhaul);
|
||||
txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
|
||||
timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
|
||||
txp,
|
||||
siglen+sf_extension,
|
||||
ru->nb_tx,
|
||||
flags);
|
||||
stop_meas(&ru->tx_fhaul);
|
||||
LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
|
||||
(long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
||||
AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %u/%d)\n", txs, siglen);
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD &&
|
||||
slot_type == NR_DOWNLINK_SLOT &&
|
||||
nextslot_type == NR_UPLINK_SLOT) {
|
||||
flags = 3; // end of burst
|
||||
}
|
||||
|
||||
if (fp->freq_range==nr_FR2) {
|
||||
// the beam index is written in bits 8-10 of the flags
|
||||
// bit 11 enables the gpio programming
|
||||
int beam=0;
|
||||
if (slot==0) beam = 11; //3 for boresight & 8 to enable
|
||||
/*
|
||||
if (slot==0 || slot==40) beam=0&8;
|
||||
if (slot==10 || slot==50) beam=1&8;
|
||||
if (slot==20 || slot==60) beam=2&8;
|
||||
if (slot==30 || slot==70) beam=3&8;
|
||||
*/
|
||||
flags |= beam<<8;
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot );
|
||||
for (i=0; i<ru->nb_tx; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
|
||||
// prepare tx buffer pointers
|
||||
txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
|
||||
timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
|
||||
txp,
|
||||
siglen+sf_extension,
|
||||
ru->nb_tx,
|
||||
flags);
|
||||
LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %d\n",ru->idx,
|
||||
(long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
||||
AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %u/%d)\n", txs, siglen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -789,11 +804,12 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
* \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
|
||||
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
|
||||
*/
|
||||
static void *ru_thread_asynch_rxtx( void *param ) {
|
||||
void *ru_thread_asynch_rxtx( void *param ) {
|
||||
static int ru_thread_asynch_rxtx_status;
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
int subframe=0, frame=0;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
int slot=0, frame=0;
|
||||
// wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
|
||||
wait_sync("ru_thread_asynch_rxtx");
|
||||
// wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
|
||||
@@ -803,22 +819,20 @@ static void *ru_thread_asynch_rxtx( void *param ) {
|
||||
|
||||
while (!oai_exit) {
|
||||
|
||||
if (subframe==9) {
|
||||
subframe=0;
|
||||
if (slot==ru->nr_frame_parms->slots_per_frame) {
|
||||
slot=0;
|
||||
frame++;
|
||||
frame&=1023;
|
||||
} else {
|
||||
subframe++;
|
||||
slot++;
|
||||
}
|
||||
|
||||
LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
|
||||
|
||||
// asynchronous receive from south (Mobipass)
|
||||
if (ru->fh_south_asynch_in) ru->fh_south_asynch_in(ru,&frame,&subframe);
|
||||
// asynchronous receive from north (RRU IF4/IF5)
|
||||
else if (ru->fh_north_asynch_in) {
|
||||
if (nr_slot_select(&ru->gNB_list[0]->gNB_config,subframe,frame)!=SF_UL)
|
||||
ru->fh_north_asynch_in(ru,&frame,&subframe);
|
||||
if (ru->fh_north_asynch_in) {
|
||||
if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0)
|
||||
ru->fh_north_asynch_in(ru,&frame,&slot);
|
||||
} else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
|
||||
}
|
||||
|
||||
@@ -834,7 +848,7 @@ static void *ru_thread_asynch_rxtx( void *param ) {
|
||||
* \param param is a \ref RU_proc_t structure which contains the info what to process.
|
||||
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
|
||||
*/
|
||||
static void *ru_thread_prach( void *param ) {
|
||||
void *ru_thread_prach( void *param ) {
|
||||
static int ru_thread_prach_status;
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = (RU_proc_t *)&ru->proc;
|
||||
@@ -1004,7 +1018,7 @@ void wakeup_gNB_L1s(RU_t *ru) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline int wakeup_prach_ru(RU_t *ru) {
|
||||
int wakeup_prach_ru(RU_t *ru) {
|
||||
struct timespec wait;
|
||||
wait.tv_sec=0;
|
||||
wait.tv_nsec=5000000L;
|
||||
@@ -1039,10 +1053,10 @@ static inline int wakeup_prach_ru(RU_t *ru) {
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
int i;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_t *gNB_config = &ru->gNB_list[0]->gNB_config; //tmp index
|
||||
nfapi_nr_config_request_scf_t *gNB_config = &ru->gNB_list[0]->gNB_config; //tmp index
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
int N_RB = gNB_config->rf_config.dl_carrier_bandwidth.value;
|
||||
int mu = gNB_config->subframe_config.numerology_index_mu.value;
|
||||
int mu = gNB_config->ssb_config.scs_common.value;
|
||||
int N_RB = gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value;
|
||||
|
||||
if (mu == NR_MU_0) { //or if LTE
|
||||
if(N_RB == 100) {
|
||||
@@ -1111,11 +1125,23 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
} else {
|
||||
AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
|
||||
}
|
||||
} else if (mu == NR_MU_3) {
|
||||
if (N_RB == 66) {
|
||||
cfg->sample_rate = 122.88e6;
|
||||
cfg->samples_per_frame = 1228800;
|
||||
cfg->tx_bw = 100e6;
|
||||
cfg->rx_bw = 100e6;
|
||||
} else if(N_RB == 32) {
|
||||
cfg->sample_rate=61.44e6;
|
||||
cfg->samples_per_frame = 614400;
|
||||
cfg->tx_bw = 50e6;
|
||||
cfg->rx_bw = 50e6;
|
||||
}
|
||||
} else {
|
||||
AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu);
|
||||
}
|
||||
|
||||
if (gNB_config->subframe_config.duplex_mode.value==TDD)
|
||||
if (gNB_config->cell_config.frame_duplex_type.value==TDD)
|
||||
cfg->duplex_mode = duplex_mode_TDD;
|
||||
else //FDD
|
||||
cfg->duplex_mode = duplex_mode_FDD;
|
||||
@@ -1126,8 +1152,14 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
cfg->rx_num_channels=ru->nb_rx;
|
||||
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
|
||||
cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;
|
||||
if (ru->if_frequency == 0) {
|
||||
cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
|
||||
cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;
|
||||
}
|
||||
else {
|
||||
cfg->tx_freq[i] = (double)ru->if_frequency;
|
||||
cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq);
|
||||
}
|
||||
cfg->tx_gain[i] = ru->att_tx;
|
||||
cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx;
|
||||
cfg->configFilename = rf_config_file;
|
||||
@@ -1199,7 +1231,7 @@ int setup_RU_buffers(RU_t *ru) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void *ru_stats_thread(void *param) {
|
||||
void *ru_stats_thread(void *param) {
|
||||
RU_t *ru = (RU_t *)param;
|
||||
wait_sync("ru_stats_thread");
|
||||
|
||||
@@ -1230,7 +1262,7 @@ static void *ru_stats_thread(void *param) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static void *ru_thread_tx( void *param ) {
|
||||
void *ru_thread_tx( void *param ) {
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
@@ -1250,7 +1282,10 @@ static void *ru_thread_tx( void *param ) {
|
||||
|
||||
LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n");
|
||||
// wait until eNBs are finished subframe RX n and TX n+4
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 );
|
||||
wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 );
|
||||
|
||||
ret = pthread_mutex_lock(&proc->mutex_gNBs);
|
||||
AssertFatal(ret == 0,"mutex_lock return %d\n",ret);
|
||||
@@ -1345,12 +1380,12 @@ static void *ru_thread_tx( void *param ) {
|
||||
// the thread can now be woken up
|
||||
if (L1_proc->instance_cnt_RUs == -1) {
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
|
||||
AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
|
||||
"ERROR pthread_cond_signal for gNB_L1_thread\n");
|
||||
} //else AssertFatal(1==0,"gNB TX thread is not ready\n");
|
||||
ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx);
|
||||
AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1359,7 +1394,7 @@ static void *ru_thread_tx( void *param ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *ru_thread( void *param ) {
|
||||
void *ru_thread( void *param ) {
|
||||
static int ru_thread_status;
|
||||
RU_t *ru = (RU_t *)param;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
@@ -1371,7 +1406,9 @@ static void *ru_thread( void *param ) {
|
||||
int print_frame = 8;
|
||||
int i = 0;
|
||||
int aa;
|
||||
// set default return value
|
||||
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
|
||||
// set default return value
|
||||
ru_thread_status = 0;
|
||||
// set default return value
|
||||
@@ -1417,6 +1454,7 @@ static void *ru_thread( void *param ) {
|
||||
}
|
||||
}
|
||||
|
||||
sf_ahead = (uint16_t) ceil((float)6/(0x01<<fp->numerology_index));
|
||||
LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
|
||||
pthread_mutex_lock(&RC.ru_mutex);
|
||||
RC.ru_mask &= ~(1<<ru->idx);
|
||||
@@ -1468,12 +1506,12 @@ static void *ru_thread( void *param ) {
|
||||
if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot);
|
||||
else AssertFatal(1==0, "No fronthaul interface at south port");
|
||||
|
||||
LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0][0]:[RX:%d%d TX(SFN):%d]\n",
|
||||
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][0]->proc.frame_rx,RC.gNB[0][0]->proc.slot_rx,
|
||||
RC.gNB[0][0]->proc.frame_tx);
|
||||
RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx,
|
||||
RC.gNB[0]->proc.frame_tx);
|
||||
/*
|
||||
LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n",
|
||||
ru->do_prach,
|
||||
@@ -1490,19 +1528,21 @@ static void *ru_thread( void *param ) {
|
||||
|
||||
// do RX front-end processing (frequency-shift, dft) if needed
|
||||
|
||||
if (proc->tti_rx == NR_UPLINK_SLOT || fp->frame_type == FDD) {
|
||||
int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx);
|
||||
if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
//if (proc->tti_rx==8) {
|
||||
|
||||
if (ru->feprx) ru->feprx(ru,proc->tti_rx);
|
||||
//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);
|
||||
LOG_D(PHY,"Copying rxdataF from RU to gNB\n");
|
||||
|
||||
for (aa=0;aa<ru->nb_rx;aa++)
|
||||
memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa],
|
||||
(void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t));
|
||||
}
|
||||
|
||||
LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx);
|
||||
LOG_D(PHY,"Copying rxdataF from RU to gNB\n");
|
||||
|
||||
for (aa=0; aa<ru->nb_rx; aa++)
|
||||
memcpy((void *)RC.gNB[0][0]->common_vars.rxdataF[aa],
|
||||
(void *)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t));
|
||||
|
||||
// At this point, all information for subframe has been received on FH interface
|
||||
|
||||
// wakeup all gNB processes waiting for this RU
|
||||
@@ -1814,19 +1854,19 @@ int check_capabilities(RU_t *ru,RRU_capabilities_t *cap)
|
||||
FH_fmt_options_t fmt = cap->FH_fmt;
|
||||
int i;
|
||||
int found_band=0;
|
||||
LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->nr_frame_parms->eutra_band);
|
||||
LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->nr_frame_parms->nr_band);
|
||||
|
||||
for (i=0; i<cap->num_bands; i++) {
|
||||
LOG_I(PHY,"band %d on RRU %d\n",cap->band_list[i],ru->idx);
|
||||
|
||||
if (ru->nr_frame_parms->eutra_band == cap->band_list[i]) {
|
||||
if (ru->nr_frame_parms->nr_band == cap->band_list[i]) {
|
||||
found_band=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_band == 0) {
|
||||
LOG_I(PHY,"Couldn't find target EUTRA band %d on RRU %d\n",ru->nr_frame_parms->eutra_band,ru->idx);
|
||||
LOG_I(PHY,"Couldn't find target NR band %d on RRU %d\n",ru->nr_frame_parms->nr_band,ru->idx);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
@@ -1871,7 +1911,7 @@ void configure_ru(int idx,
|
||||
RU_t *ru = RC.ru[idx];
|
||||
RRU_config_t *config = (RRU_config_t *)arg;
|
||||
RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg;
|
||||
nfapi_nr_config_request_t *gNB_config = &ru->gNB_list[0]->gNB_config;
|
||||
nfapi_nr_config_request_scf_t *gNB_config = &ru->gNB_list[0]->gNB_config;
|
||||
int ret;
|
||||
LOG_I(PHY, "Received capabilities from RRU %d\n",idx);
|
||||
|
||||
@@ -1883,19 +1923,19 @@ void configure_ru(int idx,
|
||||
ru->nb_tx = capabilities->nb_tx[0];
|
||||
ru->nb_rx = capabilities->nb_rx[0];
|
||||
// Pass configuration to RRU
|
||||
LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->nr_frame_parms->eutra_band);
|
||||
LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->nr_frame_parms->nr_band);
|
||||
// wait for configuration
|
||||
config->FH_fmt = ru->if_south;
|
||||
config->num_bands = 1;
|
||||
config->band_list[0] = ru->nr_frame_parms->eutra_band;
|
||||
config->band_list[0] = ru->nr_frame_parms->nr_band;
|
||||
config->tx_freq[0] = ru->nr_frame_parms->dl_CarrierFreq;
|
||||
config->rx_freq[0] = ru->nr_frame_parms->ul_CarrierFreq;
|
||||
//config->tdd_config[0] = ru->nr_frame_parms->tdd_config;
|
||||
//config->tdd_config_S[0] = ru->nr_frame_parms->tdd_config_S;
|
||||
config->att_tx[0] = ru->att_tx;
|
||||
config->att_rx[0] = ru->att_rx;
|
||||
config->N_RB_DL[0] = gNB_config->rf_config.dl_carrier_bandwidth.value;
|
||||
config->N_RB_UL[0] = gNB_config->rf_config.ul_carrier_bandwidth.value;
|
||||
config->N_RB_DL[0] = gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value;
|
||||
config->N_RB_UL[0] = gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value;
|
||||
config->threequarter_fs[0] = ru->nr_frame_parms->threequarter_fs;
|
||||
/* if (ru->if_south==REMOTE_IF4p5) {
|
||||
config->prach_FreqOffset[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset;
|
||||
@@ -1910,22 +1950,23 @@ void configure_rru(int idx,
|
||||
void *arg) {
|
||||
RRU_config_t *config = (RRU_config_t *)arg;
|
||||
RU_t *ru = RC.ru[idx];
|
||||
nfapi_nr_config_request_t *gNB_config = &ru->gNB_list[0]->gNB_config;
|
||||
ru->nr_frame_parms->eutra_band = config->band_list[0];
|
||||
nfapi_nr_config_request_scf_t *gNB_config = &ru->gNB_list[0]->gNB_config;
|
||||
ru->nr_frame_parms->nr_band = config->band_list[0];
|
||||
ru->nr_frame_parms->dl_CarrierFreq = config->tx_freq[0];
|
||||
ru->nr_frame_parms->ul_CarrierFreq = config->rx_freq[0];
|
||||
|
||||
if (ru->nr_frame_parms->dl_CarrierFreq == ru->nr_frame_parms->ul_CarrierFreq) {
|
||||
gNB_config->subframe_config.duplex_mode.value = TDD;
|
||||
gNB_config->cell_config.frame_duplex_type.value = TDD;
|
||||
//ru->nr_frame_parms->tdd_config = config->tdd_config[0];
|
||||
//ru->nr_frame_parms->tdd_config_S = config->tdd_config_S[0];
|
||||
} else
|
||||
gNB_config->subframe_config.duplex_mode.value = FDD;
|
||||
gNB_config->cell_config.frame_duplex_type.value = FDD;
|
||||
|
||||
ru->att_tx = config->att_tx[0];
|
||||
ru->att_rx = config->att_rx[0];
|
||||
gNB_config->rf_config.dl_carrier_bandwidth.value = config->N_RB_DL[0];
|
||||
gNB_config->rf_config.ul_carrier_bandwidth.value = config->N_RB_UL[0];
|
||||
int mu = gNB_config->ssb_config.scs_common.value;
|
||||
gNB_config->carrier_config.dl_grid_size[mu].value = config->N_RB_DL[0];
|
||||
gNB_config->carrier_config.dl_grid_size[mu].value = config->N_RB_UL[0];
|
||||
ru->nr_frame_parms->threequarter_fs = config->threequarter_fs[0];
|
||||
|
||||
//ru->nr_frame_parms->pdsch_config_common.referenceSignalPower = ru->max_pdschReferenceSignalPower-config->att_tx[0];
|
||||
@@ -2117,8 +2158,6 @@ void set_function_spec_param(RU_t *ru) {
|
||||
} // switch on interface type
|
||||
}
|
||||
|
||||
extern void RCconfig_RU(void);
|
||||
|
||||
void init_NR_RU(char *rf_config_file)
|
||||
{
|
||||
int ru_id;
|
||||
@@ -2137,10 +2176,6 @@ void init_NR_RU(char *rf_config_file)
|
||||
RCconfig_RU();
|
||||
LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs());
|
||||
|
||||
if (RC.nb_nr_CC != 0)
|
||||
for (i=0; i<RC.nb_nr_L1_inst; i++)
|
||||
for (CC_id=0; CC_id<RC.nb_nr_CC[i]; CC_id++) RC.gNB[i][CC_id]->num_RU=0;
|
||||
|
||||
LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
|
||||
|
||||
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
@@ -2153,11 +2188,11 @@ void init_NR_RU(char *rf_config_file)
|
||||
// NOTE: multiple CC_id are not handled here yet!
|
||||
|
||||
if (ru->num_gNB > 0) {
|
||||
LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0][0], ru->rf_config_file);
|
||||
LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0], ru->rf_config_file);
|
||||
|
||||
if (ru->gNB_list[0] == 0) {
|
||||
LOG_E(PHY,"%s() DJP - ru->gNB_list ru->num_gNB are not initialized - so do it manually\n", __FUNCTION__);
|
||||
ru->gNB_list[0] = RC.gNB[0][0];
|
||||
ru->gNB_list[0] = RC.gNB[0];
|
||||
ru->num_gNB=1;
|
||||
//
|
||||
// DJP - feptx_prec() / feptx_ofdm() parses the gNB_list (based on num_gNB) and copies the txdata_F to txdata in RU
|
||||
@@ -2167,7 +2202,7 @@ void init_NR_RU(char *rf_config_file)
|
||||
}
|
||||
}
|
||||
|
||||
gNB_RC = RC.gNB[0][0];
|
||||
gNB_RC = RC.gNB[0];
|
||||
gNB0 = ru->gNB_list[0];
|
||||
fp = ru->nr_frame_parms;
|
||||
LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
|
||||
@@ -2239,7 +2274,7 @@ void RCconfig_RU(void)
|
||||
else
|
||||
RC.ru[j]->num_gNB = 0;
|
||||
|
||||
for (i=0; i<RC.ru[j]->num_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0];
|
||||
for (i=0; i<RC.ru[j]->num_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]];
|
||||
|
||||
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) {
|
||||
RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr));
|
||||
@@ -2332,18 +2367,14 @@ void RCconfig_RU(void)
|
||||
RC.ru[j]->if_south = REMOTE_IF4p5;
|
||||
RC.ru[j]->function = NGFI_RAU_IF4p5;
|
||||
RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
|
||||
} else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if5_mobipass") == 0) {
|
||||
RC.ru[j]->if_south = REMOTE_IF5;
|
||||
RC.ru[j]->function = NGFI_RAU_IF5;
|
||||
RC.ru[j]->if_timing = synch_to_other;
|
||||
RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF5_MOBIPASS;
|
||||
}
|
||||
}
|
||||
} /* strcmp(local_rf, "yes") != 0 */
|
||||
|
||||
RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr);
|
||||
RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
|
||||
RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
|
||||
RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
|
||||
RC.ru[j]->if_frequency = *(RUParamList.paramarray[j][RU_IF_FREQUENCY].u64ptr);
|
||||
|
||||
if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) {
|
||||
RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt;
|
||||
@@ -2359,3 +2390,4 @@ void RCconfig_RU(void)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n"
|
||||
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
|
||||
#define CONFIG_HLP_DISABLETIMECORR "disable UE timing correction\n"
|
||||
#define CONFIG_HLP_RRC_CFG_PATH "path for RRC configuration\n"
|
||||
|
||||
#define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n"
|
||||
#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n"
|
||||
@@ -126,7 +127,7 @@ extern pthread_mutex_t sync_mutex;
|
||||
extern int sync_var;
|
||||
|
||||
|
||||
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
extern int rx_input_level_dBm;
|
||||
|
||||
+54
-68
@@ -84,6 +84,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "executables/thread-common.h"
|
||||
#include "NB_IoT_interface.h"
|
||||
#include "x2ap_eNB.h"
|
||||
|
||||
short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT] = {0,0,16384,16384,-16384,-16384,16384,16384,16384,-16384,-16384,16384,-16384,-16384,7327,7327,7327,21981,21981,7327,21981,21981,7327,-7327,7327,-21981,21981,-7327,21981,-21981,-7327,7327,-7327,21981,-21981,7327,-21981,21981,-7327,-7327,-7327,-21981,-21981,-7327,-21981,-21981,10726,10726,10726,3576,3576,10726,3576,3576,10726,17876,10726,25027,3576,17876,3576,25027,17876,10726,17876,3576,25027,10726,25027,3576,17876,17876,17876,25027,25027,17876,25027,25027,10726,-10726,10726,-3576,3576,-10726,3576,-3576,10726,-17876,10726,-25027,3576,-17876,3576,-25027,17876,-10726,17876,-3576,25027,-10726,25027,-3576,17876,-17876,17876,-25027,25027,-17876,25027,-25027,-10726,10726,-10726,3576,-3576,10726,-3576,3576,-10726,17876,-10726,25027,-3576,17876,-3576,25027,-17876,10726,-17876,3576,-25027,10726,-25027,3576,-17876,17876,-17876,25027,-25027,17876,-25027,25027,-10726,-10726,-10726,-3576,-3576,-10726,-3576,-3576,-10726,-17876,-10726,-25027,-3576,-17876,-3576,-25027,-17876,-10726,-17876,-3576,-25027,-10726,-25027,-3576,-17876,-17876,-17876,-25027,-25027,-17876,-25027,-25027,8886,8886,8886,12439,12439,8886,12439,12439,8886,5332,8886,1778,12439,5332,12439,1778,5332,8886,5332,12439,1778,8886,1778,12439,5332,5332,5332,1778,1778,5332,1778,1778,8886,19547,8886,15993,12439,19547,12439,15993,8886,23101,8886,26655,12439,23101,12439,26655,5332,19547,5332,15993,1778,19547,1778,15993,5332,23101,5332,26655,1778,23101,1778,26655,19547,8886,19547,12439,15993,8886,15993,12439,19547,5332,19547,1778,15993,5332,15993,1778,23101,8886,23101,12439,26655,8886,26655,12439,23101,5332,23101,1778,26655,5332,26655,1778,19547,19547,19547,15993,15993,19547,15993,15993,19547,23101,19547,26655,15993,23101,15993,26655,23101,19547,23101,15993,26655,19547,26655,15993,23101,23101,23101,26655,26655,23101,26655,26655,8886,-8886,8886,-12439,12439,-8886,12439,-12439,8886,-5332,8886,-1778,12439,-5332,12439,-1778,5332,-8886,5332,-12439,1778,-8886,1778,-12439,5332,-5332,5332,-1778,1778,-5332,1778,-1778,8886,-19547,8886,-15993,12439,-19547,12439,-15993,8886,-23101,8886,-26655,12439,-23101,12439,-26655,5332,-19547,5332,-15993,1778,-19547,1778,-15993,5332,-23101,5332,-26655,1778,-23101,1778,-26655,19547,-8886,19547,-12439,15993,-8886,15993,-12439,19547,-5332,19547,-1778,15993,-5332,15993,-1778,23101,-8886,23101,-12439,26655,-8886,26655,-12439,23101,-5332,23101,-1778,26655,-5332,26655,-1778,19547,-19547,19547,-15993,15993,-19547,15993,-15993,19547,-23101,19547,-26655,15993,-23101,15993,-26655,23101,-19547,23101,-15993,26655,-19547,26655,-15993,23101,-23101,23101,-26655,26655,-23101,26655,-26655,-8886,8886,-8886,12439,-12439,8886,-12439,12439,-8886,5332,-8886,1778,-12439,5332,-12439,1778,-5332,8886,-5332,12439,-1778,8886,-1778,12439,-5332,5332,-5332,1778,-1778,5332,-1778,1778,-8886,19547,-8886,15993,-12439,19547,-12439,15993,-8886,23101,-8886,26655,-12439,23101,-12439,26655,-5332,19547,-5332,15993,-1778,19547,-1778,15993,-5332,23101,-5332,26655,-1778,23101,-1778,26655,-19547,8886,-19547,12439,-15993,8886,-15993,12439,-19547,5332,-19547,1778,-15993,5332,-15993,1778,-23101,8886,-23101,12439,-26655,8886,-26655,12439,-23101,5332,-23101,1778,-26655,5332,-26655,1778,-19547,19547,-19547,15993,-15993,19547,-15993,15993,-19547,23101,-19547,26655,-15993,23101,-15993,26655,-23101,19547,-23101,15993,-26655,19547,-26655,15993,-23101,23101,-23101,26655,-26655,23101,-26655,26655,-8886,-8886,-8886,-12439,-12439,-8886,-12439,-12439,-8886,-5332,-8886,-1778,-12439,-5332,-12439,-1778,-5332,-8886,-5332,-12439,-1778,-8886,-1778,-12439,-5332,-5332,-5332,-1778,-1778,-5332,-1778,-1778,-8886,-19547,-8886,-15993,-12439,-19547,-12439,-15993,-8886,-23101,-8886,-26655,-12439,-23101,-12439,-26655,-5332,-19547,-5332,-15993,-1778,-19547,-1778,-15993,-5332,-23101,-5332,-26655,-1778,-23101,-1778,-26655,-19547,-8886,-19547,-12439,-15993,-8886,-15993,-12439,-19547,-5332,-19547,-1778,-15993,-5332,-15993,-1778,-23101,-8886,-23101,-12439,-26655,-8886,-26655,-12439,-23101,-5332,-23101,-1778,-26655,-5332,-26655,-1778,-19547,-19547,-19547,-15993,-15993,-19547,-15993,-15993,-19547,-23101,-19547,-26655,-15993,-23101,-15993,-26655,-23101,-19547,-23101,-15993,-26655,-19547,-26655,-15993,-23101,-23101,-23101,-26655,-26655,-23101,-26655,-26655};
|
||||
|
||||
@@ -109,7 +110,7 @@ int single_thread_flag=1;
|
||||
|
||||
int8_t threequarter_fs=0;
|
||||
|
||||
uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
//Temp fix for inexistent NR upper layer
|
||||
@@ -204,7 +205,7 @@ char uecap_xer_in=0;
|
||||
uint8_t abstraction_flag=0;
|
||||
|
||||
/* forward declarations */
|
||||
void set_default_frame_parms(nfapi_nr_config_request_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
|
||||
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
|
||||
|
||||
/*---------------------BMC: timespec helpers -----------------------------*/
|
||||
|
||||
@@ -389,6 +390,18 @@ int create_gNB_tasks(uint32_t gnb_nb) {
|
||||
LOG_E(GNB_APP, "Create task for gNB APP failed\n");
|
||||
return -1;
|
||||
}
|
||||
if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0){
|
||||
LOG_E(SCTP, "Create task for SCTP failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (is_x2ap_enabled()) {
|
||||
if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0){
|
||||
LOG_E(X2AP, "Create task for X2AP failed\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_I(X2AP, "X2AP is disabled.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -457,18 +470,18 @@ static void get_options(void) {
|
||||
}
|
||||
|
||||
|
||||
void set_default_frame_parms(nfapi_nr_config_request_t *config[MAX_NUM_CCs],
|
||||
NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs])
|
||||
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs],
|
||||
NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs])
|
||||
{
|
||||
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
frame_parms[CC_id] = (NR_DL_FRAME_PARMS *) malloc(sizeof(NR_DL_FRAME_PARMS));
|
||||
config[CC_id] = (nfapi_nr_config_request_t *) malloc(sizeof(nfapi_nr_config_request_t));
|
||||
config[CC_id]->subframe_config.numerology_index_mu.value =1;
|
||||
config[CC_id]->subframe_config.duplex_mode.value = 1; //FDD
|
||||
config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
|
||||
config[CC_id]->rf_config.dl_carrier_bandwidth.value = 106;
|
||||
config[CC_id]->rf_config.ul_carrier_bandwidth.value = 106;
|
||||
config[CC_id]->sch_config.physical_cell_id.value = 0;
|
||||
config[CC_id] = (nfapi_nr_config_request_scf_t *) malloc(sizeof(nfapi_nr_config_request_scf_t));
|
||||
config[CC_id]->ssb_config.scs_common.value = 1;
|
||||
config[CC_id]->cell_config.frame_duplex_type.value = 1; //FDD
|
||||
//config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
|
||||
config[CC_id]->carrier_config.dl_grid_size[1].value = 106;
|
||||
config[CC_id]->carrier_config.ul_grid_size[1].value = 106;
|
||||
config[CC_id]->cell_config.phy_cell_id.value = 0;
|
||||
///dl frequency to be filled in
|
||||
/* //Set some default values that may be overwritten while reading options
|
||||
frame_parms[CC_id]->frame_type = FDD;
|
||||
@@ -480,7 +493,7 @@ void set_default_frame_parms(nfapi_nr_config_request_t *config[MAX_NUM_CCs],
|
||||
frame_parms[CC_id]->Ncp_UL = NORMAL;
|
||||
frame_parms[CC_id]->Nid_cell = 0;
|
||||
frame_parms[CC_id]->num_MBSFN_config = 0;
|
||||
frame_parms[CC_id]->nb_antenna_ports_eNB = 1;
|
||||
frame_parms[CC_id]->nb_antenna_ports_gNB = 1;
|
||||
frame_parms[CC_id]->nb_antennas_tx = 1;
|
||||
frame_parms[CC_id]->nb_antennas_rx = 1;
|
||||
|
||||
@@ -557,8 +570,8 @@ void init_openair0(void) {
|
||||
openair0_cfg[card].duplex_mode = duplex_mode_FDD;
|
||||
|
||||
printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
|
||||
RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value,
|
||||
RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value );
|
||||
RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value,
|
||||
RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value );
|
||||
openair0_cfg[card].Mod_id = 0;
|
||||
|
||||
openair0_cfg[card].num_rb_dl=config[0]->rf_config.dl_carrier_bandwidth.value;
|
||||
@@ -566,8 +579,8 @@ void init_openair0(void) {
|
||||
openair0_cfg[card].clock_source = clock_source;
|
||||
|
||||
|
||||
openair0_cfg[card].tx_num_channels=min(2,RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value );
|
||||
openair0_cfg[card].rx_num_channels=min(2,RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value );
|
||||
openair0_cfg[card].tx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value );
|
||||
openair0_cfg[card].rx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value );
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
|
||||
@@ -583,7 +596,7 @@ void init_openair0(void) {
|
||||
|
||||
openair0_cfg[card].autocal[i] = 1;
|
||||
openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
|
||||
openair0_cfg[card].rx_gain[i] = RC.gNB[0][0]->rx_total_gain_dB;
|
||||
openair0_cfg[card].rx_gain[i] = RC.gNB[0]->rx_total_gain_dB;
|
||||
|
||||
|
||||
openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
|
||||
@@ -612,7 +625,7 @@ void wait_RUs(void) {
|
||||
}
|
||||
|
||||
void wait_gNBs(void) {
|
||||
int i,j;
|
||||
int i;
|
||||
int waiting=1;
|
||||
|
||||
while (waiting==1) {
|
||||
@@ -621,13 +634,10 @@ void wait_gNBs(void) {
|
||||
waiting=0;
|
||||
|
||||
for (i=0; i<RC.nb_nr_L1_inst; i++) {
|
||||
printf("RC.nb_nr_L1_CC[%d]:%d\n", i, RC.nb_nr_L1_CC[i]);
|
||||
|
||||
for (j=0; j<RC.nb_nr_L1_CC[i]; j++) {
|
||||
if (RC.gNB[i][j]->configured==0) {
|
||||
waiting=1;
|
||||
break;
|
||||
}
|
||||
if (RC.gNB[i]->configured==0) {
|
||||
waiting=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -686,10 +696,9 @@ int stop_L1L2(module_id_t gnb_id) {
|
||||
kill_NR_RU_proc(gnb_id);
|
||||
oai_exit = 0;
|
||||
|
||||
for (int cc_id = 0; cc_id < RC.nb_nr_CC[gnb_id]; cc_id++) {
|
||||
//free_transport(RC.gNB[gnb_id][cc_id]);
|
||||
phy_free_nr_gNB(RC.gNB[gnb_id][cc_id]);
|
||||
}
|
||||
//free_transport(RC.gNB[gnb_id]);
|
||||
phy_free_nr_gNB(RC.gNB[gnb_id]);
|
||||
|
||||
|
||||
nr_phy_free_RU(RC.ru[gnb_id]);
|
||||
free_lte_top();
|
||||
@@ -707,14 +716,13 @@ int restart_L1L2(module_id_t gnb_id) {
|
||||
/* block threads */
|
||||
sync_var = -1;
|
||||
|
||||
for (cc_id = 0; cc_id < RC.nb_nr_L1_CC[gnb_id]; cc_id++) {
|
||||
RC.gNB[gnb_id][cc_id]->configured = 0;
|
||||
}
|
||||
RC.gNB[gnb_id]->configured = 0;
|
||||
|
||||
|
||||
RC.ru_mask |= (1 << ru->idx);
|
||||
/* copy the changed frame parameters to the RU */
|
||||
/* TODO this should be done for all RUs associated to this gNB */
|
||||
memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id][0]->frame_parms, sizeof(NR_DL_FRAME_PARMS));
|
||||
memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id]->frame_parms, sizeof(NR_DL_FRAME_PARMS));
|
||||
set_function_spec_param(RC.ru[gnb_id]);
|
||||
LOG_I(GNB_APP, "attempting to create ITTI tasks\n");
|
||||
// No more rrc thread, as many race conditions are hidden behind
|
||||
@@ -784,9 +792,10 @@ void init_pdcp(void) {
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
int i, ru_id, CC_id = 0;
|
||||
int ru_id, CC_id = 0;
|
||||
start_background_system();
|
||||
|
||||
///static configuration for NR at the moment
|
||||
@@ -859,11 +868,13 @@ if(!IS_SOFTMODEM_NOS1)
|
||||
}
|
||||
|
||||
/* Start the agent. If it is turned off in the configuration, it won't start */
|
||||
/*
|
||||
RCconfig_nr_flexran();
|
||||
|
||||
for (i = 0; i < RC.nb_nr_L1_inst; i++) {
|
||||
flexran_agent_start(i);
|
||||
}
|
||||
*/
|
||||
|
||||
// init UE_PF_PO and mutex lock
|
||||
pthread_mutex_init(&ue_pf_po_mutex, NULL);
|
||||
@@ -871,38 +882,8 @@ if(!IS_SOFTMODEM_NOS1)
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
pthread_cond_init(&sync_cond,NULL);
|
||||
pthread_mutex_init(&sync_mutex, NULL);
|
||||
/*#ifdef XFORMS
|
||||
int UE_id;
|
||||
|
||||
if (do_forms==1) {
|
||||
fl_initialize (&argc, argv, NULL, 0, 0);
|
||||
form_stats_l2 = create_form_stats_form();
|
||||
fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats");
|
||||
form_stats = create_form_stats_form();
|
||||
fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
|
||||
|
||||
for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
|
||||
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
form_gnb[CC_id][UE_id] = create_phy_scope_gnb();
|
||||
sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id);
|
||||
fl_show_form (form_gnb[CC_id][UE_id]->phy_scope_gnb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
|
||||
|
||||
if (otg_enabled) {
|
||||
fl_set_button(form_gnb[CC_id][UE_id]->button_0,1);
|
||||
fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic ON");
|
||||
} else {
|
||||
fl_set_button(form_gnb[CC_id][UE_id]->button_0,0);
|
||||
fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic OFF");
|
||||
}
|
||||
} // CC_id
|
||||
} // UE_id
|
||||
|
||||
threadCreate(&forms_thread, scope_thread, NULL, "scope", -1, OAI_PRIORITY_RT_LOW);
|
||||
printf("Scope thread created, ret=%d\n",ret);
|
||||
}
|
||||
|
||||
#endif*/
|
||||
usleep(10*1000);
|
||||
usleep(1000);
|
||||
|
||||
if (nfapi_mode) {
|
||||
printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
|
||||
@@ -972,6 +953,13 @@ if(!IS_SOFTMODEM_NOS1)
|
||||
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
|
||||
printf("ALL RUs ready - init gNBs\n");
|
||||
|
||||
if (do_forms==1) {
|
||||
scopeParms_t p;
|
||||
p.argc=&argc;
|
||||
p.argv=argv;
|
||||
startScope(&p);
|
||||
}
|
||||
|
||||
if (nfapi_mode != 1 && nfapi_mode != 2) {
|
||||
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
|
||||
init_eNB_afterRU();
|
||||
@@ -1028,10 +1016,8 @@ if(!IS_SOFTMODEM_NOS1)
|
||||
/* release memory used by the RU/gNB threads (incomplete), after all
|
||||
* threads have been stopped (they partially use the same memory) */
|
||||
for (int inst = 0; inst < NB_gNB_INST; inst++) {
|
||||
for (int cc_id = 0; cc_id < RC.nb_nr_CC[inst]; cc_id++) {
|
||||
//free_transport(RC.gNB[inst][cc_id]);
|
||||
phy_free_nr_gNB(RC.gNB[inst][cc_id]);
|
||||
}
|
||||
//free_transport(RC.gNB[inst]);
|
||||
phy_free_nr_gNB(RC.gNB[inst]);
|
||||
}
|
||||
|
||||
for (int inst = 0; inst < NB_RU; inst++) {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&wait_for_sync, defintval:0, TYPE_INT, 0}, \
|
||||
{"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
|
||||
{"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT64, 0}, \
|
||||
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \
|
||||
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
|
||||
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \
|
||||
|
||||
+212
-202
@@ -136,14 +136,12 @@ typedef enum {
|
||||
} sync_mode_t;
|
||||
|
||||
|
||||
PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t UE_id,
|
||||
uint8_t abstraction_flag)
|
||||
|
||||
void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t UE_id,
|
||||
uint8_t abstraction_flag)
|
||||
{
|
||||
PHY_VARS_NR_UE *ue;
|
||||
ue = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE));
|
||||
memset(ue,0,sizeof(PHY_VARS_NR_UE));
|
||||
|
||||
memcpy(&(ue->frame_parms), frame_parms, sizeof(NR_DL_FRAME_PARMS));
|
||||
|
||||
ue->Mod_id = UE_id;
|
||||
@@ -153,7 +151,6 @@ PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms,
|
||||
init_nr_ue_signal(ue,1,abstraction_flag);
|
||||
// intialize transport
|
||||
init_nr_ue_transport(ue,abstraction_flag);
|
||||
return(ue);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -175,22 +172,19 @@ static void UE_synch(void *arg) {
|
||||
int freq_offset=0;
|
||||
UE->is_synchronized = 0;
|
||||
|
||||
|
||||
if (UE->UE_scan == 0) {
|
||||
get_band(downlink_frequency[CC_id][0], &UE->frame_parms.eutra_band, &uplink_frequency_offset[CC_id][0], &UE->frame_parms.frame_type);
|
||||
LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n",
|
||||
downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],
|
||||
LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu64", UL %"PRIu64" (oai_exit %d, rx_num_channels %d)\n",
|
||||
UE->frame_parms.dl_CarrierFreq, UE->frame_parms.ul_CarrierFreq,
|
||||
oai_exit, openair0_cfg[0].rx_num_channels);
|
||||
|
||||
for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
|
||||
openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
|
||||
downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq;
|
||||
openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq;
|
||||
openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
|
||||
|
||||
if (uplink_frequency_offset[CC_id][i] != 0) //
|
||||
if (UE->frame_parms.frame_type == FDD)
|
||||
openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
|
||||
else //FDD
|
||||
else
|
||||
openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
|
||||
}
|
||||
|
||||
@@ -248,13 +242,14 @@ static void UE_synch(void *arg) {
|
||||
|
||||
if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) {
|
||||
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
|
||||
hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_slot;
|
||||
LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
|
||||
hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) +
|
||||
round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0);
|
||||
LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %lu, UL %lu), UE_scan_carrier %d\n",
|
||||
hw_slot_offset,
|
||||
freq_offset,
|
||||
UE->rx_total_gain_dB,
|
||||
downlink_frequency[0][0]+freq_offset,
|
||||
downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
|
||||
UE->frame_parms.dl_CarrierFreq+freq_offset,
|
||||
UE->frame_parms.ul_CarrierFreq+freq_offset,
|
||||
UE->UE_scan_carrier );
|
||||
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
@@ -267,8 +262,8 @@ static void UE_synch(void *arg) {
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset);
|
||||
|
||||
openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
|
||||
downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+(UE->frame_parms.ul_CarrierFreq-UE->frame_parms.dl_CarrierFreq);
|
||||
UE->frame_parms.dl_CarrierFreq = openair0_cfg[CC_id].rx_freq[i];
|
||||
}
|
||||
|
||||
// reconfigure for potentially different bandwidth
|
||||
@@ -300,6 +295,12 @@ static void UE_synch(void *arg) {
|
||||
openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
|
||||
// openair0_cfg[0].rx_gain[0] -= 0;
|
||||
break;
|
||||
|
||||
case 66:
|
||||
openair0_cfg[UE->rf_map.card].sample_rate=122.88e6;
|
||||
openair0_cfg[UE->rf_map.card].rx_bw=100.e6;
|
||||
openair0_cfg[UE->rf_map.card].tx_bw=100.e6;
|
||||
break;
|
||||
}
|
||||
|
||||
if (UE->mode != loop_through_memory) {
|
||||
@@ -327,15 +328,15 @@ static void UE_synch(void *arg) {
|
||||
freq_offset += 100;
|
||||
|
||||
freq_offset *= -1;
|
||||
LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
|
||||
LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %lu, UL %lu)\n",
|
||||
freq_offset,
|
||||
UE->rx_total_gain_dB,
|
||||
downlink_frequency[0][0]+freq_offset,
|
||||
downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
|
||||
UE->frame_parms.dl_CarrierFreq+freq_offset,
|
||||
UE->frame_parms.ul_CarrierFreq+freq_offset );
|
||||
|
||||
for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
|
||||
openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
|
||||
openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq+freq_offset;
|
||||
openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq+freq_offset;
|
||||
openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
|
||||
|
||||
if (UE->UE_scan_carrier==1)
|
||||
@@ -355,25 +356,24 @@ static void UE_synch(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
|
||||
nr_dcireq_t dcireq;
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
uint32_t nb_rb, start_rb;
|
||||
uint8_t nb_symb_sch, start_symbol, mcs, precod_nbr_layers, harq_pid, rvidx;
|
||||
uint16_t n_rnti;
|
||||
|
||||
// Process Rx data for one sub-frame
|
||||
if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_DOWNLINK_SLOT) {
|
||||
//TODO: all of this has to be moved to the MAC!!!
|
||||
nr_dcireq_t dcireq;
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
|
||||
// program PUSCH. this should actually be done by the MAC upon reception of an UL DCI
|
||||
if (proc->nr_tti_tx == 8 || UE->frame_parms.frame_type == FDD){
|
||||
|
||||
dcireq.module_id = UE->Mod_id;
|
||||
dcireq.gNB_index = 0;
|
||||
dcireq.cc_id = 0;
|
||||
dcireq.frame = proc->frame_rx;
|
||||
dcireq.slot = proc->nr_tti_rx;
|
||||
nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
|
||||
|
||||
scheduled_response.dl_config = &dcireq.dl_config_req;
|
||||
scheduled_response.dl_config = NULL;
|
||||
scheduled_response.ul_config = &dcireq.ul_config_req;
|
||||
scheduled_response.tx_request = NULL;
|
||||
scheduled_response.module_id = UE->Mod_id;
|
||||
@@ -381,19 +381,18 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
scheduled_response.frame = proc->frame_rx;
|
||||
scheduled_response.slot = proc->nr_tti_rx;
|
||||
//--------------------------Temporary configuration-----------------------------//
|
||||
//--------------------------Temporary configuration-----------------------------//
|
||||
n_rnti = 0x1234;
|
||||
nb_rb = 50;
|
||||
start_rb = 0;
|
||||
nb_symb_sch = 12;
|
||||
start_symbol = 0;
|
||||
start_symbol = 2;
|
||||
precod_nbr_layers = 1;
|
||||
mcs = 9;
|
||||
harq_pid = 0;
|
||||
rvidx = 0;
|
||||
//------------------------------------------------------------------------------//
|
||||
|
||||
scheduled_response.ul_config->sfn_slot = NR_UPLINK_SLOT;
|
||||
scheduled_response.ul_config->slot = 8;
|
||||
scheduled_response.ul_config->number_pdus = 1;
|
||||
scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH;
|
||||
scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.rnti = n_rnti;
|
||||
@@ -406,8 +405,53 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.rv = rvidx;
|
||||
scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.n_layers = precod_nbr_layers;
|
||||
scheduled_response.ul_config->ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.harq_process_nbr = harq_pid;
|
||||
nr_ue_scheduled_response(&scheduled_response);
|
||||
|
||||
nr_ue_scheduled_response(&scheduled_response);
|
||||
|
||||
if (UE->mode != loop_through_memory) {
|
||||
uint8_t thread_id = PHY_vars_UE_g[UE->Mod_id][0]->current_thread_id[proc->nr_tti_tx];
|
||||
phy_procedures_nrUE_TX(UE,proc,0,thread_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
|
||||
nr_dcireq_t dcireq;
|
||||
nr_scheduled_response_t scheduled_response;
|
||||
uint8_t ssb_period = UE->nrUE_config.ssb_table.ssb_period;
|
||||
|
||||
//program DCI for slot 1
|
||||
//TODO: all of this has to be moved to the MAC!!!
|
||||
if (proc->nr_tti_rx == NR_DOWNLINK_SLOT || UE->frame_parms.frame_type == FDD){
|
||||
dcireq.module_id = UE->Mod_id;
|
||||
dcireq.gNB_index = 0;
|
||||
dcireq.cc_id = 0;
|
||||
dcireq.frame = proc->frame_rx;
|
||||
dcireq.slot = proc->nr_tti_rx;
|
||||
nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
|
||||
|
||||
// we should have received a DL DCI here, so configure DL accordingly
|
||||
scheduled_response.dl_config = &dcireq.dl_config_req;
|
||||
scheduled_response.ul_config = NULL;
|
||||
scheduled_response.tx_request = NULL;
|
||||
scheduled_response.module_id = UE->Mod_id;
|
||||
scheduled_response.CC_id = 0;
|
||||
if (!((proc->frame_rx)%(1<<(ssb_period-1)))) {
|
||||
if(proc->frame_rx > dcireq.dl_config_req.sfn)
|
||||
UE->frame_gap = proc->frame_rx - dcireq.dl_config_req.sfn;
|
||||
if(proc->frame_rx < dcireq.dl_config_req.sfn)
|
||||
UE->frame_gap = dcireq.dl_config_req.sfn - proc->frame_rx;
|
||||
proc->frame_rx = dcireq.dl_config_req.sfn;
|
||||
}
|
||||
scheduled_response.frame = proc->frame_rx;
|
||||
scheduled_response.slot = proc->nr_tti_rx;
|
||||
|
||||
nr_ue_scheduled_response(&scheduled_response);
|
||||
}
|
||||
|
||||
// Process Rx data for one sub-frame
|
||||
if ( proc->nr_tti_rx >=0 && proc->nr_tti_rx <= 1 ) {
|
||||
#ifdef UE_SLOT_PARALLELISATION
|
||||
phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
|
||||
#else
|
||||
@@ -416,14 +460,15 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500);
|
||||
//printf(">>> nr_ue_pdcch_procedures ended\n");
|
||||
#endif
|
||||
if(IS_SOFTMODEM_NOS1){ //&& proc->nr_tti_rx==1
|
||||
//Hardcoded rnti value
|
||||
protocol_ctxt_t ctxt;
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO,
|
||||
0x1234, proc->frame_rx,
|
||||
proc->nr_tti_rx, 0);
|
||||
pdcp_run(&ctxt);
|
||||
}
|
||||
|
||||
if(IS_SOFTMODEM_NOS1){ //&& proc->nr_tti_rx==1
|
||||
//Hardcoded rnti value
|
||||
protocol_ctxt_t ctxt;
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO,
|
||||
0x1234, proc->frame_rx,
|
||||
proc->nr_tti_rx, 0);
|
||||
pdcp_run(&ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
// no UL for now
|
||||
@@ -458,11 +503,10 @@ typedef struct processingData_s {
|
||||
} processingData_t;
|
||||
|
||||
void UE_processing(void *arg) {
|
||||
uint8_t thread_id;
|
||||
processingData_t *rxtxD=(processingData_t *) arg;
|
||||
UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
|
||||
PHY_VARS_NR_UE *UE = rxtxD->UE;
|
||||
processSlotRX(UE, proc);
|
||||
|
||||
uint8_t gNB_id = 0;
|
||||
// params for UL time alignment procedure
|
||||
// params for UL time alignment procedure
|
||||
@@ -472,18 +516,6 @@ void UE_processing(void *arg) {
|
||||
int slot_tx = proc->nr_tti_tx;
|
||||
int frame_tx = proc->frame_tx;
|
||||
|
||||
//printf(">>> mac ended\n");
|
||||
// Prepare the future Tx data
|
||||
/*
|
||||
#ifndef NO_RAT_NR
|
||||
|
||||
if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_UPLINK_SLOT)
|
||||
#else
|
||||
if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
|
||||
(UE->frame_parms.frame_type == FDD) )
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* UL time alignment
|
||||
// If the current tx frame and slot match the TA configuration in ul_time_alignment
|
||||
// then timing advance is processed and set to be applied in the next UL transmission */
|
||||
@@ -500,80 +532,60 @@ void UE_processing(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
if (proc->nr_tti_tx == NR_UPLINK_SLOT || UE->frame_parms.frame_type == FDD) {
|
||||
processSlotRX(UE, proc);
|
||||
|
||||
thread_id = PHY_vars_UE_g[UE->Mod_id][0]->current_thread_id[proc->nr_tti_tx];
|
||||
processSlotTX(UE, proc);
|
||||
|
||||
|
||||
if (UE->mode != loop_through_memory)
|
||||
phy_procedures_nrUE_TX(UE,proc,gNB_id,thread_id);
|
||||
|
||||
}
|
||||
|
||||
//phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
|
||||
|
||||
#if 0
|
||||
|
||||
if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
|
||||
(UE->frame_parms.frame_type == TDD))
|
||||
if (UE->mode != loop_through_memory)
|
||||
//phy_procedures_UE_S_TX(UE,0,0,no_relay);
|
||||
updateTimes(current, &t3, 10000, timing_proc_name);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
|
||||
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
|
||||
dummy_tx[i]=malloc16_clear(writeBlockSize*4);
|
||||
|
||||
for(int x=0; x<20; x++) { // two frames for initial sync
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe;
|
||||
|
||||
AssertFatal( UE->frame_parms.samples_per_subframe ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
rxp,
|
||||
UE->frame_parms.samples_per_subframe,
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
}
|
||||
AssertFatal( writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
dummy_tx,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
4),"");
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
free(dummy_tx[i]);
|
||||
}
|
||||
|
||||
void trashFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
|
||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) {
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
|
||||
void *dummy_rx[UE->frame_parms.nb_antennas_rx];
|
||||
for(int x=0; x<20; x++) { // two frames for initial sync
|
||||
for (int slot=0; slot<UE->frame_parms.slots_per_subframe; slot ++ ) {
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) {
|
||||
if (toTrash)
|
||||
rxp[i]=malloc16(UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms)*4);
|
||||
else
|
||||
rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) +
|
||||
4*((x*UE->frame_parms.samples_per_subframe)+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot,&UE->frame_parms,0));
|
||||
}
|
||||
|
||||
AssertFatal( UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms) ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
rxp,
|
||||
UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms),
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
dummy_rx[i]=malloc16(UE->frame_parms.samples_per_subframe*4);
|
||||
|
||||
for (int sf=0; sf<NR_NUMBER_OF_SUBFRAMES_PER_FRAME; sf++) {
|
||||
// printf("Reading dummy sf %d\n",sf);
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
dummy_rx,
|
||||
UE->frame_parms.samples_per_subframe,
|
||||
UE->frame_parms.nb_antennas_rx);
|
||||
if (IS_SOFTMODEM_RFSIM ) {
|
||||
usleep(1000); // slow down, as would do actual rf to let cpu for the synchro thread
|
||||
if (IS_SOFTMODEM_RFSIM)
|
||||
dummyWrite(UE,*timestamp, UE->frame_parms.get_samples_per_slot(slot,&UE->frame_parms));
|
||||
if (toTrash)
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
free(rxp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
free(dummy_tx[i]);
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
free(dummy_rx[i]);
|
||||
}
|
||||
|
||||
void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
@@ -581,21 +593,20 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
|
||||
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
|
||||
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
}
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
free(dummy_tx[i]);
|
||||
*timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
|
||||
int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
|
||||
// we write before read becasue gNB waits for UE to write and both executions halt
|
||||
// this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot
|
||||
if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer);
|
||||
AssertFatal(unitTransfer ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
unitTransfer,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
*timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -622,6 +633,22 @@ int computeSamplesShift(PHY_VARS_NR_UE *UE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
if (fp->numerology_index == 0)
|
||||
return fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
|
||||
int num_samples = (slot%(fp->slots_per_subframe/2)) ? fp->nb_prefix_samples : fp->nb_prefix_samples0;
|
||||
num_samples += fp->ofdm_symbol_size;
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
int rem_samples = fp->get_samples_per_slot(slot, fp) - get_firstSymSamp(slot, fp);
|
||||
int next_slot_first_symbol = 0;
|
||||
if (slot < (fp->slots_per_frame-1))
|
||||
next_slot_first_symbol = get_firstSymSamp(slot+1, fp);
|
||||
return rem_samples + next_slot_first_symbol;
|
||||
}
|
||||
|
||||
void *UE_thread(void *arg) {
|
||||
//this thread should be over the processing thread to keep in real time
|
||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
|
||||
@@ -629,7 +656,6 @@ void *UE_thread(void *arg) {
|
||||
openair0_timestamp timestamp;
|
||||
void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
|
||||
int start_rx_stream = 0;
|
||||
const uint16_t table_sf_slot[20] = {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9};
|
||||
AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
|
||||
UE->rfdevice.host_type = RAU_HOST;
|
||||
AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
|
||||
@@ -639,13 +665,14 @@ void *UE_thread(void *arg) {
|
||||
int thread_idx=0;
|
||||
notifiedFIFO_t freeBlocks;
|
||||
initNotifiedFIFO_nothreadSafe(&freeBlocks);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
|
||||
for (int i=0; i<RX_NB_TH+1; i++) // RX_NB_TH working + 1 we are making to be pushed
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks,
|
||||
newNotifiedFIFO_elt(sizeof(processingData_t), 0,&nf,UE_processing));
|
||||
|
||||
bool syncRunning=false;
|
||||
const int nb_slot_frame = 10*UE->frame_parms.slots_per_subframe;
|
||||
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
|
||||
int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
|
||||
|
||||
while (!oai_exit) {
|
||||
@@ -656,11 +683,11 @@ void *UE_thread(void *arg) {
|
||||
syncRunning=false;
|
||||
syncData_t *tmp=(syncData_t *)NotifiedFifoData(res);
|
||||
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
|
||||
decoded_frame_rx=(tmp->proc.decoded_frame_rx+trashed_frames) % MAX_FRAME_NUMBER;
|
||||
decoded_frame_rx=(tmp->proc.decoded_frame_rx + (!UE->init_sync_frame) + trashed_frames) % MAX_FRAME_NUMBER;
|
||||
delNotifiedFIFO_elt(res);
|
||||
} else {
|
||||
trashFrame(UE, ×tamp);
|
||||
trashed_frames++;
|
||||
readFrame(UE, ×tamp, true);
|
||||
trashed_frames+=2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -668,7 +695,7 @@ void *UE_thread(void *arg) {
|
||||
AssertFatal( !syncRunning, "At this point synchronization can't be running\n");
|
||||
|
||||
if (!UE->is_synchronized) {
|
||||
readFrame(UE, ×tamp);
|
||||
readFrame(UE, ×tamp, false);
|
||||
notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(syncData_t),0,&nf,UE_synch);
|
||||
syncData_t *syncMsg=(syncData_t *)NotifiedFifoData(Msg);
|
||||
syncMsg->UE=UE;
|
||||
@@ -695,7 +722,7 @@ void *UE_thread(void *arg) {
|
||||
// and we shifted above to the first slot of next frame
|
||||
decoded_frame_rx++;
|
||||
// we do ++ first in the regular processing, so it will be begin of frame;
|
||||
absolute_slot=decoded_frame_rx*nb_slot_frame + nb_slot_frame -1;
|
||||
absolute_slot=decoded_frame_rx*nb_slot_frame -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -715,11 +742,11 @@ void *UE_thread(void *arg) {
|
||||
curMsg->UE->current_thread_id[slot_nr] = thread_idx;
|
||||
curMsg->proc.CC_id = 0;
|
||||
curMsg->proc.nr_tti_rx= slot_nr;
|
||||
curMsg->proc.subframe_rx=table_sf_slot[slot_nr];
|
||||
curMsg->proc.subframe_rx=slot_nr/(nb_slot_frame/10);
|
||||
curMsg->proc.nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
|
||||
curMsg->proc.subframe_tx=curMsg->proc.nr_tti_rx;
|
||||
curMsg->proc.frame_rx = ( absolute_slot/nb_slot_frame ) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.frame_tx = ( (absolute_slot + DURATION_RX_TO_TX) /nb_slot_frame ) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.frame_rx = ((absolute_slot/nb_slot_frame)+UE->frame_gap) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.frame_tx = (((absolute_slot+DURATION_RX_TO_TX)/nb_slot_frame)+UE->frame_gap) % MAX_FRAME_NUMBER;
|
||||
curMsg->proc.decoded_frame_rx=-1;
|
||||
//LOG_I(PHY,"Process slot %d thread Idx %d total gain %d\n", slot_nr, thread_idx, UE->rx_total_gain_dB);
|
||||
|
||||
@@ -732,26 +759,25 @@ void *UE_thread(void *arg) {
|
||||
}*/
|
||||
#endif
|
||||
|
||||
int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms);
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
|
||||
UE->frame_parms.nb_prefix_samples0+
|
||||
slot_nr*UE->frame_parms.samples_per_slot];
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)];
|
||||
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
|
||||
txp[i] = (void *)&UE->common_vars.txdata[i][((curMsg->proc.nr_tti_rx + DURATION_RX_TO_TX)%nb_slot_frame)*UE->frame_parms.samples_per_slot];
|
||||
txp[i] = (void *)&UE->common_vars.txdata[i][UE->frame_parms.get_samples_slot_timestamp(
|
||||
((curMsg->proc.nr_tti_rx + DURATION_RX_TO_TX)%nb_slot_frame),&UE->frame_parms,0)];
|
||||
|
||||
int readBlockSize, writeBlockSize;
|
||||
|
||||
if (slot_nr<(nb_slot_frame - 1)) {
|
||||
readBlockSize=UE->frame_parms.samples_per_slot;
|
||||
writeBlockSize=UE->frame_parms.samples_per_slot;
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms);
|
||||
} else {
|
||||
UE->rx_offset_diff = computeSamplesShift(UE);
|
||||
readBlockSize=UE->frame_parms.samples_per_slot -
|
||||
UE->frame_parms.ofdm_symbol_size -
|
||||
UE->frame_parms.nb_prefix_samples0 -
|
||||
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
|
||||
UE->rx_offset_diff;
|
||||
writeBlockSize=UE->frame_parms.samples_per_slot -
|
||||
writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms) -
|
||||
UE->rx_offset_diff;
|
||||
}
|
||||
|
||||
@@ -762,33 +788,20 @@ void *UE_thread(void *arg) {
|
||||
readBlockSize,
|
||||
UE->frame_parms.nb_antennas_rx),"");
|
||||
|
||||
if (slot_nr == (20+NR_UPLINK_SLOT-DURATION_RX_TO_TX - 1)%20)
|
||||
AssertFatal( writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
timestamp+
|
||||
(DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot) -
|
||||
UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
|
||||
openair0_cfg[0].tx_sample_advance,
|
||||
txp,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
2),"");
|
||||
|
||||
if (slot_nr == (20+NR_UPLINK_SLOT-DURATION_RX_TO_TX)%20)
|
||||
AssertFatal( writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
timestamp+
|
||||
(DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot) -
|
||||
UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
|
||||
openair0_cfg[0].tx_sample_advance,
|
||||
txp,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
3),"");
|
||||
AssertFatal( writeBlockSize ==
|
||||
UE->rfdevice.trx_write_func(&UE->rfdevice,
|
||||
timestamp+
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr,
|
||||
&UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp -
|
||||
openair0_cfg[0].tx_sample_advance,
|
||||
txp,
|
||||
writeBlockSize,
|
||||
UE->frame_parms.nb_antennas_tx,
|
||||
1),"");
|
||||
|
||||
if( slot_nr==(nb_slot_frame-1)) {
|
||||
// read in first symbol of next frame and adjust for timing drift
|
||||
int first_symbols=writeBlockSize-readBlockSize;
|
||||
int first_symbols=UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0; // first symbol of every frames
|
||||
|
||||
if ( first_symbols > 0 )
|
||||
AssertFatal(first_symbols ==
|
||||
@@ -802,8 +815,9 @@ void *UE_thread(void *arg) {
|
||||
}
|
||||
|
||||
curMsg->proc.timestamp_tx = timestamp+
|
||||
(DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot)-
|
||||
UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
|
||||
UE->frame_parms.get_samples_slot_timestamp(slot_nr,
|
||||
&UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp;
|
||||
|
||||
notifiedFIFO_elt_t *res;
|
||||
|
||||
while (nbSlotProcessing >= RX_NB_TH) {
|
||||
@@ -812,7 +826,8 @@ void *UE_thread(void *arg) {
|
||||
processingData_t *tmp=(processingData_t *)res->msgData;
|
||||
|
||||
if (tmp->proc.decoded_frame_rx != -1)
|
||||
decoded_frame_rx=tmp->proc.decoded_frame_rx;
|
||||
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
|
||||
//decoded_frame_rx=tmp->proc.decoded_frame_rx;
|
||||
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
|
||||
}
|
||||
@@ -838,7 +853,8 @@ void *UE_thread(void *arg) {
|
||||
processingData_t *tmp=(processingData_t *)res->msgData;
|
||||
|
||||
if (tmp->proc.decoded_frame_rx != -1)
|
||||
decoded_frame_rx=tmp->proc.decoded_frame_rx;
|
||||
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
|
||||
//decoded_frame_rx=tmp->proc.decoded_frame_rx;
|
||||
|
||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
|
||||
}
|
||||
@@ -847,30 +863,27 @@ void *UE_thread(void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_NR_UE(int nb_inst) {
|
||||
void init_NR_UE(int nb_inst, char* rrc_config_path) {
|
||||
int inst;
|
||||
NR_UE_MAC_INST_t *mac_inst;
|
||||
NR_UE_RRC_INST_t* rrc_inst;
|
||||
|
||||
for (inst=0; inst < nb_inst; inst++) {
|
||||
AssertFatal((rrc_inst = nr_l3_init_ue(rrc_config_path)) != NULL, "can not initialize RRC module\n");
|
||||
AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst)) != NULL, "can not initialize L2 module\n");
|
||||
AssertFatal((mac_inst->if_module = nr_ue_if_module_init(inst)) != NULL, "can not initialize IF module\n");
|
||||
}
|
||||
}
|
||||
|
||||
void init_NR_UE_threads(int nb_inst) {
|
||||
int inst;
|
||||
|
||||
pthread_t threads[nb_inst];
|
||||
|
||||
for (inst=0; inst < nb_inst; inst++) {
|
||||
PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0];
|
||||
AssertFatal((UE->if_inst = nr_ue_if_module_init(inst)) != NULL, "can not initial IF module\n");
|
||||
nr_l3_init_ue();
|
||||
nr_l2_init_ue();
|
||||
mac_inst = get_mac_inst(inst);
|
||||
mac_inst->if_module = UE->if_inst;
|
||||
// Initial bandwidth part configuration -- full carrier bandwidth
|
||||
mac_inst->initial_bwp_dl.bwp_id = 0;
|
||||
mac_inst->initial_bwp_dl.location = 0;
|
||||
mac_inst->initial_bwp_dl.scs = UE->frame_parms.subcarrier_spacing;
|
||||
mac_inst->initial_bwp_dl.N_RB = UE->frame_parms.N_RB_DL;
|
||||
mac_inst->initial_bwp_dl.cyclic_prefix = UE->frame_parms.Ncp;
|
||||
mac_inst->initial_bwp_ul.bwp_id = 0;
|
||||
mac_inst->initial_bwp_ul.location = 0;
|
||||
mac_inst->initial_bwp_ul.scs = UE->frame_parms.subcarrier_spacing;
|
||||
mac_inst->initial_bwp_ul.N_RB = UE->frame_parms.N_RB_UL;
|
||||
mac_inst->initial_bwp_ul.cyclic_prefix = UE->frame_parms.Ncp;
|
||||
LOG_I(PHY,"Initializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
|
||||
|
||||
LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
|
||||
threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
|
||||
|
||||
#ifdef UE_DLSCH_PARALLELISATION
|
||||
@@ -879,8 +892,6 @@ void init_NR_UE(int nb_inst) {
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
printf("UE threads created by %ld\n", gettid());
|
||||
}
|
||||
|
||||
/* HACK: this function is needed to compile the UE
|
||||
@@ -895,4 +906,3 @@ int8_t find_dlsch(uint16_t rnti,
|
||||
}
|
||||
|
||||
void multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP) {}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ static double snr_dB=20;
|
||||
|
||||
int threequarter_fs=0;
|
||||
|
||||
uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
//int32_t uplink_counter = 0;
|
||||
|
||||
@@ -221,6 +221,8 @@ tpool_t *Tpool;
|
||||
|
||||
char *usrp_args=NULL;
|
||||
|
||||
char *rrc_config_path=NULL;
|
||||
|
||||
/* forward declarations */
|
||||
void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
|
||||
|
||||
@@ -472,7 +474,7 @@ void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
/* Set some default values that may be overwritten while reading options */
|
||||
frame_parms[CC_id] = (NR_DL_FRAME_PARMS *) calloc(sizeof(NR_DL_FRAME_PARMS),1);
|
||||
frame_parms[CC_id]->eutra_band = 78;
|
||||
frame_parms[CC_id]->nr_band = 78;
|
||||
frame_parms[CC_id]->frame_type = FDD;
|
||||
frame_parms[CC_id]->tdd_config = 3;
|
||||
//frame_parms[CC_id]->tdd_config_S = 0;
|
||||
@@ -482,7 +484,7 @@ void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
|
||||
//frame_parms[CC_id]->Ncp_UL = NORMAL;
|
||||
frame_parms[CC_id]->Nid_cell = 0;
|
||||
//frame_parms[CC_id]->num_MBSFN_config = 0;
|
||||
frame_parms[CC_id]->nb_antenna_ports_eNB = 1;
|
||||
frame_parms[CC_id]->nb_antenna_ports_gNB = 1;
|
||||
frame_parms[CC_id]->nb_antennas_tx = 1;
|
||||
frame_parms[CC_id]->nb_antennas_rx = 1;
|
||||
//frame_parms[CC_id]->nushift = 0;
|
||||
@@ -500,8 +502,25 @@ void init_openair0(void) {
|
||||
for (card=0; card<MAX_CARDS; card++) {
|
||||
openair0_cfg[card].configFilename = NULL;
|
||||
openair0_cfg[card].threequarter_fs = frame_parms[0]->threequarter_fs;
|
||||
numerology = frame_parms[0]->numerology_index;
|
||||
|
||||
if(frame_parms[0]->N_RB_DL == 217) {
|
||||
if(frame_parms[0]->N_RB_DL == 66) {
|
||||
if (numerology==3) {
|
||||
openair0_cfg[card].sample_rate=122.88e6;
|
||||
openair0_cfg[card].samples_per_frame = 1228800;
|
||||
} else {
|
||||
LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}else if(frame_parms[0]->N_RB_DL == 32) {
|
||||
if (numerology==3) {
|
||||
openair0_cfg[card].sample_rate=61.44e6;
|
||||
openair0_cfg[card].samples_per_frame = 614400;
|
||||
} else {
|
||||
LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}else if(frame_parms[0]->N_RB_DL == 217) {
|
||||
if (numerology==1) {
|
||||
if (frame_parms[0]->threequarter_fs) {
|
||||
openair0_cfg[card].sample_rate=92.16e6;
|
||||
@@ -584,12 +603,12 @@ void init_openair0(void) {
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
if (i<openair0_cfg[card].tx_num_channels)
|
||||
openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
|
||||
openair0_cfg[card].tx_freq[i] = frame_parms[0]->ul_CarrierFreq;
|
||||
else
|
||||
openair0_cfg[card].tx_freq[i]=0.0;
|
||||
|
||||
if (i<openair0_cfg[card].rx_num_channels)
|
||||
openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
|
||||
openair0_cfg[card].rx_freq[i] = frame_parms[0]->dl_CarrierFreq;
|
||||
else
|
||||
openair0_cfg[card].rx_freq[i]=0.0;
|
||||
|
||||
@@ -631,7 +650,7 @@ void init_pdcp(void) {
|
||||
}
|
||||
|
||||
// Stupid function addition because UE itti messages queues definition is common with eNB
|
||||
void *rrc_enb_process_itti_msg(void *notUsed) {
|
||||
void *rrc_enb_process_msg(void *notUsed) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -674,35 +693,28 @@ int main( int argc, char **argv ) {
|
||||
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
|
||||
|
||||
init_opt() ;
|
||||
if(IS_SOFTMODEM_NOS1)
|
||||
init_pdcp();
|
||||
load_nrLDPClib();
|
||||
|
||||
if (ouput_vcd) {
|
||||
vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef PDCP_USE_NETLINK
|
||||
netlink_init();
|
||||
#if defined(PDCP_USE_NETLINK_QUEUES)
|
||||
pdcp_netlink_init();
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
#ifndef PACKAGE_VERSION
|
||||
#ifndef PACKAGE_VERSION
|
||||
# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
|
||||
#endif
|
||||
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
||||
|
||||
// init the parameters
|
||||
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx;
|
||||
frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx;
|
||||
frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
|
||||
frame_parms[CC_id]->threequarter_fs = threequarter_fs;
|
||||
LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx);
|
||||
get_band(downlink_frequency[CC_id][0], &frame_parms[CC_id]->eutra_band, &uplink_frequency_offset[CC_id][0], &frame_parms[CC_id]->frame_type);
|
||||
}
|
||||
init_NR_UE(1,rrc_config_path);
|
||||
if(IS_SOFTMODEM_NOS1)
|
||||
init_pdcp();
|
||||
/*
|
||||
#ifdef PDCP_USE_NETLINK
|
||||
netlink_init();
|
||||
#if defined(PDCP_USE_NETLINK_QUEUES)
|
||||
pdcp_netlink_init();
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
|
||||
NB_UE_INST=1;
|
||||
NB_INST=1;
|
||||
@@ -710,17 +722,38 @@ int main( int argc, char **argv ) {
|
||||
PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE *)*MAX_NUM_CCs);
|
||||
|
||||
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
printf("frame_parms %hu\n",frame_parms[CC_id]->ofdm_symbol_size);
|
||||
nr_init_frame_parms_ue(frame_parms[CC_id],numerology,NORMAL,frame_parms[CC_id]->N_RB_DL,(frame_parms[CC_id]->N_RB_DL-20)>>1,0);
|
||||
PHY_vars_UE_g[0][CC_id] = init_nr_ue_vars(frame_parms[CC_id], 0,abstraction_flag);
|
||||
UE[CC_id] = PHY_vars_UE_g[0][CC_id];
|
||||
printf("frame_parms %d\n",frame_parms[CC_id]->ofdm_symbol_size);
|
||||
frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx;
|
||||
frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx;
|
||||
frame_parms[CC_id]->nb_antenna_ports_gNB = 1; //initial value overwritten by initial sync later
|
||||
frame_parms[CC_id]->threequarter_fs = threequarter_fs;
|
||||
LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx);
|
||||
|
||||
PHY_vars_UE_g[0][CC_id] = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE));
|
||||
|
||||
UE[CC_id] = PHY_vars_UE_g[0][CC_id];
|
||||
memset(UE[CC_id],0,sizeof(PHY_VARS_NR_UE));
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
if(mac->if_module != NULL && mac->if_module->phy_config_request != NULL)
|
||||
mac->if_module->phy_config_request(&mac->phy_config);
|
||||
|
||||
fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
|
||||
nr_init_frame_parms_ue(frame_parms[CC_id],nrUE_config,NORMAL);
|
||||
|
||||
// Overwrite DL frequency (for FR2 testing)
|
||||
if (downlink_frequency[0][0]!=0)
|
||||
frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
|
||||
|
||||
init_nr_ue_vars(UE[CC_id],frame_parms[CC_id],0,abstraction_flag);
|
||||
|
||||
if (get_softmodem_params()->phy_test==1)
|
||||
UE[CC_id]->mac_enabled = 0;
|
||||
else
|
||||
UE[CC_id]->mac_enabled = 1;
|
||||
|
||||
UE[CC_id]->mac_enabled = 1;
|
||||
UE[CC_id]->if_inst = nr_ue_if_module_init(0);
|
||||
UE[CC_id]->UE_scan = UE_scan;
|
||||
UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
|
||||
UE[CC_id]->UE_fo_compensation = UE_fo_compensation;
|
||||
@@ -728,13 +761,6 @@ int main( int argc, char **argv ) {
|
||||
UE[CC_id]->no_timing_correction = UE_no_timing_correction;
|
||||
printf("UE[%d]->mode = %d\n",CC_id,mode);
|
||||
|
||||
for (uint8_t i=0; i<RX_NB_TH_MAX; i++) {
|
||||
if (UE[CC_id]->mac_enabled == 1)
|
||||
UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1234;
|
||||
else
|
||||
UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1235;
|
||||
}
|
||||
|
||||
UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off;
|
||||
UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
|
||||
|
||||
@@ -769,11 +795,14 @@ int main( int argc, char **argv ) {
|
||||
#else
|
||||
PHY_vars_UE_g[0][CC_id]->hw_timing_advance = 160;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
init_NR_UE_threads(1);
|
||||
printf("UE threads created by %ld\n", gettid());
|
||||
|
||||
// wait for end of program
|
||||
printf("TYPE <CTRL-C> TO TERMINATE\n");
|
||||
init_NR_UE(1);
|
||||
|
||||
while(true)
|
||||
sleep(3600);
|
||||
|
||||
@@ -54,8 +54,6 @@
|
||||
{"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200", TYPE_STRING, 0} \
|
||||
}
|
||||
|
||||
#define DEFAULT_DLF 2680000000
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -65,7 +63,7 @@
|
||||
{"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
|
||||
{"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
|
||||
{"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0,TYPE_UINT64, 0}, \
|
||||
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \
|
||||
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:&do_forms, defintval:0, TYPE_INT, 0}, \
|
||||
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0}, \
|
||||
@@ -74,13 +72,14 @@
|
||||
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
|
||||
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
|
||||
{"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, iptr:&vcdflag, defintval:0, TYPE_INT, 0}, \
|
||||
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \
|
||||
{"numerology" , CONFIG_HLP_NUMEROLOGY, 0, iptr:&numerology, defintval:0, TYPE_INT, 0}, \
|
||||
{"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \
|
||||
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
|
||||
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0}, \
|
||||
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&UE_no_timing_correction, defintval:0, TYPE_INT, 0} \
|
||||
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&UE_no_timing_correction, defintval:0, TYPE_INT, 0}, \
|
||||
{"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH,0, strptr:(char **)&rrc_config_path, defstrval:"./", TYPE_STRING, 0} \
|
||||
}
|
||||
|
||||
|
||||
@@ -92,11 +91,12 @@ extern int T_dont_fork;
|
||||
// In nr-ue.c
|
||||
extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
|
||||
extern void fill_ue_band_info(void);
|
||||
extern void init_NR_UE(int);
|
||||
extern void init_NR_UE(int, char*);
|
||||
extern void init_NR_UE_threads(int);
|
||||
extern void reset_opp_meas(void);
|
||||
extern void print_opp_meas(void);
|
||||
void *UE_thread(void *arg);
|
||||
PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
void init_nr_ue_vars(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
extern tpool_t *Tpool;
|
||||
extern tpool_t *Tpool_dl;
|
||||
#endif
|
||||
|
||||
+248
-247
@@ -77,9 +77,14 @@ int nfapi_sync_var=-1;
|
||||
uint8_t nfapi_mode = NFAPI_MONOLITHIC; // Default to monolithic mode
|
||||
double cpuf;
|
||||
|
||||
uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
|
||||
pthread_cond_t sync_cond;
|
||||
pthread_mutex_t sync_mutex;
|
||||
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
|
||||
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
time_stats_t softmodem_stats_mt; // main thread
|
||||
time_stats_t softmodem_stats_hw; // hw acquisition
|
||||
time_stats_t softmodem_stats_rxtx_sf; // total tx time
|
||||
@@ -111,6 +116,8 @@ extern double cpuf;
|
||||
short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT] = {0,0,16384,16384,-16384,-16384,16384,16384,16384,-16384,-16384,16384,-16384,-16384,7327,7327,7327,21981,21981,7327,21981,21981,7327,-7327,7327,-21981,21981,-7327,21981,-21981,-7327,7327,-7327,21981,-21981,7327,-21981,21981,-7327,-7327,-7327,-21981,-21981,-7327,-21981,-21981,10726,10726,10726,3576,3576,10726,3576,3576,10726,17876,10726,25027,3576,17876,3576,25027,17876,10726,17876,3576,25027,10726,25027,3576,17876,17876,17876,25027,25027,17876,25027,25027,10726,-10726,10726,-3576,3576,-10726,3576,-3576,10726,-17876,10726,-25027,3576,-17876,3576,-25027,17876,-10726,17876,-3576,25027,-10726,25027,-3576,17876,-17876,17876,-25027,25027,-17876,25027,-25027,-10726,10726,-10726,3576,-3576,10726,-3576,3576,-10726,17876,-10726,25027,-3576,17876,-3576,25027,-17876,10726,-17876,3576,-25027,10726,-25027,3576,-17876,17876,-17876,25027,-25027,17876,-25027,25027,-10726,-10726,-10726,-3576,-3576,-10726,-3576,-3576,-10726,-17876,-10726,-25027,-3576,-17876,-3576,-25027,-17876,-10726,-17876,-3576,-25027,-10726,-25027,-3576,-17876,-17876,-17876,-25027,-25027,-17876,-25027,-25027,8886,8886,8886,12439,12439,8886,12439,12439,8886,5332,8886,1778,12439,5332,12439,1778,5332,8886,5332,12439,1778,8886,1778,12439,5332,5332,5332,1778,1778,5332,1778,1778,8886,19547,8886,15993,12439,19547,12439,15993,8886,23101,8886,26655,12439,23101,12439,26655,5332,19547,5332,15993,1778,19547,1778,15993,5332,23101,5332,26655,1778,23101,1778,26655,19547,8886,19547,12439,15993,8886,15993,12439,19547,5332,19547,1778,15993,5332,15993,1778,23101,8886,23101,12439,26655,8886,26655,12439,23101,5332,23101,1778,26655,5332,26655,1778,19547,19547,19547,15993,15993,19547,15993,15993,19547,23101,19547,26655,15993,23101,15993,26655,23101,19547,23101,15993,26655,19547,26655,15993,23101,23101,23101,26655,26655,23101,26655,26655,8886,-8886,8886,-12439,12439,-8886,12439,-12439,8886,-5332,8886,-1778,12439,-5332,12439,-1778,5332,-8886,5332,-12439,1778,-8886,1778,-12439,5332,-5332,5332,-1778,1778,-5332,1778,-1778,8886,-19547,8886,-15993,12439,-19547,12439,-15993,8886,-23101,8886,-26655,12439,-23101,12439,-26655,5332,-19547,5332,-15993,1778,-19547,1778,-15993,5332,-23101,5332,-26655,1778,-23101,1778,-26655,19547,-8886,19547,-12439,15993,-8886,15993,-12439,19547,-5332,19547,-1778,15993,-5332,15993,-1778,23101,-8886,23101,-12439,26655,-8886,26655,-12439,23101,-5332,23101,-1778,26655,-5332,26655,-1778,19547,-19547,19547,-15993,15993,-19547,15993,-15993,19547,-23101,19547,-26655,15993,-23101,15993,-26655,23101,-19547,23101,-15993,26655,-19547,26655,-15993,23101,-23101,23101,-26655,26655,-23101,26655,-26655,-8886,8886,-8886,12439,-12439,8886,-12439,12439,-8886,5332,-8886,1778,-12439,5332,-12439,1778,-5332,8886,-5332,12439,-1778,8886,-1778,12439,-5332,5332,-5332,1778,-1778,5332,-1778,1778,-8886,19547,-8886,15993,-12439,19547,-12439,15993,-8886,23101,-8886,26655,-12439,23101,-12439,26655,-5332,19547,-5332,15993,-1778,19547,-1778,15993,-5332,23101,-5332,26655,-1778,23101,-1778,26655,-19547,8886,-19547,12439,-15993,8886,-15993,12439,-19547,5332,-19547,1778,-15993,5332,-15993,1778,-23101,8886,-23101,12439,-26655,8886,-26655,12439,-23101,5332,-23101,1778,-26655,5332,-26655,1778,-19547,19547,-19547,15993,-15993,19547,-15993,15993,-19547,23101,-19547,26655,-15993,23101,-15993,26655,-23101,19547,-23101,15993,-26655,19547,-26655,15993,-23101,23101,-23101,26655,-26655,23101,-26655,26655,-8886,-8886,-8886,-12439,-12439,-8886,-12439,-12439,-8886,-5332,-8886,-1778,-12439,-5332,-12439,-1778,-5332,-8886,-5332,-12439,-1778,-8886,-1778,-12439,-5332,-5332,-5332,-1778,-1778,-5332,-1778,-1778,-8886,-19547,-8886,-15993,-12439,-19547,-12439,-15993,-8886,-23101,-8886,-26655,-12439,-23101,-12439,-26655,-5332,-19547,-5332,-15993,-1778,-19547,-1778,-15993,-5332,-23101,-5332,-26655,-1778,-23101,-1778,-26655,-19547,-8886,-19547,-12439,-15993,-8886,-15993,-12439,-19547,-5332,-19547,-1778,-15993,-5332,-15993,-1778,-23101,-8886,-23101,-12439,-26655,-8886,-26655,-12439,-23101,-5332,-23101,-1778,-26655,-5332,-26655,-1778,-19547,-19547,-19547,-15993,-15993,-19547,-15993,-15993,-19547,-23101,-19547,-26655,-15993,-23101,-15993,-26655,-23101,-19547,-23101,-15993,-26655,-19547,-26655,-15993,-23101,-23101,-23101,-26655,-26655,-23101,-26655,-26655};
|
||||
|
||||
static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx) {
|
||||
sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
start_meas(&softmodem_stats_rxtx_sf);
|
||||
|
||||
// *******************************************************************
|
||||
@@ -151,10 +158,27 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
gNB->UL_INFO.CC_id = gNB->CC_id;
|
||||
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
// RX processing
|
||||
int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx);
|
||||
int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx);
|
||||
|
||||
//if (slot_rx == NR_UPLINK_SLOT || gNB->frame_parms.frame_type == FDD)
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
|
||||
// UE-specific RX processing for subframe n
|
||||
// TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
}
|
||||
|
||||
if (oai_exit) return(-1);
|
||||
|
||||
// *****************************************
|
||||
// TX processing for subframe n+sf_ahead
|
||||
// run PHY TX procedures the one after the other for all CCs to avoid race conditions
|
||||
// (may be relaxed in the future for performance reasons)
|
||||
// *****************************************
|
||||
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
|
||||
phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
|
||||
}
|
||||
|
||||
stop_meas( &softmodem_stats_rxtx_sf );
|
||||
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
|
||||
@@ -168,15 +192,14 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, struct RU_t_s *ru) {
|
||||
RU_proc_t *ru_proc=&ru->proc;
|
||||
proc->frame_rx = frame_rx;
|
||||
proc->slot_rx = slot_rx;
|
||||
sl_ahead = sf_ahead*fp->slots_per_subframe;
|
||||
|
||||
if (!oai_exit) {
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot);
|
||||
L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
|
||||
L1_proc->frame_rx = ru_proc->frame_rx;
|
||||
L1_proc->slot_rx = ru_proc->tti_rx;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ?
|
||||
(L1_proc->frame_rx+1)&1023 :
|
||||
L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
|
||||
|
||||
if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx) < 0)
|
||||
LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
|
||||
@@ -189,141 +212,107 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, struct RU_t_s *ru) {
|
||||
|
||||
static void *process_stats_thread(void *param) {
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
RU_t *ru = (RU_t *)NULL;
|
||||
reset_meas(&gNB->dlsch_encoding_stats);
|
||||
reset_meas(&gNB->dlsch_scrambling_stats);
|
||||
reset_meas(&gNB->dlsch_modulation_stats);
|
||||
reset_meas(&softmodem_stats_mt);
|
||||
reset_meas(&softmodem_stats_hw);
|
||||
for (int sfn=0; sfn < 10; sfn++) {
|
||||
reset_meas(&softmodem_stats_rxtx_sf);
|
||||
reset_meas(&softmodem_stats_rx_sf);
|
||||
}
|
||||
wait_sync("process_stats_thread");
|
||||
|
||||
while(!oai_exit) {
|
||||
sleep(1);
|
||||
print_meas(&gNB->dlsch_encoding_stats, "pdsch_encoding", NULL, NULL);
|
||||
print_meas(&gNB->dlsch_scrambling_stats, "pdsch_scrambling", NULL, NULL);
|
||||
print_meas(&gNB->dlsch_modulation_stats, "pdsch_modulation", NULL, NULL);
|
||||
print_meas(&softmodem_stats_mt, "Main gNB Thread", NULL, NULL);
|
||||
print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
|
||||
print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
|
||||
print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL);
|
||||
print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL);
|
||||
print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
|
||||
print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL);
|
||||
print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
|
||||
print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
|
||||
print_meas(&ru->compression,"compression",NULL,NULL);
|
||||
print_meas(&ru->transport,"transport",NULL,NULL);
|
||||
for (int sfn=0; sfn < 10; sfn++) {
|
||||
print_meas(&softmodem_stats_rxtx_sf,"[gNB][total_phy_proc_rxtx]",NULL, NULL);
|
||||
print_meas(&softmodem_stats_rx_sf,"[gNB][total_phy_proc_rx]",NULL,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void init_gNB_proc(int inst) {
|
||||
int CC_id;
|
||||
PHY_VARS_gNB *gNB;
|
||||
gNB_L1_proc_t *proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx;
|
||||
|
||||
for (CC_id=0; CC_id<RC.nb_nr_CC[inst]; CC_id++) {
|
||||
gNB = RC.gNB[inst][CC_id];
|
||||
proc = &gNB->proc;
|
||||
L1_proc = &proc->L1_proc;
|
||||
L1_proc_tx = &proc->L1_proc_tx;
|
||||
L1_proc->instance_cnt = -1;
|
||||
L1_proc_tx->instance_cnt = -1;
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
L1_proc_tx->instance_cnt_RUs = 0;
|
||||
proc->instance_cnt_prach = -1;
|
||||
proc->instance_cnt_asynch_rxtx = -1;
|
||||
proc->CC_id = CC_id;
|
||||
proc->first_rx =1;
|
||||
proc->first_tx =1;
|
||||
proc->RU_mask =0;
|
||||
proc->RU_mask_tx = (1<<gNB->num_RU)-1;
|
||||
proc->RU_mask_prach =0;
|
||||
pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
|
||||
}
|
||||
PHY_VARS_gNB *gNB = RC.gNB[inst];
|
||||
gNB_L1_proc_t *proc = &gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx;
|
||||
L1_proc->instance_cnt = -1;
|
||||
L1_proc_tx->instance_cnt = -1;
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
L1_proc_tx->instance_cnt_RUs = 0;
|
||||
proc->instance_cnt_prach = -1;
|
||||
proc->instance_cnt_asynch_rxtx = -1;
|
||||
proc->CC_id = 0;
|
||||
proc->first_rx =1;
|
||||
proc->first_tx =1;
|
||||
proc->RU_mask =0;
|
||||
proc->RU_mask_tx = (1<<gNB->num_RU)-1;
|
||||
proc->RU_mask_prach =0;
|
||||
pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
|
||||
}
|
||||
|
||||
/// eNB kept in function name for nffapi calls, TO FIX
|
||||
void init_eNB_afterRU(void) {
|
||||
int inst,CC_id,ru_id,i,aa;
|
||||
int inst,ru_id,i,aa;
|
||||
PHY_VARS_gNB *gNB;
|
||||
LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst);
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_inst; inst++) {
|
||||
LOG_I(PHY,"RC.nb_nr_CC[inst]:%d\n", RC.nb_nr_CC[inst]);
|
||||
LOG_I(PHY,"RC.nb_nr_CC[inst:%d]:%p\n", inst, RC.gNB[inst]);
|
||||
gNB = RC.gNB[inst];
|
||||
phy_init_nr_gNB(gNB,0,0);
|
||||
LOG_I(PHY,"Mapping RX ports from %d RUs to gNB %d\n",gNB->num_RU,gNB->Mod_id);
|
||||
//LOG_I(PHY,"Overwriting gNB->prach_vars.rxsigF[0]:%p\n", gNB->prach_vars.rxsigF[0]);
|
||||
// gNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *));
|
||||
LOG_I(PHY,"gNB->num_RU:%d\n", gNB->num_RU);
|
||||
|
||||
for (CC_id=0; CC_id<RC.nb_nr_CC[inst]; CC_id++) {
|
||||
LOG_I(PHY,"RC.nb_nr_CC[inst:%d][CC_id:%d]:%p\n", inst, CC_id, RC.gNB[inst][CC_id]);
|
||||
gNB = RC.gNB[inst][CC_id];
|
||||
phy_init_nr_gNB(gNB,0,0);
|
||||
for (ru_id=0,aa=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);
|
||||
|
||||
LOG_I(PHY,"Mapping RX ports from %d RUs to gNB %d\n",gNB->num_RU,gNB->Mod_id);
|
||||
//LOG_I(PHY,"Overwriting gNB->prach_vars.rxsigF[0]:%p\n", gNB->prach_vars.rxsigF[0]);
|
||||
// gNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *));
|
||||
LOG_I(PHY,"gNB->num_RU:%d\n", gNB->num_RU);
|
||||
|
||||
for (ru_id=0,aa=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 (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[0][aa] = gNB->RU_list[ru_id]->prach_rxsigF[i];
|
||||
gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i];
|
||||
}
|
||||
for (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[i];
|
||||
gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i];
|
||||
}
|
||||
//init_precoding_weights(RC.gNB[inst][CC_id]);
|
||||
}
|
||||
}
|
||||
|
||||
//init_precoding_weights(RC.gNB[inst][CC_id]);
|
||||
}
|
||||
}
|
||||
|
||||
void init_gNB(int single_thread_flag,int wait_for_sync) {
|
||||
int CC_id;
|
||||
int inst;
|
||||
PHY_VARS_gNB *gNB;
|
||||
LOG_I(PHY,"[nr-softmodem.c] gNB structure about to be allocated RC.nb_nr_L1_inst:%d RC.nb_nr_L1_CC[0]:%d\n",RC.nb_nr_L1_inst,RC.nb_nr_L1_CC[0]);
|
||||
if (RC.gNB == NULL)
|
||||
RC.gNB = (PHY_VARS_gNB **) calloc(1,(1+RC.nb_nr_L1_inst)*sizeof(PHY_VARS_gNB *));
|
||||
|
||||
AssertFatal(RC.gNB != NULL,"");
|
||||
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
AssertFatal(RC.gNB[inst] != NULL,"");
|
||||
for (int inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
if (RC.gNB[inst] == NULL )
|
||||
RC.gNB[inst] = (PHY_VARS_gNB *) calloc(1,sizeof(PHY_VARS_gNB));
|
||||
|
||||
for (CC_id=0; CC_id<RC.nb_nr_L1_CC[inst]; CC_id++) {
|
||||
AssertFatal(RC.gNB[inst][CC_id] != NULL,"");
|
||||
gNB = RC.gNB[inst][CC_id];
|
||||
gNB->abstraction_flag = false;
|
||||
gNB->single_thread_flag = true;
|
||||
/*nr_polar_init(&gNB->nrPolar_params,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);*/
|
||||
LOG_I(PHY,"Registering with MAC interface module\n");
|
||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(inst))!=NULL,"Cannot register interface");
|
||||
gNB->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
|
||||
memset((void *)&gNB->UL_tti_req,0,sizeof(nfapi_nr_ul_tti_request_t));
|
||||
//memset((void *)&gNB->Sched_INFO,0,sizeof(gNB->Sched_INFO));
|
||||
LOG_I(PHY,"Setting indication lists\n");
|
||||
gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = gNB->rx_pdu_list;
|
||||
gNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = gNB->crc_pdu_list;
|
||||
gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
|
||||
gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;
|
||||
gNB->prach_energy_counter = 0;
|
||||
}
|
||||
PHY_VARS_gNB *gNB= RC.gNB[inst];
|
||||
gNB->abstraction_flag = false;
|
||||
gNB->single_thread_flag = true;
|
||||
/*nr_polar_init(&gNB->nrPolar_params,
|
||||
NR_POLAR_PBCH_MESSAGE_TYPE,
|
||||
NR_POLAR_PBCH_PAYLOAD_BITS,
|
||||
NR_POLAR_PBCH_AGGREGATION_LEVEL);*/
|
||||
LOG_I(PHY,"Registering with MAC interface module\n");
|
||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(inst))!=NULL,"Cannot register interface");
|
||||
gNB->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
|
||||
memset((void *)&gNB->UL_tti_req,0,sizeof(nfapi_nr_ul_tti_request_t));
|
||||
//memset((void *)&gNB->Sched_INFO,0,sizeof(gNB->Sched_INFO));
|
||||
LOG_I(PHY,"Setting indication lists\n");
|
||||
gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = gNB->rx_pdu_list;
|
||||
gNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = gNB->crc_pdu_list;
|
||||
gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
|
||||
gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
|
||||
gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;
|
||||
gNB->prach_energy_counter = 0;
|
||||
}
|
||||
|
||||
LOG_I(PHY,"[nr-softmodem.c] gNB structure allocated\n");
|
||||
}
|
||||
|
||||
@@ -385,19 +374,16 @@ static void init_pdcp(void) {
|
||||
void init_main_gNB(void) {
|
||||
RCconfig_NR_L1();
|
||||
RCconfig_nr_macrlc();
|
||||
|
||||
if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n");
|
||||
|
||||
|
||||
LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst);
|
||||
|
||||
RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *));
|
||||
LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc);
|
||||
|
||||
int gnb_id=0; // only 1 gnb per process, index 0 for now
|
||||
|
||||
RC.nrrrc[gnb_id] = (gNB_RRC_INST*)malloc(sizeof(gNB_RRC_INST));
|
||||
RC.nrrrc[gnb_id] = (gNB_RRC_INST *)malloc(sizeof(gNB_RRC_INST));
|
||||
memset((void *)RC.nrrrc[gnb_id],0,sizeof(gNB_RRC_INST));
|
||||
MessageDef *msg_p = itti_alloc_new_message (TASK_GNB_APP, NRRRC_CONFIGURATION_REQ);
|
||||
|
||||
RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]);
|
||||
openair_rrc_gNB_configuration(GNB_INSTANCE_TO_MODULE_ID(ITTI_MSG_INSTANCE(msg_p)), &NRRRC_CONFIGURATION_REQ(msg_p));
|
||||
}
|
||||
@@ -414,7 +400,6 @@ static void wait_nfapi_init(char *thread_name) {
|
||||
}
|
||||
|
||||
void wait_gNBs(void) {
|
||||
int i,j;
|
||||
int waiting=1;
|
||||
|
||||
while (waiting==1) {
|
||||
@@ -422,14 +407,10 @@ void wait_gNBs(void) {
|
||||
usleep(50*1000);
|
||||
waiting=0;
|
||||
|
||||
for (i=0; i<RC.nb_nr_L1_inst; i++) {
|
||||
printf("RC.nb_nr_L1_CC[%d]:%d\n", i, RC.nb_nr_L1_CC[i]);
|
||||
|
||||
for (j=0; j<RC.nb_nr_L1_CC[i]; j++) {
|
||||
if (RC.gNB[i][j]->configured==0) {
|
||||
waiting=1;
|
||||
break;
|
||||
}
|
||||
for (int i=0; i<RC.nb_nr_L1_inst; i++) {
|
||||
if (RC.gNB[i]->configured==0) {
|
||||
waiting=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,7 +474,7 @@ void RCconfig_RU(void) {
|
||||
else
|
||||
RC.ru[j]->num_gNB = 0;
|
||||
|
||||
for (i=0; i<RC.ru[j]->num_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0];
|
||||
for (i=0; i<RC.ru[j]->num_gNB; i++) RC.ru[j]->gNB_list[i] = &RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0];
|
||||
|
||||
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) {
|
||||
RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr));
|
||||
@@ -561,132 +542,145 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
void *rxp[ru->nb_rx];
|
||||
unsigned int rxs;
|
||||
int i;
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp);
|
||||
openair0_timestamp ts,old_ts;
|
||||
AssertFatal(*slot<fp->slots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame);
|
||||
|
||||
for (i=0; i<ru->nb_rx; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][*slot*fp->samples_per_slot];
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
|
||||
old_ts = proc->timestamp_rx;
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",fp->samples_per_slot,*slot,rxp[0]);
|
||||
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]);
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
|
||||
&ts,
|
||||
rxp,
|
||||
fp->samples_per_slot,
|
||||
ru->nb_rx);
|
||||
|
||||
&ts,
|
||||
rxp,
|
||||
samples_per_slot,
|
||||
ru->nb_rx);
|
||||
proc->timestamp_rx = ts-ru->ts_offset;
|
||||
|
||||
|
||||
//AssertFatal(rxs == fp->samples_per_subframe,
|
||||
//"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs);
|
||||
if (rxs != fp->samples_per_slot)
|
||||
LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_slot,rxs);
|
||||
|
||||
if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs);
|
||||
|
||||
if (proc->first_rx == 1) {
|
||||
ru->ts_offset = proc->timestamp_rx;
|
||||
proc->timestamp_rx = 0;
|
||||
AssertFatal(proc->tti_rx == *slot && proc->frame_rx == *frame ,
|
||||
"Received Timestamp (%llu) doesn't correspond to the time we think it is \n\
|
||||
(proc->tti_rx %d, subframe %d, proc->frame_rx %d frame %d)\n",
|
||||
(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot, proc->frame_rx,*frame);
|
||||
} else {
|
||||
if (proc->timestamp_rx - old_ts != fp->samples_per_slot) {
|
||||
LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",
|
||||
proc->timestamp_rx - old_ts - fp->samples_per_slot,ru->ts_offset);
|
||||
ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_slot);
|
||||
if (proc->timestamp_rx - old_ts != fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp)) {
|
||||
LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot,ru->ts_offset);
|
||||
ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot);
|
||||
proc->timestamp_rx = ts-ru->ts_offset;
|
||||
}
|
||||
}
|
||||
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_slot*fp->slots_per_frame))&1023;
|
||||
proc->tti_rx = (proc->timestamp_rx / fp->samples_per_slot)%fp->slots_per_frame;
|
||||
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
|
||||
uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe;
|
||||
proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame);
|
||||
*frame = proc->frame_rx;
|
||||
*slot = proc->tti_rx;
|
||||
proc->first_rx = 0;
|
||||
|
||||
if (rxs != fp->samples_per_slot)
|
||||
LOG_E(PHY, "problem receiving samples\n");
|
||||
}
|
||||
|
||||
if (rxs != samples_per_slot) {
|
||||
LOG_E(PHY, "problem receiving samples\n");
|
||||
}
|
||||
}
|
||||
void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
//nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
void *txp[ru->nb_tx];
|
||||
unsigned int txs;
|
||||
int i;
|
||||
int i,txsymb;
|
||||
T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot),
|
||||
T_INT(0), T_BUFFER(&ru->common.txdata[0][slot * fp->samples_per_slot], fp->samples_per_slot * 4));
|
||||
int sf_extension = 0;
|
||||
//nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame,frame);
|
||||
T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4));
|
||||
int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame);
|
||||
int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame);
|
||||
int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame);
|
||||
int sf_extension = 0; //sf_extension = ru->sf_extension;
|
||||
int siglen=fp->get_samples_per_slot(slot,fp);
|
||||
int flags=1;
|
||||
|
||||
if ((slot == 0) ||
|
||||
(slot == 1) || IS_SOFTMODEM_RFSIM ) {
|
||||
int siglen=fp->samples_per_slot;
|
||||
int flags;
|
||||
//nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame);
|
||||
if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) {
|
||||
if(slot_type == NR_MIXED_SLOT) {
|
||||
txsymb = 0;
|
||||
|
||||
if (slot==0)
|
||||
flags = 2;
|
||||
else if (slot==1)
|
||||
flags=3;
|
||||
else
|
||||
flags=4;
|
||||
for(int symbol_count =0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0)
|
||||
txsymb++;
|
||||
}
|
||||
|
||||
/*
|
||||
if (SF_type == SF_S) {
|
||||
siglen = fp->dl_symbols_in_S_subframe*(fp->ofdm_symbol_size+fp->nb_prefix_samples0);
|
||||
flags=3; // end of burst
|
||||
}
|
||||
if ((fp->frame_type == TDD) &&
|
||||
(SF_type == SF_DL)&&
|
||||
(prevSF_type == SF_UL) &&
|
||||
(nextSF_type == SF_DL)) {
|
||||
flags = 2; // start of burst
|
||||
sf_extension = ru->N_TA_offset<<1;
|
||||
}
|
||||
AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb);
|
||||
|
||||
if ((cfg->subframe_config.duplex_mode == TDD) &&
|
||||
(SF_type == SF_DL)&&
|
||||
(prevSF_type == SF_UL) &&
|
||||
(nextSF_type == SF_UL)) {
|
||||
flags = 4; // start of burst and end of burst (only one DL SF between two UL)
|
||||
sf_extension = ru->N_TA_offset<<1;
|
||||
} */
|
||||
if(slot%(fp->slots_per_subframe/2))
|
||||
siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
else
|
||||
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||
|
||||
//+ ru->end_of_burst_delay;
|
||||
flags=3; // end of burst
|
||||
}
|
||||
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD &&
|
||||
slot_type == NR_DOWNLINK_SLOT &&
|
||||
prevslot_type == NR_UPLINK_SLOT) {
|
||||
flags = 2; // start of burst
|
||||
}
|
||||
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD &&
|
||||
slot_type == NR_DOWNLINK_SLOT &&
|
||||
nextslot_type == NR_UPLINK_SLOT) {
|
||||
flags = 3; // end of burst
|
||||
}
|
||||
|
||||
if (fp->freq_range==nr_FR2) {
|
||||
// the beam index is written in bits 8-10 of the flags
|
||||
// bit 11 enables the gpio programming
|
||||
int beam=0;
|
||||
|
||||
if (slot==0) beam = 11; //3 for boresight & 8 to enable
|
||||
|
||||
/*
|
||||
if (slot==0 || slot==40) beam=0&8;
|
||||
if (slot==10 || slot==50) beam=1&8;
|
||||
if (slot==20 || slot==60) beam=2&8;
|
||||
if (slot==30 || slot==70) beam=3&8;
|
||||
*/
|
||||
flags |= beam<<8;
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot );
|
||||
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
txp[i] = (void *)&ru->common.txdata[i][(slot*fp->samples_per_slot)-sf_extension];
|
||||
}
|
||||
for (i=0; i<ru->nb_tx; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
|
||||
// prepare tx buffer pointers
|
||||
start_meas(&ru->tx_fhaul);
|
||||
txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
|
||||
timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
|
||||
txp,
|
||||
siglen+sf_extension,
|
||||
ru->nb_tx,
|
||||
flags);
|
||||
stop_meas(&ru->tx_fhaul);
|
||||
LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
|
||||
LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %d\n",ru->idx,
|
||||
(long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
||||
AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %u/%d)\n", txs, siglen);
|
||||
}
|
||||
}
|
||||
|
||||
// this is for RU with local RF unit
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
int i;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_t *gNB_config = &ru->gNB_list[0]->gNB_config; //tmp index
|
||||
nfapi_nr_config_request_scf_t *gNB_config = &ru->gNB_list[0]->gNB_config; //tmp index
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
int N_RB = gNB_config->rf_config.dl_carrier_bandwidth.value;
|
||||
int mu = gNB_config->subframe_config.numerology_index_mu.value;
|
||||
int mu = gNB_config->ssb_config.scs_common.value;
|
||||
int N_RB = gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value;
|
||||
fp->threequarter_fs=threequarter_fs;
|
||||
|
||||
if (mu == NR_MU_0) { //or if LTE
|
||||
if(N_RB == 100) {
|
||||
@@ -754,11 +748,23 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
} else {
|
||||
AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
|
||||
}
|
||||
} else if (mu == NR_MU_3) {
|
||||
if (N_RB == 66) {
|
||||
cfg->sample_rate = 122.88e6;
|
||||
cfg->samples_per_frame = 1228800;
|
||||
cfg->tx_bw = 100e6;
|
||||
cfg->rx_bw = 100e6;
|
||||
} else if(N_RB == 32) {
|
||||
cfg->sample_rate=61.44e6;
|
||||
cfg->samples_per_frame = 614400;
|
||||
cfg->tx_bw = 50e6;
|
||||
cfg->rx_bw = 50e6;
|
||||
}
|
||||
} else {
|
||||
AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu);
|
||||
}
|
||||
|
||||
if (gNB_config->subframe_config.duplex_mode.value==TDD)
|
||||
if (gNB_config->cell_config.frame_duplex_type.value==TDD)
|
||||
cfg->duplex_mode = duplex_mode_TDD;
|
||||
else //FDD
|
||||
cfg->duplex_mode = duplex_mode_FDD;
|
||||
@@ -769,8 +775,14 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
cfg->rx_num_channels=ru->nb_rx;
|
||||
|
||||
for (i=0; i<ru->nb_tx; i++) {
|
||||
cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
|
||||
cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;
|
||||
if (ru->if_frequency == 0) {
|
||||
cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
|
||||
cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;
|
||||
} else {
|
||||
cfg->tx_freq[i] = (double)ru->if_frequency;
|
||||
cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq);
|
||||
}
|
||||
|
||||
cfg->tx_gain[i] = ru->att_tx;
|
||||
cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx;
|
||||
cfg->configFilename = rf_config_file;
|
||||
@@ -781,24 +793,21 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
cfg->rx_freq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static 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;
|
||||
int slot = fp->slots_per_frame-1;
|
||||
int frame = 1023;
|
||||
|
||||
LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
|
||||
|
||||
fp->threequarter_fs=threequarter_fs;
|
||||
nr_init_frame_parms(&ru->gNB_list[0]->gNB_config, fp);
|
||||
nr_dump_frame_parms(fp);
|
||||
fill_rf_config(ru,ru->rf_config_file);
|
||||
nr_phy_init_RU(ru);
|
||||
|
||||
AssertFatal(openair0_device_load(&ru->rfdevice,&ru->openair0_cfg)==0,"Cannot connect to local radio\n");
|
||||
AssertFatal(openair0_device_load(&ru->rfdevice,&ru->openair0_cfg)==0,"Cannot connect to local radio\n");
|
||||
AssertFatal(ru->rfdevice.trx_start_func(&ru->rfdevice) == 0,"Could not start the RF device\n");
|
||||
|
||||
|
||||
// This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
|
||||
while (!oai_exit) {
|
||||
// these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
|
||||
@@ -814,13 +823,12 @@ static void *ru_thread( void *param ) {
|
||||
// synchronization on input FH interface, acquire signals/data and block
|
||||
LOG_D(PHY,"[RU_thread] read data: frame_rx = %d, tti_rx = %d\n", frame, slot);
|
||||
rx_rf(ru,&frame,&slot);
|
||||
|
||||
LOG_D(PHY,"AFTER rx_rf - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0][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][0]->proc.frame_rx,RC.gNB[0][0]->proc.slot_rx,
|
||||
RC.gNB[0][0]->proc.frame_tx);
|
||||
RC.gNB[0][0].proc.frame_rx,RC.gNB[0][0].proc.slot_rx,
|
||||
RC.gNB[0][0].proc.frame_tx);
|
||||
/*
|
||||
LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n",
|
||||
ru->do_prach,
|
||||
@@ -835,81 +843,76 @@ static void *ru_thread( void *param ) {
|
||||
//printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx);
|
||||
if (ru->idx!=0)
|
||||
proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
|
||||
|
||||
|
||||
// do RX front-end processing (frequency-shift, dft) if needed
|
||||
|
||||
|
||||
if (proc->tti_rx == NR_UPLINK_SLOT || fp->frame_type == FDD) {
|
||||
nr_fep_full(ru,proc->tti_rx);
|
||||
}
|
||||
|
||||
gNB_top(RC.gNB[0][0], frame, slot, ru);
|
||||
|
||||
gNB_top(&RC.gNB[0][0], frame, slot, ru);
|
||||
// do TX front-end processing if needed (precoding and/or IDFTs)
|
||||
//ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx);
|
||||
nr_feptx_prec(ru,proc->frame_tx,proc->tti_tx);
|
||||
// do OFDM with/without TX front-end processing if needed
|
||||
//ru->feptx_ofdm
|
||||
nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
if (nr_slot_select(cfg,proc->tti_tx,proc->frame_tx ) != SF_UL) {
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
|
||||
if (nr_slot_select(cfg,proc->frame_tx, proc->tti_tx ) != SF_UL) {
|
||||
int aa=0; // antenna 0 hardcoded
|
||||
NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
|
||||
nr_feptx0(ru,proc->tti_tx,0,fp->symbols_per_slot,aa);
|
||||
}
|
||||
|
||||
|
||||
// do outgoing fronthaul (south) if needed
|
||||
tx_rf(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx);
|
||||
}
|
||||
|
||||
|
||||
printf( "Exiting ru_thread \n");
|
||||
ru->rfdevice.trx_end_func(&ru->rfdevice);
|
||||
|
||||
static int ru_thread_status = 0;
|
||||
return &ru_thread_status;
|
||||
}
|
||||
|
||||
void launch_NR_RU(char *rf_config_file) {
|
||||
printf("configuring RU from file\n");
|
||||
RCconfig_RU();
|
||||
LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",
|
||||
RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs());
|
||||
|
||||
RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs());
|
||||
LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
|
||||
|
||||
for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
LOG_D(PHY,"Process RC.ru[%d]\n",ru_id);
|
||||
RU_t *ru = RC.ru[ru_id];
|
||||
RU_t *ru = RC.ru[ru_id];
|
||||
ru->rf_config_file = rf_config_file;
|
||||
ru->idx = ru_id;
|
||||
ru->ts_offset = 0;
|
||||
// use gNB_list[0] as a reference for RU frame parameters
|
||||
// NOTE: multiple CC_id are not handled here yet!
|
||||
|
||||
LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0][0]:%p rf_config_file:%s\n",
|
||||
__FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0][0], ru->rf_config_file);
|
||||
LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p rf_config_file:%s\n",
|
||||
__FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], ru->rf_config_file);
|
||||
LOG_E(PHY,"ru->gNB_list ru->num_gNB hardcoded: one RU connected to carrier 0 of gNB 0\n");
|
||||
ru->gNB_list[0] = RC.gNB[0][0];
|
||||
ru->gNB_list[0] = &RC.gNB[0][0];
|
||||
ru->num_gNB=1;
|
||||
LOG_I(PHY,"Copying frame parms from gNB in RC to ru %d and frame_parms in ru\n",ru->idx);
|
||||
memcpy((void *)ru->nr_frame_parms,&RC.gNB[0][0]->frame_parms,sizeof(NR_DL_FRAME_PARMS));
|
||||
memcpy((void *)ru->nr_frame_parms,&RC.gNB[0][0].frame_parms,sizeof(NR_DL_FRAME_PARMS));
|
||||
|
||||
for (int i=0; i<ru->num_gNB; i++) {
|
||||
PHY_VARS_gNB *gNB0 = ru->gNB_list[i];
|
||||
PHY_VARS_gNB *gNB0 = ru->gNB_list[i];
|
||||
gNB0->RU_list[gNB0->num_RU++] = ru;
|
||||
}
|
||||
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
int main( int argc, char **argv ) {
|
||||
|
||||
AssertFatal(load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY),
|
||||
"[SOFTMODEM] Error, configuration module init failed\n");
|
||||
"[SOFTMODEM] Error, configuration module init failed\n");
|
||||
logInit();
|
||||
#ifndef PACKAGE_VERSION
|
||||
# define PACKAGE_VERSION "UNKNOWN"
|
||||
#endif
|
||||
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
||||
|
||||
configure_linux();
|
||||
get_options ();
|
||||
get_common_options(SOFTMODEM_GNB_BIT );
|
||||
@@ -918,46 +921,43 @@ int main( int argc, char **argv ) {
|
||||
fprintf(stderr,"Getting configuration failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
|
||||
set_taus_seed (0);
|
||||
|
||||
init_opt();
|
||||
|
||||
if(IS_SOFTMODEM_NOS1)
|
||||
init_pdcp();
|
||||
|
||||
init_main_gNB();
|
||||
|
||||
/* Start the agent. If it is turned off in the configuration, it won't start */
|
||||
RCconfig_nr_flexran();
|
||||
|
||||
for (int i = 0; i < RC.nb_nr_L1_inst; i++) {
|
||||
flexran_agent_start(i);
|
||||
}
|
||||
|
||||
// init UE_PF_PO and mutex lock (paging from S1AP)
|
||||
pthread_mutex_init(&ue_pf_po_mutex, NULL);
|
||||
|
||||
printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
|
||||
pthread_cond_init(&nfapi_sync_cond,NULL);
|
||||
pthread_mutex_init(&nfapi_sync_mutex, NULL);
|
||||
|
||||
const char *nfapi_mode_str[] = {
|
||||
"MONOLITHIC", "PNF", "VNF", };
|
||||
"MONOLITHIC", "PNF", "VNF",
|
||||
};
|
||||
AssertFatal(nfapi_mode < 3,"");
|
||||
printf("NFAPI MODE:%s\n", nfapi_mode_str[nfapi_mode]);
|
||||
|
||||
|
||||
if (nfapi_mode==NFAPI_MODE_VNF) // VNF
|
||||
wait_nfapi_init("main?");
|
||||
|
||||
number_of_cards = 1;
|
||||
LOG_I(PHY,"Initializing gNB threads\n");
|
||||
init_gNB(single_thread_flag,wait_for_sync);
|
||||
|
||||
printf("wait_gNBs()\n");
|
||||
wait_gNBs();
|
||||
printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
|
||||
|
||||
config_sync_var=0;
|
||||
|
||||
if (nfapi_mode==NFAPI_MODE_PNF) { // PNF
|
||||
@@ -978,6 +978,7 @@ int main( int argc, char **argv ) {
|
||||
}
|
||||
|
||||
init_gNB_proc(0); // only instance 0 (one gNB per process)
|
||||
|
||||
if (RC.nb_RU >0) {
|
||||
printf("Initializing RU threads\n");
|
||||
launch_NR_RU(get_softmodem_params()->rf_config_file);
|
||||
@@ -986,17 +987,17 @@ int main( int argc, char **argv ) {
|
||||
if (opp_enabled ==1) {
|
||||
pthread_t t;
|
||||
threadCreate(&t, process_stats_thread,
|
||||
(void *)NULL, "time_meas", -1, OAI_PRIORITY_RT_LOW);
|
||||
(void *)NULL, "time_meas", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
|
||||
if (do_forms==1) {
|
||||
scopeParms_t tmp={&argc, argv};
|
||||
scopeParms_t tmp= {&argc, argv};
|
||||
startScope(&tmp);
|
||||
}
|
||||
|
||||
while(!oai_exit)
|
||||
sleep(1);
|
||||
|
||||
|
||||
for(int ru_id=0; ru_id<NB_RU; ru_id++) {
|
||||
if (RC.ru[ru_id]->rfdevice.trx_end_func)
|
||||
RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
|
||||
|
||||
@@ -144,7 +144,6 @@ void get_common_options(uint32_t execmask) {
|
||||
|
||||
if(worker_config != NULL) set_worker_conf(worker_config);
|
||||
}
|
||||
|
||||
void softmodem_printresources(int sig, telnet_printfunc_t pf) {
|
||||
struct rusage usage;
|
||||
struct timespec stop;
|
||||
@@ -204,3 +203,4 @@ void set_softmodem_sighandler(void) {
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGABRT, signal_handler);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ extern "C"
|
||||
{"clock", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \
|
||||
{"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \
|
||||
{"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \
|
||||
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \
|
||||
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
|
||||
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
|
||||
@@ -198,7 +198,7 @@ extern "C"
|
||||
|
||||
typedef struct {
|
||||
uint64_t optmask;
|
||||
THREAD_STRUCT thread_struct;
|
||||
//THREAD_STRUCT thread_struct;
|
||||
char rf_config_file[1024];
|
||||
char split73[1024];
|
||||
char threadPoolConfig[1024];
|
||||
@@ -223,7 +223,7 @@ extern void get_common_options(uint32_t execmask);
|
||||
extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr);
|
||||
#define SOFTMODEM_RTSIGNAL (SIGRTMIN+1)
|
||||
extern void set_softmodem_sighandler(void);
|
||||
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user