Commit 0ad9ab94 authored by Raymond Knopp's avatar Raymond Knopp

dmrs-based OTA synchronization for RU

parent fe861bf4
......@@ -92,6 +92,15 @@ int lte_sync_time_eNB_emul(PHY_VARS_eNB *phy_vars_eNb,
uint8_t sect_id,
int32_t *sync_val);
int ru_sync_time_init(RU_t *ru);
int ru_sync_time(RU_t *ru,
int64_t *lev,
int64_t *avg);
void ru_sync_time_free(RU_t *ru);
/*!
\brief This function performs channel estimation including frequency and temporal interpolation
\param phy_vars_ue Pointer to UE PHY variables
......
......@@ -479,6 +479,65 @@ int lte_sync_time(int **rxdata, ///rx data in time domain
}
int ru_sync_time_init(RU_t *ru) // LTE_UE_COMMON *common_vars
{
int16_t dmrs[2048];
int16_t *dmrsp[2] = {dmrs,NULL};
ru->dmrssync = (int16_t*)malloc16_clear(ru->frame_parms.N_RB_DL*2*sizeof(int16_t));
generate_drs_pusch(NULL,NULL,
&ru->frame_parms,
(int32_t**)dmrsp,
0,
AMP,
0,
0,
ru->frame_parms.N_RB_DL,
0);
switch (ru->frame_parms.N_RB_DL) {
case 6:
idft128(dmrs, /// complex input
ru->dmrssync, /// complex output
1);
break;
case 25:
idft512(dmrs,
ru->dmrssync, /// complex output
1);
break;
case 50:
idft1024(dmrs,
ru->dmrssync, /// complex output
1);
break;
case 75:
idft1536(dmrs,
ru->dmrssync,
1); /// complex output
break;
case 100:
idft2048(dmrs,
ru->dmrssync, /// complex output
1);
break;
default:
AssertFatal(1==0,"Unsupported N_RB_DL %d\n",ru->frame_parms.N_RB_DL);
break;
}
return(0);
}
void ru_sync_time_free(RU_t *ru) {
AssertFatal(ru->dmrssync!=NULL,"ru->dmrssync is NULL\n");
free(ru->dmrssync);
}
//#define DEBUG_PHY
int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
......@@ -570,3 +629,62 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
}
int ru_sync_time(RU_t *ru,
int64_t *lev,
int64_t *avg)
{
LTE_DL_FRAME_PARMS *frame_parms = &ru->frame_parms;
// perform a time domain correlation using the oversampled sync sequence
int length = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti;
// circular copy of beginning to end of rxdata buffer. Note: buffer should be big enough upon calling this function
for (int ar=0;ar<ru->nb_rx;ar++) memcpy((void*)&ru->common.rxdata[ar][2*length],
(void*)&ru->common.rxdata[ar][0],
frame_parms->ofdm_symbol_size);
int32_t tmp0;
int32_t magtmp0,maxlev0=0;
int maxpos0=0;
int64_t avg0=0;
int32_t result;
for (int n=0; n<length; n+=4) {
tmp0 = 0;
//calculate dot product of primary_synch0_time and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n];
for (int ar=0; ar<ru->nb_rx; ar++) {
result = dot_product(ru->dmrssync,
(int16_t*) &ru->common.rxdata[ar][n],
frame_parms->ofdm_symbol_size,
11);
((int16_t*)&tmp0)[0] += ((int16_t*) &result)[0];
((int16_t*)&tmp0)[1] += ((int16_t*) &result)[1];
}
// tmpi holds <synchi,rx0>+<synci,rx1>+...+<synchi,rx_{nbrx-1}>
magtmp0 = abs32(tmp0);
// this does max |tmp0(n)|^2 and argmax |tmp0(n)|^2
if (magtmp0>maxlev0) { maxlev0 = magtmp0; maxpos0 = n; }
avg0 += magtmp0;
}
avg0/=(length/4);
int dmrsoffset = 2*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples) + frame_parms->nb_prefix_samples0;
if ((int64_t)maxlev0 > (5*avg0)) {*lev = maxlev0; *avg=avg0; return((length+maxpos0-dmrsoffset)%length);}
return(-1);
}
......@@ -36,6 +36,8 @@
int generate_drs_pusch(PHY_VARS_UE *ue,
UE_rxtx_proc_t *proc,
LTE_DL_FRAME_PARMS *frame_parms,
int32_t **txdataF,
uint8_t eNB_id,
short amp,
unsigned int subframe,
......@@ -54,29 +56,33 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
int16_t alpha_re[12] = {32767, 28377, 16383, 0,-16384, -28378,-32768,-28378,-16384, -1, 16383, 28377};
int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384};
uint8_t cyclic_shift,cyclic_shift0,cyclic_shift1;
LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
int32_t *txdataF = ue->common_vars.txdataF[ant];
uint8_t cyclic_shift,cyclic_shift0=0,cyclic_shift1=0;
LTE_DL_FRAME_PARMS *fp = (ue==NULL) ? frame_parms : &ue->frame_parms;
int32_t *txF = (ue==NULL) ? txdataF[ant] : ue->common_vars.txdataF[ant];
uint32_t u,v,alpha_ind;
uint32_t u0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1];
uint32_t u1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)];
uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
uint32_t u0=0,u1=0,v0=0,v1=0;
int32_t ref_re,ref_im;
uint8_t harq_pid = subframe2harq_pid(frame_parms,proc->frame_tx,subframe);
cyclic_shift0 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
// printf("PUSCH.cyclicShift %d, n_DMRS2 %d, nPRS %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,ue->ulsch[eNB_id]->n_DMRS2,ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]);
cyclic_shift1 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
uint8_t harq_pid = (proc == NULL) ? 0: subframe2harq_pid(fp,proc->frame_tx,subframe);
if (ue!=NULL) {
cyclic_shift0 = (fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
// printf("PUSCH.cyclicShift %d, n_DMRS2 %d, nPRS %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,ue->ulsch[eNB_id]->n_DMRS2,ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]);
cyclic_shift1 = (fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
u0=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1];
u1=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)];
v0=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
v1=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
}
// cyclic_shift0 = 0;
// cyclic_shift1 = 0;
Msc_RS = 12*nb_rb;
......@@ -90,9 +96,9 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
return(-1);
}
for (l = (3 - frame_parms->Ncp),u=u0,v=v0,cyclic_shift=cyclic_shift0;
for (l = (3 - fp->Ncp),u=u0,v=v0,cyclic_shift=cyclic_shift0;
l<frame_parms->symbols_per_tti;
l += (7 - frame_parms->Ncp),u=u1,v=v1,cyclic_shift=cyclic_shift1) {
l += (7 - fp->Ncp),u=u1,v=v1,cyclic_shift=cyclic_shift1) {
drs_offset = 0;
#ifdef DEBUG_DRS
......@@ -100,9 +106,9 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
#endif
re_offset = frame_parms->first_carrier_offset;
subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->ofdm_symbol_size;
symbol_offset = subframe_offset + frame_parms->ofdm_symbol_size*l;
re_offset = fp->first_carrier_offset;
subframe_offset = subframe*fp->symbols_per_tti*frame_parms->ofdm_symbol_size;
symbol_offset = subframe_offset + fp->ofdm_symbol_size*l;
#ifdef DEBUG_DRS
......@@ -110,7 +116,7 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
#endif
alpha_ind = 0;
for (rb=0; rb<frame_parms->N_RB_UL; rb++) {
for (rb=0; rb<fp->N_RB_UL; rb++) {
if ((rb >= first_rb) && (rb<(first_rb+nb_rb))) {
......@@ -122,12 +128,12 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
ref_re = (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][drs_offset<<1];
ref_im = (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][(drs_offset<<1)+1];
((int16_t*) txdataF)[2*(symbol_offset + re_offset)] = (int16_t) (((ref_re*alpha_re[alpha_ind]) -
((int16_t*) txF)[2*(symbol_offset + re_offset)] = (int16_t) (((ref_re*alpha_re[alpha_ind]) -
(ref_im*alpha_im[alpha_ind]))>>15);
((int16_t*) txdataF)[2*(symbol_offset + re_offset)+1] = (int16_t) (((ref_re*alpha_im[alpha_ind]) +
((int16_t*) txF)[2*(symbol_offset + re_offset)+1] = (int16_t) (((ref_re*alpha_im[alpha_ind]) +
(ref_im*alpha_re[alpha_ind]))>>15);
((short*) txdataF)[2*(symbol_offset + re_offset)] = (short) ((((short*) txdataF)[2*(symbol_offset + re_offset)]*(int32_t)amp)>>15);
((short*) txdataF)[2*(symbol_offset + re_offset)+1] = (short) ((((short*) txdataF)[2*(symbol_offset + re_offset)+1]*(int32_t)amp)>>15);
((short*) txF)[2*(symbol_offset + re_offset)] = (short) ((((short*) txF)[2*(symbol_offset + re_offset)]*(int32_t)amp)>>15);
((short*) txF)[2*(symbol_offset + re_offset)+1] = (short) ((((short*) txF)[2*(symbol_offset + re_offset)+1]*(int32_t)amp)>>15);
alpha_ind = (alpha_ind + cyclic_shift);
......@@ -140,14 +146,14 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
symbol_offset,
alpha_ind,
re_offset,
((short*) txdataF)[2*(symbol_offset + re_offset)],
((short*) txdataF)[2*(symbol_offset + re_offset)+1]);
((short*) txF)[2*(symbol_offset + re_offset)],
((short*) txF)[2*(symbol_offset + re_offset)+1]);
#endif // DEBUG_DRS
re_offset++;
drs_offset++;
if (re_offset >= frame_parms->ofdm_symbol_size)
if (re_offset >= fp->ofdm_symbol_size)
re_offset = 0;
}
......@@ -156,8 +162,8 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
// check if we crossed the symbol boundary and skip DC
if (re_offset >= frame_parms->ofdm_symbol_size) {
if (frame_parms->N_RB_DL&1) // odd number of RBs
if (re_offset >= fp->ofdm_symbol_size) {
if (fp->N_RB_DL&1) // odd number of RBs
re_offset=6;
else // even number of RBs (doesn't straddle DC)
re_offset=0;
......
......@@ -1660,15 +1660,17 @@ int32_t generate_srs_tx(PHY_VARS_UE *phy_vars_ue,
/*!
\brief This function generates the downlink reference signal for the PUSCH according to 36.211 v8.6.0. The DRS occuies the RS defined by rb_alloc and the symbols 2 and 8 for extended CP and 3 and 10 for normal CP.
*/
int generate_drs_pusch(PHY_VARS_UE *ue,
UE_rxtx_proc_t *proc,
LTE_DL_FRAME_PARMS *frame_parms,
int32_t **txdataF,
uint8_t eNB_id,
short amp,
unsigned int subframe,
unsigned int first_rb,
unsigned int nb_rb,
uint8_t ant);
int32_t generate_drs_pusch(PHY_VARS_UE *phy_vars_ue,
UE_rxtx_proc_t *proc,
uint8_t eNB_id,
int16_t amp,
uint32_t subframe,
uint32_t first_rb,
uint32_t nb_rb,
uint8_t ant);
/*!
\brief This function initializes the Group Hopping, Sequence Hopping and nPRS sequences for PUCCH/PUSCH according to 36.211 v8.6.0. It should be called after configuration of UE (reception of SIB2/3) and initial configuration of eNB (or after reconfiguration of cell-specific parameters).
......
......@@ -717,6 +717,8 @@ typedef struct RU_t_s{
int rx_offset;
/// flag to indicate the RU is a slave to another source
int is_slave;
/// flag to indicate that the RU should generate the DMRS sequence in slot 2 (subframe 1) for OTA synchronization and calibration
int generate_dmrs_sync;
/// flag to indicate if the RU has a control channel
int has_ctrl_prt;
/// counter to delay start of processing of RU until HW settles
......@@ -830,6 +832,8 @@ typedef struct RU_t_s{
RU_proc_t proc;
/// stats thread pthread descriptor
pthread_t ru_stats_thread;
/// OTA synchronization signal
int16_t *dmrssync;
} RU_t;
......
......@@ -1851,6 +1851,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
for (aa=0; aa<1/*frame_parms->nb_antennas_tx*/; aa++)
generate_drs_pusch(ue,
proc,
(LTE_DL_FRAME_PARMS *)NULL,
(int32_t**)NULL,
eNB_id,
tx_amp,
subframe_tx,
......
......@@ -84,11 +84,28 @@ void feptx0(RU_t *ru,int slot) {
6,
fp->nb_prefix_samples,
CYCLIC_PREFIX);
else normal_prefix_mod(&ru->common.txdataF_BF[aa][slot*slot_sizeF],
(int*)&ru->common.txdata[aa][slot_offset],
7,
fp);
else {
AssertFatal(ru->generate_dmrs_sync==1 && (fp->frame_type != TDD || ru->is_slave == 1),
"ru->generate_dmrs_sync should not be set, frame_type %d, is_slave %d\n",
fp->frame_type,ru->is_slave);
if (ru->generate_dmrs_sync == 1 && slot == 0 && subframe == 1 && aa==0) {
generate_drs_pusch((PHY_VARS_UE *)NULL,
(UE_rxtx_proc_t*)NULL,
fp,
ru->common.txdataF_BF,
0,
AMP,
1,
0,
fp->N_RB_DL,
aa);
}
normal_prefix_mod(&ru->common.txdataF_BF[aa][slot*slot_sizeF],
(int*)&ru->common.txdata[aa][slot_offset],
7,
fp);
}
/*
len = fp->samples_per_tti>>1;
......
......@@ -123,7 +123,7 @@ extern volatile int oai_exit;
extern void phy_init_RU(RU_t*);
extern void phy_free_RU(RU_t*);
void init_RU(char*,clock_source_t clock_source,clock_source_t time_source);
void init_RU(char*,clock_source_t clock_source,clock_source_t time_source,int generate_dmrssync);
void stop_RU(int nb_ru);
void do_ru_sync(RU_t *ru);
......@@ -2042,8 +2042,8 @@ void *ru_thread_synch(void *arg) {
RU_t *ru = (RU_t*)arg;
LTE_DL_FRAME_PARMS *fp=&ru->frame_parms;
int32_t sync_pos,sync_pos2;
uint32_t peak_val;
uint32_t sync_corr[307200] __attribute__((aligned(32)));
int64_t peak_val;
int64_t avg;
static int ru_thread_synch_status=0;
int cnt=0;
......@@ -2052,7 +2052,7 @@ void *ru_thread_synch(void *arg) {
wait_sync("ru_thread_synch");
// initialize variables for PSS detection
lte_sync_time_init(&ru->frame_parms);
ru_sync_time_init(ru);
while (!oai_exit) {
......@@ -2064,63 +2064,22 @@ void *ru_thread_synch(void *arg) {
// run intial synch like UE
LOG_I(PHY,"Running initial synchronization\n");
sync_pos = lte_sync_time_eNB(ru->common.rxdata,
fp,
fp->samples_per_tti*5,
ru->rx_offset = ru_sync_time(ru,
&peak_val,
sync_corr);
&avg);
LOG_I(PHY,"RU synch cnt %d: %d, val %d\n",cnt,sync_pos,peak_val);
cnt++;
if (sync_pos >= 0) {
if (sync_pos >= fp->nb_prefix_samples)
sync_pos2 = sync_pos - fp->nb_prefix_samples;
else
sync_pos2 = sync_pos + (fp->samples_per_tti*10) - fp->nb_prefix_samples;
int sync_pos_slot;
if (fp->frame_type == FDD) {
// PSS is hypothesized in last symbol of first slot in Frame
sync_pos_slot = (fp->samples_per_tti>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples;
}
else {
// PSS is hypothesized in 2nd symbol of third slot in Frame (S-subframe)
sync_pos_slot = fp->samples_per_tti +
(fp->ofdm_symbol_size<<1) +
fp->nb_prefix_samples0 +
(fp->nb_prefix_samples);
}
if (sync_pos2 >= sync_pos_slot)
ru->rx_offset = sync_pos2 - sync_pos_slot;
else
ru->rx_offset = (fp->samples_per_tti*10) + sync_pos2 - sync_pos_slot;
LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset);
/*
if ((peak_val > 300000) && (sync_pos > 0)) {
// if (sync_pos++ > 3) {
write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_tti*5,1,2);
write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_tti*10,1,1);
exit(-1);
}
*/
LOG_I(PHY,"Estimated peak_val %d dB, avg %d => timing offset %d\n",ru->rx_offset,dB_fixed(peak_val),dB_fixed(ru->rx_offset));
ru->in_synch = 1;
} // symc_pos > 0
else {
if (cnt>1000) {
write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_tti*5,1,2);
write_output("ru_rx.m","rxs",(void*)ru->common.rxdata[0],fp->samples_per_tti*10,1,1);
exit(1);
}
}
else AssertFatal(cnt<1000,"Cannot find synch reference\n");
} // ru->in_synch==0
if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break;
} // oai_exit
lte_sync_time_free();
ru_sync_time_free(ru);
ru_thread_synch_status = 0;
return &ru_thread_synch_status;
......@@ -2735,7 +2694,7 @@ void set_function_spec_param(RU_t *ru)
extern void RCconfig_RU(void);
void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t time_source) {
void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t time_source,int send_dmrssync) {
int ru_id;
RU_t *ru;
......
......@@ -134,6 +134,7 @@ volatile int oai_exit = 0;
static clock_source_t clock_source = internal,time_source=internal;
static int wait_for_sync = 0;
static int send_dmrssync = 0;
unsigned int mmapped_dma=0;
int single_thread_flag=1;
......@@ -1167,7 +1168,7 @@ int main( int argc, char **argv )
printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
if (RC.nb_RU >0) {
printf("Initializing RU threads\n");
init_RU(rf_config_file,clock_source,time_source);
init_RU(rf_config_file,clock_source,time_source,send_dmrssync);
for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
RC.ru[ru_id]->rf_map.card=0;
RC.ru[ru_id]->rf_map.chain=CC_id+chain_offset;
......
......@@ -63,6 +63,7 @@
#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n"
#define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n"
#define CONFIG_HLP_EXCCLK "tells hardware to use an external clock reference\n"
#define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0"
#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n"
#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n"
#define CONFIG_HLP_TADV "Set timing_advance\n"
......@@ -145,6 +146,7 @@ extern int16_t dlsch_demod_shift;
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \
{"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \
{"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \
{"send_dmrs_sync", CONFIG_HLP_DMRSSYNC, PARAMFLAG_BOOL, uptr:&send_dmrssync, defintval:0, TYPE_INT, 0}, \
{"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}, \
{"threadIQ", NULL, 0, iptr:&(threads.iq), defintval:1, TYPE_INT, 0}, \
......@@ -245,7 +247,7 @@ extern void stop_eNB(int);
extern void kill_eNB_proc(int inst);
// In lte-ru.c
extern void init_RU(const char*,clock_source_t clock_source,clock_source_t time_source);
extern void init_RU(const char*,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync);
extern void init_RU_proc(RU_t *ru);
extern void stop_RU(int nb_ru);
extern void kill_RU_proc(int inst);
......
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