Improved initial CFO estimation for PRACH. Fixed bug in PDCCH after changing cell

This commit is contained in:
Ismael Gomez 2017-09-06 18:05:07 +02:00
parent f1bacd009a
commit 394d8f166a
7 changed files with 85 additions and 62 deletions

View File

@ -75,6 +75,8 @@ typedef struct SRSLTE_API {
uint32_t frame_size;
uint32_t max_offset;
bool enable_cfo_corr;
bool mean_cfo2_isunset;
bool mean_cfo_isunset;
float mean_cfo;
float mean_cfo2;
int cfo_i;

View File

@ -29,6 +29,7 @@
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/sync/sync.h>
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/common/phy_common.h"
@ -79,6 +80,8 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
q->max_offset = max_offset;
q->sss_alg = SSS_FULL;
q->max_frame_size = frame_size;
q->mean_cfo_isunset = true;
q->mean_cfo2_isunset = true;
q->enable_cfo_corr = true;
if (srslte_cfo_init(&q->cfocorr, q->frame_size)) {
@ -287,7 +290,10 @@ float srslte_sync_get_cfo(srslte_sync_t *q) {
}
void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) {
q->mean_cfo = cfo;
q->mean_cfo = cfo;
q->mean_cfo2 = cfo;
q->mean_cfo2_isunset = false;
q->mean_cfo_isunset = false;
}
void srslte_sync_set_cfo_i(srslte_sync_t *q, int cfo_i) {
@ -515,11 +521,16 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
cf_t *input_cfo = input;
if (q->enable_cfo_corr) {
float cfo = cfo_estimate(q, input);
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
float cfo = cfo_estimate(q, input);
if (q->mean_cfo_isunset) {
q->mean_cfo = cfo;
q->mean_cfo_isunset = false;
} else {
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
}
/* Correct CFO with the averaged CFO estimation */
srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size);
@ -574,7 +585,12 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
if (q->mean_cfo2_isunset) {
q->mean_cfo2 = cfo2;
q->mean_cfo2_isunset = true;
} else {
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
}
ret = SRSLTE_SYNC_FOUND;
} else {
@ -596,7 +612,9 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
}
void srslte_sync_reset(srslte_sync_t *q) {
q->M_ext_avg = 0;
q->mean_cfo2_isunset = true;
q->mean_cfo_isunset = true;
q->M_ext_avg = 0;
q->M_norm_avg = 0;
srslte_pss_synch_reset(&q->pss);
}

View File

@ -27,6 +27,7 @@
#include "srslte/phy/ue/ue_dl.h"
#include <string.h>
#include <srslte/srslte.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -228,6 +229,7 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell)
fprintf(stderr, "Error creating PDSCH object\n");
return SRSLTE_ERROR;
}
q->current_rnti = 0;
}
ret = SRSLTE_SUCCESS;
} else {
@ -242,6 +244,7 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell)
* For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
*/
void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) {
srslte_pdsch_set_rnti(&q->pdsch, rnti);
// Compute UE-specific and Common search space for this RNTI

View File

@ -149,8 +149,6 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
int ret = SRSLTE_SUCCESS;
cf_t *ce_slot1[SRSLTE_MAX_PORTS];
/* Run FFT for the slot symbols */
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols);

View File

@ -140,7 +140,7 @@ private:
uint32_t current_earfcn;
uint32_t sync_sfn_cnt;
const static uint32_t SYNC_SFN_TIMEOUT = 100;
const static uint32_t SYNC_SFN_TIMEOUT = 200;
float ul_dl_factor;
int cur_earfcn_index;
bool cell_search_in_progress;

View File

@ -95,7 +95,7 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_
if (srslte_ue_cellsearch_init_multi(&cs, 5, radio_recv_wrapper_cs, nof_rx_antennas,
radio_h)) {
Error("Initiating UE cell search\n");
Error("SYNC: Initiating UE cell search\n");
return;
}
@ -109,22 +109,22 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_
}
if (srslte_ue_dl_init(&ue_dl_measure, SRSLTE_MAX_PRB, nof_rx_antennas)) {
Error("Initiating ue_dl_measure\n");
Error("SYNC: Initiating ue_dl_measure\n");
return;
}
if (srslte_ue_mib_init(&ue_mib, SRSLTE_MAX_PRB)) {
Error("Initiating UE MIB decoder\n");
Error("SYNC: Initiating UE MIB decoder\n");
return;
}
if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, radio_recv_wrapper_cs, nof_rx_antennas, radio_h)) {
Error("Initiating ue_sync\n");
Error("SYNC: Initiating ue_sync\n");
return;
}
if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, radio_recv_wrapper_cs, nof_rx_antennas, radio_h)) {
Error("Initiating UE MIB synchronization\n");
Error("SYNC: Initiating UE MIB synchronization\n");
return;
}
@ -186,7 +186,7 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) {
} else if (!worker_com->args->sss_algorithm.compare("full")) {
sss_alg = SSS_FULL;
} else {
Warning("Invalid SSS algorithm %s. Using 'full'\n", worker_com->args->sss_algorithm.c_str());
Warning("SYNC: Invalid SSS algorithm %s. Using 'full'\n", worker_com->args->sss_algorithm.c_str());
}
srslte_sync_set_sss_algorithm(&q->strack, (sss_alg_t) sss_alg);
srslte_sync_set_sss_algorithm(&q->sfind, (sss_alg_t) sss_alg);
@ -195,11 +195,11 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) {
bool phch_recv::set_cell() {
cell_is_set = false;
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
Error("Setting cell: initiating ue_mib\n");
Error("SYNC: Setting cell: initiating ue_mib\n");
return false;
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
Error("Setting cell: initiating ue_sync");
Error("SYNC: Setting cell: initiating ue_sync");
return false;
}
@ -207,7 +207,7 @@ bool phch_recv::set_cell() {
set_ue_sync_opts(&ue_sync);
if (srslte_ue_dl_set_cell(&ue_dl_measure, cell)) {
Error("Setting cell: initiating ue_dl_measure\n");
Error("SYNC: Setting cell: initiating ue_dl_measure\n");
return false;
}
@ -215,7 +215,7 @@ bool phch_recv::set_cell() {
for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) {
if (!((phch_worker *) workers_pool->get_worker(i))->set_cell(cell)) {
Error("Setting cell: initiating PHCH worker\n");
Error("SYNC: Setting cell: initiating PHCH worker\n");
return false;
}
}
@ -246,7 +246,7 @@ bool phch_recv::cell_search(int force_N_id_2) {
uint32_t max_peak_cell = 0;
int ret = SRSLTE_ERROR;
Info("Searching for cell...\n");
Info("SYNC: Searching for cell...\n");
printf("."); fflush(stdout);
if (force_N_id_2 >= 0 && force_N_id_2 < 3) {
@ -260,11 +260,11 @@ bool phch_recv::cell_search(int force_N_id_2) {
if (ret < 0) {
radio_h->stop_rx();
Error("Error decoding MIB: Error searching PSS\n");
Error("SYNC: Error decoding MIB: Error searching PSS\n");
return false;
} else if (ret == 0) {
radio_h->stop_rx();
Info("Could not find any cell in this frequency\n");
Info("SYNC: Could not find any cell in this frequency\n");
return false;
}
// Save result
@ -277,7 +277,7 @@ bool phch_recv::cell_search(int force_N_id_2) {
cell.id, cellsearch_cfo/1000, srslte_cp_string(cell.cp));
if (srslte_ue_mib_sync_set_cell(&ue_mib_sync, cell.id, cell.cp)) {
Error("Setting UE MIB cell\n");
Error("SYNC: Setting UE MIB cell\n");
return false;
}
@ -314,7 +314,7 @@ bool phch_recv::cell_search(int force_N_id_2) {
return true;
} else {
Warning("Found PSS but could not decode PBCH\n");
Warning("SYNC: Found PSS but could not decode PBCH\n");
return false;
}
}
@ -328,14 +328,15 @@ int phch_recv::cell_sync_sfn(void) {
srslte_ue_sync_decode_sss_on_track(&ue_sync, true);
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
if (ret < 0) {
Error("Error calling ue_sync_get_buffer");
Error("SYNC: Error calling ue_sync_get_buffer");
return -1;
}
if (ret == 1) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
int sfn_offset = 0;
Info("SYNC: Trying to decode MIB...\n");
Info("SYNC: Trying to decode MIB... SNR=%.1f dB\n",
10*log10(srslte_chest_dl_get_snr(&ue_mib.chest)));
int n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
if (n < 0) {
Error("SYNC: Error decoding MIB while synchronising SFN");
@ -375,10 +376,11 @@ int phch_recv::cell_meas_rsrp() {
return -1;
}
float rsrp = srslte_chest_dl_get_rsrp(&ue_dl_measure.chest);
float snr = srslte_chest_dl_get_snr(&ue_dl_measure.chest);
measure_rsrp = SRSLTE_VEC_CMA(rsrp, measure_rsrp, measure_cnt);
measure_cnt++;
log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm\n",
measure_cnt, RSRP_MEASURE_NOF_FRAMES, sf_idx, 10 * log10(rsrp / 1000));
log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n",
measure_cnt, RSRP_MEASURE_NOF_FRAMES, sf_idx, 10 * log10(rsrp / 1000), 10*log10(snr));
if (measure_cnt >= RSRP_MEASURE_NOF_FRAMES) {
return 1;
}
@ -433,7 +435,7 @@ void phch_recv::cell_search_next() {
if (cell_search_in_progress) {
cell_search_in_progress = false;
if (!stop_sync()) {
log_h->warning("Couldn't stop sync\n");
log_h->warning("SYNC: Couldn't stop PHY\n");
}
cell_search_inc();
phy_state = CELL_SEARCH;
@ -446,9 +448,9 @@ void phch_recv::cell_search_start() {
cell_search_in_progress = true;
cur_earfcn_index = -1;
cell_search_next();
log_h->info("Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size());
log_h->info("SYNC: Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size());
} else {
log_h->info("Empty EARFCN list. Stopping cell search...\n");
log_h->info("SYNC: Empty EARFCN list. Stopping cell search...\n");
log_h->console("Empty EARFCN list. Stopping cell search...\n");
}
}
@ -500,7 +502,7 @@ bool phch_recv::set_frequency()
float dl_freq = 1e6*srslte_band_fd(current_earfcn);
float ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(current_earfcn));
if (dl_freq > 0 && ul_freq > 0) {
log_h->info("Set DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n",
log_h->info("SYNC: Set DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n",
current_earfcn, dl_freq / 1e6, ul_freq / 1e6);
log_h->console("Searching cell in DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n",
@ -514,7 +516,7 @@ bool phch_recv::set_frequency()
return true;
} else {
log_h->error("Cell Search: Invalid EARFCN=%d\n", current_earfcn);
log_h->error("SYNC: Cell Search: Invalid EARFCN=%d\n", current_earfcn);
return false;
}
}
@ -523,7 +525,7 @@ void phch_recv::set_sampling_rate()
{
float srate = (float) srslte_sampling_freq_hz(cell.nof_prb);
Info("Setting sampling rate %.1f MHz\n", srate/1000000);
Info("SYNC: Setting sampling rate %.2f MHz\n", srate/1000000);
if (30720 % ((int) srate / 1000) == 0) {
radio_h->set_master_clock_rate(30.72e6);
@ -545,13 +547,13 @@ void phch_recv::run_thread() {
while (running) {
if (phy_state != IDLE) {
is_in_idle = false;
Debug("SYNC state=%d\n", phy_state);
Debug("SYNC: state=%d\n", phy_state);
}
switch (phy_state) {
case CELL_SEARCH:
if (cell_search() && cell_search_in_progress) {
if (!srslte_cell_isvalid(&cell)) {
Error("Detected invalid cell\n");
Error("SYNC: Detected invalid cell\n");
phy_state = IDLE;
break;
}
@ -572,7 +574,7 @@ void phch_recv::run_thread() {
switch (cell_sync_sfn()) {
default:
log_h->console("Going IDLE\n");
log_h->console("SYNC: Going IDLE\n");
phy_state = IDLE;
break;
case 1:
@ -592,14 +594,14 @@ void phch_recv::run_thread() {
sync_sfn_cnt++;
if (sync_sfn_cnt >= SYNC_SFN_TIMEOUT) {
sync_sfn_cnt = 0;
phy_state = IDLE;
log_h->warning("Timeout while synchronizing SFN\n");
phy_state = CELL_SEARCH;
log_h->warning("SYNC: Timeout while synchronizing SFN\n");
}
break;
case CELL_MEASURE:
switch(cell_meas_rsrp()) {
case 1:
log_h->info("Measured OK. Camping on cell PCI=%d...\n", cell.id);
log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id);
phy_state = CELL_CAMP;
rrc->cell_found(earfcn[cur_earfcn_index], cell, 10*log10(measure_rsrp/1000));
break;
@ -623,7 +625,7 @@ void phch_recv::run_thread() {
log_h->step(tti);
Debug("Worker %d synchronized\n", worker->get_id());
Debug("SYNC: Worker %d synchronized\n", worker->get_id());
metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync);
metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync);
@ -640,7 +642,7 @@ void phch_recv::run_thread() {
srslte_timestamp_add(&tx_time, 0, 4e-3 - time_adv_sec);
worker->set_tx_time(tx_time);
Debug("Setting TTI=%d, tx_mutex=%d to worker %d\n", tti, tx_mutex_cnt, worker->get_id());
Debug("SYNC: Setting TTI=%d, tx_mutex=%d to worker %d\n", tti, tx_mutex_cnt, worker->get_id());
worker->set_tti(tti, tx_mutex_cnt);
tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex;
@ -657,10 +659,10 @@ void phch_recv::run_thread() {
// Notify RRC in-sync every 1 frame
if ((tti % 10) == 0) {
rrc->in_sync();
log_h->debug("Sending in-sync to RRC\n");
log_h->debug("SYNC: Sending in-sync to RRC\n");
}
} else {
log_h->error("Sync error. Sending out-of-sync to RRC\n");
log_h->error("SYNC: Sync error. Sending out-of-sync to RRC\n");
// Notify RRC of out-of-sync frame
rrc->out_of_sync();
worker->release();

View File

@ -405,7 +405,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
srslte_dci_msg_t dci_msg;
srslte_ra_dl_dci_t dci_unpacked;
Debug("Looking for RNTI=0x%x\n", dl_rnti);
Info("Looking for RNTI=0x%x\n", dl_rnti);
if (srslte_ue_dl_find_dl_dci_type(&ue_dl, phy->config->dedicated.antenna_info_explicit_value.tx_mode, cfi, tti%10,
dl_rnti, type, &dci_msg) != 1) {
@ -681,23 +681,23 @@ void phch_worker::reset_uci()
bzero(&uci_data, sizeof(srslte_uci_data_t));
}
void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb) {
if (nof_tb > 0) {
uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0);
}
if (nof_tb > 1) {
uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0);
}
if (nof_tb > 2) {
Error("Number of transport blocks is not supported");
}
uci_data.uci_ack_len = nof_tb;
void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb) {
if (nof_tb > 0) {
uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0);
}
if (nof_tb > 1) {
uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0);
}
if (nof_tb > 2) {
Error("Number of transport blocks is not supported");
}
uci_data.uci_ack_len = nof_tb;
}
void phch_worker::set_uci_sr()
{
uci_data.scheduling_request = false;