srsLTE/srslte/lib/ue/ue_mib.c

241 lines
6.6 KiB
C
Raw Normal View History

/**
*
* \section COPYRIGHT
*
2015-11-13 04:22:33 -08:00
* 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
2015-05-08 08:05:40 -07:00
* 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
2015-05-08 08:05:40 -07:00
* GNU Affero General Public License for more details.
*
2015-05-08 08:05:40 -07:00
* 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 <stdlib.h>
#include <string.h>
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include "srslte/ue/ue_mib.h"
#include "srslte/utils/debug.h"
#include "srslte/utils/vector.h"
2015-03-18 11:14:24 -07:00
int srslte_ue_mib_init(srslte_ue_mib_t * q,
srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
2014-10-24 03:06:04 -07:00
if (q != NULL &&
cell.nof_ports <= SRSLTE_MAX_PORTS)
2014-10-24 03:06:04 -07:00
{
ret = SRSLTE_ERROR;
2015-03-18 11:14:24 -07:00
bzero(q, sizeof(srslte_ue_mib_t));
if (srslte_pbch_init(&q->pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
goto clean_exit;
}
if (cell.nof_ports == 0) {
cell.nof_ports = SRSLTE_MAX_PORTS;
}
2015-03-18 11:14:24 -07:00
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
2014-11-11 10:20:09 -08:00
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
2014-10-24 03:06:04 -07:00
for (int i=0;i<cell.nof_ports;i++) {
2015-03-18 11:14:24 -07:00
q->ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (!q->ce[i]) {
perror("malloc");
goto clean_exit;
}
}
2015-04-08 01:50:01 -07:00
if (srslte_ofdm_rx_init(&q->fft, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initializing FFT\n");
goto clean_exit;
}
2015-03-18 05:41:50 -07:00
if (srslte_chest_dl_init(&q->chest, cell)) {
fprintf(stderr, "Error initializing reference signal\n");
goto clean_exit;
}
2015-03-18 11:14:24 -07:00
srslte_ue_mib_reset(q);
ret = SRSLTE_SUCCESS;
}
clean_exit:
if (ret == SRSLTE_ERROR) {
2015-03-18 11:14:24 -07:00
srslte_ue_mib_free(q);
}
return ret;
}
2015-03-18 11:14:24 -07:00
void srslte_ue_mib_free(srslte_ue_mib_t * q)
{
2014-11-11 10:20:09 -08:00
if (q->sf_symbols) {
free(q->sf_symbols);
}
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
if (q->ce[i]) {
free(q->ce[i]);
}
}
2015-03-18 11:14:24 -07:00
srslte_sync_free(&q->sfind);
2015-03-18 05:41:50 -07:00
srslte_chest_dl_free(&q->chest);
2015-03-18 11:14:24 -07:00
srslte_pbch_free(&q->pbch);
2015-04-08 01:50:01 -07:00
srslte_ofdm_rx_free(&q->fft);
2015-03-18 11:14:24 -07:00
bzero(q, sizeof(srslte_ue_mib_t));
}
2015-03-18 11:14:24 -07:00
void srslte_ue_mib_reset(srslte_ue_mib_t * q)
{
q->frame_cnt = 0;
2015-03-18 11:14:24 -07:00
srslte_pbch_decode_reset(&q->pbch);
}
2015-03-18 11:14:24 -07:00
int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset)
{
int ret = SRSLTE_SUCCESS;
2015-03-18 05:41:50 -07:00
cf_t *ce_slot1[SRSLTE_MAX_PORTS];
/* Run FFT for the slot symbols */
2015-04-08 01:50:01 -07:00
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols);
2014-10-24 03:06:04 -07:00
/* Get channel estimates of sf idx #0 for each port */
2015-03-18 05:41:50 -07:00
ret = srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0);
if (ret < 0) {
return SRSLTE_ERROR;
}
/* Reset decoder if we missed a frame */
if (q->frame_cnt > 8) {
INFO("Resetting PBCH decoder after %d frames\n", q->frame_cnt);
2015-03-18 11:14:24 -07:00
srslte_ue_mib_reset(q);
}
2015-03-18 05:41:50 -07:00
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
2015-03-18 05:59:29 -07:00
ce_slot1[i] = &q->ce[i][SRSLTE_SLOT_LEN_RE(q->chest.cell.nof_prb, q->chest.cell.cp)];
}
2015-10-14 13:30:41 -07:00
/* Decode PBCH */
2015-03-18 11:14:24 -07:00
ret = srslte_pbch_decode(&q->pbch, &q->sf_symbols[SRSLTE_SLOT_LEN_RE(q->chest.cell.nof_prb, q->chest.cell.cp)],
ce_slot1, srslte_chest_dl_get_noise_estimate(&q->chest),
bch_payload, nof_tx_ports, sfn_offset);
2015-10-14 13:30:41 -07:00
if (ret < 0) {
fprintf(stderr, "Error decoding PBCH (%d)\n", ret);
} else if (ret == 1) {
INFO("MIB decoded: %u\n", q->frame_cnt);
2015-03-18 11:14:24 -07:00
srslte_ue_mib_reset(q);
ret = SRSLTE_UE_MIB_FOUND;
} else {
ret = SRSLTE_UE_MIB_NOTFOUND;
2016-04-04 12:44:07 -07:00
INFO("MIB not decoded: %u\n", q->frame_cnt);
q->frame_cnt++;
}
return ret;
}
2014-10-24 03:06:04 -07:00
2015-03-18 11:14:24 -07:00
int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
uint32_t cell_id,
2015-03-18 05:41:50 -07:00
srslte_cp_t cp,
2015-03-18 08:05:38 -07:00
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*),
void *stream_handler)
2014-10-21 11:03:05 -07:00
{
2015-03-18 05:41:50 -07:00
srslte_cell_t cell;
// If the ports are set to 0, ue_mib goes through 1, 2 and 4 ports to blindly detect nof_ports
cell.nof_ports = 0;
cell.id = cell_id;
cell.cp = cp;
2015-03-18 11:14:24 -07:00
cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB;
2015-03-18 11:14:24 -07:00
if (srslte_ue_mib_init(&q->ue_mib, cell)) {
fprintf(stderr, "Error initiating ue_mib\n");
return SRSLTE_ERROR;
}
2015-03-18 11:14:24 -07:00
if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n");
2015-03-18 11:14:24 -07:00
srslte_ue_mib_free(&q->ue_mib);
return SRSLTE_ERROR;
}
2015-03-18 11:14:24 -07:00
srslte_ue_sync_decode_sss_on_track(&q->ue_sync, true);
return SRSLTE_SUCCESS;
}
2014-10-21 11:03:05 -07:00
2015-03-18 11:14:24 -07:00
void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q) {
srslte_ue_mib_free(&q->ue_mib);
srslte_ue_sync_free(&q->ue_sync);
}
2015-03-18 11:14:24 -07:00
void srslte_ue_mib_sync_reset(srslte_ue_mib_sync_t * q) {
srslte_ue_mib_reset(&q->ue_mib);
srslte_ue_sync_reset(&q->ue_sync);
}
2014-10-14 05:56:18 -07:00
2015-03-18 11:14:24 -07:00
int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
uint32_t max_frames_timeout,
2015-03-24 07:58:33 -07:00
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN],
uint32_t *nof_tx_ports,
int *sfn_offset)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
cf_t *sf_buffer = NULL;
uint32_t nof_frames = 0;
2015-03-18 11:14:24 -07:00
int mib_ret = SRSLTE_UE_MIB_NOTFOUND;
if (q != NULL)
{
ret = SRSLTE_SUCCESS;
do {
2015-03-18 11:14:24 -07:00
mib_ret = SRSLTE_UE_MIB_NOTFOUND;
ret = srslte_ue_sync_get_buffer(&q->ue_sync, &sf_buffer);
if (ret < 0) {
2015-03-18 11:14:24 -07:00
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
break;
2015-03-18 11:14:24 -07:00
} else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) {
if (ret == 1) {
2015-03-18 11:14:24 -07:00
mib_ret = srslte_ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset);
} else {
2015-05-13 02:44:01 -07:00
DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt);
2015-03-18 11:14:24 -07:00
srslte_ue_mib_reset(&q->ue_mib);
}
nof_frames++;
2014-10-14 05:56:18 -07:00
}
2015-03-18 11:14:24 -07:00
} while (mib_ret == SRSLTE_UE_MIB_NOTFOUND && ret >= 0 && nof_frames < max_frames_timeout);
if (mib_ret < 0) {
ret = mib_ret;
}
}
return mib_ret;
}