Commit 570ac353 authored by Raymond Knopp's avatar Raymond Knopp

frame resynchronization in RAU and RRU

parent 103471e9
...@@ -559,7 +559,9 @@ typedef struct eNB_proc_t_s { ...@@ -559,7 +559,9 @@ typedef struct eNB_proc_t_s {
/// mutex for RU access to eNB processing (PRACH BR) /// mutex for RU access to eNB processing (PRACH BR)
pthread_mutex_t mutex_RU_PRACH_br; pthread_mutex_t mutex_RU_PRACH_br;
/// mask for RUs serving eNB (PDSCH/PUSCH) /// mask for RUs serving eNB (PDSCH/PUSCH)
int RU_mask; int RU_mask[10];
/// time measurements for RU arrivals
struct timespec t[10];
/// mask for RUs serving eNB (PRACH) /// mask for RUs serving eNB (PRACH)
int RU_mask_prach; int RU_mask_prach;
#ifdef Rel14 #ifdef Rel14
...@@ -687,7 +689,8 @@ typedef enum { ...@@ -687,7 +689,8 @@ typedef enum {
/// Some commamds to RRU. Not sure we should do it like this ! /// Some commamds to RRU. Not sure we should do it like this !
typedef enum { typedef enum {
EMPTY = 0, EMPTY = 0,
STOP_RU = 1 STOP_RU = 1,
RU_FRAME_RESYNCH = 2
} rru_cmd_t; } rru_cmd_t;
typedef struct RU_t_s{ typedef struct RU_t_s{
...@@ -709,6 +712,8 @@ typedef struct RU_t_s{ ...@@ -709,6 +712,8 @@ typedef struct RU_t_s{
int rx_offset; int rx_offset;
/// flag to indicate the RU is a slave to another source /// flag to indicate the RU is a slave to another source
int is_slave; int is_slave;
/// counter to delay start of processing of RU until HW settles
int wait_cnt;
/// Total gain of receive chain /// Total gain of receive chain
uint32_t rx_total_gain_dB; uint32_t rx_total_gain_dB;
/// number of bands that this device can support /// number of bands that this device can support
...@@ -812,6 +817,8 @@ typedef struct RU_t_s{ ...@@ -812,6 +817,8 @@ typedef struct RU_t_s{
rru_state_t state; rru_state_t state;
/// Command to do /// Command to do
rru_cmd_t cmd; rru_cmd_t cmd;
/// value to be passed using command
uint16_t cmdval;
/// process scheduling variables /// process scheduling variables
RU_proc_t proc; RU_proc_t proc;
/// stats thread pthread descriptor /// stats thread pthread descriptor
...@@ -1501,7 +1508,8 @@ typedef enum { ...@@ -1501,7 +1508,8 @@ typedef enum {
RRU_config_ok=4, RRU_config_ok=4,
RRU_start=5, RRU_start=5,
RRU_stop=6, RRU_stop=6,
RRU_sync_ok=7 RRU_sync_ok=7,
RRU_frame_resynch=8
} rru_config_msg_type_t; } rru_config_msg_type_t;
......
...@@ -225,6 +225,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam ...@@ -225,6 +225,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
// UE-specific RX processing for subframe n // UE-specific RX processing for subframe n
if (nfapi_mode == 0 || nfapi_mode == 1) { if (nfapi_mode == 0 || nfapi_mode == 1) {
LOG_I(PHY,"Calling RX procedures for SFNSF %d.%d\n",proc->frame_rx,proc->subframe_rx);
phy_procedures_eNB_uespec_RX(eNB, proc, no_relay ); phy_procedures_eNB_uespec_RX(eNB, proc, no_relay );
} }
...@@ -250,7 +251,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam ...@@ -250,7 +251,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
if (oai_exit) return(-1); if (oai_exit) return(-1);
LOG_D(PHY,"Calling eNB_procedures_TX for SFN.SF %d.%d\n",proc->frame_tx,proc->subframe_tx); LOG_I(PHY,"Calling eNB_procedures_TX for SFN.SF %d.%d\n",proc->frame_tx,proc->subframe_tx);
phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1); phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
stop_meas( &softmodem_stats_rxtx_sf ); stop_meas( &softmodem_stats_rxtx_sf );
...@@ -416,21 +417,21 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) { ...@@ -416,21 +417,21 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
pthread_mutex_lock(&proc->mutex_RU); pthread_mutex_lock(&proc->mutex_RU);
for (i=0;i<eNB->num_RU;i++) { for (i=0;i<eNB->num_RU;i++) {
if (ru == eNB->RU_list[i]) { if (ru == eNB->RU_list[i]) {
if ((proc->RU_mask&(1<<i)) > 0) if ((proc->RU_mask[ru->proc.subframe_rx]&(1<<i)) > 0)
LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask); eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask[ru->proc.subframe_rx]);
proc->RU_mask |= (1<<i); proc->RU_mask[ru->proc.subframe_rx] |= (1<<i);
}else if (eNB->RU_list[i]->state == RU_SYNC){ }else if (eNB->RU_list[i]->state == RU_SYNC){
proc->RU_mask |= (1<<i); proc->RU_mask[ru->proc.subframe_rx] |= (1<<i);
} }
} }
if (proc->RU_mask != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return if (proc->RU_mask[ru->proc.subframe_rx] != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return
LOG_E(PHY,"Not all RUs have provided their info\n"); LOG_E(PHY,"Not all RUs have provided their info\n");
pthread_mutex_unlock(&proc->mutex_RU); pthread_mutex_unlock(&proc->mutex_RU);
return(0); return(0);
} }
else { // all RUs have provided their information so continue on and wakeup eNB processing else { // all RUs have provided their information so continue on and wakeup eNB processing
proc->RU_mask = 0; proc->RU_mask[ru->proc.subframe_rx] = 0;
pthread_mutex_unlock(&proc->mutex_RU); pthread_mutex_unlock(&proc->mutex_RU);
} }
...@@ -724,7 +725,7 @@ void init_eNB_proc(int inst) { ...@@ -724,7 +725,7 @@ void init_eNB_proc(int inst) {
proc->first_rx=1; proc->first_rx=1;
proc->first_tx=1; proc->first_tx=1;
proc->RU_mask=0; for (i=0;i<10;i++) proc->RU_mask[i]=0;
proc->RU_mask_prach=0; proc->RU_mask_prach=0;
pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
......
...@@ -584,6 +584,7 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) { ...@@ -584,6 +584,7 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) {
do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
if (ru->cmd == STOP_RU) break;
// grab first prach information for this new subframe // grab first prach information for this new subframe
if (got_prach_info==0) { if (got_prach_info==0) {
prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx); prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx);
...@@ -793,6 +794,12 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { ...@@ -793,6 +794,12 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
ru->nb_rx); ru->nb_rx);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
if (ru->cmd==RU_FRAME_RESYNCH) {
ru->ts_offset += (proc->frame_rx - ru->cmdval)*fp->samples_per_tti*10;
*frame = ru->cmdval;
ru->cmd=EMPTY;
}
proc->timestamp_rx = ts-ru->ts_offset; proc->timestamp_rx = ts-ru->ts_offset;
...@@ -1240,6 +1247,7 @@ void wakeup_eNBs(RU_t *ru) { ...@@ -1240,6 +1247,7 @@ void wakeup_eNBs(RU_t *ru) {
PHY_VARS_eNB **eNB_list = ru->eNB_list; PHY_VARS_eNB **eNB_list = ru->eNB_list;
PHY_VARS_eNB *eNB=eNB_list[0]; PHY_VARS_eNB *eNB=eNB_list[0];
eNB_proc_t *proc = &eNB->proc; eNB_proc_t *proc = &eNB->proc;
struct timespec t;
LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d (state %s)ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru_states[ru->state],ru->eNB_top); LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d (state %s)ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru_states[ru->state],ru->eNB_top);
...@@ -1248,32 +1256,36 @@ void wakeup_eNBs(RU_t *ru) { ...@@ -1248,32 +1256,36 @@ void wakeup_eNBs(RU_t *ru) {
char string[20]; char string[20];
sprintf(string,"Incoming RU %d",ru->idx); sprintf(string,"Incoming RU %d",ru->idx);
LOG_D(PHY,"Frame %d, Subframe %d: RU %d Waking up eNB,RU_mask %x\n",ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,proc->RU_mask);
pthread_mutex_lock(&proc->mutex_RU); pthread_mutex_lock(&proc->mutex_RU);
LOG_D(PHY,"Frame %d, Subframe %d: RU %d done,RU_mask[%d] %x\n",ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx]);
if (proc->RU_mask[ru->proc.subframe_rx] == 0)
clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.subframe_rx]);
for (i=0;i<eNB->num_RU;i++) { for (i=0;i<eNB->num_RU;i++) {
LOG_D(PHY,"RU %d state %s\n",eNB->RU_list[i]->idx,ru_states[eNB->RU_list[i]->state]); LOG_D(PHY,"RU %d state %s\n",eNB->RU_list[i]->idx,ru_states[eNB->RU_list[i]->state]);
if (ru == eNB->RU_list[i]) { if (ru == eNB->RU_list[i]) {
// AssertFatal((proc->RU_mask&(1<<i)) == 0, "eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",eNB->Mod_id,ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask); // AssertFatal((proc->RU_mask&(1<<i)) == 0, "eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",eNB->Mod_id,ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask);
proc->RU_mask |= (1<<i); proc->RU_mask[ru->proc.subframe_rx] |= (1<<i);
}else if (eNB->RU_list[i]->state == RU_SYNC){ }else if (eNB->RU_list[i]->state == RU_SYNC || eNB->RU_list[i]->wait_cnt > 0){
proc->RU_mask |= (1<<i); proc->RU_mask[ru->proc.subframe_rx] |= (1<<i);
} }
} }
LOG_D(PHY,"RU mask is now %x\n",proc->RU_mask); LOG_D(PHY,"RU mask is now %x\n",proc->RU_mask[ru->proc.subframe_rx]);
if (proc->RU_mask != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return
pthread_mutex_unlock(&proc->mutex_RU); if (proc->RU_mask[ru->proc.subframe_rx] == (1<<eNB->num_RU)-1) {
return(0); proc->RU_mask[ru->proc.subframe_rx] = 0;
clock_gettime(CLOCK_MONOTONIC,&t);
AssertFatal(t.tv_nsec > proc->t[ru->proc.subframe_rx].tv_nsec+500000,
"Time difference for subframe %d => %d > 5ms\n",
ru->proc.subframe_rx,t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec);
} }
else { // all RUs have provided their information so continue on and wakeup eNB processing
proc->RU_mask = 0; pthread_mutex_unlock(&proc->mutex_RU);
pthread_mutex_unlock(&proc->mutex_RU);
}
LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.subframe_rx); LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.subframe_rx);
ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string); ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string);
} }
else { else { // multiple eNB case for later
LOG_D(PHY,"ru->num_eNB:%d\n", ru->num_eNB); LOG_D(PHY,"ru->num_eNB:%d\n", ru->num_eNB);
...@@ -1564,9 +1576,8 @@ static void* ru_thread_control( void* param ) { ...@@ -1564,9 +1576,8 @@ static void* ru_thread_control( void* param ) {
break; break;
case RRU_capabilities: // RAU case RRU_capabilities: // RAU
if (ru->if_south == LOCAL_RF){ if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_capab msg...Ignoring\n");
LOG_I(PHY,"Received RRU_capab msg...Ignoring\n");
}
else{ else{
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
...@@ -1629,15 +1640,13 @@ static void* ru_thread_control( void* param ) { ...@@ -1629,15 +1640,13 @@ static void* ru_thread_control( void* param ) {
"RU %d failed send CONFIG_OK to RAU\n",ru->idx); "RU %d failed send CONFIG_OK to RAU\n",ru->idx);
reset_proc(ru); reset_proc(ru);
ru->state = RU_READY; ru->state = RU_READY;
}else{ } else LOG_E(PHY,"Received RRU_config msg...Ignoring\n");
LOG_I(PHY,"Received RRU_config msg...Ignoring\n");
}
break; break;
case RRU_config_ok: // RAU case RRU_config_ok: // RAU
if (ru->if_south == LOCAL_RF){ if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n");
LOG_I(PHY,"Received RRU_config_ok msg...Ignoring\n"); else{
}else{
if (setup_RU_buffers(ru)!=0) { if (setup_RU_buffers(ru)!=0) {
printf("Exiting, cannot initialize RU Buffers\n"); printf("Exiting, cannot initialize RU Buffers\n");
...@@ -1701,27 +1710,30 @@ static void* ru_thread_control( void* param ) { ...@@ -1701,27 +1710,30 @@ static void* ru_thread_control( void* param ) {
break; break;
} }
} }
else{ else LOG_E(PHY,"RRU not ready, cannot start\n");
LOG_I(PHY,"RRU not ready, cannot start\n");
} } else LOG_E(PHY,"Received RRU_start msg...Ignoring\n");
}else{
LOG_I(PHY,"Received RRU_start msg...Ignoring\n");
}
break; break;
case RRU_sync_ok: //RAU case RRU_sync_ok: //RAU
if (ru->if_south == LOCAL_RF){ if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n");
LOG_I(PHY,"Received RRU_config_ok msg...Ignoring\n"); else{
}else{
if (ru->is_slave == 1){ if (ru->is_slave == 1){
LOG_I(PHY,"Received RRU_sync_ok from RRU %d\n",ru->idx);
// Just change the state of the RRU to unblock ru_thread() // Just change the state of the RRU to unblock ru_thread()
ru->state = RU_RUN; ru->state = RU_RUN;
}else{ }else LOG_E(PHY,"Received RRU_sync_ok from a master RRU...Ignoring\n");
LOG_I(PHY,"Received RRU_sync_ok from a master RRU...Ignoring\n");
}
} }
break; break;
case RRU_frame_resynch: //RRU
if (ru->if_south != LOCAL_RF) LOG_E(PHY,"Received RRU frame resynch message, should not happen in RAU\n");
else {
ru->cmd = RU_FRAME_RESYNCH;
ru->cmdval = ((uint16_t*)&rru_config_msg.msg[0])[0];
}
break;
case RRU_stop: // RRU case RRU_stop: // RRU
if (ru->if_south == LOCAL_RF){ if (ru->if_south == LOCAL_RF){
...@@ -1735,9 +1747,8 @@ static void* ru_thread_control( void* param ) { ...@@ -1735,9 +1747,8 @@ static void* ru_thread_control( void* param ) {
}else{ }else{
LOG_I(PHY,"RRU not running, can't stop\n"); LOG_I(PHY,"RRU not running, can't stop\n");
} }
}else{ }else LOG_E(PHY,"Received RRU_stop msg...Ignoring\n");
LOG_I(PHY,"Received RRU_stop msg...Ignoring\n");
}
break; break;
default: default:
...@@ -1778,16 +1789,17 @@ static void* ru_thread( void* param ) { ...@@ -1778,16 +1789,17 @@ static void* ru_thread( void* param ) {
LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]); LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
while (!oai_exit) { while (!oai_exit) {
if (ru->if_south != LOCAL_RF) ru->wait_cnt = 100;
else ru->wait_cnt = 0;
// wait to be woken up // wait to be woken up
if (wait_on_condition(&ru->proc.mutex_ru,&ru->proc.cond_ru_thread,&ru->proc.instance_cnt_ru,"ru_thread")<0) break; if (wait_on_condition(&ru->proc.mutex_ru,&ru->proc.cond_ru_thread,&ru->proc.instance_cnt_ru,"ru_thread")<0) break;
if (ru->is_slave == 0) AssertFatal(ru->state == RU_RUN,"ru->state = %d != RU_RUN\n",ru->state); if (ru->is_slave == 0) AssertFatal(ru->state == RU_RUN,"ru-%d state = %s != RU_RUN\n",ru->idx,ru_states[ru->state]);
else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC,"ru->state = %d != RU_SYNC\n",ru->state); else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC || ru->state == RU_RUN,"ru %d state = %s != RU_SYNC or RU_RUN\n",ru->idx,ru_states[ru->state]);
// Start RF device if any // Start RF device if any
if (ru->start_rf) { if (ru->start_rf) {
if (ru->start_rf(ru) != 0) if (ru->start_rf(ru) != 0)
...@@ -1826,10 +1838,6 @@ static void* ru_thread( void* param ) { ...@@ -1826,10 +1838,6 @@ static void* ru_thread( void* param ) {
subframe++; subframe++;
} }
LOG_D(PHY,"RU thread %d, frame %d (%p), subframe %d (%p)\n",
ru->idx, frame,&frame,subframe,&subframe);
// synchronization on input FH interface, acquire signals/data and block // synchronization on input FH interface, acquire signals/data and block
if (ru->stop_rf && ru->cmd == STOP_RU) { if (ru->stop_rf && ru->cmd == STOP_RU) {
...@@ -1848,43 +1856,62 @@ static void* ru_thread( void* param ) { ...@@ -1848,43 +1856,62 @@ static void* ru_thread( void* param ) {
if (ru->fh_south_in && ru->state == RU_RUN ) ru->fh_south_in(ru,&frame,&subframe); if (ru->fh_south_in && ru->state == RU_RUN ) ru->fh_south_in(ru,&frame,&subframe);
else AssertFatal(1==0, "No fronthaul interface at south port"); else AssertFatal(1==0, "No fronthaul interface at south port");
if (ru->wait_cnt > 0) {
if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) { ru->wait_cnt--;
wakeup_prach_ru(ru);
if (ru->if_south!=LOCAL_RF && ru->wait_cnt <=20 && subframe == 5 && frame != RC.ru[0]->proc.frame_rx) {
// Send RRU_frame adjust
RRU_CONFIG_msg_t rru_config_msg;
rru_config_msg.type = RRU_frame_resynch;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len
((uint16_t*)&rru_config_msg.msg[0])[0] = RC.ru[0]->proc.frame_rx;
LOG_I(PHY,"Sending Frame Resynch %d to RRU\n", ru->idx,RC.ru[0]->proc.frame_rx);
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RAU %d\n",ru->idx);
}
} }
else {
LOG_D(PHY,"RU thread %d, frame %d, subframe %d \n",
ru->idx,frame,subframe);
if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) {
wakeup_prach_ru(ru);
}
#ifdef Rel14 #ifdef Rel14
else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) { else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) {
wakeup_prach_ru_br(ru); wakeup_prach_ru_br(ru);
} }
#endif #endif
// adjust for timing offset between RU // adjust for timing offset between RU
if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
// At this point, all information for subframe has been received on FH interface // At this point, all information for subframe has been received on FH interface
// If this proc is to provide synchronization, do so // If this proc is to provide synchronization, do so
wakeup_slaves(proc); wakeup_slaves(proc);
// do RX front-end processing (frequency-shift, dft) if needed // do RX front-end processing (frequency-shift, dft) if needed
if (ru->feprx) ru->feprx(ru); if (ru->feprx) ru->feprx(ru);
// wakeup all eNB processes waiting for this RU // wakeup all eNB processes waiting for this RU
if (ru->num_eNB>0) wakeup_eNBs(ru); if (ru->num_eNB>0) wakeup_eNBs(ru);
// wait until eNBs are finished subframe RX n and TX n+4 // wait until eNBs are finished subframe RX n and TX n+4
wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread"); wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread");
// do TX front-end processing if needed (precoding and/or IDFTs) // do TX front-end processing if needed (precoding and/or IDFTs)
if (ru->feptx_prec) ru->feptx_prec(ru); if (ru->feptx_prec) ru->feptx_prec(ru);
// do OFDM if needed // do OFDM if needed
if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
// do outgoing fronthaul (south) if needed // do outgoing fronthaul (south) if needed
if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
if (ru->fh_north_out) ru->fh_north_out(ru); if (ru->fh_north_out) ru->fh_north_out(ru);
}
} }
} // while !oai_exit } // while !oai_exit
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment