From ab6d7afd09b02963ba345c983acef44acfdf8322 Mon Sep 17 00:00:00 2001
From: Roberto Louro Magueta <rmagueta@allbesmart.pt>
Date: Mon, 9 May 2022 15:54:20 +0100
Subject: [PATCH] Compute the SNR per RB using the SRS

---
 openair1/PHY/INIT/nr_init.c                   |  2 +
 .../NR_ESTIMATION/nr_ul_channel_estimation.c  | 37 ++++++++++++++-----
 openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h |  4 +-
 openair1/PHY/defs_nr_common.h                 |  2 +
 openair1/SCHED_NR/phy_procedures_nr_gNB.c     |  4 +-
 5 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index 64bbdfa4878..21ebcc14059 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -618,8 +618,10 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
     gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
     gNB->nr_srs_info[id]->sc_list = (uint16_t *) malloc16_clear(6*fp->N_RB_UL*sizeof(uint16_t));
     gNB->nr_srs_info[id]->srs_generated_signal = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+    gNB->nr_srs_info[id]->signal_power = (uint32_t*)malloc16_clear(sizeof(uint32_t));
     gNB->nr_srs_info[id]->noise_power_per_rb = (uint32_t*)malloc16_clear(fp->N_RB_UL*sizeof(uint32_t));
     gNB->nr_srs_info[id]->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t));
+    gNB->nr_srs_info[id]->snr_per_rb = (int8_t*)malloc16_clear(fp->N_RB_UL*sizeof(int8_t));
     gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*));
     gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*));
     gNB->nr_srs_info[id]->srs_estimated_channel_freq = (int32_t **)malloc16(Prx*sizeof(int32_t*));
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
index ffdf07860dd..8db33e3e185 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
@@ -1079,9 +1079,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
   }//Antenna loop
 }
 
-uint32_t calc_power(uint16_t *x, uint32_t size) {
-  uint64_t sum_x = 0;
-  uint64_t sum_x2 = 0;
+uint32_t calc_power(const int16_t *x, uint32_t size) {
+  int64_t sum_x = 0;
+  int64_t sum_x2 = 0;
   for(int k = 0; k<size; k++) {
     sum_x = sum_x + x[k];
     sum_x2 = sum_x2 + x[k]*x[k];
@@ -1099,8 +1099,10 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
                               int32_t **srs_estimated_channel_freq,
                               int32_t **srs_estimated_channel_time,
                               int32_t **srs_estimated_channel_time_shifted,
+                              uint32_t *signal_power,
                               uint32_t *noise_power_per_rb,
-                              uint32_t *noise_power) {
+                              uint32_t *noise_power,
+                              int8_t *snr_per_rb) {
 
   if(nr_srs_info->sc_list_length == 0) {
     LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot);
@@ -1110,8 +1112,10 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
   NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
   int32_t **srs_ls_estimated_channel = nr_srs_info->srs_ls_estimated_channel;
 
-  uint16_t noise_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
-  uint16_t noise_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
+  int16_t ch_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
+  int16_t ch_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
+  int16_t noise_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
+  int16_t noise_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
 
   int16_t ls_estimated[2];
 
@@ -1199,8 +1203,10 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
 
     // Compute noise
     for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
-      noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) & 0xFFFF));
-      noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)(((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) >> 16) & 0xFFFF));
+      ch_real[ant*nr_srs_info->sc_list_length + sc_idx] = (int16_t)(srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF);
+      ch_imag[ant*nr_srs_info->sc_list_length + sc_idx] = (int16_t)((srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF);
+      noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)(srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF) - ch_real[ant*nr_srs_info->sc_list_length + sc_idx]);
+      noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF) - ch_imag[ant*nr_srs_info->sc_list_length + sc_idx]);
     }
 
     // Convert to time domain
@@ -1217,8 +1223,20 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
            (gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t));
   }
 
+  // Compute signal power
+  *signal_power = calc_power(ch_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length)
+                  + calc_power(ch_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length);
+
+#ifdef SRS_DEBUG
+  LOG_I(NR_PHY,"signal_power = %u\n", *signal_power);
+#endif
+
   // Compute noise power
 
+  uint8_t signal_power_bits = log2_approx(*signal_power);
+  uint8_t factor_bits = signal_power_bits < 32 ? 32 - signal_power_bits : 0; // 32 due to input of dB_fixed(uint32_t x)
+  int32_t factor_dB = dB_fixed(1<<factor_bits);
+
   uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12;
   uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3;
   uint8_t n_noise_estimates = frame_parms->nb_antennas_rx*srs_symbols_per_rb;
@@ -1247,6 +1265,7 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
       if (count_estimates == n_noise_estimates) {
         noise_power_per_rb[rb] = sum_re2/n_noise_estimates - (sum_re/n_noise_estimates)*(sum_re/n_noise_estimates) +
                                  sum_im2/n_noise_estimates - (sum_im/n_noise_estimates)*(sum_im/n_noise_estimates);
+        snr_per_rb[rb] = dB_fixed((int32_t)((*signal_power<<factor_bits)/noise_power_per_rb[rb])) - factor_dB;
         count_estimates = 0;
         sum_re = 0;
         sum_re2 = 0;
@@ -1254,7 +1273,7 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
         sum_im2 = 0;
 
 #ifdef SRS_DEBUG
-        LOG_I(NR_PHY,"noise_power_per_rb[%i] = %i\n", rb, noise_power_per_rb[rb]);
+        LOG_I(NR_PHY,"noise_power_per_rb[%i] = %i, snr_per_rb[%i] = %i dB\n", rb, noise_power_per_rb[rb], rb, snr_per_rb[rb]);
 #endif
 
       }
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
index 9c7d67b25d6..f7ac055dcc0 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
@@ -73,6 +73,8 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
                               int32_t **srs_estimated_channel_freq,
                               int32_t **srs_estimated_channel_time,
                               int32_t **srs_estimated_channel_time_shifted,
+                              uint32_t *signal_power,
                               uint32_t *noise_power_per_rb,
-                              uint32_t *noise_power);
+                              uint32_t *noise_power,
+                              int8_t *snr_per_rb);
 #endif
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 80842eef386..4109b138317 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -244,8 +244,10 @@ typedef struct {
   int32_t **srs_estimated_channel_freq;
   int32_t **srs_estimated_channel_time;
   int32_t **srs_estimated_channel_time_shifted;
+  uint32_t *signal_power;
   uint32_t *noise_power_per_rb;
   uint32_t *noise_power;
+  int8_t *snr_per_rb;
 } nr_srs_info_t;
 
 typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS;
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index aa75cc64ef3..b342b87fa80 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -834,8 +834,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
                                   gNB->nr_srs_info[i]->srs_estimated_channel_freq,
                                   gNB->nr_srs_info[i]->srs_estimated_channel_time,
                                   gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted,
+                                  gNB->nr_srs_info[i]->signal_power,
                                   gNB->nr_srs_info[i]->noise_power_per_rb,
-                                  gNB->nr_srs_info[i]->noise_power);
+                                  gNB->nr_srs_info[i]->noise_power,
+                                  gNB->nr_srs_info[i]->snr_per_rb);
 
         T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0),
           T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_freq[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t)));
-- 
GitLab