Commit d8c35774 authored by Raymond Knoppp's avatar Raymond Knoppp

modifications at slave RRU

parent 5ac4ced1
......@@ -36,26 +36,38 @@ void init_7_5KHz(void);
int phy_init_RU(RU_t *ru) {
LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
RU_CALIBRATION *calibration = &ru->calibration;
int i,j;
int p;
int re;
LOG_I(PHY,"Initializing RU signal buffers (if_south %s) nb_tx %d\n",ru_if_types[ru->if_south],ru->nb_tx);
if (ru->is_slave == 1) {
generate_ul_ref_sigs_rx();
init_dfts();
}
if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so allocate memory for time-domain signals
// Time-domain signals
ru->common.txdata = (int32_t**)malloc16(ru->nb_tx*sizeof(int32_t*));
ru->common.rxdata = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
for (i=0; i<ru->nb_tx; i++) {
// Allocate 10 subframes of I/Q TX signal data (time) if not
ru->common.txdata[i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
LOG_I(PHY,"[INIT] common.txdata[%d] = %p (%lu bytes)\n",i,ru->common.txdata[i],
fp->samples_per_tti*10*sizeof(int32_t));
}
if (ru->is_slave == 1) {
calibration->drs_ch_estimates_time = (int32_t**)malloc16_clear(ru->nb_rx*sizeof(int32_t*));
for (i=0; i<ru->nb_rx; i++) {
calibration->drs_ch_estimates_time[i] = (int32_t*)malloc16_clear(2*sizeof(int32_t)*fp->ofdm_symbol_size);
}
}
for (i=0;i<ru->nb_rx;i++) {
ru->common.rxdata[i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
}
......@@ -91,6 +103,18 @@ int phy_init_RU(RU_t *ru) {
ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(2*fp->ofdm_symbol_size*fp->symbols_per_tti) );
LOG_I(PHY,"rxdataF[%d] %p for RU %d\n",i,ru->common.rxdataF[i],ru->idx);
}
if (ru->is_slave == 1) {
// allocate FFT output buffers after extraction (RX)
calibration->rxdataF_ext = (int32_t**)malloc16(2*sizeof(int32_t*));
calibration->drs_ch_estimates = (int32_t**)malloc16(2*sizeof(int32_t*));
for (i=0; i<ru->nb_rx; i++) {
// allocate 2 subframes of I/Q signal data (frequency)
calibration->rxdataF_ext[i] = (int32_t*)malloc16_clear(sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
LOG_I(PHY,"rxdataF_ext[%d] %p for RU %d\n",i,calibration->rxdataF_ext[i],ru->idx);
calibration->drs_ch_estimates[i] = (int32_t*)malloc16_clear(sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti);
}
}
/* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */
//AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]),
......@@ -162,12 +186,19 @@ void phy_free_RU(RU_t *ru)
{
int i,j;
int p;
RU_CALIBRATION *calibration = &ru->calibration;
LOG_I(PHY, "Feeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx);
if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals
for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdata[i]);
for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata[i]);
if (ru->is_slave == 1) {
for (i = 0; i < ru->nb_rx; i++) {
free_and_zero(calibration->drs_ch_estimates_time[i]);
}
free_and_zero(calibration->drs_ch_estimates_time);
}
free_and_zero(ru->common.txdata);
free_and_zero(ru->common.rxdata);
} // else: IF5 or local RF -> nothing to free()
......@@ -183,6 +214,14 @@ void phy_free_RU(RU_t *ru)
// free FFT output buffers (RX)
for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdataF[i]);
free_and_zero(ru->common.rxdataF);
if (ru->is_slave == 1) {
for (i = 0; i < ru->nb_rx; i++) {
free_and_zero(calibration->rxdataF_ext[i]);
free_and_zero(calibration->drs_ch_estimates[i]);
}
free_and_zero(calibration->rxdataF_ext);
free_and_zero(calibration->drs_ch_estimates);
}
for (i = 0; i < ru->nb_rx; i++) {
free_and_zero(ru->prach_rxsigF[i]);
......
......@@ -112,17 +112,23 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms,
}
int lte_est_timing_advance_pusch(PHY_VARS_eNB* eNB,module_id_t UE_id)
int lte_est_timing_advance_pusch(PHY_VARS_eNB *eNB,module_id_t UE_id)
{
int temp, i, aa, max_pos=0, max_val=0;
short Re,Im;
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
RU_t *ru;
ru = RC.ru[UE_id];
//LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
LTE_DL_FRAME_PARMS *frame_parms = (eNB==NULL) ? &ru->frame_parms : &eNB->frame_parms;
LTE_eNB_PUSCH *eNB_pusch_vars = eNB->pusch_vars[UE_id];
int32_t **ul_ch_estimates_time= eNB_pusch_vars->drs_ch_estimates_time;
RU_CALIBRATION *calibration = &ru->calibration;
//int32_t **ul_ch_estimates_time= eNB_pusch_vars->drs_ch_estimates_time;
int32_t **ul_ch_estimates_time = calibration->drs_ch_estimates_time;
//int32_t **ul_ch_estimates_time = (eNB==NULL) ? calibration->drs_ch_estimates_time : eNB_pusch_vars->drs_ch_estimates_time;
uint8_t cyclic_shift = 0;
int sync_pos = (frame_parms->ofdm_symbol_size-cyclic_shift*frame_parms->ofdm_symbol_size/12)%(frame_parms->ofdm_symbol_size);
AssertFatal(frame_parms->ofdm_symbol_size > 127,"frame_parms->ofdm_symbol_size %d<128\n",frame_parms->ofdm_symbol_size);
AssertFatal(frame_parms->nb_antennas_rx >0 && frame_parms->nb_antennas_rx<3,"frame_parms->nb_antennas_rx %d not in [0,1]\n",
frame_parms->nb_antennas_rx);
......
......@@ -217,6 +217,19 @@ int lte_ul_channel_estimation(PHY_VARS_eNB *phy_vars_eNB,
uint8_t l,
uint8_t Ns);
int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **ul_ch_estimates,
int32_t **ul_ch_estimates_time,
int32_t **rxdataF_ext,
int N_rb_alloc,
int frame_rx,
int subframe_rx,
uint32_t u,
uint32_t v,
uint32_t cyclic_shift,
unsigned char l,
int interpolate,
uint16_t rnti);
int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms,
int32_t *ul_ch_estimates,
......
......@@ -648,6 +648,7 @@ int ru_sync_time(RU_t *ru,
LTE_DL_FRAME_PARMS *frame_parms = &ru->frame_parms;
RU_CALIBRATION *calibration = &ru->calibration;
// perform a time domain correlation using the oversampled sync sequence
......@@ -671,6 +672,14 @@ int ru_sync_time(RU_t *ru,
maxval = max(maxval,ru->dmrssync[i]);
maxval = max(maxval,-ru->dmrssync[i]);
}
if (ru->state == RU_CHECK_SYNC) {
for (int i=0;i<2*(frame_parms->ofdm_symbol_size);i++) {
maxval = max(maxval,calibration->drs_ch_estimates_time[0][i]);
maxval = max(maxval,-calibration->drs_ch_estimates_time[0][i]);
}
}
int shift = log2_approx(maxval);
for (int n=0; n<length; n+=4) {
......@@ -684,6 +693,13 @@ int ru_sync_time(RU_t *ru,
(int16_t*) &ru->common.rxdata[ar][n],
frame_parms->ofdm_symbol_size,
shift);
if (ru->state == RU_CHECK_SYNC) {
result = dot_product64((int16_t*) &calibration->drs_ch_estimates_time[ar],
(int16_t*) &ru->common.rxdata[ar][n],
frame_parms->ofdm_symbol_size,
shift);
}
dmrs_corr += abs64(result);
}
if (ru->dmrs_corr != NULL) ru->dmrs_corr[n] = dmrs_corr;
......@@ -696,7 +712,7 @@ int ru_sync_time(RU_t *ru,
}
avg0/=(length/4);
int dmrsoffset = frame_parms->samples_per_tti + (3*frame_parms->ofdm_symbol_size)+(2*frame_parms->nb_prefix_samples) + frame_parms->nb_prefix_samples0;
int dmrsoffset = frame_parms->samples_per_tti + (3*frame_parms->ofdm_symbol_size)+(3*frame_parms->nb_prefix_samples) + frame_parms->nb_prefix_samples0;
if ((int64_t)maxlev0 > (10*avg0)) {*lev = maxlev0; *avg=avg0; return((length+maxpos0-dmrsoffset)%length);}
......
......@@ -39,14 +39,26 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
module_id_t UE_id,
unsigned char l,
unsigned char Ns) {
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
RU_t *ru;
ru = RC.ru[UE_id];
LTE_DL_FRAME_PARMS *frame_parms = (eNB==NULL) ? &eNB->frame_parms : &ru->frame_parms;
//LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
LTE_eNB_PUSCH *pusch_vars = eNB->pusch_vars[UE_id];
int32_t **ul_ch_estimates=pusch_vars->drs_ch_estimates;
int32_t **ul_ch_estimates_time= pusch_vars->drs_ch_estimates_time;
int32_t **rxdataF_ext= pusch_vars->rxdataF_ext;
int subframe = proc->subframe_rx;
RU_CALIBRATION *calibration = &ru->calibration;
//int32_t **ul_ch_estimates=pusch_vars->drs_ch_estimates;
int32_t **ul_ch_estimates = (eNB==NULL) ? pusch_vars->drs_ch_estimates : calibration->drs_ch_estimates;
//int32_t **ul_ch_estimates_time= pusch_vars->drs_ch_estimates_time;
int32_t **ul_ch_estimates_time = (eNB==NULL) ? pusch_vars->drs_ch_estimates_time : calibration->drs_ch_estimates_time;
//int32_t **rxdataF_ext= pusch_vars->rxdataF_ext;
int32_t **rxdataF_ext = (eNB==NULL) ? pusch_vars->rxdataF_ext : calibration->rxdataF_ext;
int subframe = (eNB==NULL) ? proc->subframe_rx : ru->proc.subframe_rx;
//int subframe = proc->subframe_rx;
uint8_t harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
int16_t delta_phase = 0;
int16_t *ru1 = ru_90;
int16_t *ru2 = ru_90;
......@@ -413,6 +425,356 @@ int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
return(0);
}
int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **ul_ch_estimates,
int32_t **ul_ch_estimates_time,
int32_t **rxdataF_ext,
int N_rb_alloc,
int frame_rx,
int subframe_rx,
uint32_t u,
uint32_t v,
uint32_t cyclic_shift,
unsigned char l,
int interpolate,
uint16_t rnti) {
int16_t delta_phase = 0;
int16_t *ru1 = ru_90;
int16_t *ru2 = ru_90;
int16_t current_phase1,current_phase2;
uint16_t aa,Msc_RS,Msc_RS_idx;
uint16_t * Msc_idx_ptr;
int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp;
int32_t *ul_ch1=NULL, *ul_ch2=NULL;
int16_t ul_ch_estimates_re,ul_ch_estimates_im;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
uint32_t alpha_ind;
int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16)));
int symbol_offset,i;
//debug_msg("lte_ul_channel_estimation_RRU: cyclic shift %d\n",cyclicShift);
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};
#if defined(__x86_64__) || defined(__i386__)
__m128i *rxdataF128,*ul_ref128,*ul_ch128;
__m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3;
#elif defined(__arm__)
int16x8_t *rxdataF128,*ul_ref128,*ul_ch128;
int32x4_t mmtmp0,mmtmp1,mmtmp_re,mmtmp_im;
#endif
int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
AssertFatal(l==pilot_pos1 || l==pilot_pos2,"%d is not a valid symbol for DMRS, should be %d or %d\n",
l,pilot_pos1,pilot_pos2);
Msc_RS = N_rb_alloc*12;
/*
*/
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 33, sizeof(uint16_t), compareints);
if (Msc_idx_ptr)
Msc_RS_idx = Msc_idx_ptr - dftsizes;
else {
LOG_E(PHY,"lte_ul_channel_estimation_RRU: index for Msc_RS=%d not found\n",Msc_RS);
return(-1);
}
LOG_D(PHY,"subframe %d, l %d, Msc_RS = %d, Msc_RS_idx = %d, u %d, v %d, cyclic_shift %d\n",subframe_rx,l,Msc_RS, Msc_RS_idx,u,v,cyclic_shift);
#ifdef DEBUG_CH
if (l==pilot_pos1)
write_output("drs_seq0.m","drsseq0",ul_ref_sigs_rx[u][v][Msc_RS_idx],Msc_RS,1,1);
else
write_output("drs_seq1.m","drsseq1",ul_ref_sigs_rx[u][v][Msc_RS_idx],Msc_RS,1,1);
#endif
symbol_offset = frame_parms->N_RB_UL*12*l;
for (aa=0; aa<nb_antennas_rx; aa++) {
#if defined(__x86_64__) || defined(__i386__)
rxdataF128 = (__m128i *)&rxdataF_ext[aa][symbol_offset];
ul_ch128 = (__m128i *)&ul_ch_estimates[aa][symbol_offset];
ul_ref128 = (__m128i *)ul_ref_sigs_rx[u][v][Msc_RS_idx];
#elif defined(__arm__)
rxdataF128 = (int16x8_t *)&rxdataF_ext[aa][symbol_offset];
ul_ch128 = (int16x8_t *)&ul_ch_estimates[aa][symbol_offset];
ul_ref128 = (int16x8_t *)ul_ref_sigs_rx[u][v][Msc_RS_idx];
#endif
for (i=0; i<Msc_RS/12; i++) {
#if defined(__x86_64__) || defined(__i386__)
// multiply by conjugated channel
mmtmpU0 = _mm_madd_epi16(ul_ref128[0],rxdataF128[0]);
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[0],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)&conjugate[0]);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
// printf("rb %d ch: %d %d\n",i,((int16_t*)ul_ch128)[0],((int16_t*)ul_ch128)[1]);
// multiply by conjugated channel
mmtmpU0 = _mm_madd_epi16(ul_ref128[1],rxdataF128[1]);
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[1],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
mmtmpU0 = _mm_madd_epi16(ul_ref128[2],rxdataF128[2]);
// mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[2],_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]);
// mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
ul_ch128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
#elif defined(__arm__)
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]);
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++;
ul_ref128++;
rxdataF128++;
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]);
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++;
ul_ref128++;
rxdataF128++;
mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]);
mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]);
mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]);
mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]);
mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
ul_ch128++;
ul_ref128++;
rxdataF128++;
#endif
ul_ch128+=3;
ul_ref128+=3;
rxdataF128+=3;
}
alpha_ind = 0;
if((cyclic_shift != 0)) {
// Compensating for the phase shift introduced at the transmitte
#ifdef DEBUG_CH
write_output("drs_est_pre.m","drsest_pre",ul_ch_estimates[0],300*12,1,1);
#endif
for(i=symbol_offset; i<symbol_offset+Msc_RS; i++) {
ul_ch_estimates_re = ((int16_t*) ul_ch_estimates[aa])[i<<1];
ul_ch_estimates_im = ((int16_t*) ul_ch_estimates[aa])[(i<<1)+1];
// ((int16_t*) ul_ch_estimates[aa])[i<<1] = (i%2 == 1? 1:-1) * ul_ch_estimates_re;
((int16_t*) ul_ch_estimates[aa])[i<<1] =
(int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_re) +
(int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_im))>>15);
//((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] = (i%2 == 1? 1:-1) * ul_ch_estimates_im;
((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] =
(int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_im) -
(int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_re))>>15);
alpha_ind+=cyclic_shift;
if (alpha_ind>11)
alpha_ind-=12;
}
#ifdef DEBUG_CH
write_output("drs_est_post.m","drsest_post",ul_ch_estimates[0],300*12,1,1);
#endif
}
if (ul_ch_estimates_time && ul_ch_estimates_time[aa]) {
// Convert to time domain for visualization
memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
for(i=0; i<Msc_RS; i++)
((int32_t*)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i];
switch(frame_parms->N_RB_DL) {
case 6:
idft128((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 25:
idft512((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 50:
idft1024((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 100:
idft2048((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
}
#if T_TRACER
if (aa == 0)
T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(0), T_INT(rnti),
T_INT(frame_rx), T_INT(subframe_rx),
T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4));
#endif
}
#ifdef DEBUG_CH
if (aa==1) {
if (l == pilot_pos1) {
write_output("rxdataF_ext.m","rxF_ext",&rxdataF_ext[aa][symbol_offset],512*2,2,1);
write_output("tmpin_ifft.m","drs_in",temp_in_ifft_0,512,1,1);
if (ul_ch_estimates_time[aa]) write_output("drs_est0.m","drs0",ul_ch_estimates_time[aa],512,1,1);
} else
if (ul_ch_estimates_time[aa]) write_output("drs_est1.m","drs1",ul_ch_estimates_time[aa],512,1,1);
}
#endif
if (l==pilot_pos2 && interpolate==1) {//we are in the second slot of the sub-frame, so do the interpolation
ul_ch1 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1];
ul_ch2 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2];
// Estimation of phase difference between the 2 channel estimates
delta_phase = lte_ul_freq_offset_estimation(frame_parms,
ul_ch_estimates[aa],
N_rb_alloc);
// negative phase index indicates negative Im of ru
// msg("delta_phase: %d\n",delta_phase);
#ifdef DEBUG_CH
LOG_D(PHY,"lte_ul_channel_estimation_RRU: ul_ch1 = %p, ul_ch2 = %p, pilot_pos1=%d, pilot_pos2=%d\n",ul_ch1, ul_ch2, pilot_pos1,pilot_pos2);
#endif
for (k=0; k<frame_parms->symbols_per_tti; k++) {
#ifdef DEBUG_CH
// LOG_D(PHY,"lte_ul_channel_estimation: k=%d, alpha = %d, beta = %d\n",k,alpha,beta);
#endif
//symbol_offset_subframe = frame_parms->N_RB_UL*12*k;
// interpolate between estimates
if ((k != pilot_pos1) && (k != pilot_pos2)) {
// the phase is linearly interpolated
current_phase1 = (delta_phase/7)*(k-pilot_pos1);
current_phase2 = (delta_phase/7)*(k-pilot_pos2);
// msg("sym: %d, current_phase1: %d, current_phase2: %d\n",k,current_phase1,current_phase2);
// set the right quadrant
(current_phase1 > 0) ? (ru1 = ru_90) : (ru1 = ru_90c);
(current_phase2 > 0) ? (ru2 = ru_90) : (ru2 = ru_90c);
// take absolute value and clip
current_phase1 = cmin(abs(current_phase1),127);
current_phase2 = cmin(abs(current_phase2),127);
// msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]);
// rotate channel estimates by estimated phase
rotate_cpx_vector((int16_t*) ul_ch1,
&ru1[2*current_phase1],
(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
Msc_RS,
15);
rotate_cpx_vector((int16_t*) ul_ch2,
&ru2[2*current_phase2],
(int16_t*) &tmp_estimates[0],
Msc_RS,
15);
// Combine the two rotated estimates
multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
}
} //for(k=...
// because of the scaling of alpha and beta we also need to scale the final channel estimate at the pilot positions
// multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) ul_ch1,1,Msc_RS);
// multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) ul_ch2,1,Msc_RS);
} //if (Ns&1 && interpolate==1)
else if (interpolate == 0 && l == pilot_pos1)
for (k=0;k<frame_parms->symbols_per_tti>>1;k++) {
if (k==pilot_pos1) k++;
memcpy((void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
(void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1],
frame_parms->N_RB_UL*12*sizeof(int));
}
else if (interpolate == 0 && l == pilot_pos2) {
for (k=0;k<frame_parms->symbols_per_tti>>1;k++) {
if (k==pilot_pos2) k++;
memcpy((void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*(k+(frame_parms->symbols_per_tti>>1))],
(void*)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2],
frame_parms->N_RB_UL*12*sizeof(int));
}
delta_phase = lte_ul_freq_offset_estimation(frame_parms,
ul_ch_estimates[aa],
N_rb_alloc);
LOG_D(PHY,"delta_phase = %d\n",delta_phase);
}
} //for(aa=...
return(0);
}
extern uint16_t transmission_offset_tdd[16];
//#define DEBUG_SRS
......
......@@ -147,6 +147,17 @@ void remove_7_5_kHz(RU_t *ru,uint8_t slot)
#endif
}
}
// undo 7.5 kHz offset for symbol 3 in case RU is slave (for OTA synchronization)
if (ru->is_slave == 1 && slot == 2){
memcpy((void*)&rxdata_7_5kHz[aa][(3*frame_parms->ofdm_symbol_size)+
(2*frame_parms->nb_prefix_samples)+
frame_parms->nb_prefix_samples0],
(void*)&rxdata[aa][slot_offset+ru->N_TA_offset+
(3*frame_parms->ofdm_symbol_size)+
(2*frame_parms->nb_prefix_samples)+
frame_parms->nb_prefix_samples0],
(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples)*sizeof(int32_t));
}
}
}
......@@ -301,7 +301,8 @@ typedef enum {
RU_READY = 2,
RU_RUN = 3,
RU_ERROR = 4,
RU_SYNC = 5
RU_SYNC = 5,
RU_CHECK_SYNC = 6
} rru_state_t;
/// Some commamds to RRU. Not sure we should do it like this !
......@@ -345,6 +346,8 @@ typedef struct RU_t_s{
int has_ctrl_prt;
/// counter to delay start of processing of RU until HW settles
int wait_cnt;
/// counter to delay start of slave RUs until stable synchronization
int wait_check;
/// Total gain of receive chain
uint32_t rx_total_gain_dB;
/// number of bands that this device can support
......@@ -441,6 +444,7 @@ typedef struct RU_t_s{
time_stats_t transport;
/// RX and TX buffers for precoder output
RU_COMMON common;
RU_CALIBRATION calibration;
/// beamforming weight vectors per eNB
int32_t **beam_weights[NUMBER_OF_eNB_MAX+1][15];
......@@ -480,7 +484,8 @@ typedef enum {
RRU_stop=5,
RRU_sync_ok=6,
RRU_frame_resynch=7,
RRU_MSG_max_num=8
RRU_MSG_max_num=8,
RRU_check_sync = 9
} rru_config_msg_type_t;
typedef struct RRU_CONFIG_msg_s {
......
......@@ -58,7 +58,7 @@ typedef struct {
/// - first index: rx antenna [0..nb_antennas_rx[
/// - second index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[
int32_t **rxdataF;
/// \brief Holds output of the sync correlator.
/// \brief Holds output of the sync correlator.
/// - first index: sample [0..samples_per_tti*10[
uint32_t *sync_corr;
/// \brief Holds the tdd reciprocity calibration coefficients
......@@ -68,4 +68,19 @@ typedef struct {
int32_t **tdd_calib_coeffs;
} RU_COMMON;
typedef struct {
/// \brief Received frequency-domain signal after extraction.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **rxdataF_ext;
/// \brief Hold the channel estimates in time domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..4*ofdm_symbol_size[
int32_t **drs_ch_estimates_time;
/// \brief Hold the channel estimates in frequency domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t **drs_ch_estimates;
} RU_CALIBRATION;
#endif
......@@ -535,7 +535,6 @@ void fep0(RU_t *ru,int slot) {
// printf("fep0: slot %d\n",slot);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+slot, 1);
remove_7_5_kHz(ru,(slot&1)+(proc->subframe_rx<<1));
for (l=0; l<fp->symbols_per_tti/2; l++) {
slot_fep_ul(ru,
......@@ -647,14 +646,20 @@ extern void kill_feptx_thread(RU_t *ru)
void ru_fep_full_2thread(RU_t *ru) {
RU_proc_t *proc = &ru->proc;
//PHY_VARS_eNB *eNB = RC.eNB[0][0];
LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
RU_CALIBRATION *calibration = &ru->calibration;
int cnt;
int check_sync_pos;
struct timespec wait;
LTE_DL_FRAME_PARMS *fp=&ru->frame_parms;
if ((fp->frame_type == TDD) &&
(subframe_select(fp,proc->subframe_rx) != SF_UL)) return;
if (proc->subframe_rx==1){
//LOG_I(PHY,"subframe type %d, RU %d\n",subframe_select(fp,proc->subframe_rx),ru->idx);
}
else if ((fp->frame_type == TDD) && (subframe_select(fp,proc->subframe_rx) != SF_UL)) {
return;
}
//if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 );
wait.tv_sec=0;
......@@ -696,9 +701,73 @@ void ru_fep_full_2thread(RU_t *ru) {
stop_meas(&ru->ofdm_demod_wait_stats);
if(opp_enabled == 1 && ru->ofdm_demod_wakeup_stats.p_time>30*3000){
print_meas_now(&ru->ofdm_demod_wakeup_stats,"fep wakeup",stderr);
printf("delay in fep wait on codition in frame_rx: %d subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx);
printf("delay in fep wait on condition in frame_rx: %d subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx);
}
if (proc->subframe_rx==1 && ru->is_slave==1/* && ru->state == RU_CHECK_SYNC*/) {
LOG_I(PHY,"Running check synchronization procedure for frame %d\n", proc->frame_rx);
ulsch_extract_rbs_single(ru->common.rxdataF,
calibration->rxdataF_ext,
0,
fp->N_RB_DL,
3%(fp->symbols_per_tti/2),// l = symbol within slot
3/(fp->symbols_per_tti/2),// Ns = slot number
fp);
/*lte_ul_channel_estimation((PHY_VARS_eNB *)NULL,
proc,
ru->idx,
3%(fp->symbols_per_tti/2),
3/(fp->symbols_per_tti/2));
*/
lte_ul_channel_estimation_RRU(fp,
calibration->drs_ch_estimates,
calibration->drs_ch_estimates_time,
calibration->rxdataF_ext,
fp->N_RB_DL, //N_rb_alloc,
proc->frame_rx,
proc->subframe_rx,
0,//u = 0..29
0,//v = 0,1
/*eNB->ulsch[ru->idx]->cyclicShift,cyclic_shift,0..7*/0,
3,//l,
0,//interpolate,
0 /*eNB->ulsch[ru->idx]->rnti rnti or ru->ulsch[eNB_id]->rnti*/);
check_sync_pos = lte_est_timing_advance_pusch((PHY_VARS_eNB *)NULL,
ru->idx);
//LOG_I(PHY,"Estimated check_sync_pos %d\n",check_sync_pos);
if (ru->state == RU_CHECK_SYNC) {
if ((check_sync_pos >= 0 && check_sync_pos<8) || (check_sync_pos < 0 && check_sync_pos>-8)) {
LOG_I(PHY,"check_sync_pos %d, frame %d, cnt %d\n",check_sync_pos,proc->frame_rx,ru->wait_check);
ru->wait_check++;
}
if (ru->wait_check==10) {
ru->state = RU_RUN;
/*LOG_M("dmrs_time.m","dmrstime",calibration->drs_ch_estimates_time[0], (fp->ofdm_symbol_size),1,1);
LOG_M("rxdataF_ext.m","rxdataFext",&calibration->rxdataF_ext[0][36*fp->N_RB_DL], 12*(fp->N_RB_DL),1,1);
LOG_M("drs_seq0.m","drsseq0",ul_ref_sigs_rx[0][0][23],600,1,1);
LOG_M("rxdata.m","rxdata",&ru->common.rxdata[0][0], fp->samples_per_tti*2,1,1);
exit(-1);*/
}
}
else if (ru->state == RU_RUN) {
// check for synchronization error
if (check_sync_pos >= 8 || check_sync_pos<=-8) {
exit(-1);
}
}
else {
AssertFatal(1==0,"Should not get here\n");
}
}
stop_meas(&ru->ofdm_demod_stats);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+ru->idx, 0 );
}
......
......@@ -245,7 +245,7 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam
}
eth->tx_nsamps = nblocks;
printf("Sending %d bytes to %s:%d\n",packet_size,str,ntohs(eth->local_addrd.sin_port));
//printf("Sending %d bytes to %s:%d\n",packet_size,str,ntohs(eth->local_addrd.sin_port));
bytes_sent = sendto(eth->sockfdd,
buff[0],
......
......@@ -601,7 +601,7 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
ru->south_in_cnt++;
LOG_I(PHY,"south_in_cnt %d\n",ru->south_in_cnt);
LOG_D(PHY,"south_in_cnt %d\n",ru->south_in_cnt);
if (ru->cmd==RU_FRAME_RESYNCH) {
LOG_I(PHY,"Applying frame resynch %d => %d\n",*frame,ru->cmdval);
......@@ -1118,14 +1118,32 @@ void do_ru_synch(RU_t *ru) {
ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
*/
ru->state = RU_RUN;
// Send RRU_sync_ok
rru_config_msg.type = RRU_sync_ok;
// Verification of synchronization procedure
ru->state = RU_CHECK_SYNC;
/* // Send RRU_check_sync
rru_config_msg.type = RRU_check_sync;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len
LOG_I(PHY,"Sending RRU_sync_ok to RAU\n");
LOG_I(PHY,"Sending RRU_check_sync to RAU\n");
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);
while (check_sync_flag){ // continuously read frames until check synch procedure is over
}
//if (synch_peak>...) {
ru->state = RU_RUN;
// Send RRU_sync_ok
rru_config_msg.type = RRU_sync_ok;
rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len
LOG_I(PHY,"Sending RRU_sync_ok to RAU\n");
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 {
//do_ru_synch(ru);
//}
*/
LOG_I(PHY,"Exiting synch routine\n");
}
......@@ -1653,8 +1671,14 @@ static void* ru_thread( void* param ) {
while (!oai_exit) {
if (ru->if_south != LOCAL_RF && ru->is_slave==1) ru->wait_cnt = 100;
else ru->wait_cnt = 0;
if (ru->if_south != LOCAL_RF && ru->is_slave==1) {
ru->wait_cnt = 100;
}
else {
ru->wait_cnt = 0;
ru->wait_check = 0;
}
// wait to be woken up
if (ru->function!=eNodeB_3GPP && ru->has_ctrl_prt == 1) {
......@@ -1663,7 +1687,7 @@ static void* ru_thread( void* param ) {
else wait_sync("ru_thread");
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 == RU_RUN,"ru %d state = %s != RU_SYNC or RU_RUN\n",ru->idx,ru_states[ru->state]);
else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC || ru->state == RU_RUN || ru->state == RU_CHECK_SYNC,"ru %d state = %s != RU_SYNC or RU_RUN or RU_CHECK_SYNC\n",ru->idx,ru_states[ru->state]);
// Start RF device if any
if (ru->start_rf) {
if (ru->start_rf(ru) != 0)
......@@ -1691,7 +1715,7 @@ static void* ru_thread( void* param ) {
LOG_D(PHY,"Starting steady-state operation\n");
// This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
while (ru->state == RU_RUN) {
while (ru->state == RU_RUN || ru->state == RU_CHECK_SYNC) {
// these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
// They are set on the first rx/tx in the underly FH routines.
......@@ -1841,7 +1865,7 @@ static void* ru_thread( void* param ) {
// 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_out) ru->fh_north_out(ru);
if ((ru->fh_north_out) && (ru->state!=RU_CHECK_SYNC)) ru->fh_north_out(ru);
}
proc->emulate_rf_busy = 0;
}
......@@ -1907,15 +1931,16 @@ void *ru_thread_synch(void *arg) {
&avg);
LOG_I(PHY,"RU synch cnt %d: %d, val %llu (%d dB,%d dB)\n",cnt,ru->rx_offset,(unsigned long long)peak_val,dB_fixed64(peak_val),dB_fixed64(avg));
cnt++;
if (/*ru->rx_offset >= 0*/dB_fixed64(peak_val)>=85 && cnt>10) {
if (/*ru->rx_offset >= 0*/dB_fixed(peak_val)>=85 && cnt>10) {
LOG_I(PHY,"Estimated peak_val %d dB, avg %d => timing offset %llu\n",dB_fixed(peak_val),dB_fixed(avg),(unsigned long long int)ru->rx_offset);
ru->in_synch = 1;
/*
LOG_M("ru_sync_rx.m","rurx",&ru->common.rxdata[0][0],LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,1);
LOG_M("ru_sync_corr.m","sync_corr",ru->dmrs_corr,LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,6);
LOG_M("ru_dmrs.m","rudmrs",&ru->dmrssync[0],fp->ofdm_symbol_size,1,1);
//exit(-1);
*/
//exit(-1);
} // sync_pos > 0
else //AssertFatal(cnt<1000,"Cannot find synch reference\n");
{
......
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