You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
6.2 KiB
C

/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <string.h>
#include <complex.h>
#include <math.h>
#include "srslte/utils/vector.h"
#include "srslte/sync/sss.h"
#define MAX_M 3
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);
}
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);
}
}
static void extract_pair_sss(srslte_sss_synch_t *q, cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) {
cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX];
float ce_mod[2*SRSLTE_SSS_N], z_real[2*SRSLTE_SSS_N], z_imag[2*SRSLTE_SSS_N];
srslte_dft_run_c(&q->dftp_input, input, input_fft);
if (ce) {
srslte_vec_div_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce, ce_mod,
&input_fft[q->fft_size/2-SRSLTE_SSS_N], z_real, z_imag,
2*SRSLTE_SSS_N);
}
for (int i = 0; i < SRSLTE_SSS_N; i++) {
y[0][i] = input_fft[q->fft_size/2-SRSLTE_SSS_N + 2 * i];
y[1][i] = input_fft[q->fft_size/2-SRSLTE_SSS_N + 2 * i + 1];
}
srslte_vec_prod_cfc(y[0], q->fc_tables[q->N_id_2].c[0], y[0], SRSLTE_SSS_N);
srslte_vec_prod_cfc(y[1], q->fc_tables[q->N_id_2].c[1], y[1], SRSLTE_SSS_N);
}
int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, cf_t *input, uint32_t *m0, float *m0_value,
uint32_t *m1, float *m1_value)
{
return srslte_sss_synch_m0m1_diff_coh(q, input, NULL, m0, m0_value, m1, m1_value);
}
/* Differential SSS estimation.
* Returns m0 and m1 estimates
*
* Source: "SSS Detection Method for Initial Cell Search in 3GPP LTE FDD/TDD Dual Mode Receiver"
* Jung-In Kim, Jung-Su Han, Hee-Jin Roh and Hyung-Jin Choi
*
*/
int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, cf_t *input, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value,
uint32_t *m1, float *m1_value)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
input != NULL &&
m0 != NULL &&
m1 != NULL)
{
cf_t yprod[SRSLTE_SSS_N];
cf_t y[2][SRSLTE_SSS_N];
extract_pair_sss(q, input, ce, y);
srslte_vec_prod_conj_ccc(&y[0][1], y[0], yprod, SRSLTE_SSS_N - 1);
corr_all_zs(yprod, q->fc_tables[q->N_id_2].sd, q->corr_output_m0);
*m0 = srslte_vec_max_fi(q->corr_output_m0, SRSLTE_SSS_N);
if (m0_value) {
*m0_value = q->corr_output_m0[*m0];
}
srslte_vec_prod_cfc(y[1], q->fc_tables[q->N_id_2].z1[*m0], y[1], SRSLTE_SSS_N);
srslte_vec_prod_conj_ccc(&y[1][1], y[1], yprod, SRSLTE_SSS_N - 1);
corr_all_zs(yprod, q->fc_tables[q->N_id_2].sd, q->corr_output_m1);
*m1 = srslte_vec_max_fi(q->corr_output_m1, SRSLTE_SSS_N);
if (m1_value) {
*m1_value = q->corr_output_m1[*m1];
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Partial correlation SSS estimation.
* Returns m0 and m1 estimates
*
* Source: "SSS Detection Method for Initial Cell Search in 3GPP LTE FDD/TDD Dual Mode Receiver"
* Jung-In Kim, Jung-Su Han, Hee-Jin Roh and Hyung-Jin Choi
*/
int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, cf_t *input, uint32_t M, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value,
uint32_t *m1, float *m1_value)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
input != NULL &&
m0 != NULL &&
m1 != NULL &&
M <= MAX_M)
{
cf_t y[2][SRSLTE_SSS_N];
extract_pair_sss(q, input, ce, y);
corr_all_sz_partial(y[0], q->fc_tables[q->N_id_2].s, M, q->corr_output_m0);
*m0 = srslte_vec_max_fi(q->corr_output_m0, SRSLTE_SSS_N);
if (m0_value) {
*m0_value = q->corr_output_m0[*m0];
}
srslte_vec_prod_cfc(y[1], q->fc_tables[q->N_id_2].z1[*m0], y[1], SRSLTE_SSS_N);
corr_all_sz_partial(y[1], q->fc_tables[q->N_id_2].s, M, q->corr_output_m1);
*m1 = srslte_vec_max_fi(q->corr_output_m1, SRSLTE_SSS_N);
if (m1_value) {
*m1_value = q->corr_output_m1[*m1];
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void convert_tables(srslte_sss_fc_tables_t *fc_tables, srslte_sss_tables_t *in) {
uint32_t i, j;
for (i = 0; i < SRSLTE_SSS_N; i++) {
for (j = 0; j < SRSLTE_SSS_N; j++) {
fc_tables->z1[i][j] = (float) in->z1[i][j];
}
}
for (i = 0; i < SRSLTE_SSS_N; i++) {
for (j = 0; j < SRSLTE_SSS_N; j++) {
fc_tables->s[i][j] = (float) in->s[i][j];
}
}
for (i = 0; i < SRSLTE_SSS_N; i++) {
for (j = 0; j < SRSLTE_SSS_N - 1; j++) {
fc_tables->sd[i][j] = (float) in->s[i][j + 1] * in->s[i][j];
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < SRSLTE_SSS_N; j++) {
fc_tables->c[i][j] = (float) in->c[i][j];
}
}
}