Esempio n. 1
0
static void corr_all_zs(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSLTE_SSS_N-1], float output[SRSLTE_SSS_N]) {
  uint32_t m;
  cf_t tmp[SRSLTE_SSS_N]; 
  
  for (m = 0; m < SRSLTE_SSS_N; m++) {
    tmp[m] = srslte_vec_dot_prod_cfc(z, s[m], SRSLTE_SSS_N - 1);    
  }
  srslte_vec_abs_square_cf(tmp, output, SRSLTE_SSS_N);
}
Esempio n. 2
0
/* Complex division is conjugate multiplication + real division */
void srslte_vec_div_ccc(cf_t *x, cf_t *y, float *y_mod, cf_t *z, float *z_real, float *z_imag, uint32_t len) {
#ifdef DIV_USE_VEC
  srslte_vec_prod_conj_ccc(x,y,z,len);
  srslte_vec_abs_square_cf(y,y_mod,len);
  srslte_vec_div_cfc(z,y_mod,z,z_real,z_imag,len);  
#else 
  int i; 
  for (i=0;i<len;i++) {
    z[i] = x[i] / y[i]; 
  }
#endif
}
Esempio n. 3
0
static void corr_all_sz_partial(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSLTE_SSS_N], uint32_t M, float output[SRSLTE_SSS_N]) {
  uint32_t Nm = SRSLTE_SSS_N/M; 
  cf_t tmp[SRSLTE_SSS_N];
  float tmp_abs[MAX_M-1][SRSLTE_SSS_N];
  int j, m; 
  float *ptr; 
  
  for (j=0;j<M;j++) {
    for (m = 0; m < SRSLTE_SSS_N; m++) {      
      tmp[m] = srslte_vec_dot_prod_cfc(&z[j*Nm], &s[m][j*Nm], Nm);        
    }
    if (j == 0) {
      ptr = output; 
    } else {
      ptr = tmp_abs[j-1];
    }
    srslte_vec_abs_square_cf(tmp, ptr, SRSLTE_SSS_N);   
  }
  for (j=1;j<M;j++) {
    srslte_vec_sum_fff(tmp_abs[j-1], output, output, SRSLTE_SSS_N);
  }    
}
Esempio n. 4
0
/** Performs time-domain PSS correlation. 
 * Returns the index of the PSS correlation peak in a subframe.
 * The frame starts at corr_peak_pos-subframe_size/2.
 * The value of the correlation is stored in corr_peak_value.
 *
 * Input buffer must be subframe_size long.
 */
int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) 
{
  int ret = SRSLTE_ERROR_INVALID_INPUTS;
  
  if (q                 != NULL  && 
      input             != NULL)
  {

    uint32_t corr_peak_pos;
    uint32_t conv_output_len;
    
    if (!srslte_N_id_2_isvalid(q->N_id_2)) {
      fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n");
      return SRSLTE_ERROR;
    }

    /* Correlate input with PSS sequence */
    if (q->frame_size >= q->fft_size) {
    #ifdef CONVOLUTION_FFT
      memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t));
            
      conv_output_len = srslte_conv_fft_cc_run(&q->conv_fft, q->tmp_input, q->pss_signal_time[q->N_id_2], q->conv_output);
    #else
      conv_output_len = srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size);
    #endif
    } else {
      for (int i=0;i<q->frame_size;i++) {
        q->conv_output[i] = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], &input[i], q->fft_size);
      }
      conv_output_len = q->frame_size; 
    }

   
  #ifdef SRSLTE_PSS_ABS_SQUARE
      srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);
  #else
      srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);
  #endif
    
    srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1);    
    srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1);    

    srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1);
    
    /* Find maximum of the absolute value of the correlation */
    corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1);
    
    // save absolute value 
    q->peak_value = q->conv_output_avg[corr_peak_pos];
    
#ifdef SRSLTE_PSS_RETURN_PSR    
    // Find second side lobe
    
    // Find end of peak lobe to the right
    int pl_ub = corr_peak_pos+1;
    while(q->conv_output_avg[pl_ub+1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) {
      pl_ub ++; 
    }
    // Find end of peak lobe to the left
    int pl_lb; 
    if (corr_peak_pos > 2) {
      pl_lb = corr_peak_pos-1;
        while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) {
        pl_lb --; 
      }      
    } else {
      pl_lb = 0; 
    }

    int sl_distance_right = conv_output_len-1-pl_ub; 
    if (sl_distance_right < 0) {
      sl_distance_right = 0; 
    }
    int sl_distance_left = pl_lb; 
    
    int sl_right = pl_ub+srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right);
    int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left);    
    float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]);    
    if (corr_peak_value) {
      *corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value;
      
      DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, 
             sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value);
    }
#else
    if (corr_peak_value) {
      *corr_peak_value = q->conv_output_avg[corr_peak_pos];
    }
#endif

    if (q->frame_size >= q->fft_size) {
      ret = (int) corr_peak_pos;                
    } else {
      ret = (int) corr_peak_pos + q->fft_size;
    }
  } 
  return ret;
}
Esempio n. 5
0
File: pss.c Progetto: srsLTE/srsLTE
/** Performs time-domain PSS correlation.
 * Returns the index of the PSS correlation peak in a subframe.
 * The frame starts at corr_peak_pos-subframe_size/2.
 * The value of the correlation is stored in corr_peak_value.
 *
 * Input buffer must be subframe_size long.
 */
int srslte_pss_find_pss(srslte_pss_t *q, const cf_t *input, float *corr_peak_value)
{
  int ret = SRSLTE_ERROR_INVALID_INPUTS;

  if (q                 != NULL  &&
      input             != NULL)
  {

    uint32_t corr_peak_pos;
    uint32_t conv_output_len;

    if (!srslte_N_id_2_isvalid(q->N_id_2)) {
      ERROR("Error finding PSS peak, Must set N_id_2 first\n");
      return SRSLTE_ERROR;
    }

    /* Correlate input with PSS sequence
     *
     * We do not reverse time-domain PSS signal because it's conjugate is symmetric.
     * The conjugate operation on pss_signal_time has been done in srslte_pss_init_N_id_2
     * This is why we can use FFT-based convolution
     */
    if (q->frame_size >= q->fft_size) {
    #ifdef CONVOLUTION_FFT
      memcpy(q->tmp_input, input, (q->frame_size * q->decimate) * sizeof(cf_t));
      if(q->decimate > 1) {
        srslte_filt_decim_cc_execute(&(q->filter), q->tmp_input, q->filter.downsampled_input, q->filter.filter_output , (q->frame_size * q->decimate));
        conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->filter.filter_output,q->pss_signal_freq_full[q->N_id_2], q->conv_output);
      } else {
        conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->pss_signal_freq_full[q->N_id_2], q->conv_output);
      }

    #else
      conv_output_len = srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size);
    #endif
    } else {
      for (int i=0;i<q->frame_size;i++) {
        q->conv_output[i] = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], &input[i], q->fft_size);
      }
      conv_output_len = q->frame_size;
    }

    // Compute modulus square
    srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);

    // If enabled, average the absolute value from previous calls
    if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) {
      srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1);
      srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1);

      srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1);
    } else {
      memcpy(q->conv_output_avg, q->conv_output_abs, sizeof(float)*(conv_output_len-1));
    }

    /* Find maximum of the absolute value of the correlation */
    corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1);

    // save absolute value
    q->peak_value = q->conv_output_avg[corr_peak_pos];

#ifdef SRSLTE_PSS_RETURN_PSR
    if (corr_peak_value) {
      *corr_peak_value = compute_peak_sidelobe(q, corr_peak_pos, conv_output_len);
    }
#else
    if (corr_peak_value) {
      *corr_peak_value = q->conv_output_avg[corr_peak_pos];
    }
#endif

    if(q->decimate >1) {
      int decimation_correction = (q->filter.num_taps - 2);
      corr_peak_pos = corr_peak_pos - decimation_correction;
      corr_peak_pos = corr_peak_pos*q->decimate;
    }

    if (q->frame_size >= q->fft_size) {
      ret = (int) corr_peak_pos;
    } else {
      ret = (int) corr_peak_pos + q->fft_size;
    }
  }
  return ret;
}
Esempio n. 6
0
int srslte_prach_detect_offset(srslte_prach_t *p,
                               uint32_t freq_offset,
                               cf_t *signal,
                               uint32_t sig_len,
                               uint32_t *indices,
                               float *t_offsets,
                               float    *peak_to_avg,
                               uint32_t *n_indices)
{
  int ret = SRSLTE_ERROR;
  if(p       != NULL &&
     signal  != NULL &&
     sig_len > 0     &&
     indices != NULL)
  {
    
    if(sig_len < p->N_ifft_prach){
      fprintf(stderr, "srslte_prach_detect: Signal length is %d and should be %d\n", sig_len, p->N_ifft_prach);
      return SRSLTE_ERROR_INVALID_INPUTS;
    }
    
    // FFT incoming signal
    srslte_dft_run(p->fft, signal, p->signal_fft);

    *n_indices = 0;

    // Extract bins of interest
    uint32_t N_rb_ul = srslte_nof_prb(p->N_ifft_ul);
    uint32_t k_0 = freq_offset*N_RB_SC - N_rb_ul*N_RB_SC/2 + p->N_ifft_ul/2;
    uint32_t K = DELTA_F/DELTA_F_RA;
    uint32_t begin = PHI + (K*k_0) + (K/2);

    memcpy(p->prach_bins, &p->signal_fft[begin], p->N_zc*sizeof(cf_t));
    
    for(int i=0;i<p->N_roots;i++){
      cf_t *root_spec = p->dft_seqs[p->root_seqs_idx[i]];
     
      srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc);

      srslte_dft_run(p->zc_ifft, p->corr_spec, p->corr_spec);
      
      srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc);

      float corr_ave = srslte_vec_acc_ff(p->corr, p->N_zc)/p->N_zc;
      
      uint32_t winsize = 0;
      if(p->N_cs != 0){
        winsize = p->N_cs;
      }else{
        winsize = p->N_zc;
      }
      uint32_t n_wins = p->N_zc/winsize;

      float max_peak = 0; 
      for(int j=0;j<n_wins;j++) {
        uint32_t start = (p->N_zc-(j*p->N_cs))%p->N_zc;
        uint32_t end = start+winsize;
        if (end>p->deadzone) {
          end-=p->deadzone;
        }
        start += p->deadzone;
        p->peak_values[j] = 0;
        for(int k=start;k<end;k++) {
          if(p->corr[k] > p->peak_values[j]) {
            p->peak_values[j]  = p->corr[k];
            p->peak_offsets[j] = k-start; 
            if (p->peak_values[j] > max_peak) {
              max_peak = p->peak_values[j];
            }
          }
        }
      }
      if (max_peak > p->detect_factor*corr_ave) {
        for (int j=0;j<n_wins;j++) {
          if(p->peak_values[j] > p->detect_factor*corr_ave)
          {
            printf("ncs=%d, nzc=%d, nwins=%d, Nroot=%d, i=%d, j=%d, start=%d, peak_value=%f, peak_offset=%d, tseq=%f\n", 
                   p->N_cs, p->N_zc, n_wins, p->N_roots, i, j, (p->N_zc-(j*p->N_cs))%p->N_zc, p->peak_values[j], 
                   p->peak_offsets[j], p->T_seq*1e6);
            memcpy(save_corr, p->corr, p->N_zc*sizeof(float));
            if (indices) {
              indices[*n_indices]     = (i*n_wins)+j;
            }
            if (peak_to_avg) {
              peak_to_avg[*n_indices] = p->peak_values[j]/corr_ave; 
            }
            if (t_offsets) {
              t_offsets[*n_indices] = (float) p->peak_offsets[j]*p->T_seq/p->N_zc; 
            }            
            (*n_indices)++;          
          }
        }
      }
    }

    ret = SRSLTE_SUCCESS;
  }
  return ret;
}