Commit 1b974c6a authored by Rakesh Mundlamuri's avatar Rakesh Mundlamuri

merge timing_advance_offset and timing_advance_offset_ns computation

parent b378acf2
...@@ -346,6 +346,7 @@ float get_beta_dmrs(int num_cdm_groups_no_data, bool is_type2); ...@@ -346,6 +346,7 @@ float get_beta_dmrs(int num_cdm_groups_no_data, bool is_type2);
#define CEILIDIV(a,b) ((a+b-1)/b) #define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
#define BOUNDED_EVAL(a, b, c) (min(c, max(a, b)))
static const char *const duplex_mode_txt[] = {"FDD", "TDD"}; static const char *const duplex_mode_txt[] = {"FDD", "TDD"};
......
...@@ -36,52 +36,73 @@ ...@@ -36,52 +36,73 @@
#define I0_SKIP_DC 1 #define I0_SKIP_DC 1
int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size,
const c16_t srs_estimated_channel_time[][NR_SRS_IDFT_OVERSAMP_FACTOR * frame_parms->ofdm_symbol_size]) const c16_t srs_estimated_channel_time[][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
uint8_t ant,
uint8_t N_ap,
uint32_t samples_per_frame,
uint16_t *ta_offset,
int16_t *ta_offset_nsec)
{ {
int timing_advance = 0; int64_t mean_val = 0;
int max_val = 0; int64_t max_val = 0;
int32_t max_idx = 0;
for (int i = 0; i < NR_SRS_IDFT_OVERSAMP_FACTOR * frame_parms->ofdm_symbol_size; i++) { int16_t srs_toa = 0;
int temp = 0; int16_t ofdm_os_size = NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size;
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { for (int k = 0; k < ofdm_os_size; k++) {
int Re = ((c16_t*)srs_estimated_channel_time[aa])[i].r; int64_t abs_val = 0;
int Im = ((c16_t*)srs_estimated_channel_time[aa])[i].i; for (int p_index = 0; p_index < N_ap; p_index++) {
temp += (Re*Re/2) + (Im*Im/2); abs_val += squaredMod(srs_estimated_channel_time[p_index][k]);
} }
if (temp > max_val) { mean_val += abs_val;
timing_advance = i; if (abs_val > max_val) {
max_val = temp; max_val = abs_val;
max_idx = k;
} }
} }
max_val = max_val / N_ap;
mean_val = mean_val / (N_ap * ofdm_os_size);
if (max_idx > ofdm_os_size >> 1)
max_idx = max_idx - ofdm_os_size;
// Check for detection threshold
if ((mean_val != 0) && (max_val / mean_val > NR_SRS_DETECTION_THRESHOLD)) {
srs_toa = max_idx / NR_SRS_IDFT_OVERSAMP_FACTOR;
// restrict the computation of ta_offset to antenna 0
if (ant == 0) {
// Scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
const uint16_t bw_scaling = ofdm_symbol_size >> 7;
// do some integer rounding to improve TA accuracy
int sync_pos_rounded;
if (srs_toa > 0) {
sync_pos_rounded = srs_toa + (bw_scaling >> 1) - 1;
} else {
sync_pos_rounded = srs_toa - (bw_scaling >> 1) + 1;
}
if (timing_advance > (NR_SRS_IDFT_OVERSAMP_FACTOR * frame_parms->ofdm_symbol_size) / 2) { *ta_offset = sync_pos_rounded / bw_scaling;
timing_advance = timing_advance - (NR_SRS_IDFT_OVERSAMP_FACTOR * frame_parms->ofdm_symbol_size);
}
timing_advance = timing_advance / NR_SRS_IDFT_OVERSAMP_FACTOR;
LOG_I(NR_PHY, "Estimated SRS ToA %d\n", timing_advance);
// Scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
const uint16_t bw_scaling = frame_parms->ofdm_symbol_size >> 7;
// do some integer rounding to improve TA accuracy // put timing advance command in 0..63 range
int sync_pos_rounded; *ta_offset = BOUNDED_EVAL(0, *ta_offset + 31, 63);
if (timing_advance > 0) { }
sync_pos_rounded = timing_advance + (bw_scaling >> 1) - 1; *ta_offset_nsec = (max_idx * 1e9) / (NR_SRS_IDFT_OVERSAMP_FACTOR * samples_per_frame * 100);
} else { } else {
sync_pos_rounded = timing_advance - (bw_scaling >> 1) + 1; *ta_offset = 0xFFFF;
*ta_offset_nsec = 0x8000;
} }
int timing_advance_update = sync_pos_rounded / bw_scaling; LOG_D(NR_PHY,
"SRS estimatd ToA %d [RX ant %d]: TA offset %d, TA offset ns %d (max_val %ld, mean_val %ld, max_idx %d)\n",
// put timing advance command in 0..63 range srs_toa,
timing_advance_update += 31; ant,
*ta_offset,
if (timing_advance_update < 0) timing_advance_update = 0; *ta_offset_nsec,
if (timing_advance_update > 63) timing_advance_update = 63; max_val,
mean_val,
return timing_advance_update; max_idx);
} }
void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) { void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) {
......
...@@ -59,9 +59,13 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); ...@@ -59,9 +59,13 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB);
void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9]); void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9]);
int nr_est_timing_advance_srs( void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size,
const NR_DL_FRAME_PARMS *frame_parms, const c16_t srs_estimated_channel_time[][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
const c16_t srs_estimated_channel_time[][NR_SRS_IDFT_OVERSAMP_FACTOR * frame_parms->ofdm_symbol_size]); uint8_t ant,
uint8_t N_ap,
uint32_t samples_per_frame,
uint16_t *timing_advance_offset,
int16_t *timing_advance_offset_nsec);
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
......
...@@ -243,7 +243,9 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, ...@@ -243,7 +243,9 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
int *srs_est, int *srs_est,
c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS], c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], c16_t srs_estimated_channel_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
int16_t *snr_per_rb); int16_t *snr_per_rb,
uint16_t *timing_advance_offset,
int16_t *timing_advance_offset_nsec);
int get_nr_prach_duration(uint8_t prach_format); int get_nr_prach_duration(uint8_t prach_format);
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#define MAX_NUM_RU_PER_gNB 8 #define MAX_NUM_RU_PER_gNB 8
#define MAX_PUCCH0_NID 8 #define MAX_PUCCH0_NID 8
#define NR_SRS_IDFT_OVERSAMP_FACTOR 2 #define NR_SRS_IDFT_OVERSAMP_FACTOR 2
#define NR_SRS_DETECTION_THRESHOLD 10
typedef struct { typedef struct {
int nb_id; int nb_id;
......
...@@ -869,7 +869,9 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, ...@@ -869,7 +869,9 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
int *srs_est, int *srs_est,
c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS], c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], c16_t srs_estimated_channel_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
int16_t *snr_per_rb) int16_t *snr_per_rb,
uint16_t *timing_advance_offset,
int16_t *timing_advance_offset_nsec)
{ {
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
...@@ -930,6 +932,18 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, ...@@ -930,6 +932,18 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
snr_per_rb[rb] = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_per_rb[rb] / nb_antennas_rx, 1)); snr_per_rb[rb] = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_per_rb[rb] / nb_antennas_rx, 1));
} }
stop_meas(&gNB->srs_channel_estimation_stats); stop_meas(&gNB->srs_channel_estimation_stats);
start_meas(&gNB->srs_timing_advance_stats);
for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) {
nr_est_srs_timing_advance_offset(ofdm_symbol_size,
srs_estimated_channel_time[ant_rx_ind],
ant_rx_ind,
N_ap,
frame_parms->samples_per_frame,
timing_advance_offset,
&timing_advance_offset_nsec[ant_rx_ind]);
}
stop_meas(&gNB->srs_timing_advance_stats);
} }
T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE,
...@@ -1168,6 +1182,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N ...@@ -1168,6 +1182,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports; uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports;
int16_t snr_per_rb[srs->srs_pdu.bwp_size]; int16_t snr_per_rb[srs->srs_pdu.bwp_size];
nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
uint16_t timing_advance_offset;
int16_t timing_advance_offset_nsec[nb_antennas_rx];
int srs_est; int srs_est;
c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
...@@ -1186,7 +1202,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N ...@@ -1186,7 +1202,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
&srs_est, &srs_est,
srs_estimated_channel_freq, srs_estimated_channel_freq,
srs_estimated_channel_time, srs_estimated_channel_time,
snr_per_rb); snr_per_rb,
&timing_advance_offset,
timing_advance_offset_nsec);
if ((gNB->srs->snr * 10) < gNB->srs_thres) { if ((gNB->srs->snr * 10) < gNB->srs_thres) {
srs_est = -1; srs_est = -1;
...@@ -1200,13 +1218,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N ...@@ -1200,13 +1218,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++; nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++;
srs_indication->handle = srs_pdu->handle; srs_indication->handle = srs_pdu->handle;
srs_indication->rnti = srs_pdu->rnti; srs_indication->rnti = srs_pdu->rnti;
start_meas(&gNB->srs_timing_advance_stats); srs_indication->timing_advance_offset = srs_est >= 0 ? timing_advance_offset : 0xFFFF;
srs_indication->timing_advance_offset = // TODO: currently we fill timing_advance_offset_nsec for antenna 0. Need to extend it for other antennas
srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, srs_estimated_channel_time[0]) : 0xFFFF; srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? timing_advance_offset_nsec[0] : 0x8000;
stop_meas(&gNB->srs_timing_advance_stats);
srs_indication->timing_advance_offset_nsec =
srs_est >= 0 ? (int16_t)((((int32_t)srs_indication->timing_advance_offset - 31) * ((int32_t)TC_NSEC_x32768)) >> 15)
: 0xFFFF;
switch (srs_pdu->srs_parameters_v4.usage) { switch (srs_pdu->srs_parameters_v4.usage) {
case 0: case 0:
LOG_W(NR_PHY, "SRS report was not requested by MAC\n"); LOG_W(NR_PHY, "SRS report was not requested by MAC\n");
......
...@@ -88,9 +88,8 @@ int main(int argc, char *argv[]) ...@@ -88,9 +88,8 @@ int main(int argc, char *argv[])
sigaction(SIGINT, &sigint_action, &oldaction); sigaction(SIGINT, &sigint_action, &oldaction);
double SNR, snr0 = 0, snr1 = 20.0; double SNR, snr0 = 0, snr1 = 20.0;
double sum_srs_snr = 0;
double sigma, sigma_dB; double sigma, sigma_dB;
double snr_step = 5; double snr_step = 1;
uint8_t snr1set = 0; uint8_t snr1set = 0;
double **s_re, **s_im, **r_re, **r_im; double **s_re, **s_im, **r_re, **r_im;
int trial, n_trials = 1, delay = 0; int trial, n_trials = 1, delay = 0;
...@@ -128,7 +127,7 @@ int main(int argc, char *argv[]) ...@@ -128,7 +127,7 @@ int main(int argc, char *argv[])
InitSinLUT(); InitSinLUT();
int c; int c;
while ((c = getopt(argc, argv, "--:O:a:b:c:d:e:f:g:h:i:k:l:m:n:p:s:u:y:z:A:B:C:H:PR:S:L:")) != -1) { while ((c = getopt(argc, argv, "--:O:a:b:c:d:e:f:g:h:i:kl:m:n:p:s:u:y:z:A:B:C:H:PR:S:L:")) != -1) {
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */ /* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */ /* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
if (c == 1 || c == '-' || c == 'O') if (c == 1 || c == '-' || c == 'O')
...@@ -570,7 +569,8 @@ int main(int argc, char *argv[]) ...@@ -570,7 +569,8 @@ int main(int argc, char *argv[])
reset_meas(&gNB->srs_channel_estimation_stats); reset_meas(&gNB->srs_channel_estimation_stats);
reset_meas(&gNB->srs_timing_advance_stats); reset_meas(&gNB->srs_timing_advance_stats);
sum_srs_snr = 0; double sum_srs_snr = 0;
int tao_ns_count = 0;
for (trial = 0; trial < n_trials && !stop; trial++) { for (trial = 0; trial < n_trials && !stop; trial++) {
// Estimate noise power from the transmitter level and SNR // Estimate noise power from the transmitter level and SNR
sigma_dB = 10 * log10(((double)txlev_sum) * ((double)ofdm_symbol_size / (12 * srs_pdu.bwp_size))) - SNR; sigma_dB = 10 * log10(((double)txlev_sum) * ((double)ofdm_symbol_size / (12 * srs_pdu.bwp_size))) - SNR;
...@@ -627,6 +627,8 @@ int main(int argc, char *argv[]) ...@@ -627,6 +627,8 @@ int main(int argc, char *argv[])
uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports; uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports;
uint8_t nb_antennas_rx = fp->nb_antennas_rx; uint8_t nb_antennas_rx = fp->nb_antennas_rx;
int16_t snr_per_rb[srs->srs_pdu.bwp_size]; int16_t snr_per_rb[srs->srs_pdu.bwp_size];
uint16_t timing_advance_offset;
int16_t timing_advance_offset_nsec[nb_antennas_rx];
int srs_est; int srs_est;
c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
c16_t srs_estimated_channel_time[nb_antennas_rx][N_ap][ofdm_symbol_size] __attribute__((aligned(32))); c16_t srs_estimated_channel_time[nb_antennas_rx][N_ap][ofdm_symbol_size] __attribute__((aligned(32)));
...@@ -643,16 +645,41 @@ int main(int argc, char *argv[]) ...@@ -643,16 +645,41 @@ int main(int argc, char *argv[])
&srs_est, &srs_est,
srs_estimated_channel_freq, srs_estimated_channel_freq,
srs_estimated_channel_time, srs_estimated_channel_time,
snr_per_rb); snr_per_rb,
&timing_advance_offset,
timing_advance_offset_nsec);
start_meas(&gNB->srs_timing_advance_stats);
nr_est_timing_advance_srs(fp, srs_estimated_channel_time[0]);
stop_meas(&gNB->srs_timing_advance_stats);
sum_srs_snr += pow(10, (double)gNB->srs->snr / 10.0); sum_srs_snr += pow(10, (double)gNB->srs->snr / 10.0);
int16_t delay_ns = delay * 1e9 / (fp->samples_per_frame * 100);
for (int ant_idx = 0; ant_idx < nb_antennas_rx; ant_idx++) {
if (n_trials == 1)
printf("[RX ant %d] SRS estimated: TA offset %d, TA offset ns %d \n",
ant_idx,
timing_advance_offset,
timing_advance_offset_nsec[ant_idx]);
if (timing_advance_offset_nsec[ant_idx] == delay_ns)
tao_ns_count++;
}
stop_meas(&gNB->rx_srs_stats); stop_meas(&gNB->rx_srs_stats);
} // trail loop } // trail loop
sum_srs_snr /= n_trials; float tao_ns_rate = (float)tao_ns_count / (n_trials * n_rx);
printf("Actual SNR : %f, Estimated SNR from SRS %f (dB)\n", SNR, 10 * log10(sum_srs_snr)); float SRS_SNR_dB = 10 * log10(sum_srs_snr / n_trials);
printf("Actual SNR : %f, Estimated SNR from SRS %f (dB), TA offset success rate %f %%\n", SNR, SRS_SNR_dB, tao_ns_rate * 100);
int srs_ret = 1;
if (SNR > 30 && SRS_SNR_dB > 30) {
srs_ret = 0;
} else if (SNR >= SRS_SNR_dB) {
srs_ret = SRS_SNR_dB >= 0.7 * SNR ? 0 : 1;
} else if (SRS_SNR_dB > SNR) {
srs_ret = SNR >= 0.7 * SRS_SNR_dB ? 0 : 1;
}
if (tao_ns_rate > 0.9 && srs_ret == 0) {
ret = 0;
break;
}
if (print_perf == 1) { if (print_perf == 1) {
printf("\ngNB RX\n"); printf("\ngNB RX\n");
...@@ -666,6 +693,10 @@ int main(int argc, char *argv[]) ...@@ -666,6 +693,10 @@ int main(int argc, char *argv[])
} // SNR loop } // SNR loop
printf("*************\n");
printf("SRS test %s\n", ret == 0 ? "OK" : "FAILED");
printf("*************\n");
// free memory // free memory
for (i = 0; i < n_tx; i++) { for (i = 0; i < n_tx; i++) {
......
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